⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cook_fix.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 3 页
字号:
    if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return;

    length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1;
    for (i=0 ; i<length ; i++) {
       decouple_tab[cplband[q->js_subband_start] + i] = get_bits(&q->gb, q->js_vlc_bits);
    }
    return;
}


/**
 * function for decoding joint stereo data
 * Decoupling calculation for joint stereo coefficients.
 *
 * @param q                 pointer to the COOKContext
 * @param mlt_buffer1       pointer to left channel mlt coefficients
 * @param mlt_buffer2       pointer to right channel mlt coefficients
 * @param x                 mono coefficient
 * @param table             number of decoupling table
 * @param i                 table index
 */

static void joint_decode(COOKContext *q, float* mlt_buffer1,
                         float* mlt_buffer2) {
    int i,j;
    int decouple_tab[SUBBAND_SIZE];
    float decode_buffer[1060];
    int idx, cpl_tmp,tmp_idx;
    float f1,f2;
    float* cplscale;

    memset(decouple_tab, 0, sizeof(decouple_tab));
    memset(decode_buffer, 0, sizeof(decode_buffer));

    /* Make sure the buffers are zeroed out. */
    memset(mlt_buffer1,0, 1024*sizeof(float));
    memset(mlt_buffer2,0, 1024*sizeof(float));
    decouple_info(q, decouple_tab);
    mono_decode(q, decode_buffer);

    /* The two channels are stored interleaved in decode_buffer. */
    for (i=0 ; i<q->js_subband_start ; i++) {
        for (j=0 ; j<SUBBAND_SIZE ; j++) {
            mlt_buffer1[i*20+j] = decode_buffer[i*40+j];
            mlt_buffer2[i*20+j] = decode_buffer[i*40+20+j];
        }
    }

    /* When we reach js_subband_start (the higher frequencies)
       the coefficients are stored in a coupling scheme. */
    idx = (1 << q->js_vlc_bits) - 1;
    for (i=q->js_subband_start ; i<q->subbands ; i++) {
        cpl_tmp = cplband[i];
        idx -=decouple_tab[cpl_tmp];
        cplscale = (float*)cplscales[q->js_vlc_bits-2];  //choose decoupler table
        f1 = cplscale[decouple_tab[cpl_tmp]];
        f2 = cplscale[idx-1];
        for (j=0 ; j<SUBBAND_SIZE ; j++) {
            tmp_idx = ((q->js_subband_start + i)*20)+j;
            mlt_buffer1[20*i + j] = f1 * decode_buffer[tmp_idx];
            mlt_buffer2[20*i + j] = f2 * decode_buffer[tmp_idx];
        }
        idx = (1 << q->js_vlc_bits) - 1;
    }
}

/**
 * First part of subpacket decoding:
 *  decode raw stream bytes and read gain info.
 *
 * @param q                 pointer to the COOKContext
 * @param inbuffer          pointer to raw stream data
 * @param gain_ptr          array of current/prev gain pointers
 */

static inline void
decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer,
                      cook_gains *gains_ptr)
static inline float cplscale_math(float x, int table, int i)
{
    int offset;

    offset = decode_bytes(inbuffer, q->decoded_bytes_buffer,
                          q->bits_per_subpacket/8);
    init_get_bits(&q->gb, q->decoded_bytes_buffer + offset,
                  q->bits_per_subpacket);
    decode_gain_info(&q->gb, gains_ptr->now);

    /* Swap current and previous gains */
    FFSWAP(int *, gains_ptr->now, gains_ptr->previous);
  return x * cplscales[table-2][i];
}


/**
 * Final part of subpacket decoding:
 *  Apply modulated lapped transform, gain compensation,
 *  clip and convert to integer.
 * Final converion from floating point values to
 * signed, 16 bit sound samples. Round and clip.
 *
 * @param q                 pointer to the COOKContext
 * @param decode_buffer     pointer to the mlt coefficients
 * @param gain_ptr          array of current/prev gain pointers
 * @param previous_buffer   pointer to the previous buffer to be used for overlapping
 * @param out               pointer to the output buffer
 * @param chan              0: left or single channel, 1: right channel
 */

static inline void
mlt_compensate_output(COOKContext *q, float *decode_buffer,
                      cook_gains *gains, float *previous_buffer,
                      int16_t *out, int chan)
static inline void output_math(COOKContext *q, int16_t *out, int chan)
{
    float *output = q->mono_mdct_output + q->samples_per_channel;
    int j;

    imlt_gain(q, decode_buffer, gains, previous_buffer);

    /* Clip and convert floats to 16 bits.
    /* FIXME: Should use DSPContext.float_to_int16() here.
     */
    for (j = 0; j < q->samples_per_channel; j++) {
        out[chan + q->nb_channels * j] =
          av_clip(lrintf(output[j]), -32768, 32767);
    }
}


/**
 * Cook subpacket decoding. This function returns one decoded subpacket,
 * usually 1024 samples per channel.
 *
 * @param q                 pointer to the COOKContext
 * @param inbuffer          pointer to the inbuffer
 * @param sub_packet_size   subpacket size
 * @param outbuffer         pointer to the outbuffer
 */


static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
                            int sub_packet_size, int16_t *outbuffer) {
    /* packet dump */
//    for (i=0 ; i<sub_packet_size ; i++) {
//        av_log(NULL, AV_LOG_ERROR, "%02x", inbuffer[i]);
//    }
//    av_log(NULL, AV_LOG_ERROR, "\n");

    decode_bytes_and_gain(q, inbuffer, &q->gains1);

    if (q->joint_stereo) {
        joint_decode(q, q->decode_buffer_1, q->decode_buffer_2);
    } else {
        mono_decode(q, q->decode_buffer_1);

        if (q->nb_channels == 2) {
            decode_bytes_and_gain(q, inbuffer + sub_packet_size/2, &q->gains2);
            mono_decode(q, q->decode_buffer_2);
        }
    }

    mlt_compensate_output(q, q->decode_buffer_1, &q->gains1,
                          q->mono_previous_buffer1, outbuffer, 0);

    if (q->nb_channels == 2) {
        if (q->joint_stereo) {
            mlt_compensate_output(q, q->decode_buffer_2, &q->gains1,
                                  q->mono_previous_buffer2, outbuffer, 1);
        } else {
            mlt_compensate_output(q, q->decode_buffer_2, &q->gains2,
                                  q->mono_previous_buffer2, outbuffer, 1);
        }
    }
    return q->samples_per_frame * sizeof(int16_t);
}


/**
 * Cook frame decoding
 *
 * @param avctx     pointer to the AVCodecContext
 */

static int cook_decode_frame(AVCodecContext *avctx,
            void *data, int *data_size,
            uint8_t *buf, int buf_size) {
    COOKContext *q = avctx->priv_data;

    if (buf_size < avctx->block_align)
        return buf_size;

    *data_size = decode_subpacket(q, buf, avctx->block_align, data);

    /* Discard the first two frames: no valid audio. */
    if (avctx->frame_number < 2) *data_size = 0;

    return avctx->block_align;
}

#ifdef COOKDEBUG
static void dump_cook_context(COOKContext *q)
{
    //int i=0;
#define PRINT(a,b) av_log(NULL,AV_LOG_ERROR," %s = %d\n", a, b);
    av_log(NULL,AV_LOG_ERROR,"COOKextradata\n");
    av_log(NULL,AV_LOG_ERROR,"cookversion=%x\n",q->cookversion);
    if (q->cookversion > STEREO) {
        PRINT("js_subband_start",q->js_subband_start);
        PRINT("js_vlc_bits",q->js_vlc_bits);
    }
    av_log(NULL,AV_LOG_ERROR,"COOKContext\n");
    PRINT("nb_channels",q->nb_channels);
    PRINT("bit_rate",q->bit_rate);
    PRINT("sample_rate",q->sample_rate);
    PRINT("samples_per_channel",q->samples_per_channel);
    PRINT("samples_per_frame",q->samples_per_frame);
    PRINT("subbands",q->subbands);
    PRINT("random_state",q->random_state);
    PRINT("js_subband_start",q->js_subband_start);
    PRINT("log2_numvector_size",q->log2_numvector_size);
    PRINT("numvector_size",q->numvector_size);
    PRINT("total_subbands",q->total_subbands);
}
#endif

/**
 * Cook initialization
 *
 * @param avctx     pointer to the AVCodecContext
 */

static int cook_decode_init(AVCodecContext *avctx)
{
    COOKContext *q = avctx->priv_data;
    uint8_t *edata_ptr = avctx->extradata;

    /* Take care of the codec specific extradata. */
    if (avctx->extradata_size <= 0) {
        av_log(avctx,AV_LOG_ERROR,"Necessary extradata missing!\n");
        return -1;
    } else {
        /* 8 for mono, 16 for stereo, ? for multichannel
           Swap to right endianness so we don't need to care later on. */
        av_log(avctx,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size);
        if (avctx->extradata_size >= 8){
            q->cookversion = bytestream_get_be32(&edata_ptr);
            q->samples_per_frame =  bytestream_get_be16(&edata_ptr);
            q->subbands = bytestream_get_be16(&edata_ptr);
        }
        if (avctx->extradata_size >= 16){
            bytestream_get_be32(&edata_ptr);    //Unknown unused
            q->js_subband_start = bytestream_get_be16(&edata_ptr);
            q->js_vlc_bits = bytestream_get_be16(&edata_ptr);
        }
    }

    /* Take data from the AVCodecContext (RM container). */
    q->sample_rate = avctx->sample_rate;
    q->nb_channels = avctx->channels;
    q->bit_rate = avctx->bit_rate;

    /* Initialize RNG. */
    av_init_random(1, &q->random_state);

    /* Initialize extradata related variables. */
    q->samples_per_channel = q->samples_per_frame / q->nb_channels;
    q->bits_per_subpacket = avctx->block_align * 8;

    /* Initialize default data states. */
    q->log2_numvector_size = 5;
    q->total_subbands = q->subbands;

    /* Initialize version-dependent variables */
    av_log(NULL,AV_LOG_DEBUG,"q->cookversion=%x\n",q->cookversion);
    q->joint_stereo = 0;
    switch (q->cookversion) {
        case MONO:
            if (q->nb_channels != 1) {
                av_log(avctx,AV_LOG_ERROR,"Container channels != 1, report sample!\n");
                return -1;
            }
            av_log(avctx,AV_LOG_DEBUG,"MONO\n");
            break;
        case STEREO:
            if (q->nb_channels != 1) {
                q->bits_per_subpacket = q->bits_per_subpacket/2;
            }
            av_log(avctx,AV_LOG_DEBUG,"STEREO\n");
            break;
        case JOINT_STEREO:
            if (q->nb_channels != 2) {
                av_log(avctx,AV_LOG_ERROR,"Container channels != 2, report sample!\n");
                return -1;
            }
            av_log(avctx,AV_LOG_DEBUG,"JOINT_STEREO\n");
            if (avctx->extradata_size >= 16){
                q->total_subbands = q->subbands + q->js_subband_start;
                q->joint_stereo = 1;
            }
            if (q->samples_per_channel > 256) {
                q->log2_numvector_size  = 6;
            }
            if (q->samples_per_channel > 512) {
                q->log2_numvector_size  = 7;
            }
            break;
        case MC_COOK:
            av_log(avctx,AV_LOG_ERROR,"MC_COOK not supported!\n");
            return -1;
            break;
        default:
            av_log(avctx,AV_LOG_ERROR,"Unknown Cook version, report sample!\n");
            return -1;
            break;
    }

    /* Initialize variable relations */
    q->numvector_size = (1 << q->log2_numvector_size);

    /* Generate tables */
    init_rootpow2table(q);
    init_pow2table(q);
    init_gain_table(q);

    if (init_cook_vlc_tables(q) != 0)
        return -1;


    if(avctx->block_align >= UINT_MAX/2)
        return -1;

    /* Pad the databuffer with:
       DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(),
       FF_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */
    if (q->nb_channels==2 && q->joint_stereo==0) {
        q->decoded_bytes_buffer =
          av_mallocz(avctx->block_align/2
                     + DECODE_BYTES_PAD2(avctx->block_align/2)
                     + FF_INPUT_BUFFER_PADDING_SIZE);
    } else {
        q->decoded_bytes_buffer =
          av_mallocz(avctx->block_align
                     + DECODE_BYTES_PAD1(avctx->block_align)
                     + FF_INPUT_BUFFER_PADDING_SIZE);
    }
    if (q->decoded_bytes_buffer == NULL)
        return -1;

    q->gains1.now      = q->gain_1;
    q->gains1.previous = q->gain_2;
    q->gains2.now      = q->gain_3;
    q->gains2.previous = q->gain_4;

    /* Initialize transform. */
    if ( init_cook_mlt(q) != 0 )
        return -1;

    /* Try to catch some obviously faulty streams, othervise it might be exploitable */
    if (q->total_subbands > 53) {
        av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n");
        return -1;
    }
    if (q->subbands > 50) {
        av_log(avctx,AV_LOG_ERROR,"subbands > 50, report sample!\n");
        return -1;
    }
    if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) {
    } else {
        av_log(avctx,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel);
        return -1;
    }
    if ((q->js_vlc_bits > 6) || (q->js_vlc_bits < 0)) {
        av_log(avctx,AV_LOG_ERROR,"q->js_vlc_bits = %d, only >= 0 and <= 6 allowed!\n",q->js_vlc_bits);
        return -1;
    }

#ifdef COOKDEBUG
    dump_cook_context(q);
#endif
    return 0;
}


AVCodec cook_decoder =
{
    .name = "cook",
    .type = CODEC_TYPE_AUDIO,
    .id = CODEC_ID_COOK,
    .priv_data_size = sizeof(COOKContext),
    .init = cook_decode_init,
    .close = cook_decode_close,
    .decode = cook_decode_frame,
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -