From 13345fc1f86fc3615789e196d5a339c1c27c9068 Mon Sep 17 00:00:00 2001 From: Tim Walker Date: Wed, 11 Dec 2013 02:03:34 +0000 Subject: [PATCH] (e)ac3: parse and store the Dolby Surround, Surround EX and Headphone mode flags. --- libavcodec/ac3.h | 25 +++++++++++++++++++++++++ libavcodec/ac3_parser.c | 5 ++++- libavcodec/ac3dec.c | 28 ++++++++++++++++++++++------ libavcodec/ac3dec.h | 4 ++++ libavcodec/eac3dec.c | 10 ++++++++-- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/libavcodec/ac3.h b/libavcodec/ac3.h index 647432f02e..f01da07213 100644 --- a/libavcodec/ac3.h +++ b/libavcodec/ac3.h @@ -80,6 +80,30 @@ typedef enum { AC3_CHMODE_3F2R } AC3ChannelMode; +/** Dolby Surround mode */ +typedef enum AC3DolbySurroundMode { + AC3_DSURMOD_NOTINDICATED = 0, + AC3_DSURMOD_OFF, + AC3_DSURMOD_ON, + AC3_DSURMOD_RESERVED +} AC3DolbySurroundMode; + +/** Dolby Surround EX mode */ +typedef enum AC3DolbySurroundEXMode { + AC3_DSUREXMOD_NOTINDICATED = 0, + AC3_DSUREXMOD_OFF, + AC3_DSUREXMOD_ON, + AC3_DSUREXMOD_PLIIZ +} AC3DolbySurroundEXMode; + +/** Dolby Headphone mode */ +typedef enum AC3DolbyHeadphoneMode { + AC3_DHEADPHONMOD_NOTINDICATED = 0, + AC3_DHEADPHONMOD_OFF, + AC3_DHEADPHONMOD_ON, + AC3_DHEADPHONMOD_RESERVED +} AC3DolbyHeadphoneMode; + typedef struct AC3BitAllocParameters { int sr_code; int sr_shift; @@ -108,6 +132,7 @@ typedef struct AC3HeaderInfo { int surround_mix_level; ///< Surround mix level index uint16_t channel_map; int num_blocks; ///< number of audio blocks + int dolby_surround_mode; /** @} */ /** @name Derived values diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 4abcf168a2..5ea09f8fcd 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -68,6 +68,9 @@ int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) hdr->center_mix_level = 5; // -4.5dB hdr->surround_mix_level = 6; // -6.0dB + /* set default dolby surround mode */ + hdr->dolby_surround_mode = AC3_DSURMOD_NOTINDICATED; + if(hdr->bitstream_id <= 10) { /* Normal AC-3 */ hdr->crc1 = get_bits(gbc, 16); @@ -85,7 +88,7 @@ int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) hdr->channel_mode = get_bits(gbc, 3); if(hdr->channel_mode == AC3_CHMODE_STEREO) { - skip_bits(gbc, 2); // skip dsurmod + hdr->dolby_surround_mode = get_bits(gbc, 2); } else { if((hdr->channel_mode & 1) && hdr->channel_mode != AC3_CHMODE_MONO) hdr-> center_mix_level = center_levels[get_bits(gbc, 2)]; diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index e1c696269e..2b71c8384c 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -227,12 +227,26 @@ static int ac3_parse_header(AC3DecodeContext *s) skip_bits(gbc, 2); //skip copyright bit and original bitstream bit - /* skip the timecodes (or extra bitstream information for Alternate Syntax) + /* default dolby matrix encoding modes */ + s->dolby_surround_ex_mode = AC3_DSUREXMOD_NOTINDICATED; + s->dolby_headphone_mode = AC3_DHEADPHONMOD_NOTINDICATED; + + /* skip the timecodes or parse the Alternate Bit Stream Syntax TODO: read & use the xbsi1 downmix levels */ - if (get_bits1(gbc)) - skip_bits(gbc, 14); //skip timecode1 / xbsi1 - if (get_bits1(gbc)) - skip_bits(gbc, 14); //skip timecode2 / xbsi2 + if (s->bitstream_id != 6) { + if (get_bits1(gbc)) + skip_bits(gbc, 14); //skip timecode1 + if (get_bits1(gbc)) + skip_bits(gbc, 14); //skip timecode2 + } else { + if (get_bits1(gbc)) + skip_bits(gbc, 14); //skip xbsi1 + if (get_bits1(gbc)) { + s->dolby_surround_ex_mode = get_bits(gbc, 2); + s->dolby_headphone_mode = get_bits(gbc, 2); + skip_bits(gbc, 10); // skip adconvtyp (1), xbsi2 (8), encinfo (1) + } + } /* skip additional bitstream info */ if (get_bits1(gbc)) { @@ -259,6 +273,7 @@ static int parse_frame_header(AC3DecodeContext *s) /* get decoding parameters from header info */ s->bit_alloc_params.sr_code = hdr.sr_code; + s->bitstream_id = hdr.bitstream_id; s->bitstream_mode = hdr.bitstream_mode; s->channel_mode = hdr.channel_mode; s->lfe_on = hdr.lfe_on; @@ -274,6 +289,7 @@ static int parse_frame_header(AC3DecodeContext *s) s->num_blocks = hdr.num_blocks; s->frame_type = hdr.frame_type; s->substreamid = hdr.substreamid; + s->dolby_surround_mode = hdr.dolby_surround_mode; if (s->lfe_on) { s->start_freq[s->lfe_ch] = 0; @@ -282,7 +298,7 @@ static int parse_frame_header(AC3DecodeContext *s) s->channel_in_cpl[s->lfe_ch] = 0; } - if (hdr.bitstream_id <= 10) { + if (s->bitstream_id <= 10) { s->eac3 = 0; s->snr_offset_strategy = 2; s->block_switch_syntax = 1; diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 7b4a528f75..73ca1c3305 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -79,6 +79,7 @@ typedef struct AC3DecodeContext { int bit_rate; ///< stream bit rate, in bits-per-second int sample_rate; ///< sample frequency, in Hz int num_blocks; ///< number of audio blocks + int bitstream_id; ///< bitstream id (bsid) int bitstream_mode; ///< bitstream mode (bsmod) int channel_mode; ///< channel mode (acmod) int lfe_on; ///< lfe channel in use @@ -86,6 +87,9 @@ typedef struct AC3DecodeContext { int center_mix_level; ///< Center mix level index int surround_mix_level; ///< Surround mix level index int eac3; ///< indicates if current frame is E-AC-3 + int dolby_surround_mode; ///< dolby surround mode (dsurmod) + int dolby_surround_ex_mode; ///< dolby surround ex mode (dsurexmod) + int dolby_headphone_mode; ///< dolby headphone mode (dheadphonmod) ///@} ///@name Frame syntax parameters diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c index baba454fd6..fb6c51bcb8 100644 --- a/libavcodec/eac3dec.c +++ b/libavcodec/eac3dec.c @@ -341,6 +341,11 @@ int ff_eac3_parse_header(AC3DecodeContext *s) } } + /* default dolby matrix encoding modes */ + s->dolby_surround_mode = AC3_DSURMOD_NOTINDICATED; + s->dolby_surround_ex_mode = AC3_DSUREXMOD_NOTINDICATED; + s->dolby_headphone_mode = AC3_DHEADPHONMOD_NOTINDICATED; + /* mixing metadata */ if (get_bits1(gbc)) { /* center and surround mix levels */ @@ -413,10 +418,11 @@ int ff_eac3_parse_header(AC3DecodeContext *s) s->bitstream_mode = get_bits(gbc, 3); skip_bits(gbc, 2); // skip copyright bit and original bitstream bit if (s->channel_mode == AC3_CHMODE_STEREO) { - skip_bits(gbc, 4); // skip Dolby surround and headphone mode + s->dolby_surround_mode = get_bits(gbc, 2); + s->dolby_headphone_mode = get_bits(gbc, 2); } if (s->channel_mode >= AC3_CHMODE_2F2R) { - skip_bits(gbc, 2); // skip Dolby surround EX mode + s->dolby_surround_ex_mode = get_bits(gbc, 2); } for (i = 0; i < (s->channel_mode ? 1 : 2); i++) { if (get_bits1(gbc)) {