Re-add AC3/EAC3 audio demuxing support
Chrome used to have EAC3/DD+ support (crbug.com/215773),
but it was removed last year (crbug.com/334126). This CL
partially restores the old code and adds AC3 support.
This will allow AC3/EAC3 audio demuxing and can be used
for AC3/EAC3 pass-through support.
BUG=448878
Review URL: https://codereview.chromium.org/812643005
Cr-Original-Commit-Position: refs/heads/master@{#368476}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 063ce09474bc035a743aa565f87b7f506db8ff86
diff --git a/BUILD.gn b/BUILD.gn
index 7d03d4d..b356a33 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -14,8 +14,10 @@
buildflag_header("media_features") {
header = "media_features.h"
- flags =
- [ "ENABLE_MSE_MPEG2TS_STREAM_PARSER=$enable_mse_mpeg2ts_stream_parser" ]
+ flags = [
+ "ENABLE_AC3_EAC3_AUDIO_DEMUXING=$enable_ac3_eac3_audio_demuxing",
+ "ENABLE_MSE_MPEG2TS_STREAM_PARSER=$enable_mse_mpeg2ts_stream_parser",
+ ]
}
# Common configuration for targets in the media directory.
diff --git a/base/android/demuxer_stream_player_params.cc b/base/android/demuxer_stream_player_params.cc
index 2452711..3ce2a76 100644
--- a/base/android/demuxer_stream_player_params.cc
+++ b/base/android/demuxer_stream_player_params.cc
@@ -66,8 +66,10 @@
RETURN_STRING(kCodecPCM_S16BE);
RETURN_STRING(kCodecPCM_S24BE);
RETURN_STRING(kCodecOpus);
+ RETURN_STRING(kCodecEAC3);
RETURN_STRING(kCodecPCM_ALAW);
RETURN_STRING(kCodecALAC);
+ RETURN_STRING(kCodecAC3);
}
NOTREACHED();
return nullptr; // crash early
diff --git a/base/audio_decoder_config.cc b/base/audio_decoder_config.cc
index 17f039f..91dc9a6 100644
--- a/base/audio_decoder_config.cc
+++ b/base/audio_decoder_config.cc
@@ -122,8 +122,12 @@
return "opus";
case kCodecPCM_ALAW:
return "pcm_alaw";
+ case kCodecEAC3:
+ return "eac3";
case kCodecALAC:
return "alac";
+ case kCodecAC3:
+ return "ac3";
}
NOTREACHED();
return "";
diff --git a/base/audio_decoder_config.h b/base/audio_decoder_config.h
index e88c0eb..7205e56 100644
--- a/base/audio_decoder_config.h
+++ b/base/audio_decoder_config.h
@@ -36,16 +36,17 @@
kCodecPCM_S16BE = 10,
kCodecPCM_S24BE = 11,
kCodecOpus = 12,
- // kCodecEAC3 = 13,
+ kCodecEAC3 = 13,
kCodecPCM_ALAW = 14,
kCodecALAC = 15,
+ kCodecAC3 = 16,
// DO NOT ADD RANDOM AUDIO CODECS!
//
// The only acceptable time to add a new codec is if there is production code
// that uses said codec in the same CL.
// Must always be equal to the largest entry ever logged.
- kAudioCodecMax = kCodecALAC,
+ kAudioCodecMax = kCodecAC3,
};
// TODO(dalecurtis): FFmpeg API uses |bytes_per_channel| instead of
diff --git a/base/mime_util.cc b/base/mime_util.cc
index 01422b2..9abd15a 100644
--- a/base/mime_util.cc
+++ b/base/mime_util.cc
@@ -30,6 +30,8 @@
INVALID_CODEC,
PCM,
MP3,
+ AC3,
+ EAC3,
MPEG2_AAC_LC,
MPEG2_AAC_MAIN,
MPEG2_AAC_SSR,
@@ -152,6 +154,11 @@
case MimeUtil::VP8:
return true;
+ case MimeUtil::AC3:
+ case MimeUtil::EAC3:
+ // TODO(servolk): Revisit this for AC3/EAC3 support on AndroidTV
+ return false;
+
case MimeUtil::MPEG2_AAC_LC:
case MimeUtil::MPEG2_AAC_MAIN:
case MimeUtil::MPEG2_AAC_SSR:
@@ -210,6 +217,11 @@
// avc1.6400xx - H.264 High
static const char kMP4AudioCodecsExpression[] =
"mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.02,mp4a.40.5,"
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ // Only one variant each of ac3 and eac3 codec string is sufficient here,
+ // since these strings are parsed and mapped to MimeUtil::Codec enum values.
+ "ac-3,ec-3,"
+#endif
"mp4a.40.05,mp4a.40.29";
static const char kMP4VideoCodecsExpression[] =
// This is not a complete list of supported avc1 codecs. It is simply used
@@ -225,6 +237,11 @@
"hev1.1.6.L93.B0,"
#endif
"mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.02,mp4a.40.5,"
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ // Only one variant each of ac3 and eac3 codec string is sufficient here,
+ // since these strings are parsed and mapped to MimeUtil::Codec enum values.
+ "ac-3,ec-3,"
+#endif
"mp4a.40.05,mp4a.40.29";
#endif // USE_PROPRIETARY_CODECS
@@ -291,6 +308,20 @@
{"mp4a.40.5", MimeUtil::MPEG4_AAC_SBR_v1},
{"mp4a.40.05", MimeUtil::MPEG4_AAC_SBR_v1},
{"mp4a.40.29", MimeUtil::MPEG4_AAC_SBR_PS_v2},
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6 codec ids are
+ // valid according to RFC 6381 section 3.3, 3.4. Lower-case oti (mp4a.a5 and
+ // mp4a.a6) should be rejected. But we used to allow those in older versions
+ // of Chromecast firmware and some apps (notably MPL) depend on those codec
+ // types being supported, so they should be allowed for now
+ // (crbug.com/564960).
+ {"ac-3", MimeUtil::AC3},
+ {"mp4a.a5", MimeUtil::AC3},
+ {"mp4a.A5", MimeUtil::AC3},
+ {"ec-3", MimeUtil::EAC3},
+ {"mp4a.a6", MimeUtil::EAC3},
+ {"mp4a.A6", MimeUtil::EAC3},
+#endif
{"vorbis", MimeUtil::VORBIS},
{"opus", MimeUtil::OPUS},
{"vp8", MimeUtil::VP8},
@@ -638,6 +669,8 @@
bool MimeUtil::IsCodecProprietary(Codec codec) const {
switch (codec) {
case INVALID_CODEC:
+ case AC3:
+ case EAC3:
case MP3:
case MPEG2_AAC_LC:
case MPEG2_AAC_MAIN:
diff --git a/ffmpeg/ffmpeg_common.cc b/ffmpeg/ffmpeg_common.cc
index 3d3a8b8..b65cedd 100644
--- a/ffmpeg/ffmpeg_common.cc
+++ b/ffmpeg/ffmpeg_common.cc
@@ -14,6 +14,7 @@
#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_util.h"
+#include "media/media_features.h"
namespace media {
@@ -67,6 +68,12 @@
switch (codec_id) {
case AV_CODEC_ID_AAC:
return kCodecAAC;
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ case AV_CODEC_ID_AC3:
+ return kCodecAC3;
+ case AV_CODEC_ID_EAC3:
+ return kCodecEAC3;
+#endif
case AV_CODEC_ID_MP3:
return kCodecMP3;
case AV_CODEC_ID_VORBIS:
@@ -309,18 +316,37 @@
codec_context->channel_layout, codec_context->channels);
int sample_rate = codec_context->sample_rate;
- if (codec == kCodecOpus) {
- // |codec_context->sample_fmt| is not set by FFmpeg because Opus decoding is
- // not enabled in FFmpeg. It doesn't matter what value is set here, so long
- // as it's valid, the true sample format is selected inside the decoder.
- sample_format = kSampleFormatF32;
+ switch (codec) {
+ case kCodecOpus:
+ // |codec_context->sample_fmt| is not set by FFmpeg because Opus decoding
+ // is not enabled in FFmpeg. It doesn't matter what value is set here, so
+ // long as it's valid, the true sample format is selected inside the
+ // decoder.
+ sample_format = kSampleFormatF32;
- // Always use 48kHz for OPUS. Technically we should match to the highest
- // supported hardware sample rate among [8, 12, 16, 24, 48] kHz, but we
- // don't know the hardware sample rate at this point and those rates are
- // rarely used for output. See the "Input Sample Rate" section of the spec:
- // http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
- sample_rate = 48000;
+ // Always use 48kHz for OPUS. Technically we should match to the highest
+ // supported hardware sample rate among [8, 12, 16, 24, 48] kHz, but we
+ // don't know the hardware sample rate at this point and those rates are
+ // rarely used for output. See the "Input Sample Rate" section of the
+ // spec: http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
+ sample_rate = 48000;
+ break;
+
+ // For AC3/EAC3 we enable only demuxing, but not decoding, so FFmpeg does
+ // not fill |sample_fmt|.
+ case kCodecAC3:
+ case kCodecEAC3:
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ // The spec for AC3/EAC3 audio is ETSI TS 102 366. According to sections
+ // F.3.1 and F.5.1 in that spec the sample_format for AC3/EAC3 must be 16.
+ sample_format = kSampleFormatS16;
+#else
+ NOTREACHED();
+#endif
+ break;
+
+ default:
+ break;
}
base::TimeDelta seek_preroll;
@@ -353,9 +379,19 @@
seek_preroll,
codec_context->delay);
- if (codec != kCodecOpus) {
- DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8,
- config->bits_per_channel());
+ // Verify that AudioConfig.bits_per_channel was calculated correctly for
+ // codecs that have |sample_fmt| set by FFmpeg.
+ switch (codec) {
+ case kCodecOpus:
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ case kCodecAC3:
+ case kCodecEAC3:
+#endif
+ break;
+ default:
+ DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8,
+ config->bits_per_channel());
+ break;
}
return true;
diff --git a/filters/ffmpeg_demuxer_unittest.cc b/filters/ffmpeg_demuxer_unittest.cc
index 1869b7a..2d1a868 100644
--- a/filters/ffmpeg_demuxer_unittest.cc
+++ b/filters/ffmpeg_demuxer_unittest.cc
@@ -24,6 +24,7 @@
#include "media/filters/ffmpeg_demuxer.h"
#include "media/filters/file_data_source.h"
#include "media/formats/mp4/avc.h"
+#include "media/media_features.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::AnyNumber;
@@ -1132,4 +1133,36 @@
}
#endif
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+TEST_F(FFmpegDemuxerTest, Read_AC3_Audio) {
+ CreateDemuxer("bear-ac3-only-frag.mp4");
+ InitializeDemuxer();
+
+ // Attempt a read from the audio stream and run the message loop until done.
+ DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
+
+ // Read the first two frames and check that we are getting expected data
+ audio->Read(NewReadCB(FROM_HERE, 834, 0, true));
+ message_loop_.Run();
+
+ audio->Read(NewReadCB(FROM_HERE, 836, 34830, true));
+ message_loop_.Run();
+}
+
+TEST_F(FFmpegDemuxerTest, Read_EAC3_Audio) {
+ CreateDemuxer("bear-eac3-only-frag.mp4");
+ InitializeDemuxer();
+
+ // Attempt a read from the audio stream and run the message loop until done.
+ DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
+
+ // Read the first two frames and check that we are getting expected data
+ audio->Read(NewReadCB(FROM_HERE, 870, 0, true));
+ message_loop_.Run();
+
+ audio->Read(NewReadCB(FROM_HERE, 872, 34830, true));
+ message_loop_.Run();
+}
+#endif // ENABLE_AC3_EAC3_AUDIO_DEMUXING
+
} // namespace media
diff --git a/filters/stream_parser_factory.cc b/filters/stream_parser_factory.cc
index db626c5..43e0079 100644
--- a/filters/stream_parser_factory.cc
+++ b/filters/stream_parser_factory.cc
@@ -58,7 +58,8 @@
HISTOGRAM_MP3,
HISTOGRAM_OPUS,
HISTOGRAM_HEVC,
- HISTOGRAM_MAX = HISTOGRAM_HEVC // Must be equal to largest logged entry.
+ HISTOGRAM_AC3,
+ HISTOGRAM_MAX = HISTOGRAM_AC3 // Must be equal to largest logged entry.
};
const char* pattern;
@@ -166,6 +167,26 @@
static const CodecInfo kMPEG2AACLCCodecInfo = { "mp4a.67", CodecInfo::AUDIO,
NULL,
CodecInfo::HISTOGRAM_MPEG2AAC };
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+// The 'ac-3' and 'ec-3' are mime codec ids for AC3 and EAC3 according to
+// http://www.mp4ra.org/codecs.html
+// The object types for AC3 and EAC3 in MP4 container are 0xa5 and 0xa6, so
+// according to RFC 6381 this corresponds to codec ids 'mp4a.A5' and 'mp4a.A6'.
+// Codec ids with lower case oti (mp4a.a5 and mp4a.a6) are supported for
+// backward compatibility.
+static const CodecInfo kAC3CodecInfo1 = {"ac-3", CodecInfo::AUDIO, NULL,
+ CodecInfo::HISTOGRAM_AC3};
+static const CodecInfo kAC3CodecInfo2 = {"mp4a.a5", CodecInfo::AUDIO, NULL,
+ CodecInfo::HISTOGRAM_AC3};
+static const CodecInfo kAC3CodecInfo3 = {"mp4a.A5", CodecInfo::AUDIO, NULL,
+ CodecInfo::HISTOGRAM_AC3};
+static const CodecInfo kEAC3CodecInfo1 = {"ec-3", CodecInfo::AUDIO, NULL,
+ CodecInfo::HISTOGRAM_EAC3};
+static const CodecInfo kEAC3CodecInfo2 = {"mp4a.a6", CodecInfo::AUDIO, NULL,
+ CodecInfo::HISTOGRAM_EAC3};
+static const CodecInfo kEAC3CodecInfo3 = {"mp4a.A6", CodecInfo::AUDIO, NULL,
+ CodecInfo::HISTOGRAM_EAC3};
+#endif
static const CodecInfo* kVideoMP4Codecs[] = {
&kH264AVC1CodecInfo,
@@ -179,11 +200,17 @@
NULL
};
-static const CodecInfo* kAudioMP4Codecs[] = {
- &kMPEG4AACCodecInfo,
- &kMPEG2AACLCCodecInfo,
- NULL
-};
+static const CodecInfo* kAudioMP4Codecs[] = {&kMPEG4AACCodecInfo,
+ &kMPEG2AACLCCodecInfo,
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ &kAC3CodecInfo1,
+ &kAC3CodecInfo2,
+ &kAC3CodecInfo3,
+ &kEAC3CodecInfo1,
+ &kEAC3CodecInfo2,
+ &kEAC3CodecInfo3,
+#endif
+ NULL};
static StreamParser* BuildMP4Parser(const std::vector<std::string>& codecs,
const scoped_refptr<MediaLog>& media_log) {
@@ -205,6 +232,16 @@
has_sbr = true;
break;
}
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ } else if (base::MatchPattern(codec_id, kAC3CodecInfo1.pattern) ||
+ base::MatchPattern(codec_id, kAC3CodecInfo2.pattern) ||
+ base::MatchPattern(codec_id, kAC3CodecInfo3.pattern)) {
+ audio_object_types.insert(mp4::kAC3);
+ } else if (base::MatchPattern(codec_id, kEAC3CodecInfo1.pattern) ||
+ base::MatchPattern(codec_id, kEAC3CodecInfo2.pattern) ||
+ base::MatchPattern(codec_id, kEAC3CodecInfo3.pattern)) {
+ audio_object_types.insert(mp4::kEAC3);
+#endif
}
}
diff --git a/formats/mp4/es_descriptor.h b/formats/mp4/es_descriptor.h
index 26ca86d..9066291 100644
--- a/formats/mp4/es_descriptor.h
+++ b/formats/mp4/es_descriptor.h
@@ -21,8 +21,10 @@
// objectTypeIndication Values. Only values currently in use are included.
enum ObjectType {
kForbidden = 0,
- kISO_14496_3 = 0x40, // MPEG4 AAC
- kISO_13818_7_AAC_LC = 0x67 // MPEG2 AAC-LC
+ kISO_14496_3 = 0x40, // MPEG4 AAC
+ kISO_13818_7_AAC_LC = 0x67, // MPEG2 AAC-LC
+ kAC3 = 0xa5, // AC3
+ kEAC3 = 0xa6 // EAC3 / Dolby Digital Plus
};
// This class parse object type and decoder specific information from an
diff --git a/formats/mp4/fourccs.h b/formats/mp4/fourccs.h
index fd97797..38834fb 100644
--- a/formats/mp4/fourccs.h
+++ b/formats/mp4/fourccs.h
@@ -7,11 +7,17 @@
#include <string>
+#include "media/media_features.h"
+
namespace media {
namespace mp4 {
enum FourCC {
FOURCC_NULL = 0,
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ FOURCC_AC3 = 0x61632d33, // "ac-3"
+ FOURCC_EAC3 = 0x65632d33, // "ec-3"
+#endif
FOURCC_AVC1 = 0x61766331,
FOURCC_AVC3 = 0x61766333,
FOURCC_AVCC = 0x61766343,
diff --git a/formats/mp4/mp4_stream_parser.cc b/formats/mp4/mp4_stream_parser.cc
index ee88ea1..966d250 100644
--- a/formats/mp4/mp4_stream_parser.cc
+++ b/formats/mp4/mp4_stream_parser.cc
@@ -220,9 +220,18 @@
const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx];
const AAC& aac = entry.esds.aac;
- if (!(entry.format == FOURCC_MP4A ||
- (entry.format == FOURCC_ENCA &&
- entry.sinf.format.format == FOURCC_MP4A))) {
+ // For encrypted audio streams entry.format is FOURCC_ENCA and actual
+ // format is in entry.sinf.format.format.
+ FourCC audio_format = (entry.format == FOURCC_ENCA)
+ ? entry.sinf.format.format
+ : entry.format;
+
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ if (audio_format != FOURCC_MP4A && audio_format != FOURCC_AC3 &&
+ audio_format != FOURCC_EAC3) {
+#else
+ if (audio_format != FOURCC_MP4A) {
+#endif
MEDIA_LOG(ERROR, media_log_) << "Unsupported audio format 0x"
<< std::hex << entry.format
<< " in stsd box.";
@@ -230,12 +239,20 @@
}
uint8_t audio_type = entry.esds.object_type;
- DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type);
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ if (audio_type == kForbidden) {
+ if (audio_format == FOURCC_AC3)
+ audio_type = kAC3;
+ if (audio_format == FOURCC_EAC3)
+ audio_type = kEAC3;
+ }
+#endif
+ DVLOG(1) << "audio_type 0x" << std::hex << static_cast<int>(audio_type);
if (audio_object_types_.find(audio_type) == audio_object_types_.end()) {
MEDIA_LOG(ERROR, media_log_)
- << "audio object type 0x" << std::hex << audio_type
- << " does not match what is specified in the"
- << " mimetype.";
+ << "audio object type 0x" << std::hex
+ << static_cast<int>(audio_type)
+ << " does not match what is specified in the mimetype.";
return false;
}
@@ -252,9 +269,20 @@
#if defined(OS_ANDROID)
extra_data = aac.codec_specific_data();
#endif
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+ } else if (audio_type == kAC3) {
+ codec = kCodecAC3;
+ channel_layout = GuessChannelLayout(entry.channelcount);
+ sample_per_second = entry.samplerate;
+ } else if (audio_type == kEAC3) {
+ codec = kCodecEAC3;
+ channel_layout = GuessChannelLayout(entry.channelcount);
+ sample_per_second = entry.samplerate;
+#endif
} else {
MEDIA_LOG(ERROR, media_log_) << "Unsupported audio object type 0x"
- << std::hex << audio_type << " in esds.";
+ << std::hex << static_cast<int>(audio_type)
+ << " in esds.";
return false;
}
diff --git a/formats/mp4/mp4_stream_parser_unittest.cc b/formats/mp4/mp4_stream_parser_unittest.cc
index 79f68c1..eec9824 100644
--- a/formats/mp4/mp4_stream_parser_unittest.cc
+++ b/formats/mp4/mp4_stream_parser_unittest.cc
@@ -22,6 +22,7 @@
#include "media/base/video_decoder_config.h"
#include "media/formats/mp4/es_descriptor.h"
#include "media/formats/mp4/mp4_stream_parser.h"
+#include "media/media_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -341,5 +342,27 @@
EXPECT_EQ(gfx::Size(639, 360), video_decoder_config_.natural_size());
}
+#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
+TEST_F(MP4StreamParserTest, DemuxingAC3) {
+ std::set<int> audio_object_types;
+ audio_object_types.insert(kAC3);
+ parser_.reset(new MP4StreamParser(audio_object_types, false));
+ InitializeParserAndExpectLiveness(DemuxerStream::LIVENESS_RECORDED);
+ scoped_refptr<DecoderBuffer> buffer =
+ ReadTestDataFile("bear-ac3-only-frag.mp4");
+ EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
+}
+
+TEST_F(MP4StreamParserTest, DemuxingEAC3) {
+ std::set<int> audio_object_types;
+ audio_object_types.insert(kEAC3);
+ parser_.reset(new MP4StreamParser(audio_object_types, false));
+ InitializeParserAndExpectLiveness(DemuxerStream::LIVENESS_RECORDED);
+ scoped_refptr<DecoderBuffer> buffer =
+ ReadTestDataFile("bear-eac3-only-frag.mp4");
+ EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
+}
+#endif
+
} // namespace mp4
} // namespace media
diff --git a/media.gyp b/media.gyp
index 620a77a..b8d7b9e 100644
--- a/media.gyp
+++ b/media.gyp
@@ -33,9 +33,13 @@
}, {
'use_low_memory_buffer%': 0,
}],
- ['chromecast == 1', {
+ ['proprietary_codecs==1 and chromecast==1', {
+ # Enable AC3/EAC3 audio demuxing. Actual decoding must be provided by
+ # the platform (or HDMI sink in Chromecast for audio pass-through case).
+ 'enable_ac3_eac3_audio_demuxing%': 1,
'enable_mse_mpeg2ts_stream_parser%': 1,
}, {
+ 'enable_ac3_eac3_audio_demuxing%': 0,
'enable_mse_mpeg2ts_stream_parser%': 0,
}],
['chromecast==1', {
@@ -59,6 +63,7 @@
'variables': {
'buildflag_header_path': 'media/media_features.h',
'buildflag_flags': [
+ "ENABLE_AC3_EAC3_AUDIO_DEMUXING=<(enable_ac3_eac3_audio_demuxing)",
"ENABLE_MSE_MPEG2TS_STREAM_PARSER=<(enable_mse_mpeg2ts_stream_parser)",
],
},
diff --git a/media_options.gni b/media_options.gni
index fa01d0f..635c4d2 100644
--- a/media_options.gni
+++ b/media_options.gni
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/chromecast_build.gni")
+import("//build/config/features.gni")
import("//build/config/headless_build.gni")
declare_args() {
@@ -48,7 +49,12 @@
# Use low-memory buffers on non-Android builds of Chromecast.
use_low_memory_buffer = is_chromecast && !is_android
- enable_mse_mpeg2ts_stream_parser = is_chromecast
+ # Enables AC3/EAC3 audio demuxing. This is enabled only on Chromecast, since
+ # it only provides demuxing, and is only useful for AC3/EAC3 audio
+ # pass-through to HDMI sink on Chromecast.
+ enable_ac3_eac3_audio_demuxing = proprietary_codecs && is_chromecast
+
+ enable_mse_mpeg2ts_stream_parser = proprietary_codecs && is_chromecast
# Enable HEVC/H265 demuxing. Actual decoding must be provided by the
# platform. Enable by default for Chromecast.
diff --git a/mojo/interfaces/media_types.mojom b/mojo/interfaces/media_types.mojom
index befd80a..3890b2a 100644
--- a/mojo/interfaces/media_types.mojom
+++ b/mojo/interfaces/media_types.mojom
@@ -29,10 +29,11 @@
PCM_S16BE = 10,
PCM_S24BE = 11,
Opus = 12,
- // EAC3 = 13,
+ EAC3 = 13,
PCM_ALAW = 14,
ALAC = 15,
- MAX = ALAC,
+ AC3 = 16,
+ MAX = AC3,
};
// See media/base/channel_layout.h for descriptions.
diff --git a/mojo/services/media_type_converters.cc b/mojo/services/media_type_converters.cc
index d3cc1e3..679accf 100644
--- a/mojo/services/media_type_converters.cc
+++ b/mojo/services/media_type_converters.cc
@@ -54,8 +54,10 @@
ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_S16BE);
ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_S24BE);
ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, Opus);
+ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, EAC3);
ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, PCM_ALAW);
ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, ALAC);
+ASSERT_ENUM_EQ(AudioCodec, kCodec, AUDIO_CODEC_, AC3);
ASSERT_ENUM_EQ_RAW(AudioCodec, kAudioCodecMax, AUDIO_CODEC_MAX);
// ChannelLayout.
diff --git a/test/data/README b/test/data/README
index 773ff84..8ab8273 100644
--- a/test/data/README
+++ b/test/data/README
@@ -196,4 +196,13 @@
media/test/data/bear-640x360-non_square_pixel-without_pasp.mp4
Size in TKHD is (639.2x360) and size in STSD is (470x360). No PASP box is
- present.
\ No newline at end of file
+ present.
+
+// MP4 files with AC3 and EAC3 audio
+media/test/data/bear-ac3-only-frag.mp4
+ AC3 audio in framented MP4, generated with
+ ffmpeg -i bear.ac3 -acodec copy -movflags frag_keyframe bear-ac3-only-frag.mp4
+
+media/test/data/bear-eac3-only-frag.mp4
+ EAC3 audio in framented MP4, generated with
+ ffmpeg -i bear.eac3 -acodec copy -movflags frag_keyframe bear-eac3-only-frag.mp4
diff --git a/test/data/bear-ac3-only-frag.mp4 b/test/data/bear-ac3-only-frag.mp4
new file mode 100644
index 0000000..669c407
--- /dev/null
+++ b/test/data/bear-ac3-only-frag.mp4
Binary files differ
diff --git a/test/data/bear-eac3-only-frag.mp4 b/test/data/bear-eac3-only-frag.mp4
new file mode 100644
index 0000000..1530fd1
--- /dev/null
+++ b/test/data/bear-eac3-only-frag.mp4
Binary files differ