[FFmpeg-devel] [PATCH] E-AC-3 decoder, round 3

Justin Ruggles justin.ruggles
Sun Aug 24 07:25:07 CEST 2008


Michael Niedermayer wrote:
> On Tue, Aug 19, 2008 at 09:16:24PM -0400, Justin Ruggles wrote:
>> Michael Niedermayer wrote:
>>> On Tue, Aug 19, 2008 at 07:43:31PM -0400, Justin Ruggles wrote:
>>>> Michael Niedermayer wrote:
>>>>> On Tue, Aug 19, 2008 at 06:54:35PM -0400, Justin Ruggles wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Thanks for the review.
>>>>>>
>>>>>> Michael Niedermayer wrote:
>>>>>>> On Sun, Aug 17, 2008 at 07:30:26PM -0400, Justin Ruggles wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> Here is a new patch to complete support for E-AC-3 decoding within the
>>>>>>>> current AC-3 decoder.  It will be followed up by a cosmetic commit to
>>>>>>>> indent and align.
>>>>>>>>
>>>>>>>> -Justin
>>>>>>>>
>>>>>>> [...]
>>>>>>>> @@ -533,10 +547,27 @@
>>>>>>>>      }
>>>>>>>>  }
>>>>>>>>  
>>>>>>>> +static void get_transform_coeffs_ch(AC3DecodeContext *s, int blk, int ch,
>>>>>>>> +                                    mant_groups *m)
>>>>>>>> +{
>>>>>>>> +    if (!s->channel_uses_aht[ch]) {
>>>>>>>> +        ac3_get_transform_coeffs_ch(s, ch, m);
>>>>>>>> +    } else {
>>>>>>>> +        /* if AHT is used, mantissas for all blocks are encoded in the first
>>>>>>>> +           block of the frame. */
>>>>>>>> +        int bin;
>>>>>>>> +        if (!blk)
>>>>>>>> +            ff_eac3_get_transform_coeffs_aht_ch(s, ch);
>>>>>>> am i blind? or where is this function, i cannot find it in this patch
>>>>>>> nor in svn
>>>>>> oops! I forgot to svn add eac3dec.c.  I have attached the whole file
>>>>>> here.  It would be applied in the same commit with the rest of these
>>>>>> changes (minus the part you said to commit separately).
>>>>> does any of the changes i ok-ed depend on eac3dec.c ?
>>>>> if not you could commit them and resubmit what is left + eac3dec.c
>>>> Well, sort of.  I could apply all the parts OKed so far, but I would
>>>> have to comment out the 2 calls to functions which are in eac3dec.c and
>>>> leave out the part which actually detects the frame as being E-AC-3.
>>> fine
>>> every part commited moves us a step closer to full EAC3 support
>> done. new patch attached.

approved parts have been applied. new patch attached.

>>
>>      /* coupling strategy */
>> -    if (get_bits1(gbc)) {
>> +    if (!s->eac3)
>> +        s->cpl_strategy_exists[blk] = get_bits1(gbc);
>> +    if (s->cpl_strategy_exists[blk]) {
> 
> wouldnt 
> if(s->cpl_strategy_exists[blk] || get_bits1(gbc)){
> 
> work as well?

fixed.

>> @@ -860,10 +913,14 @@
>>      }
>>  
>>      /* exponent strategies for each channel */
>> -    s->exp_strategy[blk][CPL_CH] = EXP_REUSE;
>> -    s->exp_strategy[blk][s->lfe_ch] = EXP_REUSE;
> 
>> +    if (!s->eac3) {
>> +        for (ch = !cpl_in_use; ch <= s->channels; ch++) {
>> +            s->exp_strategy[blk][ch] = get_bits(gbc, 2 - (ch == s->lfe_ch));
>> +        }
>> +    }
>> +
>> +    /* check exponent strategies to set bit allocation stages */
>>      for (ch = !cpl_in_use; ch <= s->channels; ch++) {
>> -        s->exp_strategy[blk][ch] = get_bits(gbc, 2 - (ch == s->lfe_ch));
>>          if(s->exp_strategy[blk][ch] != EXP_REUSE)
> 
> why is that loop seperated? wouldnt a 
> if (!s->eac3) in there work as well?

fixed.

>> @@ -924,29 +981,71 @@
>>      }
>>  
>>      /* signal-to-noise ratio offsets and fast gains (signal-to-mask ratios) */
> 
> 
>> -    if (get_bits1(gbc)) {
>> +    if (s->snr_offset_strategy && (!s->eac3 || !blk) && get_bits1(gbc)) {
>> +        int snr = 0;
>>          int csnr;
>>          csnr = (get_bits(gbc, 6) - 15) << 4;
>> -        for (ch = !cpl_in_use; ch <= s->channels; ch++) { /* snr offset and fast gain */
>> -            s->snr_offset[ch] = (csnr + get_bits(gbc, 4)) << 2;
> 
>> -            s->fast_gain[ch] = ff_ac3_fast_gain_tab[get_bits(gbc, 3)];
> [...]
>> +                s->fast_gain[ch] = ff_ac3_fast_gain_tab[get_bits(gbc, 3)];
> 
> cosmtic

fixed.

>> +                /* run last 2 bit allocation stages if fast gain changes */
>> +                if(blk && prev != s->fast_gain[ch])
>> +                    bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2);
>> +            }
>>          }
>> -        memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS);
>> -    } else if (!blk) {
>> +    } else if (!s->eac3 && !blk) {
>>          av_log(s->avctx, AV_LOG_ERROR, "new snr offsets must be present in block 0\n");
>>          return -1;
>>      }
> 
> i was thinking a little about:
> 
> if(!s->eac3 || !blk){
>     if (s->snr_offset_strategy && get_bits1(gbc)) {
>     } else if(!s->eac3 && !blk){
>     }
> }
> 
> but iam not sure at all if its cleaner or not, just a random idea

fixed.

>>      /* coupling leak information */
>>      if (cpl_in_use) {
>> -        if (get_bits1(gbc)) {
>> +        if (s->first_cpl_leak || get_bits1(gbc)) {
> 
>> +            int prev_fl = s->bit_alloc_params.cpl_fast_leak;
>> +            int prev_sl = s->bit_alloc_params.cpl_slow_leak;
>>              s->bit_alloc_params.cpl_fast_leak = get_bits(gbc, 3);
>>              s->bit_alloc_params.cpl_slow_leak = get_bits(gbc, 3);
>> +            /* run last 2 bit allocation stages for coupling channel if
>> +               coupling leak changes */
> 
>> +            if(blk && (prev_fl != s->bit_alloc_params.cpl_fast_leak ||
>> +                    prev_sl != s->bit_alloc_params.cpl_slow_leak)) {
>>              bit_alloc_stages[CPL_CH] = FFMAX(bit_alloc_stages[CPL_CH], 2);
>> +            }
> 
> i think following is cleaner
> 
> int fl= get_bits(gbc, 3);
> int sl= get_bits(gbc, 3);
> 
> if(blk && (fl != s->bit_alloc_params.cpl_fast_leak ||
>            sl != s->bit_alloc_params.cpl_slow_leak)) {
>     bit_alloc_stages[CPL_CH] = FFMAX(bit_alloc_stages[CPL_CH], 2);
> }
> s->bit_alloc_params.cpl_fast_leak = fl;
> s->bit_alloc_params.cpl_slow_leak = sl;

fixed.

>> +
>> +void ff_eac3_get_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch)
>> +{
>> +    int bin, blk, gs;
>> +    int end_bap, gaq_mode;
>> +    GetBitContext *gbc = &s->gbc;
>> +    int gaq_gain[AC3_MAX_COEFS];
>> +
>> +    gaq_mode = get_bits(gbc, 2);
>> +    end_bap = (gaq_mode < 2) ? 12 : 17;
>> +
>> +    /* if GAQ gain is used, decode gain codes for bins with hebap between
>> +       8 and end_bap */
>> +    gs = 0;
>> +    if (gaq_mode == EAC3_GAQ_12 || gaq_mode == EAC3_GAQ_14) {
>> +        /* read 1-bit GAQ gain codes */
>> +        for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) {
>> +            if (s->bap[ch][bin] > 7 && s->bap[ch][bin] < end_bap)
>> +                gaq_gain[gs++] = get_bits1(gbc) << (gaq_mode-1);
>> +        }
>> +    } else if (gaq_mode == EAC3_GAQ_124) {
>> +        /* read 1.67-bit GAQ gain codes (3 codes in 5 bits) */
>> +        int gc = 2;
>> +        for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) {
>> +            if (s->bap[ch][bin] > 7 && s->bap[ch][bin] < end_bap) {
>> +                if (gc++ == 2) {
>> +                    int group_gain = get_bits(gbc, 5);
>> +                    gaq_gain[gs++] = ff_ac3_ungroup_3_in_5_bits_tab[group_gain][0];
>> +                    gaq_gain[gs++] = ff_ac3_ungroup_3_in_5_bits_tab[group_gain][1];
>> +                    gaq_gain[gs++] = ff_ac3_ungroup_3_in_5_bits_tab[group_gain][2];
>> +                    gc = 0;
>> +                }
>> +            }
>> +        }
>> +    }
>> +
>> +    gs=0;
>> +    for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) {
>> +        int hebap = s->bap[ch][bin];
>> +        int bits = ff_eac3_bits_vs_hebap[hebap];
>> +        if (!hebap) {
>> +            /* zero-mantissa dithering */
>> +            for (blk = 0; blk < 6; blk++) {
>> +                s->pre_mantissa[ch][bin][blk] = (av_lfg_get(&s->dith_state) & 0x7FFFFF) - 0x400000;
>> +            }
>> +        } else if (hebap < 8) {
>> +            /* Vector Quantization */
>> +            int v = get_bits(gbc, bits);
>> +            for (blk = 0; blk < 6; blk++) {
>> +                s->pre_mantissa[ch][bin][blk] = ff_eac3_vq_hebap[hebap][v][blk] << 8;
>> +            }
>> +        } else {
>> +            /* Gain Adaptive Quantization */
>> +            int gbits, log_gain;
>> +            if (gaq_mode != EAC3_GAQ_NO && hebap < end_bap) {
>> +                log_gain = gaq_gain[gs++];
>> +            } else {
>> +                log_gain = 0;
>> +            }
> 
>> +            gbits = bits - log_gain;
> 
> this is maybe missing a check for gbits<=0, iam not certain it can happen
> but i think it can

fixed.

>> +
>> +            for (blk = 0; blk < 6; blk++) {
>> +                int mant = get_sbits(gbc, gbits);
>> +                if (mant == -(1 << (gbits-1))) {
>> +                    /* large mantissa */
>> +                    int64_t b;
>> +                    mant = get_sbits(gbc, bits-2+log_gain) << (26-log_gain-bits);
>> +                    /* remap mantissa value to correct for asymmetric quantization */
>> +                    if (mant >= 0)
>> +                        b = 32768 >> log_gain;
>> +                    else
>> +                        b = ff_eac3_gaq_remap_2_4_b[hebap-8][log_gain-1];
>> +                    mant += ((int64_t)ff_eac3_gaq_remap_2_4_a[hebap-8][log_gain-1] * mant + b) >> 15;
> 
> this can be done without a 64 bit multiple i think

fixed.

>> +                } else {
>> +                    /* small mantissa, no GAQ, or Gk=1 */
>> +                    mant <<= 24 - bits;
>> +                    if (!log_gain) {
>> +                        /* remap mantissa value for no GAQ or Gk=1 */
>> +                        mant += ((int64_t)ff_eac3_gaq_remap_1[hebap-8] * mant) >> 15;
>> +                    }
> 
> mant <<= 24 - bits;
> if (!log_gain) {
>     /* remap mantissa value for no GAQ or Gk=1 */
>     mant = (ff_eac3_gaq_remap_1[hebap-8] * (mant>>8)) >> 7;
> }

fixed.


Thanks,
Justin



-------------- next part --------------
A non-text attachment was scrubbed...
Name: eac3_decoder.diff
Type: text/x-patch
Size: 25267 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080824/4f06d9d2/attachment.bin>



More information about the ffmpeg-devel mailing list