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

📄 cook.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 3 页
字号:
static void decouple_info(COOKContext *q, int* decouple_tab){    int length, i;    if(get_bits1(&q->gb)) {        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_vlc2(&q->gb, q->ccpl.table, q->ccpl.bits, 2);        }        return;    }    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 * * @param q                 pointer to the COOKContext * @param mlt_buffer1       pointer to left channel mlt coefficients * @param mlt_buffer2       pointer to right channel mlt coefficients */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;    }}/** * 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) {    int i,j;    int value;    float* tmp_ptr;    /* 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(inbuffer, q->decoded_bytes_buffer, sub_packet_size);    init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8);    decode_gain_info(&q->gb, &q->gain_current);    if(q->nb_channels==2 && q->joint_stereo==1){        joint_decode(q, q->decode_buf_ptr[0], q->decode_buf_ptr[2]);        /* Swap buffer pointers. */        tmp_ptr = q->decode_buf_ptr[1];        q->decode_buf_ptr[1] = q->decode_buf_ptr[0];        q->decode_buf_ptr[0] = tmp_ptr;        tmp_ptr = q->decode_buf_ptr[3];        q->decode_buf_ptr[3] = q->decode_buf_ptr[2];        q->decode_buf_ptr[2] = tmp_ptr;        /* FIXME: Rethink the gainbuffer handling, maybe a rename?           now/previous swap */        q->gain_now_ptr = &q->gain_now;        q->gain_previous_ptr = &q->gain_previous;        for (i=0 ; i<q->nb_channels ; i++){            cook_imlt(q, q->decode_buf_ptr[i*2], q->mono_mdct_output, q->mlt_tmp);            gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,                            q->gain_previous_ptr, q->previous_buffer_ptr[0]);            /* Swap out the previous buffer. */            tmp_ptr = q->previous_buffer_ptr[0];            q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1];            q->previous_buffer_ptr[1] = tmp_ptr;            /* Clip and convert the floats to 16 bits. */            for (j=0 ; j<q->samples_per_frame ; j++){                value = lrintf(q->mono_mdct_output[j]);                if(value < -32768) value = -32768;                else if(value > 32767) value = 32767;                outbuffer[2*j+i] = value;            }        }        memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain));        memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain));    } else if (q->nb_channels==2 && q->joint_stereo==0) {            /* channel 0 */            mono_decode(q, q->decode_buf_ptr2[0]);            tmp_ptr = q->decode_buf_ptr2[0];            q->decode_buf_ptr2[0] = q->decode_buf_ptr2[1];            q->decode_buf_ptr2[1] = tmp_ptr;            memcpy(&q->gain_channel1[0], &q->gain_current ,sizeof(COOKgain));            q->gain_now_ptr = &q->gain_channel1[0];            q->gain_previous_ptr = &q->gain_channel1[1];            cook_imlt(q, q->decode_buf_ptr2[0], q->mono_mdct_output,q->mlt_tmp);            gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,                            q->gain_previous_ptr, q->mono_previous_buffer1);            memcpy(&q->gain_channel1[1], &q->gain_channel1[0],sizeof(COOKgain));            for (j=0 ; j<q->samples_per_frame ; j++){                value = lrintf(q->mono_mdct_output[j]);                if(value < -32768) value = -32768;                else if(value > 32767) value = 32767;                outbuffer[2*j+1] = value;            }            /* channel 1 */            //av_log(NULL,AV_LOG_ERROR,"bits = %d\n",get_bits_count(&q->gb));            init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8+q->bits_per_subpacket);            q->gain_now_ptr = &q->gain_channel2[0];            q->gain_previous_ptr = &q->gain_channel2[1];            decode_gain_info(&q->gb, &q->gain_channel2[0]);            mono_decode(q, q->decode_buf_ptr[0]);            tmp_ptr = q->decode_buf_ptr[0];            q->decode_buf_ptr[0] = q->decode_buf_ptr[1];            q->decode_buf_ptr[1] = tmp_ptr;            cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp);            gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,                            q->gain_previous_ptr, q->mono_previous_buffer2);            /* Swap out the previous buffer. */            tmp_ptr = q->previous_buffer_ptr[0];            q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1];            q->previous_buffer_ptr[1] = tmp_ptr;            memcpy(&q->gain_channel2[1], &q->gain_channel2[0] ,sizeof(COOKgain));            for (j=0 ; j<q->samples_per_frame ; j++){                value = lrintf(q->mono_mdct_output[j]);                if(value < -32768) value = -32768;                else if(value > 32767) value = 32767;                outbuffer[2*j] = value;            }    } else {        mono_decode(q, q->decode_buf_ptr[0]);        /* Swap buffer pointers. */        tmp_ptr = q->decode_buf_ptr[1];        q->decode_buf_ptr[1] = q->decode_buf_ptr[0];        q->decode_buf_ptr[0] = tmp_ptr;        /* FIXME: Rethink the gainbuffer handling, maybe a rename?           now/previous swap */        q->gain_now_ptr = &q->gain_now;        q->gain_previous_ptr = &q->gain_previous;        cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp);        gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,                        q->gain_previous_ptr, q->mono_previous_buffer1);        /* Clip and convert the floats to 16 bits */        for (j=0 ; j<q->samples_per_frame ; j++){            value = lrintf(q->mono_mdct_output[j]);            if(value < -32768) value = -32768;            else if(value > 32767) value = 32767;            outbuffer[j] = value;        }        memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain));        memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain));    }    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);    return avctx->block_align;}#ifdef COOKDEBUGstatic void dump_cook_context(COOKContext *q, COOKextradata *e){    //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",e->cookversion);    if (e->cookversion > MONO_COOK2) {        PRINT("js_subband_start",e->js_subband_start);        PRINT("js_vlc_bits",e->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("mlt_size",q->mlt_size);    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){    COOKextradata *e = avctx->extradata;    COOKContext *q = avctx->priv_data;    /* Take care of the codec specific extradata. */    if (avctx->extradata_size <= 0) {        av_log(NULL,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(NULL,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size);        if (avctx->extradata_size >= 8){            e->cookversion = be2me_32(e->cookversion);            e->samples_per_frame = be2me_16(e->samples_per_frame);            e->subbands = be2me_16(e->subbands);        }        if (avctx->extradata_size >= 16){            e->js_subband_start = be2me_16(e->js_subband_start);            e->js_vlc_bits = be2me_16(e->js_vlc_bits);        }    }    /* 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 state. */    q->random_state = 1;    /* Initialize extradata related variables. */    q->samples_per_channel = e->samples_per_frame / q->nb_channels;    q->samples_per_frame = e->samples_per_frame;    q->subbands = e->subbands;    q->bits_per_subpacket = avctx->block_align * 8;    /* Initialize default data states. */    q->js_subband_start = 0;    q->log2_numvector_size = 5;    q->total_subbands = q->subbands;    /* Initialize version-dependent variables */    av_log(NULL,AV_LOG_DEBUG,"e->cookversion=%x\n",e->cookversion);    switch (e->cookversion) {        case MONO_COOK1:            if (q->nb_channels != 1) {                av_log(NULL,AV_LOG_ERROR,"Container channels != 1, report sample!\n");                return -1;            }            av_log(NULL,AV_LOG_DEBUG,"MONO_COOK1\n");            break;        case MONO_COOK2:            if (q->nb_channels != 1) {                q->joint_stereo = 0;                q->bits_per_subpacket = q->bits_per_subpacket/2;            }            av_log(NULL,AV_LOG_DEBUG,"MONO_COOK2\n");            break;        case JOINT_STEREO:            if (q->nb_channels != 2) {                av_log(NULL,AV_LOG_ERROR,"Container channels != 2, report sample!\n");                return -1;            }            av_log(NULL,AV_LOG_DEBUG,"JOINT_STEREO\n");            if (avctx->extradata_size >= 16){                q->total_subbands = q->subbands + e->js_subband_start;                q->js_subband_start = e->js_subband_start;                q->joint_stereo = 1;                q->js_vlc_bits = e->js_vlc_bits;            }            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(NULL,AV_LOG_ERROR,"MC_COOK not supported!\n");            return -1;            break;        default:            av_log(NULL,AV_LOG_ERROR,"Unknown Cook version, report sample!\n");            return -1;            break;    }    /* Initialize variable relations */    q->mlt_size = q->samples_per_channel;    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;    /* Pad the databuffer with FF_INPUT_BUFFER_PADDING_SIZE,       this is for the bitstreamreader. */    if ((q->decoded_bytes_buffer = av_mallocz((avctx->block_align+(4-avctx->block_align%4) + FF_INPUT_BUFFER_PADDING_SIZE)*sizeof(uint8_t)))  == NULL)        return -1;    q->decode_buf_ptr[0] = q->decode_buffer_1;    q->decode_buf_ptr[1] = q->decode_buffer_2;    q->decode_buf_ptr[2] = q->decode_buffer_3;    q->decode_buf_ptr[3] = q->decode_buffer_4;    q->decode_buf_ptr2[0] = q->decode_buffer_3;    q->decode_buf_ptr2[1] = q->decode_buffer_4;    q->previous_buffer_ptr[0] = q->mono_previous_buffer1;    q->previous_buffer_ptr[1] = q->mono_previous_buffer2;    /* 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(NULL,AV_LOG_ERROR,"total_subbands > 53, report sample!\n");        return -1;    }    if (q->subbands > 50) {        av_log(NULL,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(NULL,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel);        return -1;    }#ifdef COOKDEBUG    dump_cook_context(q,e);#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 + -