* [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header()
@ 2025-06-05 21:49 James Almer
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 2/3] avformat/movenc: fix writing reserved bits in EC3SpecificBox James Almer
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: James Almer @ 2025-06-05 21:49 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavcodec/ac3_parser.c | 218 +++++++++++++++++++++++++++++++
libavcodec/ac3_parser_internal.h | 19 +++
libavcodec/ac3dec.c | 88 +++----------
libavcodec/ac3dec.h | 4 +-
libavcodec/ac3defs.h | 2 +
libavcodec/eac3dec.c | 154 +++-------------------
6 files changed, 279 insertions(+), 206 deletions(-)
diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c
index 69989690dd..1cba847eaa 100644
--- a/libavcodec/ac3_parser.c
+++ b/libavcodec/ac3_parser.c
@@ -73,6 +73,216 @@ int ff_ac3_find_syncword(const uint8_t *buf, int buf_size)
return i;
}
+/**
+ * Parse the 'sync info' and 'bit stream info' from the AC-3 bitstream.
+ * GetBitContext within AC3DecodeContext must point to
+ * the start of the synchronized AC-3 bitstream.
+ */
+static int ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
+{
+ /* read the rest of the bsi. read twice for dual mono mode. */
+ for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
+ hdr->dialog_normalization[i] = -get_bits(gbc, 5);
+ hdr->compression_exists[i] = get_bits1(gbc);
+ if (hdr->compression_exists[i])
+ hdr->heavy_dynamic_range[i] = get_bits(gbc, 8);
+ if (get_bits1(gbc))
+ skip_bits(gbc, 8); //skip language code
+ if (get_bits1(gbc))
+ skip_bits(gbc, 7); //skip audio production information
+ }
+
+ skip_bits(gbc, 2); //skip copyright bit and original bitstream bit
+
+ /* skip the timecodes or parse the Alternate Bit Stream Syntax */
+ if (hdr->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)) {
+ hdr->preferred_downmix = get_bits(gbc, 2);
+ hdr->center_mix_level_ltrt = get_bits(gbc, 3);
+ hdr->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
+ hdr->center_mix_level = get_bits(gbc, 3);
+ hdr->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
+ }
+ if (get_bits1(gbc)) {
+ hdr->dolby_surround_ex_mode = get_bits(gbc, 2);
+ hdr->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)) {
+ int i = get_bits(gbc, 6);
+ do {
+ skip_bits(gbc, 8);
+ } while (i--);
+ }
+
+ return 0;
+}
+
+static int eac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
+{
+ if (hdr->frame_type == EAC3_FRAME_TYPE_RESERVED)
+ return AC3_PARSE_ERROR_FRAME_TYPE;
+ if (hdr->substreamid)
+ return AC3_PARSE_ERROR_FRAME_TYPE;
+
+ skip_bits(gbc, 5); // skip bitstream id
+
+ /* volume control params */
+ for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
+ hdr->dialog_normalization[i] = -get_bits(gbc, 5);
+ hdr->compression_exists[i] = get_bits1(gbc);
+ if (hdr->compression_exists[i])
+ hdr->heavy_dynamic_range[i] = get_bits(gbc, 8);
+ }
+
+ /* dependent stream channel map */
+ if (hdr->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
+ if (get_bits1(gbc)) {
+ int64_t channel_layout = 0;
+ int channel_map = get_bits(gbc, 16);
+
+ for (int i = 0; i < 16; i++)
+ if (channel_map & (1 << (EAC3_MAX_CHANNELS - i - 1)))
+ channel_layout |= ff_eac3_custom_channel_map_locations[i][1];
+
+ if (av_popcount64(channel_layout) > EAC3_MAX_CHANNELS) {
+ return AC3_PARSE_ERROR_CHANNEL_MAP;
+ }
+ hdr->channel_map = channel_map;
+ }
+ }
+
+ /* mixing metadata */
+ if (get_bits1(gbc)) {
+ /* center and surround mix levels */
+ if (hdr->channel_mode > AC3_CHMODE_STEREO) {
+ hdr->preferred_downmix = get_bits(gbc, 2);
+ if (hdr->channel_mode & 1) {
+ /* if three front channels exist */
+ hdr->center_mix_level_ltrt = get_bits(gbc, 3);
+ hdr->center_mix_level = get_bits(gbc, 3);
+ }
+ if (hdr->channel_mode & 4) {
+ /* if a surround channel exists */
+ hdr->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
+ hdr->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
+ }
+ }
+
+ /* lfe mix level */
+ if (hdr->lfe_on && (hdr->lfe_mix_level_exists = get_bits1(gbc))) {
+ hdr->lfe_mix_level = get_bits(gbc, 5);
+ }
+
+ /* info for mixing with other streams and substreams */
+ if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) {
+ for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
+ // TODO: apply program scale factor
+ if (get_bits1(gbc)) {
+ skip_bits(gbc, 6); // skip program scale factor
+ }
+ }
+ if (get_bits1(gbc)) {
+ skip_bits(gbc, 6); // skip external program scale factor
+ }
+ /* skip mixing parameter data */
+ switch(get_bits(gbc, 2)) {
+ case 1: skip_bits(gbc, 5); break;
+ case 2: skip_bits(gbc, 12); break;
+ case 3: {
+ int mix_data_size = (get_bits(gbc, 5) + 2) << 3;
+ skip_bits_long(gbc, mix_data_size);
+ break;
+ }
+ }
+ /* skip pan information for mono or dual mono source */
+ if (hdr->channel_mode < AC3_CHMODE_STEREO) {
+ for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
+ if (get_bits1(gbc)) {
+ /* note: this is not in the ATSC A/52B specification
+ reference: ETSI TS 102 366 V1.1.1
+ section: E.1.3.1.25 */
+ skip_bits(gbc, 8); // skip pan mean direction index
+ skip_bits(gbc, 6); // skip reserved paninfo bits
+ }
+ }
+ }
+ /* skip mixing configuration information */
+ if (get_bits1(gbc)) {
+ for (int i = 0; i < hdr->num_blocks; i++) {
+ if (hdr->num_blocks == 1 || get_bits1(gbc)) {
+ skip_bits(gbc, 5);
+ }
+ }
+ }
+ }
+ }
+
+ /* informational metadata */
+ if (get_bits1(gbc)) {
+ hdr->bitstream_mode = get_bits(gbc, 3);
+ skip_bits(gbc, 2); // skip copyright bit and original bitstream bit
+ if (hdr->channel_mode == AC3_CHMODE_STEREO) {
+ hdr->dolby_surround_mode = get_bits(gbc, 2);
+ hdr->dolby_headphone_mode = get_bits(gbc, 2);
+ }
+ if (hdr->channel_mode >= AC3_CHMODE_2F2R) {
+ hdr->dolby_surround_ex_mode = get_bits(gbc, 2);
+ }
+ for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
+ if (get_bits1(gbc)) {
+ skip_bits(gbc, 8); // skip mix level, room type, and A/D converter type
+ }
+ }
+ if (hdr->sr_code != EAC3_SR_CODE_REDUCED) {
+ skip_bits1(gbc); // skip source sample rate code
+ }
+ }
+
+ /* converter synchronization flag
+ If frames are less than six blocks, this bit should be turned on
+ once every 6 blocks to indicate the start of a frame set.
+ reference: RFC 4598, Section 2.1.3 Frame Sets */
+ if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && hdr->num_blocks != 6) {
+ skip_bits1(gbc); // skip converter synchronization flag
+ }
+
+ /* original frame size code if this stream was converted from AC-3 */
+ if (hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT &&
+ (hdr->num_blocks == 6 || get_bits1(gbc))) {
+ skip_bits(gbc, 6); // skip frame size code
+ }
+
+ /* additional bitstream info */
+ if (get_bits1(gbc)) {
+ int addbsil = get_bits(gbc, 6);
+ for (int i = 0; i < addbsil + 1; i++) {
+ if (i == 0) {
+ /* In this 8 bit chunk, the LSB is equal to flag_ec3_extension_type_a
+ which can be used to detect Atmos presence */
+ skip_bits(gbc, 7);
+ hdr->eac3_extension_type_a = get_bits1(gbc);
+ if (hdr->eac3_extension_type_a) {
+ hdr->complexity_index_type_a = get_bits(gbc, 8);
+ i++;
+ }
+ } else {
+ skip_bits(gbc, 8); // skip additional bit stream info
+ }
+ }
+ }
+
+ return 0;
+}
+
int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
{
int frame_size_code;
@@ -133,6 +343,10 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
hdr->frame_size = ff_ac3_frame_size_tab[frame_size_code][hdr->sr_code] * 2;
hdr->frame_type = EAC3_FRAME_TYPE_AC3_CONVERT; //EAC3_FRAME_TYPE_INDEPENDENT;
hdr->substreamid = 0;
+
+ int ret = ac3_parse_header(gbc, hdr);
+ if (ret < 0)
+ return ret;
} else {
/* Enhanced AC-3 */
hdr->crc1 = 0;
@@ -165,6 +379,10 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
hdr->bit_rate = 8LL * hdr->frame_size * hdr->sample_rate /
(hdr->num_blocks * 256);
hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on;
+
+ int ret = eac3_parse_header(gbc, hdr);
+ if (ret < 0)
+ return ret;
}
hdr->channel_layout = ff_ac3_channel_layout_tab[hdr->channel_mode];
if (hdr->lfe_on)
diff --git a/libavcodec/ac3_parser_internal.h b/libavcodec/ac3_parser_internal.h
index 46814bfb1f..ab5df34003 100644
--- a/libavcodec/ac3_parser_internal.h
+++ b/libavcodec/ac3_parser_internal.h
@@ -46,6 +46,7 @@ typedef struct AC3HeaderInfo {
int substreamid; ///< substream identification
int center_mix_level; ///< Center mix level index
int surround_mix_level; ///< Surround mix level index
+ uint8_t channel_map_present;
uint16_t channel_map;
int num_blocks; ///< number of audio blocks
int dolby_surround_mode;
@@ -62,6 +63,23 @@ typedef struct AC3HeaderInfo {
uint64_t channel_layout;
int8_t ac3_bit_rate_code;
/** @} */
+
+ /** @name enhanced eac3 extension coded elements
+ * @{
+ */
+ int8_t dialog_normalization[2];
+ uint8_t compression_exists[2];
+ uint8_t heavy_dynamic_range[2];
+ uint8_t center_mix_level_ltrt; ///< Center mix level index
+ uint8_t surround_mix_level_ltrt; ///< Surround mix level index
+ uint8_t dolby_headphone_mode;
+ uint8_t dolby_surround_ex_mode;
+ uint8_t lfe_mix_level_exists;
+ uint8_t lfe_mix_level;
+ uint8_t preferred_downmix;
+ uint8_t eac3_extension_type_a;
+ uint8_t complexity_index_type_a;
+ /** @} */
} AC3HeaderInfo;
typedef enum {
@@ -71,6 +89,7 @@ typedef enum {
AC3_PARSE_ERROR_FRAME_SIZE = -0x4030c0a,
AC3_PARSE_ERROR_FRAME_TYPE = -0x5030c0a,
AC3_PARSE_ERROR_CRC = -0x6030c0a,
+ AC3_PARSE_ERROR_CHANNEL_MAP = -0x7030c0a,
} AC3ParseError;
/**
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index 5eacab4475..2f0e7f5344 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -156,72 +156,6 @@ static av_cold void ac3_decode_flush(AVCodecContext *avctx)
av_lfg_init(&s->dith_state, 0);
}
-/**
- * Parse the 'sync info' and 'bit stream info' from the AC-3 bitstream.
- * GetBitContext within AC3DecodeContext must point to
- * the start of the synchronized AC-3 bitstream.
- */
-static int ac3_parse_header(AC3DecodeContext *s)
-{
- GetBitContext *gbc = &s->gbc;
- int i;
-
- /* read the rest of the bsi. read twice for dual mono mode. */
- i = !s->channel_mode;
- do {
- s->dialog_normalization[(!s->channel_mode)-i] = -get_bits(gbc, 5);
- if (s->dialog_normalization[(!s->channel_mode)-i] == 0) {
- s->dialog_normalization[(!s->channel_mode)-i] = -31;
- }
- if (s->target_level != 0) {
- s->level_gain[(!s->channel_mode)-i] = powf(2.0f,
- (float)(s->target_level -
- s->dialog_normalization[(!s->channel_mode)-i])/6.0f);
- }
- if (s->compression_exists[(!s->channel_mode)-i] = get_bits1(gbc)) {
- s->heavy_dynamic_range[(!s->channel_mode)-i] =
- AC3_HEAVY_RANGE(get_bits(gbc, 8));
- }
- if (get_bits1(gbc))
- skip_bits(gbc, 8); //skip language code
- if (get_bits1(gbc))
- skip_bits(gbc, 7); //skip audio production information
- } while (i--);
-
- skip_bits(gbc, 2); //skip copyright bit and original bitstream bit
-
- /* skip the timecodes or parse the Alternate Bit Stream Syntax */
- 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)) {
- s->preferred_downmix = get_bits(gbc, 2);
- s->center_mix_level_ltrt = get_bits(gbc, 3);
- s->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
- s->center_mix_level = get_bits(gbc, 3);
- s->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
- }
- 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)) {
- i = get_bits(gbc, 6);
- do {
- skip_bits(gbc, 8);
- } while (i--);
- }
-
- return 0;
-}
-
/**
* Common function to parse AC-3 or E-AC-3 frame header
*/
@@ -281,10 +215,25 @@ static int parse_frame_header(AC3DecodeContext *s)
s->dba_syntax = 1;
s->skip_syntax = 1;
memset(s->channel_uses_aht, 0, sizeof(s->channel_uses_aht));
- return ac3_parse_header(s);
+ /* volume control params */
+ for (int i = 0; i < (s->channel_mode ? 1 : 2); i++) {
+ s->dialog_normalization[i] = hdr.dialog_normalization[i];
+ if (s->dialog_normalization[i] == 0) {
+ s->dialog_normalization[i] = -31;
+ }
+ if (s->target_level != 0) {
+ s->level_gain[i] = powf(2.0f,
+ (float)(s->target_level - s->dialog_normalization[i])/6.0f);
+ }
+ s->compression_exists[i] = hdr.compression_exists[i];
+ if (s->compression_exists[i]) {
+ s->heavy_dynamic_range[i] = AC3_HEAVY_RANGE(hdr.heavy_dynamic_range[i]);
+ }
+ }
+ return 0;
} else if (CONFIG_EAC3_DECODER) {
s->eac3 = 1;
- return ff_eac3_parse_header(s);
+ return ff_eac3_parse_header(s, &hdr);
} else {
av_log(s->avctx, AV_LOG_ERROR, "E-AC-3 support not compiled in\n");
return AVERROR(ENOSYS);
@@ -1469,6 +1418,9 @@ dependent_frame:
av_log(avctx, AV_LOG_ERROR, "invalid frame type\n");
}
break;
+ case AC3_PARSE_ERROR_CHANNEL_MAP:
+ av_log(avctx, AV_LOG_ERROR, "invalid channel map\n");
+ return AVERROR_INVALIDDATA;
case AC3_PARSE_ERROR_CRC:
break;
default: // Normal AVERROR do not try to recover.
diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
index 4042a99b80..a099264475 100644
--- a/libavcodec/ac3dec.h
+++ b/libavcodec/ac3dec.h
@@ -260,11 +260,13 @@ typedef struct AC3DecodeContext {
///@}
} AC3DecodeContext;
+struct AC3HeaderInfo;
+
/**
* Parse the E-AC-3 frame header.
* This parses both the bit stream info and audio frame header.
*/
-static int ff_eac3_parse_header(AC3DecodeContext *s);
+static int ff_eac3_parse_header(AC3DecodeContext *s, const struct AC3HeaderInfo *hdr);
/**
* Decode mantissas in a single channel for the entire frame.
diff --git a/libavcodec/ac3defs.h b/libavcodec/ac3defs.h
index f9b1be059f..8d6a58d21f 100644
--- a/libavcodec/ac3defs.h
+++ b/libavcodec/ac3defs.h
@@ -34,6 +34,8 @@
#define AC3_CRITICAL_BANDS 50
#define AC3_MAX_CPL_BANDS 18
+#define EAC3_SR_CODE_REDUCED 3
+
/* pre-defined gain values */
#define LEVEL_PLUS_3DB M_SQRT2
#define LEVEL_PLUS_1POINT5DB 1.1892071150027209
diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c
index 2b3bffda6e..c5095b1917 100644
--- a/libavcodec/eac3dec.c
+++ b/libavcodec/eac3dec.c
@@ -53,8 +53,6 @@ typedef enum {
EAC3_GAQ_124
} EAC3GaqMode;
-#define EAC3_SR_CODE_REDUCED 3
-
static void ff_eac3_apply_spectral_extension(AC3DecodeContext *s)
{
int bin, bnd, ch, i;
@@ -287,7 +285,7 @@ static void ff_eac3_decode_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch)
}
}
-static int ff_eac3_parse_header(AC3DecodeContext *s)
+static int ff_eac3_parse_header(AC3DecodeContext *s, const AC3HeaderInfo *hdr)
{
int i, blk, ch;
int ac3_exponent_strategy, parse_aht_info, parse_spx_atten_data;
@@ -323,11 +321,10 @@ static int ff_eac3_parse_header(AC3DecodeContext *s)
avpriv_request_sample(s->avctx, "Reduced sampling rate");
return AVERROR_PATCHWELCOME;
}
- skip_bits(gbc, 5); // skip bitstream id
/* volume control params */
for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
- s->dialog_normalization[i] = -get_bits(gbc, 5);
+ s->dialog_normalization[i] = hdr->dialog_normalization[i];
if (s->dialog_normalization[i] == 0) {
s->dialog_normalization[i] = -31;
}
@@ -335,147 +332,30 @@ static int ff_eac3_parse_header(AC3DecodeContext *s)
s->level_gain[i] = powf(2.0f,
(float)(s->target_level - s->dialog_normalization[i])/6.0f);
}
- s->compression_exists[i] = get_bits1(gbc);
- if (s->compression_exists[i]) {
- s->heavy_dynamic_range[i] = AC3_HEAVY_RANGE(get_bits(gbc, 8));
+ if (hdr->compression_exists[i]) {
+ s->heavy_dynamic_range[i] = AC3_HEAVY_RANGE(hdr->heavy_dynamic_range[i]);
}
}
- /* dependent stream channel map */
- if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
- if (get_bits1(gbc)) {
- int64_t channel_layout = 0;
- int channel_map = get_bits(gbc, 16);
- av_log(s->avctx, AV_LOG_DEBUG, "channel_map: %0X\n", channel_map);
-
- for (i = 0; i < 16; i++)
- if (channel_map & (1 << (EAC3_MAX_CHANNELS - i - 1)))
- channel_layout |= ff_eac3_custom_channel_map_locations[i][1];
-
- if (av_popcount64(channel_layout) > EAC3_MAX_CHANNELS) {
- return AVERROR_INVALIDDATA;
- }
- s->channel_map = channel_map;
- }
- }
+ s->channel_map = hdr->channel_map;
/* mixing metadata */
- if (get_bits1(gbc)) {
- /* center and surround mix levels */
- if (s->channel_mode > AC3_CHMODE_STEREO) {
- s->preferred_downmix = get_bits(gbc, 2);
- if (s->channel_mode & 1) {
- /* if three front channels exist */
- s->center_mix_level_ltrt = get_bits(gbc, 3);
- s->center_mix_level = get_bits(gbc, 3);
- }
- if (s->channel_mode & 4) {
- /* if a surround channel exists */
- s->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
- s->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
- }
- }
-
- /* lfe mix level */
- if (s->lfe_on && (s->lfe_mix_level_exists = get_bits1(gbc))) {
- s->lfe_mix_level = get_bits(gbc, 5);
- }
-
- /* info for mixing with other streams and substreams */
- if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) {
- for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
- // TODO: apply program scale factor
- if (get_bits1(gbc)) {
- skip_bits(gbc, 6); // skip program scale factor
- }
- }
- if (get_bits1(gbc)) {
- skip_bits(gbc, 6); // skip external program scale factor
- }
- /* skip mixing parameter data */
- switch(get_bits(gbc, 2)) {
- case 1: skip_bits(gbc, 5); break;
- case 2: skip_bits(gbc, 12); break;
- case 3: {
- int mix_data_size = (get_bits(gbc, 5) + 2) << 3;
- skip_bits_long(gbc, mix_data_size);
- break;
- }
- }
- /* skip pan information for mono or dual mono source */
- if (s->channel_mode < AC3_CHMODE_STEREO) {
- for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
- if (get_bits1(gbc)) {
- /* note: this is not in the ATSC A/52B specification
- reference: ETSI TS 102 366 V1.1.1
- section: E.1.3.1.25 */
- skip_bits(gbc, 8); // skip pan mean direction index
- skip_bits(gbc, 6); // skip reserved paninfo bits
- }
- }
- }
- /* skip mixing configuration information */
- if (get_bits1(gbc)) {
- for (blk = 0; blk < s->num_blocks; blk++) {
- if (s->num_blocks == 1 || get_bits1(gbc)) {
- skip_bits(gbc, 5);
- }
- }
- }
- }
- }
+ s->preferred_downmix = hdr->preferred_downmix;
+ s->center_mix_level_ltrt = hdr->center_mix_level_ltrt;
+ s->center_mix_level = hdr->center_mix_level;
+ s->surround_mix_level_ltrt = hdr->surround_mix_level_ltrt;
+ s->surround_mix_level = hdr->surround_mix_level;
+ s->lfe_mix_level_exists = hdr->lfe_mix_level_exists;
+ s->lfe_mix_level = hdr->lfe_mix_level;
+ s->dolby_surround_mode = hdr->dolby_surround_mode;
+ s->dolby_headphone_mode = hdr->dolby_headphone_mode;
+ s->dolby_surround_ex_mode = hdr->dolby_surround_ex_mode;
/* informational metadata */
- if (get_bits1(gbc)) {
- 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) {
- s->dolby_surround_mode = get_bits(gbc, 2);
- s->dolby_headphone_mode = get_bits(gbc, 2);
- }
- if (s->channel_mode >= AC3_CHMODE_2F2R) {
- s->dolby_surround_ex_mode = get_bits(gbc, 2);
- }
- for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
- if (get_bits1(gbc)) {
- skip_bits(gbc, 8); // skip mix level, room type, and A/D converter type
- }
- }
- if (s->bit_alloc_params.sr_code != EAC3_SR_CODE_REDUCED) {
- skip_bits1(gbc); // skip source sample rate code
- }
- }
-
- /* converter synchronization flag
- If frames are less than six blocks, this bit should be turned on
- once every 6 blocks to indicate the start of a frame set.
- reference: RFC 4598, Section 2.1.3 Frame Sets */
- if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && s->num_blocks != 6) {
- skip_bits1(gbc); // skip converter synchronization flag
- }
-
- /* original frame size code if this stream was converted from AC-3 */
- if (s->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT &&
- (s->num_blocks == 6 || get_bits1(gbc))) {
- skip_bits(gbc, 6); // skip frame size code
- }
+ s->bitstream_mode = hdr->bitstream_mode;
/* additional bitstream info */
- if (get_bits1(gbc)) {
- int addbsil = get_bits(gbc, 6);
- for (i = 0; i < addbsil + 1; i++) {
- if (i == 0) {
- /* In this 8 bit chunk, the LSB is equal to flag_ec3_extension_type_a
- which can be used to detect Atmos presence */
- skip_bits(gbc, 7);
- if (get_bits1(gbc)) {
- s->eac3_extension_type_a = 1;
- }
- } else {
- skip_bits(gbc, 8); // skip additional bit stream info
- }
- }
- }
+ s->eac3_extension_type_a = hdr->eac3_extension_type_a;
/* audio frame syntax flags, strategy data, and per-frame data */
--
2.49.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 7+ messages in thread
* [FFmpeg-devel] [PATCH 2/3] avformat/movenc: fix writing reserved bits in EC3SpecificBox
2025-06-05 21:49 [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() James Almer
@ 2025-06-05 21:49 ` James Almer
2025-06-05 22:07 ` Baptiste Coudurier
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 3/3] avformat/movenc: handle EAC-3 extension bits for Atmos James Almer
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: James Almer @ 2025-06-05 21:49 UTC (permalink / raw)
To: ffmpeg-devel
As described in section F.6.1 from ETSI TS 102 366.
Found-by: nyanmisaka
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavformat/movenc.c | 2 +-
tests/ref/fate/copy-trac3074 | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 402611e81e..25360b004d 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -631,7 +631,7 @@ static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
put_bits(&pbc, 3, info->substream[i].bsmod);
put_bits(&pbc, 3, info->substream[i].acmod);
put_bits(&pbc, 1, info->substream[i].lfeon);
- put_bits(&pbc, 5, 0); /* reserved */
+ put_bits(&pbc, 3, 0); /* reserved */
put_bits(&pbc, 4, info->substream[i].num_dep_sub);
if (!info->substream[i].num_dep_sub) {
put_bits(&pbc, 1, 0); /* reserved */
diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074
index 53ba27e920..9ed42c8d8d 100644
--- a/tests/ref/fate/copy-trac3074
+++ b/tests/ref/fate/copy-trac3074
@@ -1,5 +1,5 @@
-36fcc0a62695bcf93068fcfe68283ee9 *tests/data/fate/copy-trac3074.mp4
-334016 tests/data/fate/copy-trac3074.mp4
+5b4a3ed9de3b2a92e5dcb127bca12e68 *tests/data/fate/copy-trac3074.mp4
+334015 tests/data/fate/copy-trac3074.mp4
#tb 0: 1/48000
#media_type 0: audio
#codec_id 0: eac3
--
2.49.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 7+ messages in thread
* [FFmpeg-devel] [PATCH 3/3] avformat/movenc: handle EAC-3 extension bits for Atmos
2025-06-05 21:49 [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() James Almer
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 2/3] avformat/movenc: fix writing reserved bits in EC3SpecificBox James Almer
@ 2025-06-05 21:49 ` James Almer
2025-06-05 22:09 ` Baptiste Coudurier
2025-06-05 22:15 ` [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() Baptiste Coudurier
2025-06-05 23:07 ` Andreas Rheinhardt
3 siblings, 1 reply; 7+ messages in thread
From: James Almer @ 2025-06-05 21:49 UTC (permalink / raw)
To: ffmpeg-devel
From: nyanmisaka <nst799610810@gmail.com>
Fixes commit #9996.
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavformat/movenc.c | 31 +++++++++++++++----------------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 25360b004d..b546c8b545 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -393,6 +393,10 @@ struct eac3_info {
uint16_t chan_loc;
/* if there is no dependent substream, then one bit reserved instead */
} substream[1]; /* TODO: support 8 independent substreams */
+ /* indicates the enhanced AC-3 extension, 1 bit */
+ uint8_t eac3_extension_type_a;
+ /* indicates the decoding complexity, 8 bits */
+ uint8_t complexity_index_type_a;
};
static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
@@ -474,6 +478,9 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
hdr->ac3_bit_rate_code);
+ info->eac3_extension_type_a = hdr->eac3_extension_type_a;
+ info->complexity_index_type_a = hdr->complexity_index_type_a;
+
num_blocks = hdr->num_blocks;
if (!info->ec3_done) {
@@ -532,8 +539,6 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
int parent = hdr->substreamid;
while (cumul_size != pkt->size) {
- GetBitContext gbc;
- int i;
ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
if (ret < 0)
goto end;
@@ -544,20 +549,9 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
info->substream[parent].num_dep_sub++;
ret /= 8;
- /* header is parsed up to lfeon, but custom channel map may be needed */
- init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
- /* skip bsid */
- skip_bits(&gbc, 5);
- /* skip volume control params */
- for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
- skip_bits(&gbc, 5); // skip dialog normalization
- if (get_bits1(&gbc)) {
- skip_bits(&gbc, 8); // skip compression gain word
- }
- }
/* get the dependent stream channel map, if exists */
- if (get_bits1(&gbc))
- info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
+ if (hdr->channel_map_present)
+ info->substream[parent].chan_loc |= (hdr->channel_map >> 5) & 0x1f;
else
info->substream[parent].chan_loc |= hdr->channel_mode;
cumul_size += hdr->frame_size;
@@ -614,7 +608,7 @@ static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
}
info = track->eac3_priv;
- size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3);
+ size = 2 + ((32 * (info->num_ind_sub + 1) + 7 + 1 + 8) >> 3);
buf = av_malloc(size);
if (!buf) {
return AVERROR(ENOMEM);
@@ -639,6 +633,11 @@ static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
put_bits(&pbc, 9, info->substream[i].chan_loc);
}
}
+ if (info->eac3_extension_type_a == 1) {
+ put_bits(&pbc, 7, 0); /* reserved */
+ put_bits(&pbc, 1, info->eac3_extension_type_a);
+ put_bits(&pbc, 8, info->complexity_index_type_a);
+ }
flush_put_bits(&pbc);
size = put_bytes_output(&pbc);
--
2.49.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/3] avformat/movenc: fix writing reserved bits in EC3SpecificBox
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 2/3] avformat/movenc: fix writing reserved bits in EC3SpecificBox James Almer
@ 2025-06-05 22:07 ` Baptiste Coudurier
0 siblings, 0 replies; 7+ messages in thread
From: Baptiste Coudurier @ 2025-06-05 22:07 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Hi James
> On Jun 5, 2025, at 2:49 PM, James Almer <jamrial@gmail.com> wrote:
>
> As described in section F.6.1 from ETSI TS 102 366.
>
> Found-by: nyanmisaka
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> libavformat/movenc.c | 2 +-
> tests/ref/fate/copy-trac3074 | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 402611e81e..25360b004d 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -631,7 +631,7 @@ static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
> put_bits(&pbc, 3, info->substream[i].bsmod);
> put_bits(&pbc, 3, info->substream[i].acmod);
> put_bits(&pbc, 1, info->substream[i].lfeon);
> - put_bits(&pbc, 5, 0); /* reserved */
> + put_bits(&pbc, 3, 0); /* reserved */
> put_bits(&pbc, 4, info->substream[i].num_dep_sub);
> if (!info->substream[i].num_dep_sub) {
> put_bits(&pbc, 1, 0); /* reserved */
> diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074
> index 53ba27e920..9ed42c8d8d 100644
> --- a/tests/ref/fate/copy-trac3074
> +++ b/tests/ref/fate/copy-trac3074
> @@ -1,5 +1,5 @@
> -36fcc0a62695bcf93068fcfe68283ee9 *tests/data/fate/copy-trac3074.mp4
> -334016 tests/data/fate/copy-trac3074.mp4
> +5b4a3ed9de3b2a92e5dcb127bca12e68 *tests/data/fate/copy-trac3074.mp4
> +334015 tests/data/fate/copy-trac3074.mp4
> #tb 0: 1/48000
> #media_type 0: audio
> #codec_id 0: eac3
Yes, I actually just noticed that :)
—
Baptiste
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH 3/3] avformat/movenc: handle EAC-3 extension bits for Atmos
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 3/3] avformat/movenc: handle EAC-3 extension bits for Atmos James Almer
@ 2025-06-05 22:09 ` Baptiste Coudurier
0 siblings, 0 replies; 7+ messages in thread
From: Baptiste Coudurier @ 2025-06-05 22:09 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> On Jun 5, 2025, at 2:49 PM, James Almer <jamrial@gmail.com> wrote:
>
> From: nyanmisaka <nst799610810@gmail.com>
>
> Fixes commit #9996.
>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> libavformat/movenc.c | 31 +++++++++++++++----------------
> 1 file changed, 15 insertions(+), 16 deletions(-)
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 25360b004d..b546c8b545 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -393,6 +393,10 @@ struct eac3_info {
> uint16_t chan_loc;
> /* if there is no dependent substream, then one bit reserved instead */
> } substream[1]; /* TODO: support 8 independent substreams */
> + /* indicates the enhanced AC-3 extension, 1 bit */
> + uint8_t eac3_extension_type_a;
> + /* indicates the decoding complexity, 8 bits */
> + uint8_t complexity_index_type_a;
> };
I think we only need complexity_index_type_a, if it’s 0 it’s not necessary
>
> static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
> @@ -474,6 +478,9 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
> info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000);
> info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code,
> hdr->ac3_bit_rate_code);
> + info->eac3_extension_type_a = hdr->eac3_extension_type_a;
> + info->complexity_index_type_a = hdr->complexity_index_type_a;
> +
> num_blocks = hdr->num_blocks;
>
> if (!info->ec3_done) {
> @@ -532,8 +539,6 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
> int parent = hdr->substreamid;
>
> while (cumul_size != pkt->size) {
> - GetBitContext gbc;
> - int i;
> ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size);
> if (ret < 0)
> goto end;
> @@ -544,20 +549,9 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
> info->substream[parent].num_dep_sub++;
> ret /= 8;
>
> - /* header is parsed up to lfeon, but custom channel map may be needed */
> - init_get_bits8(&gbc, pkt->data + cumul_size + ret, pkt->size - cumul_size - ret);
> - /* skip bsid */
> - skip_bits(&gbc, 5);
> - /* skip volume control params */
> - for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
> - skip_bits(&gbc, 5); // skip dialog normalization
> - if (get_bits1(&gbc)) {
> - skip_bits(&gbc, 8); // skip compression gain word
> - }
> - }
> /* get the dependent stream channel map, if exists */
> - if (get_bits1(&gbc))
> - info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f;
> + if (hdr->channel_map_present)
> + info->substream[parent].chan_loc |= (hdr->channel_map >> 5) & 0x1f;
Beautiful cleanup
> else
> info->substream[parent].chan_loc |= hdr->channel_mode;
> cumul_size += hdr->frame_size;
> @@ -614,7 +608,7 @@ static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
> }
>
> info = track->eac3_priv;
> - size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3);
> + size = 2 + ((32 * (info->num_ind_sub + 1) + 7 + 1 + 8) >> 3);
Let’s just make it optional on complexity_type_a
—
Baptiste
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header()
2025-06-05 21:49 [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() James Almer
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 2/3] avformat/movenc: fix writing reserved bits in EC3SpecificBox James Almer
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 3/3] avformat/movenc: handle EAC-3 extension bits for Atmos James Almer
@ 2025-06-05 22:15 ` Baptiste Coudurier
2025-06-05 23:07 ` Andreas Rheinhardt
3 siblings, 0 replies; 7+ messages in thread
From: Baptiste Coudurier @ 2025-06-05 22:15 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> On Jun 5, 2025, at 2:49 PM, James Almer <jamrial@gmail.com> wrote:
>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>
> diff --git a/libavcodec/ac3_parser_internal.h b/libavcodec/ac3_parser_internal.h
> index 46814bfb1f..ab5df34003 100644
> --- a/libavcodec/ac3_parser_internal.h
> +++ b/libavcodec/ac3_parser_internal.h
> @@ -46,6 +46,7 @@ typedef struct AC3HeaderInfo {
> int substreamid; ///< substream identification
> int center_mix_level; ///< Center mix level index
> int surround_mix_level; ///< Surround mix level index
> + uint8_t channel_map_present;
> uint16_t channel_map;
> int num_blocks; ///< number of audio blocks
> int dolby_surround_mode;
Am I missing something or this field is not set anywhere ?
Otherwise it looks great :)
—
Baptiste
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header()
2025-06-05 21:49 [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() James Almer
` (2 preceding siblings ...)
2025-06-05 22:15 ` [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() Baptiste Coudurier
@ 2025-06-05 23:07 ` Andreas Rheinhardt
3 siblings, 0 replies; 7+ messages in thread
From: Andreas Rheinhardt @ 2025-06-05 23:07 UTC (permalink / raw)
To: ffmpeg-devel
James Almer:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> libavcodec/ac3_parser.c | 218 +++++++++++++++++++++++++++++++
> libavcodec/ac3_parser_internal.h | 19 +++
> libavcodec/ac3dec.c | 88 +++----------
> libavcodec/ac3dec.h | 4 +-
> libavcodec/ac3defs.h | 2 +
> libavcodec/eac3dec.c | 154 +++-------------------
> 6 files changed, 279 insertions(+), 206 deletions(-)
>
> diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c
> index 69989690dd..1cba847eaa 100644
> --- a/libavcodec/ac3_parser.c
> +++ b/libavcodec/ac3_parser.c
> @@ -73,6 +73,216 @@ int ff_ac3_find_syncword(const uint8_t *buf, int buf_size)
> return i;
> }
>
> +/**
> + * Parse the 'sync info' and 'bit stream info' from the AC-3 bitstream.
> + * GetBitContext within AC3DecodeContext must point to
> + * the start of the synchronized AC-3 bitstream.
> + */
> +static int ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
> +{
> + /* read the rest of the bsi. read twice for dual mono mode. */
> + for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
> + hdr->dialog_normalization[i] = -get_bits(gbc, 5);
> + hdr->compression_exists[i] = get_bits1(gbc);
> + if (hdr->compression_exists[i])
> + hdr->heavy_dynamic_range[i] = get_bits(gbc, 8);
> + if (get_bits1(gbc))
> + skip_bits(gbc, 8); //skip language code
> + if (get_bits1(gbc))
> + skip_bits(gbc, 7); //skip audio production information
> + }
> +
> + skip_bits(gbc, 2); //skip copyright bit and original bitstream bit
> +
> + /* skip the timecodes or parse the Alternate Bit Stream Syntax */
> + if (hdr->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)) {
> + hdr->preferred_downmix = get_bits(gbc, 2);
> + hdr->center_mix_level_ltrt = get_bits(gbc, 3);
> + hdr->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
> + hdr->center_mix_level = get_bits(gbc, 3);
> + hdr->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
> + }
> + if (get_bits1(gbc)) {
> + hdr->dolby_surround_ex_mode = get_bits(gbc, 2);
> + hdr->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)) {
> + int i = get_bits(gbc, 6);
> + do {
> + skip_bits(gbc, 8);
> + } while (i--);
> + }
> +
> + return 0;
> +}
> +
> +static int eac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
> +{
> + if (hdr->frame_type == EAC3_FRAME_TYPE_RESERVED)
> + return AC3_PARSE_ERROR_FRAME_TYPE;
> + if (hdr->substreamid)
> + return AC3_PARSE_ERROR_FRAME_TYPE;
> +
> + skip_bits(gbc, 5); // skip bitstream id
> +
> + /* volume control params */
> + for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
> + hdr->dialog_normalization[i] = -get_bits(gbc, 5);
> + hdr->compression_exists[i] = get_bits1(gbc);
> + if (hdr->compression_exists[i])
> + hdr->heavy_dynamic_range[i] = get_bits(gbc, 8);
> + }
> +
> + /* dependent stream channel map */
> + if (hdr->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
> + if (get_bits1(gbc)) {
> + int64_t channel_layout = 0;
> + int channel_map = get_bits(gbc, 16);
> +
> + for (int i = 0; i < 16; i++)
> + if (channel_map & (1 << (EAC3_MAX_CHANNELS - i - 1)))
> + channel_layout |= ff_eac3_custom_channel_map_locations[i][1];
> +
> + if (av_popcount64(channel_layout) > EAC3_MAX_CHANNELS) {
> + return AC3_PARSE_ERROR_CHANNEL_MAP;
> + }
> + hdr->channel_map = channel_map;
> + }
> + }
> +
> + /* mixing metadata */
> + if (get_bits1(gbc)) {
> + /* center and surround mix levels */
> + if (hdr->channel_mode > AC3_CHMODE_STEREO) {
> + hdr->preferred_downmix = get_bits(gbc, 2);
> + if (hdr->channel_mode & 1) {
> + /* if three front channels exist */
> + hdr->center_mix_level_ltrt = get_bits(gbc, 3);
> + hdr->center_mix_level = get_bits(gbc, 3);
> + }
> + if (hdr->channel_mode & 4) {
> + /* if a surround channel exists */
> + hdr->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
> + hdr->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
> + }
> + }
> +
> + /* lfe mix level */
> + if (hdr->lfe_on && (hdr->lfe_mix_level_exists = get_bits1(gbc))) {
> + hdr->lfe_mix_level = get_bits(gbc, 5);
> + }
> +
> + /* info for mixing with other streams and substreams */
> + if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) {
> + for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
> + // TODO: apply program scale factor
> + if (get_bits1(gbc)) {
> + skip_bits(gbc, 6); // skip program scale factor
> + }
> + }
> + if (get_bits1(gbc)) {
> + skip_bits(gbc, 6); // skip external program scale factor
> + }
> + /* skip mixing parameter data */
> + switch(get_bits(gbc, 2)) {
> + case 1: skip_bits(gbc, 5); break;
> + case 2: skip_bits(gbc, 12); break;
> + case 3: {
> + int mix_data_size = (get_bits(gbc, 5) + 2) << 3;
> + skip_bits_long(gbc, mix_data_size);
> + break;
> + }
> + }
> + /* skip pan information for mono or dual mono source */
> + if (hdr->channel_mode < AC3_CHMODE_STEREO) {
> + for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
> + if (get_bits1(gbc)) {
> + /* note: this is not in the ATSC A/52B specification
> + reference: ETSI TS 102 366 V1.1.1
> + section: E.1.3.1.25 */
> + skip_bits(gbc, 8); // skip pan mean direction index
> + skip_bits(gbc, 6); // skip reserved paninfo bits
> + }
> + }
> + }
> + /* skip mixing configuration information */
> + if (get_bits1(gbc)) {
> + for (int i = 0; i < hdr->num_blocks; i++) {
> + if (hdr->num_blocks == 1 || get_bits1(gbc)) {
> + skip_bits(gbc, 5);
> + }
> + }
> + }
> + }
> + }
> +
> + /* informational metadata */
> + if (get_bits1(gbc)) {
> + hdr->bitstream_mode = get_bits(gbc, 3);
> + skip_bits(gbc, 2); // skip copyright bit and original bitstream bit
> + if (hdr->channel_mode == AC3_CHMODE_STEREO) {
> + hdr->dolby_surround_mode = get_bits(gbc, 2);
> + hdr->dolby_headphone_mode = get_bits(gbc, 2);
> + }
> + if (hdr->channel_mode >= AC3_CHMODE_2F2R) {
> + hdr->dolby_surround_ex_mode = get_bits(gbc, 2);
> + }
> + for (int i = 0; i < (hdr->channel_mode ? 1 : 2); i++) {
> + if (get_bits1(gbc)) {
> + skip_bits(gbc, 8); // skip mix level, room type, and A/D converter type
> + }
> + }
> + if (hdr->sr_code != EAC3_SR_CODE_REDUCED) {
> + skip_bits1(gbc); // skip source sample rate code
> + }
> + }
> +
> + /* converter synchronization flag
> + If frames are less than six blocks, this bit should be turned on
> + once every 6 blocks to indicate the start of a frame set.
> + reference: RFC 4598, Section 2.1.3 Frame Sets */
> + if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && hdr->num_blocks != 6) {
> + skip_bits1(gbc); // skip converter synchronization flag
> + }
> +
> + /* original frame size code if this stream was converted from AC-3 */
> + if (hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT &&
> + (hdr->num_blocks == 6 || get_bits1(gbc))) {
> + skip_bits(gbc, 6); // skip frame size code
> + }
> +
> + /* additional bitstream info */
> + if (get_bits1(gbc)) {
> + int addbsil = get_bits(gbc, 6);
> + for (int i = 0; i < addbsil + 1; i++) {
> + if (i == 0) {
> + /* In this 8 bit chunk, the LSB is equal to flag_ec3_extension_type_a
> + which can be used to detect Atmos presence */
> + skip_bits(gbc, 7);
> + hdr->eac3_extension_type_a = get_bits1(gbc);
> + if (hdr->eac3_extension_type_a) {
> + hdr->complexity_index_type_a = get_bits(gbc, 8);
> + i++;
> + }
> + } else {
> + skip_bits(gbc, 8); // skip additional bit stream info
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
> {
> int frame_size_code;
> @@ -133,6 +343,10 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
> hdr->frame_size = ff_ac3_frame_size_tab[frame_size_code][hdr->sr_code] * 2;
> hdr->frame_type = EAC3_FRAME_TYPE_AC3_CONVERT; //EAC3_FRAME_TYPE_INDEPENDENT;
> hdr->substreamid = 0;
> +
> + int ret = ac3_parse_header(gbc, hdr);
> + if (ret < 0)
> + return ret;
> } else {
> /* Enhanced AC-3 */
> hdr->crc1 = 0;
> @@ -165,6 +379,10 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
> hdr->bit_rate = 8LL * hdr->frame_size * hdr->sample_rate /
> (hdr->num_blocks * 256);
> hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on;
> +
> + int ret = eac3_parse_header(gbc, hdr);
> + if (ret < 0)
> + return ret;
> }
> hdr->channel_layout = ff_ac3_channel_layout_tab[hdr->channel_mode];
> if (hdr->lfe_on)
> diff --git a/libavcodec/ac3_parser_internal.h b/libavcodec/ac3_parser_internal.h
> index 46814bfb1f..ab5df34003 100644
> --- a/libavcodec/ac3_parser_internal.h
> +++ b/libavcodec/ac3_parser_internal.h
> @@ -46,6 +46,7 @@ typedef struct AC3HeaderInfo {
> int substreamid; ///< substream identification
> int center_mix_level; ///< Center mix level index
> int surround_mix_level; ///< Surround mix level index
> + uint8_t channel_map_present;
> uint16_t channel_map;
> int num_blocks; ///< number of audio blocks
> int dolby_surround_mode;
> @@ -62,6 +63,23 @@ typedef struct AC3HeaderInfo {
> uint64_t channel_layout;
> int8_t ac3_bit_rate_code;
> /** @} */
> +
> + /** @name enhanced eac3 extension coded elements
> + * @{
> + */
> + int8_t dialog_normalization[2];
> + uint8_t compression_exists[2];
> + uint8_t heavy_dynamic_range[2];
> + uint8_t center_mix_level_ltrt; ///< Center mix level index
> + uint8_t surround_mix_level_ltrt; ///< Surround mix level index
> + uint8_t dolby_headphone_mode;
> + uint8_t dolby_surround_ex_mode;
> + uint8_t lfe_mix_level_exists;
> + uint8_t lfe_mix_level;
> + uint8_t preferred_downmix;
> + uint8_t eac3_extension_type_a;
> + uint8_t complexity_index_type_a;
> + /** @} */
> } AC3HeaderInfo;
>
> typedef enum {
> @@ -71,6 +89,7 @@ typedef enum {
> AC3_PARSE_ERROR_FRAME_SIZE = -0x4030c0a,
> AC3_PARSE_ERROR_FRAME_TYPE = -0x5030c0a,
> AC3_PARSE_ERROR_CRC = -0x6030c0a,
> + AC3_PARSE_ERROR_CHANNEL_MAP = -0x7030c0a,
> } AC3ParseError;
>
> /**
> diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
> index 5eacab4475..2f0e7f5344 100644
> --- a/libavcodec/ac3dec.c
> +++ b/libavcodec/ac3dec.c
> @@ -156,72 +156,6 @@ static av_cold void ac3_decode_flush(AVCodecContext *avctx)
> av_lfg_init(&s->dith_state, 0);
> }
>
> -/**
> - * Parse the 'sync info' and 'bit stream info' from the AC-3 bitstream.
> - * GetBitContext within AC3DecodeContext must point to
> - * the start of the synchronized AC-3 bitstream.
> - */
> -static int ac3_parse_header(AC3DecodeContext *s)
> -{
> - GetBitContext *gbc = &s->gbc;
> - int i;
> -
> - /* read the rest of the bsi. read twice for dual mono mode. */
> - i = !s->channel_mode;
> - do {
> - s->dialog_normalization[(!s->channel_mode)-i] = -get_bits(gbc, 5);
> - if (s->dialog_normalization[(!s->channel_mode)-i] == 0) {
> - s->dialog_normalization[(!s->channel_mode)-i] = -31;
> - }
> - if (s->target_level != 0) {
> - s->level_gain[(!s->channel_mode)-i] = powf(2.0f,
> - (float)(s->target_level -
> - s->dialog_normalization[(!s->channel_mode)-i])/6.0f);
> - }
> - if (s->compression_exists[(!s->channel_mode)-i] = get_bits1(gbc)) {
> - s->heavy_dynamic_range[(!s->channel_mode)-i] =
> - AC3_HEAVY_RANGE(get_bits(gbc, 8));
> - }
> - if (get_bits1(gbc))
> - skip_bits(gbc, 8); //skip language code
> - if (get_bits1(gbc))
> - skip_bits(gbc, 7); //skip audio production information
> - } while (i--);
> -
> - skip_bits(gbc, 2); //skip copyright bit and original bitstream bit
> -
> - /* skip the timecodes or parse the Alternate Bit Stream Syntax */
> - 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)) {
> - s->preferred_downmix = get_bits(gbc, 2);
> - s->center_mix_level_ltrt = get_bits(gbc, 3);
> - s->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
> - s->center_mix_level = get_bits(gbc, 3);
> - s->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
> - }
> - 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)) {
> - i = get_bits(gbc, 6);
> - do {
> - skip_bits(gbc, 8);
> - } while (i--);
> - }
> -
> - return 0;
> -}
> -
> /**
> * Common function to parse AC-3 or E-AC-3 frame header
> */
> @@ -281,10 +215,25 @@ static int parse_frame_header(AC3DecodeContext *s)
> s->dba_syntax = 1;
> s->skip_syntax = 1;
> memset(s->channel_uses_aht, 0, sizeof(s->channel_uses_aht));
> - return ac3_parse_header(s);
> + /* volume control params */
> + for (int i = 0; i < (s->channel_mode ? 1 : 2); i++) {
> + s->dialog_normalization[i] = hdr.dialog_normalization[i];
> + if (s->dialog_normalization[i] == 0) {
> + s->dialog_normalization[i] = -31;
> + }
> + if (s->target_level != 0) {
> + s->level_gain[i] = powf(2.0f,
> + (float)(s->target_level - s->dialog_normalization[i])/6.0f);
> + }
> + s->compression_exists[i] = hdr.compression_exists[i];
> + if (s->compression_exists[i]) {
> + s->heavy_dynamic_range[i] = AC3_HEAVY_RANGE(hdr.heavy_dynamic_range[i]);
> + }
> + }
> + return 0;
> } else if (CONFIG_EAC3_DECODER) {
> s->eac3 = 1;
> - return ff_eac3_parse_header(s);
> + return ff_eac3_parse_header(s, &hdr);
> } else {
> av_log(s->avctx, AV_LOG_ERROR, "E-AC-3 support not compiled in\n");
> return AVERROR(ENOSYS);
> @@ -1469,6 +1418,9 @@ dependent_frame:
> av_log(avctx, AV_LOG_ERROR, "invalid frame type\n");
> }
> break;
> + case AC3_PARSE_ERROR_CHANNEL_MAP:
> + av_log(avctx, AV_LOG_ERROR, "invalid channel map\n");
> + return AVERROR_INVALIDDATA;
> case AC3_PARSE_ERROR_CRC:
> break;
> default: // Normal AVERROR do not try to recover.
> diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
> index 4042a99b80..a099264475 100644
> --- a/libavcodec/ac3dec.h
> +++ b/libavcodec/ac3dec.h
> @@ -260,11 +260,13 @@ typedef struct AC3DecodeContext {
> ///@}
> } AC3DecodeContext;
>
> +struct AC3HeaderInfo;
> +
> /**
> * Parse the E-AC-3 frame header.
> * This parses both the bit stream info and audio frame header.
> */
> -static int ff_eac3_parse_header(AC3DecodeContext *s);
> +static int ff_eac3_parse_header(AC3DecodeContext *s, const struct AC3HeaderInfo *hdr);
>
> /**
> * Decode mantissas in a single channel for the entire frame.
> diff --git a/libavcodec/ac3defs.h b/libavcodec/ac3defs.h
> index f9b1be059f..8d6a58d21f 100644
> --- a/libavcodec/ac3defs.h
> +++ b/libavcodec/ac3defs.h
> @@ -34,6 +34,8 @@
> #define AC3_CRITICAL_BANDS 50
> #define AC3_MAX_CPL_BANDS 18
>
> +#define EAC3_SR_CODE_REDUCED 3
> +
> /* pre-defined gain values */
> #define LEVEL_PLUS_3DB M_SQRT2
> #define LEVEL_PLUS_1POINT5DB 1.1892071150027209
> diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c
> index 2b3bffda6e..c5095b1917 100644
> --- a/libavcodec/eac3dec.c
> +++ b/libavcodec/eac3dec.c
> @@ -53,8 +53,6 @@ typedef enum {
> EAC3_GAQ_124
> } EAC3GaqMode;
>
> -#define EAC3_SR_CODE_REDUCED 3
> -
> static void ff_eac3_apply_spectral_extension(AC3DecodeContext *s)
> {
> int bin, bnd, ch, i;
> @@ -287,7 +285,7 @@ static void ff_eac3_decode_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch)
> }
> }
>
> -static int ff_eac3_parse_header(AC3DecodeContext *s)
> +static int ff_eac3_parse_header(AC3DecodeContext *s, const AC3HeaderInfo *hdr)
> {
> int i, blk, ch;
> int ac3_exponent_strategy, parse_aht_info, parse_spx_atten_data;
> @@ -323,11 +321,10 @@ static int ff_eac3_parse_header(AC3DecodeContext *s)
> avpriv_request_sample(s->avctx, "Reduced sampling rate");
> return AVERROR_PATCHWELCOME;
> }
> - skip_bits(gbc, 5); // skip bitstream id
>
> /* volume control params */
> for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
> - s->dialog_normalization[i] = -get_bits(gbc, 5);
> + s->dialog_normalization[i] = hdr->dialog_normalization[i];
> if (s->dialog_normalization[i] == 0) {
> s->dialog_normalization[i] = -31;
> }
> @@ -335,147 +332,30 @@ static int ff_eac3_parse_header(AC3DecodeContext *s)
> s->level_gain[i] = powf(2.0f,
> (float)(s->target_level - s->dialog_normalization[i])/6.0f);
> }
> - s->compression_exists[i] = get_bits1(gbc);
> - if (s->compression_exists[i]) {
> - s->heavy_dynamic_range[i] = AC3_HEAVY_RANGE(get_bits(gbc, 8));
> + if (hdr->compression_exists[i]) {
> + s->heavy_dynamic_range[i] = AC3_HEAVY_RANGE(hdr->heavy_dynamic_range[i]);
> }
> }
>
> - /* dependent stream channel map */
> - if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
> - if (get_bits1(gbc)) {
> - int64_t channel_layout = 0;
> - int channel_map = get_bits(gbc, 16);
> - av_log(s->avctx, AV_LOG_DEBUG, "channel_map: %0X\n", channel_map);
> -
> - for (i = 0; i < 16; i++)
> - if (channel_map & (1 << (EAC3_MAX_CHANNELS - i - 1)))
> - channel_layout |= ff_eac3_custom_channel_map_locations[i][1];
> -
> - if (av_popcount64(channel_layout) > EAC3_MAX_CHANNELS) {
> - return AVERROR_INVALIDDATA;
> - }
> - s->channel_map = channel_map;
> - }
> - }
> + s->channel_map = hdr->channel_map;
>
> /* mixing metadata */
> - if (get_bits1(gbc)) {
> - /* center and surround mix levels */
> - if (s->channel_mode > AC3_CHMODE_STEREO) {
> - s->preferred_downmix = get_bits(gbc, 2);
> - if (s->channel_mode & 1) {
> - /* if three front channels exist */
> - s->center_mix_level_ltrt = get_bits(gbc, 3);
> - s->center_mix_level = get_bits(gbc, 3);
> - }
> - if (s->channel_mode & 4) {
> - /* if a surround channel exists */
> - s->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
> - s->surround_mix_level = av_clip(get_bits(gbc, 3), 3, 7);
> - }
> - }
> -
> - /* lfe mix level */
> - if (s->lfe_on && (s->lfe_mix_level_exists = get_bits1(gbc))) {
> - s->lfe_mix_level = get_bits(gbc, 5);
> - }
> -
> - /* info for mixing with other streams and substreams */
> - if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) {
> - for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
> - // TODO: apply program scale factor
> - if (get_bits1(gbc)) {
> - skip_bits(gbc, 6); // skip program scale factor
> - }
> - }
> - if (get_bits1(gbc)) {
> - skip_bits(gbc, 6); // skip external program scale factor
> - }
> - /* skip mixing parameter data */
> - switch(get_bits(gbc, 2)) {
> - case 1: skip_bits(gbc, 5); break;
> - case 2: skip_bits(gbc, 12); break;
> - case 3: {
> - int mix_data_size = (get_bits(gbc, 5) + 2) << 3;
> - skip_bits_long(gbc, mix_data_size);
> - break;
> - }
> - }
> - /* skip pan information for mono or dual mono source */
> - if (s->channel_mode < AC3_CHMODE_STEREO) {
> - for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
> - if (get_bits1(gbc)) {
> - /* note: this is not in the ATSC A/52B specification
> - reference: ETSI TS 102 366 V1.1.1
> - section: E.1.3.1.25 */
> - skip_bits(gbc, 8); // skip pan mean direction index
> - skip_bits(gbc, 6); // skip reserved paninfo bits
> - }
> - }
> - }
> - /* skip mixing configuration information */
> - if (get_bits1(gbc)) {
> - for (blk = 0; blk < s->num_blocks; blk++) {
> - if (s->num_blocks == 1 || get_bits1(gbc)) {
> - skip_bits(gbc, 5);
> - }
> - }
> - }
> - }
> - }
> + s->preferred_downmix = hdr->preferred_downmix;
> + s->center_mix_level_ltrt = hdr->center_mix_level_ltrt;
> + s->center_mix_level = hdr->center_mix_level;
> + s->surround_mix_level_ltrt = hdr->surround_mix_level_ltrt;
> + s->surround_mix_level = hdr->surround_mix_level;
> + s->lfe_mix_level_exists = hdr->lfe_mix_level_exists;
> + s->lfe_mix_level = hdr->lfe_mix_level;
> + s->dolby_surround_mode = hdr->dolby_surround_mode;
> + s->dolby_headphone_mode = hdr->dolby_headphone_mode;
> + s->dolby_surround_ex_mode = hdr->dolby_surround_ex_mode;
>
> /* informational metadata */
> - if (get_bits1(gbc)) {
> - 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) {
> - s->dolby_surround_mode = get_bits(gbc, 2);
> - s->dolby_headphone_mode = get_bits(gbc, 2);
> - }
> - if (s->channel_mode >= AC3_CHMODE_2F2R) {
> - s->dolby_surround_ex_mode = get_bits(gbc, 2);
> - }
> - for (i = 0; i < (s->channel_mode ? 1 : 2); i++) {
> - if (get_bits1(gbc)) {
> - skip_bits(gbc, 8); // skip mix level, room type, and A/D converter type
> - }
> - }
> - if (s->bit_alloc_params.sr_code != EAC3_SR_CODE_REDUCED) {
> - skip_bits1(gbc); // skip source sample rate code
> - }
> - }
> -
> - /* converter synchronization flag
> - If frames are less than six blocks, this bit should be turned on
> - once every 6 blocks to indicate the start of a frame set.
> - reference: RFC 4598, Section 2.1.3 Frame Sets */
> - if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && s->num_blocks != 6) {
> - skip_bits1(gbc); // skip converter synchronization flag
> - }
> -
> - /* original frame size code if this stream was converted from AC-3 */
> - if (s->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT &&
> - (s->num_blocks == 6 || get_bits1(gbc))) {
> - skip_bits(gbc, 6); // skip frame size code
> - }
> + s->bitstream_mode = hdr->bitstream_mode;
>
> /* additional bitstream info */
> - if (get_bits1(gbc)) {
> - int addbsil = get_bits(gbc, 6);
> - for (i = 0; i < addbsil + 1; i++) {
> - if (i == 0) {
> - /* In this 8 bit chunk, the LSB is equal to flag_ec3_extension_type_a
> - which can be used to detect Atmos presence */
> - skip_bits(gbc, 7);
> - if (get_bits1(gbc)) {
> - s->eac3_extension_type_a = 1;
> - }
> - } else {
> - skip_bits(gbc, 8); // skip additional bit stream info
> - }
> - }
> - }
> + s->eac3_extension_type_a = hdr->eac3_extension_type_a;
>
> /* audio frame syntax flags, strategy data, and per-frame data */
>
Seems like av_ac3_parse_header() simply presumes the buffer to be padded
(like av_adts_header_parse() until 6c812a80ddfadb), although this is not
a documented requirement. Your patch will make it worse, because it
parses more.
- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-06-05 23:07 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-05 21:49 [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() James Almer
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 2/3] avformat/movenc: fix writing reserved bits in EC3SpecificBox James Almer
2025-06-05 22:07 ` Baptiste Coudurier
2025-06-05 21:49 ` [FFmpeg-devel] [PATCH 3/3] avformat/movenc: handle EAC-3 extension bits for Atmos James Almer
2025-06-05 22:09 ` Baptiste Coudurier
2025-06-05 22:15 ` [FFmpeg-devel] [PATCH 1/3] avcodec/ac3_parser: handle more header bits in ff_ac3_parse_header() Baptiste Coudurier
2025-06-05 23:07 ` Andreas Rheinhardt
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git