diff options
author | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-21 00:31:27 +0000 |
---|---|---|
committer | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-21 00:31:27 +0000 |
commit | 034cc134ec96cab8adcf1c1dafa95b10c449c94d (patch) | |
tree | 962675f868833a1b38d54a16f7aa85fe44ab9872 /media/mp4 | |
parent | 891e1af1bbfe34c7b336ceac982df62c5625cc6e (diff) | |
download | chromium_src-034cc134ec96cab8adcf1c1dafa95b10c449c94d.zip chromium_src-034cc134ec96cab8adcf1c1dafa95b10c449c94d.tar.gz chromium_src-034cc134ec96cab8adcf1c1dafa95b10c449c94d.tar.bz2 |
Fix MediaSource code so it can handle HE-AAC content that uses implicit signalling.
BUG=135674
TEST=Manual testing with the content in the bug.
Review URL: https://chromiumcodereview.appspot.com/10795050
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147747 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/mp4')
-rw-r--r-- | media/mp4/aac.cc | 39 | ||||
-rw-r--r-- | media/mp4/aac.h | 10 | ||||
-rw-r--r-- | media/mp4/aac_unittest.cc | 20 | ||||
-rw-r--r-- | media/mp4/mp4_stream_parser.cc | 9 | ||||
-rw-r--r-- | media/mp4/mp4_stream_parser.h | 3 | ||||
-rw-r--r-- | media/mp4/mp4_stream_parser_unittest.cc | 2 |
6 files changed, 61 insertions, 22 deletions
diff --git a/media/mp4/aac.cc b/media/mp4/aac.cc index 01c831d..2804d6b 100644 --- a/media/mp4/aac.cc +++ b/media/mp4/aac.cc @@ -4,13 +4,15 @@ #include "media/mp4/aac.h" +#include <algorithm> + #include "base/logging.h" #include "media/base/bit_reader.h" #include "media/mp4/rcheck.h" // The following conversion table is extracted from ISO 14496 Part 3 - // Table 1.16 - Sampling Frequency Index. -static const uint32 kFrequencyMap[] = { +static const int kFrequencyMap[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350 }; @@ -44,7 +46,7 @@ namespace mp4 { AAC::AAC() : profile_(0), frequency_index_(0), channel_config_(0), frequency_(0), - channel_layout_(CHANNEL_LAYOUT_UNSUPPORTED) { + extension_frequency_(0), channel_layout_(CHANNEL_LAYOUT_UNSUPPORTED) { } AAC::~AAC() { @@ -57,9 +59,10 @@ bool AAC::Parse(const std::vector<uint8>& data) { BitReader reader(&data[0], data.size()); uint8 extension_type = 0; bool ps_present = false; - uint8 extension_frequency_index; + uint8 extension_frequency_index = 0xff; frequency_ = 0; + extension_frequency_ = 0; // The following code is written according to ISO 14496 Part 3 Table 1.13 - // Syntax of AudioSpecificConfig. @@ -71,15 +74,13 @@ bool AAC::Parse(const std::vector<uint8>& data) { RCHECK(reader.ReadBits(24, &frequency_)); RCHECK(reader.ReadBits(4, &channel_config_)); - extension_frequency_index = frequency_index_; - - // Read extension configuration + // Read extension configuration. if (profile_ == 5 || profile_ == 29) { ps_present = (profile_ == 29); extension_type = 5; RCHECK(reader.ReadBits(4, &extension_frequency_index)); if (extension_frequency_index == 0xf) - RCHECK(reader.ReadBits(24, &frequency_)); + RCHECK(reader.ReadBits(24, &extension_frequency_)); RCHECK(reader.ReadBits(5, &profile_)); } @@ -101,7 +102,7 @@ bool AAC::Parse(const std::vector<uint8>& data) { RCHECK(reader.ReadBits(4, &extension_frequency_index)); if (extension_frequency_index == 0xf) - RCHECK(reader.ReadBits(24, &frequency_)); + RCHECK(reader.ReadBits(24, &extension_frequency_)); RCHECK(reader.ReadBits(11, &sync_extension_type)); @@ -115,8 +116,13 @@ bool AAC::Parse(const std::vector<uint8>& data) { } if (frequency_ == 0) { + RCHECK(frequency_index_ < arraysize(kFrequencyMap)); + frequency_ = kFrequencyMap[frequency_index_]; + } + + if (extension_frequency_ == 0 && extension_frequency_index != 0xff) { RCHECK(extension_frequency_index < arraysize(kFrequencyMap)); - frequency_ = kFrequencyMap[extension_frequency_index]; + extension_frequency_ = kFrequencyMap[extension_frequency_index]; } // When Parametric Stereo is on, mono will be played as stereo. @@ -130,8 +136,19 @@ bool AAC::Parse(const std::vector<uint8>& data) { channel_config_ <= 7; } -uint32 AAC::frequency() const { - return frequency_; +int AAC::GetOutputSamplesPerSecond(bool sbr_in_mimetype) const { + if (extension_frequency_ > 0) + return extension_frequency_; + + if (!sbr_in_mimetype) + return frequency_; + + // The following code is written according to ISO 14496 Part 3 Table 1.11 and + // Table 1.22. (Table 1.11 refers to the capping to 48000, Table 1.22 refers + // to SBR doubling the AAC sample rate.) + // TODO(acolwell) : Extend sample rate cap to 96kHz for Level 5 content. + DCHECK_GT(frequency_, 0); + return std::min(2 * frequency_, 48000); } ChannelLayout AAC::channel_layout() const { diff --git a/media/mp4/aac.h b/media/mp4/aac.h index 7a2a3f8..73464ee 100644 --- a/media/mp4/aac.h +++ b/media/mp4/aac.h @@ -32,7 +32,12 @@ class MEDIA_EXPORT AAC { // configurations. bool Parse(const std::vector<uint8>& data); - uint32 frequency() const; + // Gets the output sample rate for the AAC stream. + // |sbr_in_mimetype| should be set to true if the SBR mode is + // signalled in the mimetype. (ie mp4a.40.5 in the codecs parameter). + // Returns the samples_per_second value that should used in an + // AudioDecoderConfig. + int GetOutputSamplesPerSecond(bool sbr_in_mimetype) const; ChannelLayout channel_layout() const; // This function converts a raw AAC frame into an AAC frame with an ADTS @@ -56,7 +61,8 @@ class MEDIA_EXPORT AAC { // can be used by Chromium. They are based on the AAC specific // configuration but can be overridden by extensions in elementary // stream descriptor. - uint32 frequency_; + int frequency_; + int extension_frequency_; ChannelLayout channel_layout_; }; diff --git a/media/mp4/aac_unittest.cc b/media/mp4/aac_unittest.cc index 2f61de5..c9f888c 100644 --- a/media/mp4/aac_unittest.cc +++ b/media/mp4/aac_unittest.cc @@ -18,7 +18,7 @@ TEST(AACTest, BasicProfileTest) { data.assign(buffer, buffer + sizeof(buffer)); EXPECT_TRUE(aac.Parse(data)); - EXPECT_EQ(aac.frequency(), 44100u); + EXPECT_EQ(aac.GetOutputSamplesPerSecond(false), 44100); EXPECT_EQ(aac.channel_layout(), CHANNEL_LAYOUT_STEREO); } @@ -30,7 +30,21 @@ TEST(AACTest, ExtensionTest) { data.assign(buffer, buffer + sizeof(buffer)); EXPECT_TRUE(aac.Parse(data)); - EXPECT_EQ(aac.frequency(), 48000u); + EXPECT_EQ(aac.GetOutputSamplesPerSecond(false), 48000); + EXPECT_EQ(aac.GetOutputSamplesPerSecond(true), 48000); + EXPECT_EQ(aac.channel_layout(), CHANNEL_LAYOUT_STEREO); +} + +TEST(AACTest, TestImplicitSBR) { + AAC aac; + uint8 buffer[] = {0x13, 0x10}; + std::vector<uint8> data; + + data.assign(buffer, buffer + sizeof(buffer)); + + EXPECT_TRUE(aac.Parse(data)); + EXPECT_EQ(aac.GetOutputSamplesPerSecond(false), 24000); + EXPECT_EQ(aac.GetOutputSamplesPerSecond(true), 48000); EXPECT_EQ(aac.channel_layout(), CHANNEL_LAYOUT_STEREO); } @@ -42,7 +56,7 @@ TEST(AACTest, SixChannelTest) { data.assign(buffer, buffer + sizeof(buffer)); EXPECT_TRUE(aac.Parse(data)); - EXPECT_EQ(aac.frequency(), 48000u); + EXPECT_EQ(aac.GetOutputSamplesPerSecond(false), 48000); EXPECT_EQ(aac.channel_layout(), CHANNEL_LAYOUT_5_1); } diff --git a/media/mp4/mp4_stream_parser.cc b/media/mp4/mp4_stream_parser.cc index 45d81db..05b18c1 100644 --- a/media/mp4/mp4_stream_parser.cc +++ b/media/mp4/mp4_stream_parser.cc @@ -19,14 +19,15 @@ namespace media { namespace mp4 { -MP4StreamParser::MP4StreamParser() +MP4StreamParser::MP4StreamParser(bool has_sbr) : state_(kWaitingForInit), moof_head_(0), mdat_tail_(0), has_audio_(false), has_video_(false), audio_track_id_(0), - video_track_id_(0) { + video_track_id_(0), + has_sbr_(has_sbr) { } MP4StreamParser::~MP4StreamParser() {} @@ -187,9 +188,9 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { // Check if it is MPEG4 AAC defined in ISO 14496 Part 3. RCHECK(entry.esds.object_type == kISO_14496_3); audio_config.Initialize(kCodecAAC, entry.samplesize, - aac.channel_layout(), aac.frequency(), + aac.channel_layout(), + aac.GetOutputSamplesPerSecond(has_sbr_), NULL, 0, false); - has_audio_ = true; audio_track_id_ = track->header.track_id; } diff --git a/media/mp4/mp4_stream_parser.h b/media/mp4/mp4_stream_parser.h index a830536..a19bbcc 100644 --- a/media/mp4/mp4_stream_parser.h +++ b/media/mp4/mp4_stream_parser.h @@ -22,7 +22,7 @@ class BoxReader; class MEDIA_EXPORT MP4StreamParser : public StreamParser { public: - MP4StreamParser(); + MP4StreamParser(bool has_sbr); virtual ~MP4StreamParser(); virtual void Init(const InitCB& init_cb, const NewConfigCB& config_cb, @@ -83,6 +83,7 @@ class MEDIA_EXPORT MP4StreamParser : public StreamParser { bool has_video_; uint32 audio_track_id_; uint32 video_track_id_; + bool has_sbr_; DISALLOW_COPY_AND_ASSIGN(MP4StreamParser); }; diff --git a/media/mp4/mp4_stream_parser_unittest.cc b/media/mp4/mp4_stream_parser_unittest.cc index f5be02af..db2555f 100644 --- a/media/mp4/mp4_stream_parser_unittest.cc +++ b/media/mp4/mp4_stream_parser_unittest.cc @@ -27,7 +27,7 @@ namespace mp4 { class MP4StreamParserTest : public testing::Test { public: MP4StreamParserTest() - : parser_(new MP4StreamParser), + : parser_(new MP4StreamParser(false)), got_configs_(false) { } |