Skip to content
Snippets Groups Projects
cook.c 38.7 KiB
Newer Older
  • Learn to ignore specific revisions
  •     av_log(q->avctx,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(q->avctx,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
    
    static av_cold int cook_count_channels(unsigned int mask){
        int i;
        int channels = 0;
        for(i = 0;i<32;i++){
            if(mask & (1<<i))
                ++channels;
        }
        return channels;
    }
    
    
    /**
     * Cook initialization
     *
     * @param avctx     pointer to the AVCodecContext
     */
    
    
    static av_cold int cook_decode_init(AVCodecContext *avctx)
    
    {
        COOKContext *q = avctx->priv_data;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        const 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;
    
    
        av_random_init(&q->random_state, 1);
    
    
        /* 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(avctx,AV_LOG_DEBUG,"q->cookversion=%x\n",q->cookversion);
    
                if (q->nb_channels != 1) {
    
                    av_log(avctx,AV_LOG_ERROR,"Container channels != 1, report sample!\n");
    
                av_log(avctx,AV_LOG_DEBUG,"MONO\n");
    
                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");
    
                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) {
    
                }
                if (q->samples_per_channel > 512) {
    
                av_log(avctx,AV_LOG_ERROR,"MC_COOK not supported!\n");
    
                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);
    
        init_pow2table();
    
    
        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)
    
        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. */
    
        /* Initialize COOK signal arithmetic handling */
        if (1) {
    
            q->scalar_dequant  = scalar_dequant_float;
    
            q->decouple        = decouple_float;
            q->imlt_window     = imlt_window_float;
    
            q->interpolate     = interpolate_float;
    
            q->saturate_output = saturate_output_float;
        }
    
    
        /* 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");
    
            av_log(avctx,AV_LOG_ERROR,"subbands > 50, report sample!\n");
    
        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);
    
        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;
        }
    
    Benjamin Larsson's avatar
    Benjamin Larsson committed
        avctx->channel_layout = (avctx->channels==2) ? CH_LAYOUT_STEREO : CH_LAYOUT_MONO;
    
        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,
    
        .long_name = NULL_IF_CONFIG_SMALL("COOK"),