From 063ce09474bc035a743aa565f87b7f506db8ff86 Mon Sep 17 00:00:00 2001 From: servolk Date: Fri, 8 Jan 2016 16:39:51 -0800 Subject: 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-Commit-Position: refs/heads/master@{#368476} --- media/formats/mp4/es_descriptor.h | 6 ++-- media/formats/mp4/fourccs.h | 6 ++++ media/formats/mp4/mp4_stream_parser.cc | 44 ++++++++++++++++++++----- media/formats/mp4/mp4_stream_parser_unittest.cc | 23 +++++++++++++ 4 files changed, 69 insertions(+), 10 deletions(-) (limited to 'media/formats') diff --git a/media/formats/mp4/es_descriptor.h b/media/formats/mp4/es_descriptor.h index 26ca86d..9066291 100644 --- a/media/formats/mp4/es_descriptor.h +++ b/media/formats/mp4/es_descriptor.h @@ -21,8 +21,10 @@ namespace mp4 { // 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/media/formats/mp4/fourccs.h b/media/formats/mp4/fourccs.h index fd97797..38834fb 100644 --- a/media/formats/mp4/fourccs.h +++ b/media/formats/mp4/fourccs.h @@ -7,11 +7,17 @@ #include +#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/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index ee88ea1..966d250 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc @@ -220,9 +220,18 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { 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 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { } uint8_t audio_type = entry.esds.object_type; - DVLOG(1) << "audio_type " << std::hex << static_cast(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(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(audio_type) + << " does not match what is specified in the mimetype."; return false; } @@ -252,9 +269,20 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { #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(audio_type) + << " in esds."; return false; } diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc index 79f68c1..eec9824 100644 --- a/media/formats/mp4/mp4_stream_parser_unittest.cc +++ b/media/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 @@ TEST_F(MP4StreamParserTest, NaturalSizeWithPASP) { EXPECT_EQ(gfx::Size(639, 360), video_decoder_config_.natural_size()); } +#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +TEST_F(MP4StreamParserTest, DemuxingAC3) { + std::set audio_object_types; + audio_object_types.insert(kAC3); + parser_.reset(new MP4StreamParser(audio_object_types, false)); + InitializeParserAndExpectLiveness(DemuxerStream::LIVENESS_RECORDED); + scoped_refptr buffer = + ReadTestDataFile("bear-ac3-only-frag.mp4"); + EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512)); +} + +TEST_F(MP4StreamParserTest, DemuxingEAC3) { + std::set audio_object_types; + audio_object_types.insert(kEAC3); + parser_.reset(new MP4StreamParser(audio_object_types, false)); + InitializeParserAndExpectLiveness(DemuxerStream::LIVENESS_RECORDED); + scoped_refptr buffer = + ReadTestDataFile("bear-eac3-only-frag.mp4"); + EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512)); +} +#endif + } // namespace mp4 } // namespace media -- cgit v1.1