From 2476139973aac278e591e4c0678d824e800fddbd Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 11 Mar 2007 16:44:14 +0000 Subject: [PATCH] move AC-3 header parsing to ac3.c Originally committed as revision 8323 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/ac3.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/ac3.h | 44 ++++++++++++++++++++++++++++++++++++++ libavcodec/parser.c | 41 +++++++++++------------------------- 3 files changed, 107 insertions(+), 29 deletions(-) diff --git a/libavcodec/ac3.c b/libavcodec/ac3.c index a1c46c6d2e..47c49c0d05 100644 --- a/libavcodec/ac3.c +++ b/libavcodec/ac3.c @@ -27,6 +27,7 @@ #include "avcodec.h" #include "ac3.h" #include "ac3tab.h" +#include "bitstream.h" static inline int calc_lowcomp1(int a, int b0, int b1, int c) { @@ -208,3 +209,53 @@ void ac3_common_init(void) ff_ac3_frame_sizes[i][2] = ( 3*br ); } } + +int ff_ac3_parse_header(const uint8_t buf[7], AC3HeaderInfo *hdr) +{ + GetBitContext gbc; + + memset(hdr, 0, sizeof(*hdr)); + + init_get_bits(&gbc, buf, 54); + + hdr->sync_word = get_bits(&gbc, 16); + if(hdr->sync_word != 0x0B77) + return -1; + + /* read ahead to bsid to make sure this is AC-3, not E-AC-3 */ + hdr->bsid = show_bits_long(&gbc, 29) & 0x1F; + if(hdr->bsid > 10) + return -2; + + hdr->crc1 = get_bits(&gbc, 16); + hdr->fscod = get_bits(&gbc, 2); + if(hdr->fscod == 3) + return -3; + + hdr->frmsizecod = get_bits(&gbc, 6); + if(hdr->frmsizecod > 37) + return -4; + + skip_bits(&gbc, 5); // skip bsid, already got it + + hdr->bsmod = get_bits(&gbc, 3); + hdr->acmod = get_bits(&gbc, 3); + if((hdr->acmod & 1) && hdr->acmod != 1) { + hdr->cmixlev = get_bits(&gbc, 2); + } + if(hdr->acmod & 4) { + hdr->surmixlev = get_bits(&gbc, 2); + } + if(hdr->acmod == 2) { + hdr->dsurmod = get_bits(&gbc, 2); + } + hdr->lfeon = get_bits1(&gbc); + + hdr->halfratecod = FFMAX(hdr->bsid, 8) - 8; + hdr->sample_rate = ff_ac3_freqs[hdr->fscod] >> hdr->halfratecod; + hdr->bit_rate = (ff_ac3_bitratetab[hdr->frmsizecod>>1] * 1000) >> hdr->halfratecod; + hdr->channels = ff_ac3_channels[hdr->acmod] + hdr->lfeon; + hdr->frame_size = ff_ac3_frame_sizes[hdr->frmsizecod][hdr->fscod] * 2; + + return 0; +} diff --git a/libavcodec/ac3.h b/libavcodec/ac3.h index 28c7f03956..757f446572 100644 --- a/libavcodec/ac3.h +++ b/libavcodec/ac3.h @@ -45,6 +45,50 @@ typedef struct AC3BitAllocParameters { int cplfleak, cplsleak; } AC3BitAllocParameters; +/** + * @struct AC3HeaderInfo + * Coded AC-3 header values up to the lfeon element, plus derived values. + */ +typedef struct { + /** @defgroup coded Coded elements + * @{ + */ + uint16_t sync_word; + uint16_t crc1; + uint8_t fscod; + uint8_t frmsizecod; + uint8_t bsid; + uint8_t bsmod; + uint8_t acmod; + uint8_t cmixlev; + uint8_t surmixlev; + uint8_t dsurmod; + uint8_t lfeon; + /** @} */ + + /** @defgroup derived Derived values + * @{ + */ + uint8_t halfratecod; + uint16_t sample_rate; + uint32_t bit_rate; + uint8_t channels; + uint16_t frame_size; + /** @} */ +} AC3HeaderInfo; + +/** + * Parses AC-3 frame header. + * Parses the header up to the lfeon element, which is the first 52 or 54 bits + * depending on the audio coding mode. + * @param buf[in] Array containing the first 7 bytes of the frame. + * @param hdr[out] Pointer to struct where header info is written. + * @return Returns 0 on success, -1 if there is a sync word mismatch, + * -2 if the bsid (version) element is invalid, -3 if the fscod (sample rate) + * element is invalid, or -4 if the frmsizecod (bit rate) element is invalid. + */ +int ff_ac3_parse_header(const uint8_t buf[7], AC3HeaderInfo *hdr); + extern uint16_t ff_ac3_frame_sizes[38][3]; extern const uint8_t ff_ac3_channels[8]; extern const uint16_t ff_ac3_freqs[3]; diff --git a/libavcodec/parser.c b/libavcodec/parser.c index bafe9c831e..8693cd67f7 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -604,43 +604,26 @@ static const int aac_channels[8] = { static int ac3_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int *samples) { - unsigned int fscod, frmsizecod, acmod, bsid, lfeon, halfratecod; + int err; + unsigned int fscod, acmod, bsid, lfeon; unsigned int strmtyp, substreamid, frmsiz, fscod2, numblkscod; GetBitContext bits; + AC3HeaderInfo hdr; - init_get_bits(&bits, buf, AC3_HEADER_SIZE * 8); + err = ff_ac3_parse_header(buf, &hdr); - if(get_bits(&bits, 16) != 0x0b77) + if(err < 0 && err != -2) return 0; - bsid = show_bits_long(&bits, 29) & 0x1f; + bsid = hdr.bsid; if(bsid <= 10) { /* Normal AC-3 */ - skip_bits(&bits, 16); /* crc */ - fscod = get_bits(&bits, 2); - frmsizecod = get_bits(&bits, 6); - - if(fscod == 3 && frmsizecod > 37) - return 0; - - skip_bits(&bits, 5); /* bsid */ - 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 */ - lfeon = get_bits1(&bits); - - halfratecod = FFMAX(bsid, 8) - 8; - *sample_rate = ff_ac3_freqs[fscod] >> halfratecod; - *bit_rate = (ff_ac3_bitratetab[frmsizecod] * 1000) >> halfratecod; - *channels = ff_ac3_channels[acmod] + lfeon; - *samples = 6 * 256; - - return ff_ac3_frame_sizes[frmsizecod][fscod] * 2; + *sample_rate = hdr.sample_rate; + *bit_rate = hdr.bit_rate; + *channels = hdr.channels; + *samples = AC3_FRAME_SIZE; + return hdr.frame_size; } else if (bsid > 10 && bsid <= 16) { /* Enhanced AC-3 */ + init_get_bits(&bits, &buf[2], (AC3_HEADER_SIZE-2) * 8); strmtyp = get_bits(&bits, 2); substreamid = get_bits(&bits, 3);