Skip to content
Snippets Groups Projects
mpegaudiodec.c 85.1 KiB
Newer Older
  • Learn to ignore specific revisions
  •                           int32_t *sb_samples,
                              int32_t *mdct_buf)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        int32_t *ptr, *win, *win1, *buf, *out_ptr, *ptr1;
    
        int32_t out2[12];
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        int i, j, mdct_long_end, v, sblimit;
    
    
        /* find last non zero block */
        ptr = g->sb_hybrid + 576;
        ptr1 = g->sb_hybrid + 2 * 18;
        while (ptr >= ptr1) {
            ptr -= 6;
            v = ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5];
            if (v != 0)
                break;
        }
        sblimit = ((ptr - g->sb_hybrid) / 18) + 1;
    
        if (g->block_type == 2) {
            /* XXX: check for 8000 Hz */
            if (g->switch_point)
                mdct_long_end = 2;
            else
                mdct_long_end = 0;
        } else {
            mdct_long_end = sblimit;
        }
    
        buf = mdct_buf;
        ptr = g->sb_hybrid;
        for(j=0;j<mdct_long_end;j++) {
            /* apply window & overlap with previous buffer */
            out_ptr = sb_samples + j;
            /* select window */
            if (g->switch_point && j < 2)
                win1 = mdct_win[0];
            else
                win1 = mdct_win[g->block_type];
            /* select frequency inversion */
            win = win1 + ((4 * 36) & -(j & 1));
    
            imdct36(out_ptr, buf, ptr, win);
            out_ptr += 18*SBLIMIT;
    
            ptr += 18;
            buf += 18;
        }
        for(j=mdct_long_end;j<sblimit;j++) {
            /* select frequency inversion */
            win = mdct_win[2] + ((4 * 36) & -(j & 1));
            out_ptr = sb_samples + j;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            for(i=0; i<6; i++){
                *out_ptr = buf[i];
                out_ptr += SBLIMIT;
            }
            imdct12(out2, ptr + 0);
            for(i=0;i<6;i++) {
                *out_ptr = MULH(out2[i], win[i]) + buf[i + 6*1];
                buf[i + 6*2] = MULH(out2[i + 6], win[i + 6]);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            imdct12(out2, ptr + 1);
            for(i=0;i<6;i++) {
                *out_ptr = MULH(out2[i], win[i]) + buf[i + 6*2];
                buf[i + 6*0] = MULH(out2[i + 6], win[i + 6]);
                out_ptr += SBLIMIT;
            }
            imdct12(out2, ptr + 2);
            for(i=0;i<6;i++) {
                buf[i + 6*0] = MULH(out2[i], win[i]) + buf[i + 6*0];
                buf[i + 6*1] = MULH(out2[i + 6], win[i + 6]);
                buf[i + 6*2] = 0;
            }
    
            ptr += 18;
            buf += 18;
        }
        /* zero bands */
        for(j=sblimit;j<SBLIMIT;j++) {
            /* overlap */
            out_ptr = sb_samples + j;
            for(i=0;i<18;i++) {
                *out_ptr = buf[i];
                buf[i] = 0;
                out_ptr += SBLIMIT;
            }
            buf += 18;
        }
    }
    
    
    #if defined(DEBUG)
    
    void sample_dump(int fnum, int32_t *tab, int n)
    
        int32_t v;
    
            snprintf(buf, sizeof(buf), "/tmp/out%d.%s.pcm",
                    fnum,
    
            av_log(NULL, AV_LOG_DEBUG, "pos=%d\n", pos);
    
                av_log(NULL, AV_LOG_DEBUG, " %0.4f", (double)tab[i] / FRAC_ONE);
    
                    av_log(NULL, AV_LOG_DEBUG, "\n");
    
        for(i=0;i<n;i++) {
            /* normalize to 23 frac bits */
            v = tab[i] << (23 - FRAC_BITS);
    
            fwrite(&v, 1, sizeof(int32_t), f);
    
    }
    #endif
    
    
    /* main layer3 decoding function */
    static int mp_decode_layer3(MPADecodeContext *s)
    {
        int nb_granules, main_data_begin, private_bits;
    
        int gr, ch, blocksplit_flag, i, j, k, n, bits_pos;
    
        int16_t exponents[576];
    
    
        /* read side info */
        if (s->lsf) {
            main_data_begin = get_bits(&s->gb, 8);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            private_bits = get_bits(&s->gb, s->nb_channels);
    
            nb_granules = 1;
        } else {
            main_data_begin = get_bits(&s->gb, 9);
            if (s->nb_channels == 2)
                private_bits = get_bits(&s->gb, 3);
            else
                private_bits = get_bits(&s->gb, 5);
            nb_granules = 2;
            for(ch=0;ch<s->nb_channels;ch++) {
                granules[ch][0].scfsi = 0; /* all scale factors are transmitted */
                granules[ch][1].scfsi = get_bits(&s->gb, 4);
            }
        }
    
        for(gr=0;gr<nb_granules;gr++) {
            for(ch=0;ch<s->nb_channels;ch++) {
                dprintf("gr=%d ch=%d: side_info\n", gr, ch);
                g = &granules[ch][gr];
                g->part2_3_length = get_bits(&s->gb, 12);
                g->big_values = get_bits(&s->gb, 9);
    
                if(g->big_values > 288){
                    av_log(NULL, AV_LOG_ERROR, "big_values too big\n");
                    return -1;
                }
    
    
                g->global_gain = get_bits(&s->gb, 8);
                /* if MS stereo only is selected, we precompute the
                   1/sqrt(2) renormalization factor */
    
                if ((s->mode_ext & (MODE_EXT_MS_STEREO | MODE_EXT_I_STEREO)) ==
    
                    MODE_EXT_MS_STEREO)
                    g->global_gain -= 2;
                if (s->lsf)
                    g->scalefac_compress = get_bits(&s->gb, 9);
                else
                    g->scalefac_compress = get_bits(&s->gb, 4);
                blocksplit_flag = get_bits(&s->gb, 1);
                if (blocksplit_flag) {
                    g->block_type = get_bits(&s->gb, 2);
    
                    if (g->block_type == 0){
                        av_log(NULL, AV_LOG_ERROR, "invalid block type\n");
    
                    g->switch_point = get_bits(&s->gb, 1);
                    for(i=0;i<2;i++)
                        g->table_select[i] = get_bits(&s->gb, 5);
    
                    for(i=0;i<3;i++)
    
                        g->subblock_gain[i] = get_bits(&s->gb, 3);
                    /* compute huffman coded region sizes */
                    if (g->block_type == 2)
                        g->region_size[0] = (36 / 2);
                    else {
    
                        if (s->sample_rate_index <= 2)
    
                        else if (s->sample_rate_index != 8)
    
                            g->region_size[0] = (54 / 2);
                        else
                            g->region_size[0] = (108 / 2);
                    }
                    g->region_size[1] = (576 / 2);
                } else {
                    int region_address1, region_address2, l;
                    g->block_type = 0;
                    g->switch_point = 0;
                    for(i=0;i<3;i++)
                        g->table_select[i] = get_bits(&s->gb, 5);
                    /* compute huffman coded region sizes */
                    region_address1 = get_bits(&s->gb, 4);
                    region_address2 = get_bits(&s->gb, 3);
    
                    dprintf("region1=%d region2=%d\n",
    
                    g->region_size[0] =
    
                        band_index_long[s->sample_rate_index][region_address1 + 1] >> 1;
                    l = region_address1 + region_address2 + 2;
                    /* should not overflow */
                    if (l > 22)
                        l = 22;
    
                    g->region_size[1] =
    
                        band_index_long[s->sample_rate_index][l] >> 1;
                }
                /* convert region offsets to region sizes and truncate
                   size to big_values */
                g->region_size[2] = (576 / 2);
                j = 0;
                for(i=0;i<3;i++) {
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                    k = FFMIN(g->region_size[i], g->big_values);
    
                    g->region_size[i] = k - j;
                    j = k;
                }
    
                /* compute band indexes */
                if (g->block_type == 2) {
                    if (g->switch_point) {
                        /* if switched mode, we handle the 36 first samples as
                           long blocks.  For 8000Hz, we handle the 48 first
                           exponents as long blocks (XXX: check this!) */
                        if (s->sample_rate_index <= 2)
                            g->long_end = 8;
                        else if (s->sample_rate_index != 8)
                            g->long_end = 6;
                        else
                            g->long_end = 4; /* 8000 Hz */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                        g->short_start = 2 + (s->sample_rate_index != 8);
    
                    } else {
                        g->long_end = 0;
                        g->short_start = 0;
                    }
                } else {
                    g->short_start = 13;
                    g->long_end = 22;
                }
    
                g->preflag = 0;
                if (!s->lsf)
                    g->preflag = get_bits(&s->gb, 1);
                g->scalefac_scale = get_bits(&s->gb, 1);
                g->count1table_select = get_bits(&s->gb, 1);
                dprintf("block_type=%d switch_point=%d\n",
                        g->block_type, g->switch_point);
            }
        }
    
    
    Roberto Togni's avatar
    Roberto Togni committed
      if (!s->adu_mode) {
    
        const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb)>>3);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        assert((get_bits_count(&s->gb) & 7) == 0);
    
        /* now we get bits from the main_data_begin offset */
        dprintf("seekback: %d\n", main_data_begin);
    
    //av_log(NULL, AV_LOG_ERROR, "backstep:%d, lastbuf:%d\n", main_data_begin, s->last_buf_size);
    
        memcpy(s->last_buf + s->last_buf_size, ptr, EXTRABYTES);
        s->in_gb= s->gb;
    
            init_get_bits(&s->gb, s->last_buf, s->last_buf_size*8);
            skip_bits_long(&s->gb, 8*(s->last_buf_size - main_data_begin));
    
    
        for(gr=0;gr<nb_granules;gr++) {
            for(ch=0;ch<s->nb_channels;ch++) {
                g = &granules[ch][gr];
    
                if(get_bits_count(&s->gb)<0){
                    av_log(NULL, AV_LOG_ERROR, "mdb:%d, lastbuf:%d skiping granule %d\n",
                                                main_data_begin, s->last_buf_size, gr);
                    skip_bits_long(&s->gb, g->part2_3_length);
                    memset(g->sb_hybrid, 0, sizeof(g->sb_hybrid));
                    if(get_bits_count(&s->gb) >= s->gb.size_in_bits && s->in_gb.buffer){
                        skip_bits_long(&s->in_gb, get_bits_count(&s->gb) - s->gb.size_in_bits);
                        s->gb= s->in_gb;
                        s->in_gb.buffer=NULL;
                    }
                    continue;
                }
    
                    uint8_t *sc;
    
                    int slen, slen1, slen2;
    
                    /* MPEG1 scale factors */
                    slen1 = slen_table[0][g->scalefac_compress];
                    slen2 = slen_table[1][g->scalefac_compress];
                    dprintf("slen1=%d slen2=%d\n", slen1, slen2);
                    if (g->block_type == 2) {
                        n = g->switch_point ? 17 : 18;
                        j = 0;
    
                        if(slen1){
                            for(i=0;i<n;i++)
                                g->scale_factors[j++] = get_bits(&s->gb, slen1);
                        }else{
                            for(i=0;i<n;i++)
                                g->scale_factors[j++] = 0;
                        }
                        if(slen2){
                            for(i=0;i<18;i++)
                                g->scale_factors[j++] = get_bits(&s->gb, slen2);
                            for(i=0;i<3;i++)
                                g->scale_factors[j++] = 0;
                        }else{
                            for(i=0;i<21;i++)
                                g->scale_factors[j++] = 0;
                        }
    
                    } else {
                        sc = granules[ch][0].scale_factors;
                        j = 0;
                        for(k=0;k<4;k++) {
                            n = (k == 0 ? 6 : 5);
                            if ((g->scfsi & (0x8 >> k)) == 0) {
                                slen = (k < 2) ? slen1 : slen2;
    
                                if(slen){
                                    for(i=0;i<n;i++)
                                        g->scale_factors[j++] = get_bits(&s->gb, slen);
                                }else{
                                    for(i=0;i<n;i++)
                                        g->scale_factors[j++] = 0;
                                }
    
                            } else {
                                /* simply copy from last granule */
                                for(i=0;i<n;i++) {
                                    g->scale_factors[j] = sc[j];
                                    j++;
                                }
                            }
                        }
                        g->scale_factors[j++] = 0;
                    }
    
    #if defined(DEBUG)
    
                        dprintf("scfsi=%x gr=%d ch=%d scale_factors:\n",
    
                            dprintf(" %d", g->scale_factors[i]);
                        dprintf("\n");
    
                    }
    #endif
                } else {
                    int tindex, tindex2, slen[4], sl, sf;
    
                    /* LSF scale factors */
                    if (g->block_type == 2) {
                        tindex = g->switch_point ? 2 : 1;
                    } else {
                        tindex = 0;
                    }
                    sf = g->scalefac_compress;
                    if ((s->mode_ext & MODE_EXT_I_STEREO) && ch == 1) {
                        /* intensity stereo case */
                        sf >>= 1;
                        if (sf < 180) {
                            lsf_sf_expand(slen, sf, 6, 6, 0);
                            tindex2 = 3;
                        } else if (sf < 244) {
                            lsf_sf_expand(slen, sf - 180, 4, 4, 0);
                            tindex2 = 4;
                        } else {
                            lsf_sf_expand(slen, sf - 244, 3, 0, 0);
                            tindex2 = 5;
                        }
                    } else {
                        /* normal case */
                        if (sf < 400) {
                            lsf_sf_expand(slen, sf, 5, 4, 4);
                            tindex2 = 0;
                        } else if (sf < 500) {
                            lsf_sf_expand(slen, sf - 400, 5, 4, 0);
                            tindex2 = 1;
                        } else {
                            lsf_sf_expand(slen, sf - 500, 3, 0, 0);
                            tindex2 = 2;
                            g->preflag = 1;
                        }
                    }
    
                    j = 0;
                    for(k=0;k<4;k++) {
                        n = lsf_nsf_table[tindex2][tindex][k];
                        sl = slen[k];
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                        if(sl){
    
                            for(i=0;i<n;i++)
                                g->scale_factors[j++] = get_bits(&s->gb, sl);
                        }else{
                            for(i=0;i<n;i++)
                                g->scale_factors[j++] = 0;
                        }
    
                    }
                    /* XXX: should compute exact size */
                    for(;j<40;j++)
                        g->scale_factors[j] = 0;
    
    #if defined(DEBUG)
    
                        dprintf("gr=%d ch=%d scale_factors:\n",
    
                            dprintf(" %d", g->scale_factors[i]);
                        dprintf("\n");
    
                    }
    #endif
                }
    
                exponents_from_scale_factors(s, g, exponents);
    
                /* read Huffman coded residue */
    
                huffman_decode(s, g, exponents, bits_pos + g->part2_3_length);
    
    #if defined(DEBUG)
                sample_dump(0, g->sb_hybrid, 576);
    
    #endif
            } /* ch */
    
            if (s->nb_channels == 2)
                compute_stereo(s, &granules[0][gr], &granules[1][gr]);
    
            for(ch=0;ch<s->nb_channels;ch++) {
                g = &granules[ch][gr];
    
                reorder_block(s, g);
    
    #if defined(DEBUG)
    
                compute_imdct(s, g, &s->sb_samples[ch][18 * gr][0], s->mdct_buf[ch]);
    
                sample_dump(2, &s->sb_samples[ch][18 * gr][0], 576);
    #endif
            }
        } /* gr */
    
        if(get_bits_count(&s->gb)<0)
            skip_bits_long(&s->gb, -get_bits_count(&s->gb));
    
    static int mp_decode_frame(MPADecodeContext *s,
    
                               OUT_INT *samples, const uint8_t *buf, int buf_size)
    
        init_get_bits(&s->gb, buf + HEADER_SIZE, (buf_size - HEADER_SIZE)*8);
    
        /* skip error protection field */
        if (s->error_protection)
            get_bits(&s->gb, 16);
    
        dprintf("frame %d:\n", s->frame_count);
        switch(s->layer) {
        case 1:
            nb_frames = mp_decode_layer1(s);
            break;
        case 2:
            nb_frames = mp_decode_layer2(s);
            break;
        case 3:
        default:
            nb_frames = mp_decode_layer3(s);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            s->last_buf_size=0;
            if(s->in_gb.buffer){
                align_get_bits(&s->gb);
                i= (s->gb.size_in_bits - get_bits_count(&s->gb))>>3;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                if(i >= 0 && i <= BACKSTEP_SIZE){
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                    memmove(s->last_buf, s->gb.buffer + (get_bits_count(&s->gb)>>3), i);
                    s->last_buf_size=i;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                }else
                    av_log(NULL, AV_LOG_ERROR, "invalid old backstep %d\n", i);
    
                s->in_gb.buffer= NULL;
    
            align_get_bits(&s->gb);
            assert((get_bits_count(&s->gb) & 7) == 0);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            i= (s->gb.size_in_bits - get_bits_count(&s->gb))>>3;
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            if(i<0 || i > BACKSTEP_SIZE || nb_frames<0){
                av_log(NULL, AV_LOG_ERROR, "invalid new backstep %d\n", i);
                i= FFMIN(BACKSTEP_SIZE, buf_size - HEADER_SIZE);
            }
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            assert(i <= buf_size - HEADER_SIZE && i>= 0);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            memcpy(s->last_buf + s->last_buf_size, s->gb.buffer + buf_size - HEADER_SIZE - i, i);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            s->last_buf_size += i;
    
            break;
        }
    #if defined(DEBUG)
        for(i=0;i<nb_frames;i++) {
            for(ch=0;ch<s->nb_channels;ch++) {
                int j;
    
                dprintf("%d-%d:", i, ch);
    
                    dprintf(" %0.6f", (double)s->sb_samples[ch][i][j] / FRAC_ONE);
                dprintf("\n");
    
            }
        }
    #endif
        /* apply the synthesis filter */
        for(ch=0;ch<s->nb_channels;ch++) {
            samples_ptr = samples + ch;
            for(i=0;i<nb_frames;i++) {
    
                ff_mpa_synth_filter(s->synth_buf[ch], &(s->synth_buf_offset[ch]),
    
                             window, &s->dither_state,
                             samples_ptr, s->nb_channels,
    
                             s->sb_samples[ch][i]);
                samples_ptr += 32 * s->nb_channels;
            }
        }
    #ifdef DEBUG
    
        s->frame_count++;
    
        return nb_frames * 32 * sizeof(OUT_INT) * s->nb_channels;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    static int decode_frame(AVCodecContext * avctx,
    
                            void *data, int *data_size,
                            uint8_t * buf, int buf_size)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        MPADecodeContext *s = avctx->priv_data;
    
        uint32_t header;
    
        OUT_INT *out_samples = data;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    retry:
        if(buf_size < HEADER_SIZE)
            return -1;
    
        header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
        if(ff_mpa_check_header(header) < 0){
            buf++;
    //        buf_size--;
    
    Diego Biurrun's avatar
    Diego Biurrun committed
            av_log(avctx, AV_LOG_ERROR, "Header missing skipping one byte.\n");
    
            goto retry;
        }
    
        if (decode_header(s, header) == 1) {
            /* free format: prepare to compute frame size */
            s->frame_size = -1;
            return -1;
        }
        /* update codec info */
        avctx->channels = s->nb_channels;
        avctx->bit_rate = s->bit_rate;
        avctx->sub_id = s->layer;
        switch(s->layer) {
        case 1:
            avctx->frame_size = 384;
            break;
        case 2:
            avctx->frame_size = 1152;
            break;
        case 3:
            if (s->lsf)
                avctx->frame_size = 576;
            else
                avctx->frame_size = 1152;
            break;
        }
    
    
        if(s->frame_size<=0 || s->frame_size > buf_size){
    
            av_log(avctx, AV_LOG_ERROR, "incomplete frame\n");
            return -1;
    
        }else if(s->frame_size < buf_size){
            av_log(avctx, AV_LOG_ERROR, "incorrect frame size\n");
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
        out_size = mp_decode_frame(s, out_samples, buf, buf_size);
    
            avctx->sample_rate = s->sample_rate;
            //FIXME maybe move the other codec info stuff from above here too
        }else
    
    Diego Biurrun's avatar
    Diego Biurrun committed
            av_log(avctx, AV_LOG_DEBUG, "Error while decoding MPEG audio frame.\n"); //FIXME return -1 / but also return the number of bytes consumed
    
    static void flush(AVCodecContext *avctx){
        MPADecodeContext *s = avctx->priv_data;
        s->last_buf_size= 0;
    }
    
    
    #ifdef CONFIG_MP3ADU_DECODER
    
    Roberto Togni's avatar
    Roberto Togni committed
    static int decode_frame_adu(AVCodecContext * avctx,
    
                            void *data, int *data_size,
                            uint8_t * buf, int buf_size)
    
    Roberto Togni's avatar
    Roberto Togni committed
    {
        MPADecodeContext *s = avctx->priv_data;
        uint32_t header;
        int len, out_size;
    
        OUT_INT *out_samples = data;
    
    Roberto Togni's avatar
    Roberto Togni committed
    
        len = buf_size;
    
        // Discard too short frames
        if (buf_size < HEADER_SIZE) {
            *data_size = 0;
            return buf_size;
        }
    
    
        if (len > MPA_MAX_CODED_FRAME_SIZE)
            len = MPA_MAX_CODED_FRAME_SIZE;
    
        // Get header and restore sync word
    
        header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3] | 0xffe00000;
    
        if (ff_mpa_check_header(header) < 0) { // Bad header, discard frame
    
    Roberto Togni's avatar
    Roberto Togni committed
            *data_size = 0;
            return buf_size;
        }
    
        decode_header(s, header);
        /* update codec info */
        avctx->sample_rate = s->sample_rate;
        avctx->channels = s->nb_channels;
        avctx->bit_rate = s->bit_rate;
        avctx->sub_id = s->layer;
    
        avctx->frame_size=s->frame_size = len;
    
        if (avctx->parse_only) {
    
    Roberto Togni's avatar
    Roberto Togni committed
        } else {
    
            out_size = mp_decode_frame(s, out_samples, buf, buf_size);
    
    Roberto Togni's avatar
    Roberto Togni committed
        }
    
        *data_size = out_size;
        return buf_size;
    }
    
    #endif /* CONFIG_MP3ADU_DECODER */
    
    #ifdef CONFIG_MP3ON4_DECODER
    
    /* Next 3 arrays are indexed by channel config number (passed via codecdata) */
    static int mp3Frames[16] = {0,1,1,2,3,3,4,5,2};   /* number of mp3 decoder instances */
    static int mp3Channels[16] = {0,1,2,3,4,5,6,8,4}; /* total output channels */
    /* offsets into output buffer, assume output order is FL FR BL BR C LFE */
    static int chan_offset[9][5] = {
        {0},
        {0},            // C
        {0},            // FLR
        {2,0},          // C FLR
        {2,0,3},        // C FLR BS
        {4,0,2},        // C FLR BLRS
        {4,0,2,5},      // C FLR BLRS LFE
        {4,0,2,6,5},    // C FLR BLRS BLR LFE
        {0,2}           // FLR BLRS
    };
    
    
    static int decode_init_mp3on4(AVCodecContext * avctx)
    {
        MP3On4DecodeContext *s = avctx->priv_data;
        int i;
    
        if ((avctx->extradata_size < 2) || (avctx->extradata == NULL)) {
            av_log(avctx, AV_LOG_ERROR, "Codec extradata missing or too short.\n");
            return -1;
        }
    
        s->chan_cfg = (((unsigned char *)avctx->extradata)[1] >> 3) & 0x0f;
        s->frames = mp3Frames[s->chan_cfg];
        if(!s->frames) {
            av_log(avctx, AV_LOG_ERROR, "Invalid channel config number.\n");
            return -1;
        }
        avctx->channels = mp3Channels[s->chan_cfg];
    
        /* Init the first mp3 decoder in standard way, so that all tables get builded
         * We replace avctx->priv_data with the context of the first decoder so that
         * decode_init() does not have to be changed.
         * Other decoders will be inited here copying data from the first context
         */
        // Allocate zeroed memory for the first decoder context
        s->mp3decctx[0] = av_mallocz(sizeof(MPADecodeContext));
        // Put decoder context in place to make init_decode() happy
        avctx->priv_data = s->mp3decctx[0];
        decode_init(avctx);
        // Restore mp3on4 context pointer
        avctx->priv_data = s;
        s->mp3decctx[0]->adu_mode = 1; // Set adu mode
    
        /* Create a separate codec/context for each frame (first is already ok).
         * Each frame is 1 or 2 channels - up to 5 frames allowed
         */
        for (i = 1; i < s->frames; i++) {
            s->mp3decctx[i] = av_mallocz(sizeof(MPADecodeContext));
            s->mp3decctx[i]->compute_antialias = s->mp3decctx[0]->compute_antialias;
            s->mp3decctx[i]->adu_mode = 1;
        }
    
        return 0;
    }
    
    
    static int decode_close_mp3on4(AVCodecContext * avctx)
    {
        MP3On4DecodeContext *s = avctx->priv_data;
        int i;
    
        for (i = 0; i < s->frames; i++)
            if (s->mp3decctx[i])
                av_free(s->mp3decctx[i]);
    
        return 0;
    }
    
    
    static int decode_frame_mp3on4(AVCodecContext * avctx,
    
                            void *data, int *data_size,
                            uint8_t * buf, int buf_size)
    
    {
        MP3On4DecodeContext *s = avctx->priv_data;
        MPADecodeContext *m;
        int len, out_size = 0;
        uint32_t header;
        OUT_INT *out_samples = data;
        OUT_INT decoded_buf[MPA_FRAME_SIZE * MPA_MAX_CHANNELS];
        OUT_INT *outptr, *bp;
        int fsize;
        unsigned char *start2 = buf, *start;
        int fr, i, j, n;
        int off = avctx->channels;
        int *coff = chan_offset[s->chan_cfg];
    
        len = buf_size;
    
        // Discard too short frames
        if (buf_size < HEADER_SIZE) {
            *data_size = 0;
            return buf_size;
        }
    
        // If only one decoder interleave is not needed
        outptr = s->frames == 1 ? out_samples : decoded_buf;
    
        for (fr = 0; fr < s->frames; fr++) {
            start = start2;
            fsize = (start[0] << 4) | (start[1] >> 4);
            start2 += fsize;
            if (fsize > len)
                fsize = len;
            len -= fsize;
            if (fsize > MPA_MAX_CODED_FRAME_SIZE)
                fsize = MPA_MAX_CODED_FRAME_SIZE;
            m = s->mp3decctx[fr];
            assert (m != NULL);
    
            // Get header
    
            header = (start[0] << 24) | (start[1] << 16) | (start[2] << 8) | start[3] | 0xfff00000;
    
    
            if (ff_mpa_check_header(header) < 0) { // Bad header, discard block
                *data_size = 0;
                return buf_size;
            }
    
            decode_header(m, header);
    
            mp_decode_frame(m, decoded_buf, start, fsize);
    
    
            n = MPA_FRAME_SIZE * m->nb_channels;
            out_size += n * sizeof(OUT_INT);
            if(s->frames > 1) {
                /* interleave output data */
                bp = out_samples + coff[fr];
                if(m->nb_channels == 1) {
                    for(j = 0; j < n; j++) {
                        *bp = decoded_buf[j];
                        bp += off;
                    }
                } else {
                    for(j = 0; j < n; j++) {
                        bp[0] = decoded_buf[j++];
                        bp[1] = decoded_buf[j];
                        bp += off;
                    }
                }
            }
        }
    
        /* update codec info */
        avctx->sample_rate = s->mp3decctx[0]->sample_rate;
        avctx->frame_size= buf_size;
        avctx->bit_rate = 0;
        for (i = 0; i < s->frames; i++)
            avctx->bit_rate += s->mp3decctx[i]->bit_rate;
    
        *data_size = out_size;
        return buf_size;
    }
    
    #endif /* CONFIG_MP3ON4_DECODER */
    
    #ifdef CONFIG_MP2_DECODER
    
    AVCodec mp2_decoder =
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        CODEC_TYPE_AUDIO,
        CODEC_ID_MP2,
        sizeof(MPADecodeContext),
        decode_init,
        NULL,
        NULL,
        decode_frame,
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    };
    
    #endif
    #ifdef CONFIG_MP3_DECODER
    
    AVCodec mp3_decoder =
    {
        "mp3",
        CODEC_TYPE_AUDIO,
    
        CODEC_ID_MP3,
    
        sizeof(MPADecodeContext),
        decode_init,
        NULL,
        NULL,
        decode_frame,
    
    #endif
    #ifdef CONFIG_MP3ADU_DECODER
    
    Roberto Togni's avatar
    Roberto Togni committed
    AVCodec mp3adu_decoder =
    {
        "mp3adu",
        CODEC_TYPE_AUDIO,
        CODEC_ID_MP3ADU,
        sizeof(MPADecodeContext),
        decode_init,
        NULL,
        NULL,
        decode_frame_adu,
        CODEC_CAP_PARSE_ONLY,
    
    #endif
    #ifdef CONFIG_MP3ON4_DECODER
    
    AVCodec mp3on4_decoder =
    {
        "mp3on4",
        CODEC_TYPE_AUDIO,
        CODEC_ID_MP3ON4,
        sizeof(MP3On4DecodeContext),
        decode_init_mp3on4,
        NULL,
        decode_close_mp3on4,
        decode_frame_mp3on4,