[Ffmpeg-devel] [PATCH] Correctly parse headers of E-AC3 streams

Michael Niedermayer michaelni
Fri Jan 19 00:04:35 CET 2007


Hi

On Thu, Jan 18, 2007 at 09:39:32AM +0000, Ian Caulfield wrote:
> Hi,
> 
> This patch allows the AC3 parser to read the frame size and codec parameters
> >from E-AC3 streams, allowing them to be correctly demuxed. Currently it 
> >only
> identifies the primary substream, and will skip over any additional
> dependent or independent substreams. If I can get hold of a sample stream
> containing these features, I'll try to add support for them.
> 
> Patch is supplied in two parts - the first contains functional changes, the
> second re-indents code.
> 
> Ian

> Index: libavcodec/parser.c
> ===================================================================
> --- libavcodec/parser.c	(revision 7578)
> +++ libavcodec/parser.c	(working copy)
> @@ -635,6 +635,11 @@
>  static const int ac3_channels[8] = {
>      2, 1, 2, 3, 3, 4, 4, 5
>  };
> +
> +static const int eac3_blocks[4] = {
> +    1, 2, 3, 6
> +};

a uint8_t table would safe 12 bytes ...


> +
>  #endif /* CONFIG_AC3_PARSER */
>  
>  #ifdef CONFIG_AAC_PARSER
> @@ -653,6 +658,7 @@
>                      int *bit_rate, int *samples)
>  {
>      unsigned int fscod, frmsizecod, acmod, bsid, lfeon;
> +    unsigned int strmtyp, substreamid, frmsiz, fscod2, numblkscod;
>      GetBitContext bits;
>  
>      init_get_bits(&bits, buf, AC3_HEADER_SIZE * 8);
> @@ -660,6 +666,8 @@
>      if(get_bits(&bits, 16) != 0x0b77)
>          return 0;
>  
> +    bsid = show_bits_long(&bits, 29) & 0x1f;
> +    if(bsid <= 8) {             /* Normal AC-3 */
>      skip_bits(&bits, 16);       /* crc */
>      fscod = get_bits(&bits, 2);
>      frmsizecod = get_bits(&bits, 6);
> @@ -667,9 +675,7 @@
>      if(!ac3_sample_rates[fscod])
>          return 0;
>  
> -    bsid = get_bits(&bits, 5);
> -    if(bsid > 8)
> -        return 0;
> +    skip_bits(&bits, 5);        /* bsid */
>      skip_bits(&bits, 3);        /* bsmod */
>      acmod = get_bits(&bits, 3);
>      if(acmod & 1 && acmod != 1)
> @@ -686,6 +692,41 @@
>      *samples = 6 * 256;
>  
>      return ac3_frame_sizes[frmsizecod][fscod] * 2;
> +    } else if (bsid >= 10 && bsid <= 16) { /* Enhanced AC-3 */
> +        strmtyp = get_bits(&bits, 2);
> +        substreamid = get_bits(&bits, 3);
> +
> +        if (strmtyp != 0 || substreamid != 0)
> +            return 0;   /* Currently don't support additional streams */
> +
> +        frmsiz = get_bits(&bits, 11) + 1;
> +        fscod = get_bits(&bits, 2);
> +        if (fscod == 3) {
> +            fscod2 = get_bits(&bits, 2);
> +            numblkscod = 3;
> +
> +            if(!ac3_sample_rates[fscod2])
> +                return 0;

why not if(fscod2 == 3) like above?


> +
> +            *sample_rate = ac3_sample_rates[fscod2] / 2;
> +        } else {
> +            numblkscod = get_bits(&bits, 2);
> +
> +            *sample_rate = ac3_sample_rates[fscod];
> +        }

what about: ? (no iam not sure if its better ...)

fscod = get_bits(&bits, 2);
numblkscod = get_bits(&bits, 2);
if(fscod == 3){
    if(numblkscod == 3)
        return 0;

    *sample_rate = ac3_sample_rates[numblkscod] / 2;
    numblkscod = 3;
}else
    *sample_rate = ac3_sample_rates[fscod];


> +
> +        acmod = get_bits(&bits, 3);
> +        lfeon = get_bits1(&bits);
> +
> +        *samples = eac3_blocks[numblkscod] * 256;
> +        *bit_rate = frmsiz * (*sample_rate) * 16 / (*samples);
> +        *channels = ac3_channels[acmod] + lfeon;
> +
> +        return frmsiz * 2;
> +    }

also i was thinking about something like the following but again iam not
sure if its better, i hoped more could be merged ...
iam fine with your variant too


//the following 3 are a 16bit CRC in AC-3
strmtyp = get_bits(&bits, 2);
substreamid = get_bits(&bits, 3);
frmsiz = get_bits(&bits, 11) + 1;

fscod = get_bits(&bits, 2);

/* AC-3 */
frmsizecod = show_bits(&bits, 6);

/* Enhanced AC-3 */
numblkscod = get_bits(&bits, 2);
acmod = get_bits(&bits, 3);
lfeon = get_bits1(&bits);

bsid = get_bits(&bits, 5);

if(bsid <= 8){
    if(fscod == 3)
        return 0;

    skip_bits(&bits, 3);        /* bsmod */
    acmod = get_bits(&bits, 3);
    if(acmod & 1 && acmod != 1)
        skip_bits(&bits, 2);    /* cmixlev */
    if(acmod & 4)
        skip_bits(&bits, 2);    /* surmixlev */
    if(acmod & 2)
        skip_bits(&bits, 2);    /* dsurmod */

    *sample_rate = ac3_sample_rates[fscod];
    *bit_rate = ac3_bitrates[frmsizecod] * 1000;
    *samples = 6 * 256;

    frmsiz = ac3_frame_sizes[frmsizecod][fscod];
}else if (bsid >= 10 && bsid <= 16) { /* Enhanced AC-3 */
    if (strmtyp != 0 || substreamid != 0)
        return 0;   /* Currently don't support additional streams */

    if(fscod == 3){
        if(numblkscod == 3)
            return 0;

        *sample_rate = ac3_sample_rates[numblkscod] / 2;
        numblkscod = 3;
    }else
        *sample_rate = ac3_sample_rates[fscod];

    acmod = get_bits(&bits, 3);

    *samples = eac3_blocks[numblkscod] * 256;
    *bit_rate = frmsiz * (*sample_rate) * 16 / (*samples);
}else
    return 0;

lfeon = get_bits1(&bits);
*channels = ac3_channels[acmod] + lfeon;

return frmsiz * 2;

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Opposition brings concord. Out of discord comes the fairest harmony.
-- Heraclitus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070119/fe9d0913/attachment.pgp>



More information about the ffmpeg-devel mailing list