summaryrefslogtreecommitdiffstats
path: root/media/mp4
diff options
context:
space:
mode:
authoracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-21 00:31:27 +0000
committeracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-21 00:31:27 +0000
commit034cc134ec96cab8adcf1c1dafa95b10c449c94d (patch)
tree962675f868833a1b38d54a16f7aa85fe44ab9872 /media/mp4
parent891e1af1bbfe34c7b336ceac982df62c5625cc6e (diff)
downloadchromium_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.cc39
-rw-r--r--media/mp4/aac.h10
-rw-r--r--media/mp4/aac_unittest.cc20
-rw-r--r--media/mp4/mp4_stream_parser.cc9
-rw-r--r--media/mp4/mp4_stream_parser.h3
-rw-r--r--media/mp4/mp4_stream_parser_unittest.cc2
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) {
}