diff options
author | stevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-12 17:26:56 +0000 |
---|---|---|
committer | stevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-12 17:26:56 +0000 |
commit | b859d81f7e6fdd179fc20f1afc6e0a477fda7b31 (patch) | |
tree | 2f9dec6df896983e1d0ea1a5ca49da9c64931e53 | |
parent | 128daf6bc3b24d366cf8f252ebe20f70818ea1b7 (diff) | |
download | chromium_src-b859d81f7e6fdd179fc20f1afc6e0a477fda7b31.zip chromium_src-b859d81f7e6fdd179fc20f1afc6e0a477fda7b31.tar.gz chromium_src-b859d81f7e6fdd179fc20f1afc6e0a477fda7b31.tar.bz2 |
Revert 250730 "Introduce ADTSStreamParser. Factorize MP3StreamPa..."
Causing compile failure on mac: http://build.chromium.org/p/chromium.chrome/builders/Google%20Chrome%20Mac/builds/16420/steps/compile/logs/stdio
> Introduce ADTSStreamParser. Factorize MP3StreamParser and tests.
>
> Factorizes MP3StreamParser into MPEGAudioStreamParserBase for reuse
> with a new ADTSStreamParser. In the process, also factorizes the
> MP3StreamParserTest into a new test helper StreamParserTest for
> reuse with the ADTSStreamParserTest.
>
> Introduces an adts_constants.{cc,h} to remove duplicate constants
> across the AAC and ES ADTS parsers. Fixes a channel layout bug in
> the AAC parser.
>
> sfx.adts test file will be landed manually in a separate change.
>
> BUG=341648,340426
> TEST=new unittests pass!
>
> Review URL: https://codereview.chromium.org/120503006
TBR=dalecurtis@chromium.org
Review URL: https://codereview.chromium.org/160593002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@250736 0039d316-1c4b-4281-b951-d872f2087c98
23 files changed, 592 insertions, 951 deletions
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 104dda2..f6b4832 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -1014,7 +1014,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kEnableAcceleratedOverflowScroll, switches::kEnableAcceleratedScrollableFrames, switches::kEnableAccessibilityLogging, - switches::kEnableADTSStreamParser, switches::kEnableBeginFrameScheduling, switches::kEnableBrowserPluginForAllViewTypes, switches::kEnableCompositedScrollingForFrames, diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 7377fb9..9ea08a1 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc @@ -18,9 +18,6 @@ const char kDisableVp8AlphaPlayback[] = "disable-vp8-alpha-playback"; // Set number of threads to use for video decoding. const char kVideoThreads[] = "video-threads"; -// Enables ADTS stream parser for Media Source Extensions. -const char kEnableADTSStreamParser[] = "enable-adts-stream-parser"; - // Enables MP3 stream parser for Media Source Extensions. const char kEnableMP3StreamParser[] = "enable-mp3-stream-parser"; diff --git a/media/base/media_switches.h b/media/base/media_switches.h index c1f5588..56db618 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h @@ -20,7 +20,6 @@ MEDIA_EXPORT extern const char kDisableVp8AlphaPlayback[]; MEDIA_EXPORT extern const char kVideoThreads[]; -MEDIA_EXPORT extern const char kEnableADTSStreamParser[]; MEDIA_EXPORT extern const char kEnableMP3StreamParser[]; #if defined(OS_ANDROID) diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc index 4b7ee5a..6b22f4d 100644 --- a/media/filters/stream_parser_factory.cc +++ b/media/filters/stream_parser_factory.cc @@ -10,8 +10,7 @@ #include "base/strings/string_util.h" #include "media/base/media_log.h" #include "media/base/media_switches.h" -#include "media/formats/mpeg/adts_stream_parser.h" -#include "media/formats/mpeg/mp3_stream_parser.h" +#include "media/formats/mp3/mp3_stream_parser.h" #include "media/formats/webm/webm_stream_parser.h" #if defined(OS_ANDROID) @@ -194,18 +193,6 @@ static StreamParser* BuildMP3Parser( return new MP3StreamParser(); } -static const CodecInfo kADTSCodecInfo = { NULL, CodecInfo::AUDIO, NULL, - CodecInfo::HISTOGRAM_MPEG4AAC }; -static const CodecInfo* kAudioADTSCodecs[] = { - &kADTSCodecInfo, - NULL -}; - -static StreamParser* BuildADTSParser( - const std::vector<std::string>& codecs, const LogCB& log_cb) { - return new ADTSStreamParser(); -} - #if defined(ENABLE_MPEG2TS_STREAM_PARSER) static const CodecInfo* kVideoMP2TCodecs[] = { &kH264AVC1CodecInfo, @@ -236,7 +223,6 @@ static const SupportedTypeInfo kSupportedTypeInfo[] = { { "video/webm", &BuildWebMParser, kVideoWebMCodecs }, { "audio/webm", &BuildWebMParser, kAudioWebMCodecs }, #if defined(USE_PROPRIETARY_CODECS) - { "audio/aac", &BuildADTSParser, kAudioADTSCodecs }, { "audio/mpeg", &BuildMP3Parser, kAudioMP3Codecs }, { "video/mp4", &BuildMP4Parser, kVideoMP4Codecs }, { "audio/mp4", &BuildMP4Parser, kAudioMP4Codecs }, @@ -322,6 +308,7 @@ static bool CheckTypeAndCodecs( const SupportedTypeInfo& type_info = kSupportedTypeInfo[i]; if (type == type_info.type) { if (codecs.empty()) { + #if defined(USE_PROPRIETARY_CODECS) if (type_info.codecs == kAudioMP3Codecs && !CommandLine::ForCurrentProcess()->HasSwitch( @@ -329,13 +316,6 @@ static bool CheckTypeAndCodecs( DVLOG(1) << "MP3StreamParser is not enabled."; return false; } - - if (type_info.codecs == kAudioADTSCodecs && - !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableADTSStreamParser)) { - DVLOG(1) << "ADTSStreamParser is not enabled."; - return false; - } #endif const CodecInfo* codec_info = type_info.codecs[0]; diff --git a/media/formats/common/stream_parser_test_base.cc b/media/formats/common/stream_parser_test_base.cc deleted file mode 100644 index 40d39d6..0000000 --- a/media/formats/common/stream_parser_test_base.cc +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/formats/common/stream_parser_test_base.h" - -#include "base/bind.h" -#include "media/base/test_data_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { - -static std::string BufferQueueToString( - const StreamParser::BufferQueue& buffers) { - std::stringstream ss; - - ss << "{"; - for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); - itr != buffers.end(); - ++itr) { - ss << " " << (*itr)->timestamp().InMilliseconds(); - if ((*itr)->IsKeyframe()) - ss << "K"; - } - ss << " }"; - - return ss.str(); -} - -StreamParserTestBase::StreamParserTestBase( - scoped_ptr<StreamParser> stream_parser) - : parser_(stream_parser.Pass()) {} - -StreamParserTestBase::~StreamParserTestBase() {} - -std::string StreamParserTestBase::ParseFile(const std::string& filename, - int append_bytes) { - results_stream_.clear(); - InitializeParser(); - - scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); - EXPECT_TRUE( - AppendDataInPieces(buffer->data(), buffer->data_size(), append_bytes)); - return results_stream_.str(); -} - -void StreamParserTestBase::InitializeParser() { - parser_->Init( - base::Bind(&StreamParserTestBase::OnInitDone, base::Unretained(this)), - base::Bind(&StreamParserTestBase::OnNewConfig, base::Unretained(this)), - base::Bind(&StreamParserTestBase::OnNewBuffers, base::Unretained(this)), - true, - base::Bind(&StreamParserTestBase::OnKeyNeeded, base::Unretained(this)), - base::Bind(&StreamParserTestBase::OnNewSegment, base::Unretained(this)), - base::Bind(&StreamParserTestBase::OnEndOfSegment, base::Unretained(this)), - LogCB()); -} - -bool StreamParserTestBase::AppendDataInPieces(const uint8* data, - size_t length, - size_t piece_size) { - const uint8* start = data; - const uint8* end = data + length; - while (start < end) { - size_t append_size = std::min(piece_size, static_cast<size_t>(end - start)); - if (!parser_->Parse(start, append_size)) - return false; - start += append_size; - } - return true; -} - -void StreamParserTestBase::OnInitDone(bool success, base::TimeDelta duration) { - DVLOG(1) << __FUNCTION__ << "(" << success << ", " - << duration.InMilliseconds() << ")"; -} - -bool StreamParserTestBase::OnNewConfig( - const AudioDecoderConfig& audio_config, - const VideoDecoderConfig& video_config, - const StreamParser::TextTrackConfigMap& text_config) { - DVLOG(1) << __FUNCTION__ << "(" << audio_config.IsValidConfig() << ", " - << video_config.IsValidConfig() << ")"; - EXPECT_TRUE(audio_config.IsValidConfig()); - EXPECT_FALSE(video_config.IsValidConfig()); - return true; -} - -bool StreamParserTestBase::OnNewBuffers( - const StreamParser::BufferQueue& audio_buffers, - const StreamParser::BufferQueue& video_buffers, - const StreamParser::TextBufferQueueMap& text_map) { - EXPECT_FALSE(audio_buffers.empty()); - EXPECT_TRUE(video_buffers.empty()); - - // TODO(wolenetz/acolwell): Add text track support to more MSE parsers. See - // http://crbug.com/336926. - EXPECT_TRUE(text_map.empty()); - - const std::string buffers_str = BufferQueueToString(audio_buffers); - DVLOG(1) << __FUNCTION__ << " : " << buffers_str; - results_stream_ << buffers_str; - return true; -} - -void StreamParserTestBase::OnKeyNeeded(const std::string& type, - const std::vector<uint8>& init_data) { - DVLOG(1) << __FUNCTION__ << "(" << type << ", " << init_data.size() << ")"; -} - -void StreamParserTestBase::OnNewSegment() { - DVLOG(1) << __FUNCTION__; - results_stream_ << "NewSegment"; -} - -void StreamParserTestBase::OnEndOfSegment() { - DVLOG(1) << __FUNCTION__; - results_stream_ << "EndOfSegment"; -} - -} // namespace media diff --git a/media/formats/common/stream_parser_test_base.h b/media/formats/common/stream_parser_test_base.h deleted file mode 100644 index 4e26274..0000000 --- a/media/formats/common/stream_parser_test_base.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_FORMATS_COMMON_STREAM_PARSER_TEST_BASE_H_ -#define MEDIA_FORMATS_COMMON_STREAM_PARSER_TEST_BASE_H_ - -#include "base/memory/scoped_ptr.h" -#include "media/base/audio_decoder_config.h" -#include "media/base/stream_parser.h" -#include "media/base/stream_parser_buffer.h" -#include "media/base/text_track_config.h" -#include "media/base/video_decoder_config.h" - -namespace media { - -// Test helper for verifying StreamParser behavior. -class StreamParserTestBase { - public: - explicit StreamParserTestBase(scoped_ptr<StreamParser> stream_parser); - virtual ~StreamParserTestBase(); - - protected: - // Chunks a given parser appropriate file. Appends |append_bytes| at a time - // until the file is exhausted. Returns a coded string representing the - // segments and timestamps of the extracted frames. - // - // The start of each media segment is designated by "NewSegment", similarly - // the end of each segment by "EndOfSegment". Segments end when one or more - // frames are parsed from an append. If the append contains a partial frame - // the segment will continue into the next append. - // - // Parsed frame(s) are represented as "{ xxK yyK zzK }" Where xx, yy, and zz - // are the timestamps in milliseconds of each parsed frame. For example: - // - // "NewSegment{ 0K 23K 46K }EndOfSegment" - // "NewSegment{ 0K }{ 23K }{ 46K }EndOfSegment" - // "NewSegment{ 0K }{ 23K }EndOfSegmentNewSegment{ 46K }EndOfSegment" - // - std::string ParseFile(const std::string& filename, int append_bytes); - - private: - void InitializeParser(); - bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size); - - void OnInitDone(bool success, base::TimeDelta duration); - bool OnNewConfig(const AudioDecoderConfig& audio_config, - const VideoDecoderConfig& video_config, - const StreamParser::TextTrackConfigMap& text_config); - bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, - const StreamParser::BufferQueue& video_buffers, - const StreamParser::TextBufferQueueMap& text_map); - void OnKeyNeeded(const std::string& type, - const std::vector<uint8>& init_data); - void OnNewSegment(); - void OnEndOfSegment(); - - scoped_ptr<StreamParser> parser_; - std::stringstream results_stream_; - - DISALLOW_COPY_AND_ASSIGN(StreamParserTestBase); -}; - -} // namespace media - -#endif // MEDIA_FORMATS_COMMON_STREAM_PARSER_TEST_BASE_H_
\ No newline at end of file diff --git a/media/formats/mp2t/es_parser_adts.cc b/media/formats/mp2t/es_parser_adts.cc index 2154c9e..5a47163 100644 --- a/media/formats/mp2t/es_parser_adts.cc +++ b/media/formats/mp2t/es_parser_adts.cc @@ -15,9 +15,43 @@ #include "media/base/channel_layout.h" #include "media/base/stream_parser_buffer.h" #include "media/formats/mp2t/mp2t_common.h" -#include "media/formats/mpeg/adts_constants.h" -namespace media { +// Adts header is at least 7 bytes (can be 9 bytes). +static const int kAdtsHeaderMinSize = 7; + +static const int adts_frequency_table[16] = { + 96000, + 88200, + 64000, + 48000, + 44100, + 32000, + 24000, + 22050, + 16000, + 12000, + 11025, + 8000, + 7350, + 0, + 0, + 0, +}; +static const int kMaxSupportedFrequencyIndex = 12; + +static media::ChannelLayout adts_channel_layout[8] = { + media::CHANNEL_LAYOUT_NONE, + media::CHANNEL_LAYOUT_MONO, + media::CHANNEL_LAYOUT_STEREO, + media::CHANNEL_LAYOUT_SURROUND, + media::CHANNEL_LAYOUT_4_0, + media::CHANNEL_LAYOUT_5_0_BACK, + media::CHANNEL_LAYOUT_5_1_BACK, + media::CHANNEL_LAYOUT_7_1, +}; + +// Number of samples per frame. +static const int kNumberSamplesPerAACFrame = 1024; static int ExtractAdtsFrameSize(const uint8* adts_header) { return ((static_cast<int>(adts_header[5]) >> 5) | @@ -25,11 +59,11 @@ static int ExtractAdtsFrameSize(const uint8* adts_header) { ((static_cast<int>(adts_header[3]) & 0x3) << 11)); } -static size_t ExtractAdtsFrequencyIndex(const uint8* adts_header) { +static int ExtractAdtsFrequencyIndex(const uint8* adts_header) { return ((adts_header[2] >> 2) & 0xf); } -static size_t ExtractAdtsChannelConfig(const uint8* adts_header) { +static int ExtractAdtsChannelConfig(const uint8* adts_header) { return (((adts_header[3] >> 6) & 0x3) | ((adts_header[2] & 0x1) << 2)); } @@ -53,7 +87,7 @@ static bool LookForSyncWord(const uint8* raw_es, int raw_es_size, DCHECK_GE(pos, 0); DCHECK_LE(pos, raw_es_size); - int max_offset = raw_es_size - kADTSHeaderMinSize; + int max_offset = raw_es_size - kAdtsHeaderMinSize; if (pos >= max_offset) { // Do not change the position if: // - max_offset < 0: not enough bytes to get a full header @@ -74,7 +108,7 @@ static bool LookForSyncWord(const uint8* raw_es, int raw_es_size, continue; int frame_size = ExtractAdtsFrameSize(cur_buf); - if (frame_size < kADTSHeaderMinSize) { + if (frame_size < kAdtsHeaderMinSize) { // Too short to be an ADTS frame. continue; } @@ -96,6 +130,7 @@ static bool LookForSyncWord(const uint8* raw_es, int raw_es_size, return false; } +namespace media { namespace mp2t { EsParserAdts::EsParserAdts( @@ -137,7 +172,7 @@ bool EsParserAdts::Parse(const uint8* buf, int size, << " frame_size=" << frame_size; DVLOG(LOG_LEVEL_ES) << "ADTS header: " - << base::HexEncode(&raw_es[es_position], kADTSHeaderMinSize); + << base::HexEncode(&raw_es[es_position], kAdtsHeaderMinSize); // Do not process the frame if this one is a partial frame. int remaining_size = raw_es_size - es_position; @@ -145,7 +180,7 @@ bool EsParserAdts::Parse(const uint8* buf, int size, break; // Update the audio configuration if needed. - DCHECK_GE(frame_size, kADTSHeaderMinSize); + DCHECK_GE(frame_size, kAdtsHeaderMinSize); if (!UpdateAudioConfiguration(&raw_es[es_position])) return false; @@ -158,7 +193,7 @@ bool EsParserAdts::Parse(const uint8* buf, int size, base::TimeDelta current_pts = audio_timestamp_helper_->GetTimestamp(); base::TimeDelta frame_duration = - audio_timestamp_helper_->GetFrameDuration(kSamplesPerAACFrame); + audio_timestamp_helper_->GetFrameDuration(kNumberSamplesPerAACFrame); // Emit an audio frame. bool is_key_frame = true; @@ -177,7 +212,7 @@ bool EsParserAdts::Parse(const uint8* buf, int size, emit_buffer_cb_.Run(stream_parser_buffer); // Update the PTS of the next frame. - audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); + audio_timestamp_helper_->AddFrames(kNumberSamplesPerAACFrame); // Skip the current frame. es_position += frame_size; @@ -199,24 +234,23 @@ void EsParserAdts::Reset() { } bool EsParserAdts::UpdateAudioConfiguration(const uint8* adts_header) { - size_t frequency_index = ExtractAdtsFrequencyIndex(adts_header); - if (frequency_index >= kADTSFrequencyTableSize) { + int frequency_index = ExtractAdtsFrequencyIndex(adts_header); + if (frequency_index > kMaxSupportedFrequencyIndex) { // Frequency index 13 & 14 are reserved // while 15 means that the frequency is explicitly written // (not supported). return false; } - size_t channel_configuration = ExtractAdtsChannelConfig(adts_header); - if (channel_configuration == 0 || - channel_configuration >= kADTSChannelLayoutTableSize) { + int channel_configuration = ExtractAdtsChannelConfig(adts_header); + if (channel_configuration == 0) { // TODO(damienv): Add support for inband channel configuration. return false; } // TODO(damienv): support HE-AAC frequency doubling (SBR) // based on the incoming ADTS profile. - int samples_per_second = kADTSFrequencyTable[frequency_index]; + int samples_per_second = adts_frequency_table[frequency_index]; int adts_profile = (adts_header[2] >> 6) & 0x3; // The following code is written according to ISO 14496 Part 3 Table 1.11 and @@ -230,7 +264,7 @@ bool EsParserAdts::UpdateAudioConfiguration(const uint8* adts_header) { AudioDecoderConfig audio_decoder_config( kCodecAAC, kSampleFormatS16, - kADTSChannelLayoutTable[channel_configuration], + adts_channel_layout[channel_configuration], extended_samples_per_second, NULL, 0, false); diff --git a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc b/media/formats/mp3/mp3_stream_parser.cc index ba3cbd9..2127cc4 100644 --- a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc +++ b/media/formats/mp3/mp3_stream_parser.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/formats/mpeg/mpeg_audio_stream_parser_base.h" +#include "media/formats/mp3/mp3_stream_parser.h" #include "base/bind.h" #include "base/callback_helpers.h" #include "base/message_loop/message_loop.h" +#include "media/base/bit_reader.h" #include "media/base/buffers.h" #include "media/base/stream_parser_buffer.h" #include "media/base/text_track_config.h" @@ -14,6 +15,7 @@ namespace media { +static const uint32 kMP3StartCodeMask = 0xffe00000; static const uint32 kICYStartCode = 0x49435920; // 'ICY ' // Arbitrary upper bound on the size of an IceCast header before it @@ -26,40 +28,100 @@ static const int kID3v1Size = 128; static const int kID3v1ExtendedSize = 227; static const uint32 kID3v2StartCode = 0x49443300; // 'ID3\0' -static int LocateEndOfHeaders(const uint8_t* buf, int buf_len, int i) { - bool was_lf = false; - char last_c = '\0'; - for (; i < buf_len; ++i) { - char c = buf[i]; - if (c == '\n') { - if (was_lf) - return i + 1; - was_lf = true; - } else if (c != '\r' || last_c != '\n') { - was_lf = false; - } - last_c = c; - } - return -1; +// Map that determines which bitrate_index & channel_mode combinations +// are allowed. +// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html +static const bool kIsAllowed[17][4] = { + { true, true, true, true }, // free + { true, false, false, false }, // 32 + { true, false, false, false }, // 48 + { true, false, false, false }, // 56 + { true, true, true, true }, // 64 + { true, false, false, false }, // 80 + { true, true, true, true }, // 96 + { true, true, true, true }, // 112 + { true, true, true, true }, // 128 + { true, true, true, true }, // 160 + { true, true, true, true }, // 192 + { false, true, true, true }, // 224 + { false, true, true, true }, // 256 + { false, true, true, true }, // 320 + { false, true, true, true }, // 384 + { false, false, false, false } // bad +}; + +// Maps version and layer information in the frame header +// into an index for the |kBitrateMap|. +// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html +static const int kVersionLayerMap[4][4] = { + // { reserved, L3, L2, L1 } + { 5, 4, 4, 3 }, // MPEG 2.5 + { 5, 5, 5, 5 }, // reserved + { 5, 4, 4, 3 }, // MPEG 2 + { 5, 2, 1, 0 } // MPEG 1 +}; + +// Maps the bitrate index field in the header and an index +// from |kVersionLayerMap| to a frame bitrate. +// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html +static const int kBitrateMap[16][6] = { + // { V1L1, V1L2, V1L3, V2L1, V2L2 & V2L3, reserved } + { 0, 0, 0, 0, 0, 0 }, + { 32, 32, 32, 32, 8, 0 }, + { 64, 48, 40, 48, 16, 0 }, + { 96, 56, 48, 56, 24, 0 }, + { 128, 64, 56, 64, 32, 0 }, + { 160, 80, 64, 80, 40, 0 }, + { 192, 96, 80, 96, 48, 0 }, + { 224, 112, 96, 112, 56, 0 }, + { 256, 128, 112, 128, 64, 0 }, + { 288, 160, 128, 144, 80, 0 }, + { 320, 192, 160, 160, 96, 0 }, + { 352, 224, 192, 176, 112, 0 }, + { 384, 256, 224, 192, 128, 0 }, + { 416, 320, 256, 224, 144, 0 }, + { 448, 384, 320, 256, 160, 0 }, + { 0, 0, 0, 0, 0} +}; + +// Maps the sample rate index and version fields from the frame header +// to a sample rate. +// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html +static const int kSampleRateMap[4][4] = { + // { V2.5, reserved, V2, V1 } + { 11025, 0, 22050, 44100 }, + { 12000, 0, 24000, 48000 }, + { 8000, 0, 16000, 32000 }, + { 0, 0, 0, 0 } +}; + +// Frame header field constants. +static const int kVersion2 = 2; +static const int kVersionReserved = 1; +static const int kVersion2_5 = 0; +static const int kLayerReserved = 0; +static const int kLayer1 = 3; +static const int kLayer2 = 2; +static const int kLayer3 = 1; +static const int kBitrateFree = 0; +static const int kBitrateBad = 0xf; +static const int kSampleRateReserved = 3; + +MP3StreamParser::MP3StreamParser() + : state_(UNINITIALIZED), + in_media_segment_(false) { } -MPEGAudioStreamParserBase::MPEGAudioStreamParserBase(uint32 start_code_mask, - AudioCodec audio_codec) - : state_(UNINITIALIZED), - in_media_segment_(false), - start_code_mask_(start_code_mask), - audio_codec_(audio_codec) {} - -MPEGAudioStreamParserBase::~MPEGAudioStreamParserBase() {} - -void MPEGAudioStreamParserBase::Init(const InitCB& init_cb, - const NewConfigCB& config_cb, - const NewBuffersCB& new_buffers_cb, - bool ignore_text_tracks, - const NeedKeyCB& need_key_cb, - const NewMediaSegmentCB& new_segment_cb, - const base::Closure& end_of_segment_cb, - const LogCB& log_cb) { +MP3StreamParser::~MP3StreamParser() {} + +void MP3StreamParser::Init(const InitCB& init_cb, + const NewConfigCB& config_cb, + const NewBuffersCB& new_buffers_cb, + bool ignore_text_tracks, + const NeedKeyCB& need_key_cb, + const NewMediaSegmentCB& new_segment_cb, + const base::Closure& end_of_segment_cb, + const LogCB& log_cb) { DVLOG(1) << __FUNCTION__; DCHECK_EQ(state_, UNINITIALIZED); init_cb_ = init_cb; @@ -72,7 +134,7 @@ void MPEGAudioStreamParserBase::Init(const InitCB& init_cb, ChangeState(INITIALIZED); } -void MPEGAudioStreamParserBase::Flush() { +void MP3StreamParser::Flush() { DVLOG(1) << __FUNCTION__; DCHECK_NE(state_, UNINITIALIZED); queue_.Reset(); @@ -80,7 +142,7 @@ void MPEGAudioStreamParserBase::Flush() { in_media_segment_ = false; } -bool MPEGAudioStreamParserBase::Parse(const uint8* buf, int size) { +bool MP3StreamParser::Parse(const uint8* buf, int size) { DVLOG(1) << __FUNCTION__ << "(" << size << ")"; DCHECK(buf); DCHECK_GT(size, 0); @@ -106,8 +168,8 @@ bool MPEGAudioStreamParserBase::Parse(const uint8* buf, int size) { uint32 start_code = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; int bytes_read = 0; bool parsed_metadata = true; - if ((start_code & start_code_mask_) == start_code_mask_) { - bytes_read = ParseFrame(data, data_size, &buffers); + if ((start_code & kMP3StartCodeMask) == kMP3StartCodeMask) { + bytes_read = ParseMP3Frame(data, data_size, &buffers); // Only allow the current segment to end if a full frame has been parsed. end_of_segment = bytes_read > 0; @@ -152,14 +214,157 @@ bool MPEGAudioStreamParserBase::Parse(const uint8* buf, int size) { return SendBuffers(&buffers, end_of_segment); } -void MPEGAudioStreamParserBase::ChangeState(State state) { +void MP3StreamParser::ChangeState(State state) { DVLOG(1) << __FUNCTION__ << "() : " << state_ << " -> " << state; state_ = state; } -int MPEGAudioStreamParserBase::ParseFrame(const uint8* data, - int size, - BufferQueue* buffers) { +int MP3StreamParser::ParseFrameHeader(const uint8* data, int size, + int* frame_size, + int* sample_rate, + ChannelLayout* channel_layout, + int* sample_count) const { + DCHECK(data); + DCHECK_GE(size, 0); + DCHECK(frame_size); + + if (size < 4) + return 0; + + BitReader reader(data, size); + int sync; + int version; + int layer; + int is_protected; + int bitrate_index; + int sample_rate_index; + int has_padding; + int is_private; + int channel_mode; + int other_flags; + + if (!reader.ReadBits(11, &sync) || + !reader.ReadBits(2, &version) || + !reader.ReadBits(2, &layer) || + !reader.ReadBits(1, &is_protected) || + !reader.ReadBits(4, &bitrate_index) || + !reader.ReadBits(2, &sample_rate_index) || + !reader.ReadBits(1, &has_padding) || + !reader.ReadBits(1, &is_private) || + !reader.ReadBits(2, &channel_mode) || + !reader.ReadBits(6, &other_flags)) { + return -1; + } + + DVLOG(2) << "Header data :" << std::hex + << " sync 0x" << sync + << " version 0x" << version + << " layer 0x" << layer + << " bitrate_index 0x" << bitrate_index + << " sample_rate_index 0x" << sample_rate_index + << " channel_mode 0x" << channel_mode; + + if (sync != 0x7ff || + version == kVersionReserved || + layer == kLayerReserved || + bitrate_index == kBitrateFree || bitrate_index == kBitrateBad || + sample_rate_index == kSampleRateReserved) { + MEDIA_LOG(log_cb_) << "Invalid header data :" << std::hex + << " sync 0x" << sync + << " version 0x" << version + << " layer 0x" << layer + << " bitrate_index 0x" << bitrate_index + << " sample_rate_index 0x" << sample_rate_index + << " channel_mode 0x" << channel_mode; + return -1; + } + + if (layer == kLayer2 && kIsAllowed[bitrate_index][channel_mode]) { + MEDIA_LOG(log_cb_) << "Invalid (bitrate_index, channel_mode) combination :" + << std::hex + << " bitrate_index " << bitrate_index + << " channel_mode " << channel_mode; + return -1; + } + + int bitrate = kBitrateMap[bitrate_index][kVersionLayerMap[version][layer]]; + + if (bitrate == 0) { + MEDIA_LOG(log_cb_) << "Invalid bitrate :" << std::hex + << " version " << version + << " layer " << layer + << " bitrate_index " << bitrate_index; + return -1; + } + + DVLOG(2) << " bitrate " << bitrate; + + int frame_sample_rate = kSampleRateMap[sample_rate_index][version]; + if (frame_sample_rate == 0) { + MEDIA_LOG(log_cb_) << "Invalid sample rate :" << std::hex + << " version " << version + << " sample_rate_index " << sample_rate_index; + return -1; + } + + if (sample_rate) + *sample_rate = frame_sample_rate; + + // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf + // Table 2.1.5 + int samples_per_frame; + switch (layer) { + case kLayer1: + samples_per_frame = 384; + break; + + case kLayer2: + samples_per_frame = 1152; + break; + + case kLayer3: + if (version == kVersion2 || version == kVersion2_5) + samples_per_frame = 576; + else + samples_per_frame = 1152; + break; + + default: + return -1; + } + + if (sample_count) + *sample_count = samples_per_frame; + + // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf + // Text just below Table 2.1.5. + if (layer == kLayer1) { + // This formulation is a slight variation on the equation below, + // but has slightly different truncation characteristics to deal + // with the fact that Layer 1 has 4 byte "slots" instead of single + // byte ones. + *frame_size = 4 * (12 * bitrate * 1000 / frame_sample_rate); + } else { + *frame_size = + ((samples_per_frame / 8) * bitrate * 1000) / frame_sample_rate; + } + + if (has_padding) + *frame_size += (layer == kLayer1) ? 4 : 1; + + if (channel_layout) { + // Map Stereo(0), Joint Stereo(1), and Dual Channel (2) to + // CHANNEL_LAYOUT_STEREO and Single Channel (3) to CHANNEL_LAYOUT_MONO. + *channel_layout = + (channel_mode == 3) ? CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO; + } + + return 4; +} + +int MP3StreamParser::ParseMP3Frame(const uint8* data, + int size, + BufferQueue* buffers) { DVLOG(2) << __FUNCTION__ << "(" << size << ")"; int sample_rate; @@ -178,8 +383,7 @@ int MPEGAudioStreamParserBase::ParseFrame(const uint8* data, DVLOG(2) << " sample_rate " << sample_rate << " channel_layout " << channel_layout - << " frame_size " << frame_size - << " sample_count " << sample_count; + << " frame_size " << frame_size; if (config_.IsValidConfig() && (config_.samples_per_second() != sample_rate || @@ -193,7 +397,7 @@ int MPEGAudioStreamParserBase::ParseFrame(const uint8* data, } if (!config_.IsValidConfig()) { - config_.Initialize(audio_codec_, kSampleFormatF32, channel_layout, + config_.Initialize(kCodecMP3, kSampleFormatF32, channel_layout, sample_rate, NULL, 0, false, false, base::TimeDelta(), base::TimeDelta()); @@ -229,7 +433,25 @@ int MPEGAudioStreamParserBase::ParseFrame(const uint8* data, return frame_size; } -int MPEGAudioStreamParserBase::ParseIcecastHeader(const uint8* data, int size) { +static int LocateEndOfHeaders(const uint8_t* buf, int buf_len, int i) { + bool was_lf = false; + char last_c = '\0'; + for (; i < buf_len; ++i) { + char c = buf[i]; + if (c == '\n') { + if (was_lf) + return i + 1; + was_lf = true; + } else if (c != '\r' || last_c != '\n') { + was_lf = false; + } + last_c = c; + } + return -1; +} + + +int MP3StreamParser::ParseIcecastHeader(const uint8* data, int size) { DVLOG(1) << __FUNCTION__ << "(" << size << ")"; if (size < 4) @@ -252,7 +474,7 @@ int MPEGAudioStreamParserBase::ParseIcecastHeader(const uint8* data, int size) { return offset; } -int MPEGAudioStreamParserBase::ParseID3v1(const uint8* data, int size) { +int MP3StreamParser::ParseID3v1(const uint8* data, int size) { DVLOG(1) << __FUNCTION__ << "(" << size << ")"; if (size < kID3v1Size) @@ -263,7 +485,7 @@ int MPEGAudioStreamParserBase::ParseID3v1(const uint8* data, int size) { return !memcmp(data, "TAG+", 4) ? kID3v1ExtendedSize : kID3v1Size; } -int MPEGAudioStreamParserBase::ParseID3v2(const uint8* data, int size) { +int MP3StreamParser::ParseID3v2(const uint8* data, int size) { DVLOG(1) << __FUNCTION__ << "(" << size << ")"; if (size < 10) @@ -297,8 +519,7 @@ int MPEGAudioStreamParserBase::ParseID3v2(const uint8* data, int size) { return actual_tag_size; } -bool MPEGAudioStreamParserBase::ParseSyncSafeInt(BitReader* reader, - int32* value) { +bool MP3StreamParser::ParseSyncSafeInt(BitReader* reader, int32* value) { *value = 0; for (int i = 0; i < 4; ++i) { uint8 tmp; @@ -317,8 +538,7 @@ bool MPEGAudioStreamParserBase::ParseSyncSafeInt(BitReader* reader, return true; } -int MPEGAudioStreamParserBase::FindNextValidStartCode(const uint8* data, - int size) const { +int MP3StreamParser::FindNextValidStartCode(const uint8* data, int size) const { const uint8* start = data; const uint8* end = data + size; @@ -373,8 +593,7 @@ int MPEGAudioStreamParserBase::FindNextValidStartCode(const uint8* data, return 0; } -bool MPEGAudioStreamParserBase::SendBuffers(BufferQueue* buffers, - bool end_of_segment) { +bool MP3StreamParser::SendBuffers(BufferQueue* buffers, bool end_of_segment) { DCHECK(!buffers->empty()); if (!in_media_segment_) { diff --git a/media/formats/mpeg/mpeg_audio_stream_parser_base.h b/media/formats/mp3/mp3_stream_parser.h index 5975c1b..6b4b388 100644 --- a/media/formats/mpeg/mpeg_audio_stream_parser_base.h +++ b/media/formats/mp3/mp3_stream_parser.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_FORMATS_MPEG_MPEG_AUDIO_STREAM_PARSER_BASE_H_ -#define MEDIA_FORMATS_MPEG_MPEG_AUDIO_STREAM_PARSER_BASE_H_ +#ifndef MEDIA_FORMATS_MP3_MP3_STREAM_PARSER_H_ +#define MEDIA_FORMATS_MP3_MP3_STREAM_PARSER_H_ #include <set> #include <vector> @@ -12,23 +12,21 @@ #include "base/callback.h" #include "media/base/audio_decoder_config.h" #include "media/base/audio_timestamp_helper.h" -#include "media/base/bit_reader.h" #include "media/base/byte_queue.h" #include "media/base/media_export.h" #include "media/base/stream_parser.h" namespace media { -class MEDIA_EXPORT MPEGAudioStreamParserBase : public StreamParser { +class BitReader; + +class MEDIA_EXPORT MP3StreamParser : public StreamParser { public: - // |start_code_mask| is used to find the start of each frame header. Also - // referred to as the sync code in the MP3 and ADTS header specifications. - MPEGAudioStreamParserBase(uint32 start_code_mask, AudioCodec audio_codec); - virtual ~MPEGAudioStreamParserBase(); + MP3StreamParser(); + virtual ~MP3StreamParser(); // StreamParser implementation. - virtual void Init(const InitCB& init_cb, - const NewConfigCB& config_cb, + virtual void Init(const InitCB& init_cb, const NewConfigCB& config_cb, const NewBuffersCB& new_buffers_cb, bool ignore_text_tracks, const NeedKeyCB& need_key_cb, @@ -38,13 +36,35 @@ class MEDIA_EXPORT MPEGAudioStreamParserBase : public StreamParser { virtual void Flush() OVERRIDE; virtual bool Parse(const uint8* buf, int size) OVERRIDE; - protected: - // Subclasses implement this method to parse format specific frame headers. + private: + enum State { + UNINITIALIZED, + INITIALIZED, + PARSE_ERROR + }; + + State state_; + + InitCB init_cb_; + NewConfigCB config_cb_; + NewBuffersCB new_buffers_cb_; + NewMediaSegmentCB new_segment_cb_; + base::Closure end_of_segment_cb_; + LogCB log_cb_; + + ByteQueue queue_; + + AudioDecoderConfig config_; + scoped_ptr<AudioTimestampHelper> timestamp_helper_; + bool in_media_segment_; + + void ChangeState(State state); + + // Parsing functions for various byte stream elements. // |data| & |size| describe the data available for parsing. - // - // Implementations are expected to consume an entire frame header. It should - // only return a value greater than 0 when |data| has enough bytes to - // successfully parse & consume the entire frame header. + // These functions are expected to consume an entire frame/header. + // It should only return a value greater than 0 when |data| has + // enough bytes to successfully parse & consume the entire element. // // |frame_size| - Required parameter that is set to the size of the frame, in // bytes, including the frame header if the function returns a value > 0. @@ -60,34 +80,14 @@ class MEDIA_EXPORT MPEGAudioStreamParserBase : public StreamParser { // // Returns: // > 0 : The number of bytes parsed. - // 0 : If more data is needed to parse the entire frame header. - // < 0 : An error was encountered during parsing. - virtual int ParseFrameHeader(const uint8* data, - int size, - int* frame_size, - int* sample_rate, - ChannelLayout* channel_layout, - int* sample_count) const = 0; - - const LogCB& log_cb() const { return log_cb_; } - - private: - enum State { - UNINITIALIZED, - INITIALIZED, - PARSE_ERROR - }; - - void ChangeState(State state); - - // Parsing functions for various byte stream elements. |data| & |size| - // describe the data available for parsing. - // - // Returns: - // > 0 : The number of bytes parsed. // 0 : If more data is needed to parse the entire element. // < 0 : An error was encountered during parsing. - int ParseFrame(const uint8* data, int size, BufferQueue* buffers); + int ParseFrameHeader(const uint8* data, int size, + int* frame_size, + int* sample_rate, + ChannelLayout* channel_layout, + int* sample_count) const; + int ParseMP3Frame(const uint8* data, int size, BufferQueue* buffers); int ParseIcecastHeader(const uint8* data, int size); int ParseID3v1(const uint8* data, int size); int ParseID3v2(const uint8* data, int size); @@ -118,26 +118,9 @@ class MEDIA_EXPORT MPEGAudioStreamParserBase : public StreamParser { // Returns true if the buffers are sent successfully. bool SendBuffers(BufferQueue* buffers, bool end_of_segment); - State state_; - - InitCB init_cb_; - NewConfigCB config_cb_; - NewBuffersCB new_buffers_cb_; - NewMediaSegmentCB new_segment_cb_; - base::Closure end_of_segment_cb_; - LogCB log_cb_; - - ByteQueue queue_; - - AudioDecoderConfig config_; - scoped_ptr<AudioTimestampHelper> timestamp_helper_; - bool in_media_segment_; - const uint32 start_code_mask_; - const AudioCodec audio_codec_; - - DISALLOW_COPY_AND_ASSIGN(MPEGAudioStreamParserBase); + DISALLOW_COPY_AND_ASSIGN(MP3StreamParser); }; } // namespace media -#endif // MEDIA_FORMATS_MPEG_MPEG_AUDIO_STREAM_PARSER_BASE_H_ +#endif // MEDIA_FORMATS_MP3_MP3_STREAM_PARSER_H_ diff --git a/media/formats/mp3/mp3_stream_parser_unittest.cc b/media/formats/mp3/mp3_stream_parser_unittest.cc new file mode 100644 index 0000000..4ff7853 --- /dev/null +++ b/media/formats/mp3/mp3_stream_parser_unittest.cc @@ -0,0 +1,170 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "media/base/audio_decoder_config.h" +#include "media/base/decoder_buffer.h" +#include "media/base/stream_parser_buffer.h" +#include "media/base/test_data_util.h" +#include "media/base/text_track_config.h" +#include "media/base/video_decoder_config.h" +#include "media/formats/mp3/mp3_stream_parser.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class MP3StreamParserTest : public testing::Test { + public: + MP3StreamParserTest() {} + + protected: + MP3StreamParser parser_; + std::stringstream results_stream_; + + bool AppendData(const uint8* data, size_t length) { + return parser_.Parse(data, length); + } + + bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) { + const uint8* start = data; + const uint8* end = data + length; + while (start < end) { + size_t append_size = + std::min(piece_size, static_cast<size_t>(end - start)); + if (!AppendData(start, append_size)) + return false; + start += append_size; + } + return true; + } + + void OnInitDone(bool success, base::TimeDelta duration) { + DVLOG(1) << __FUNCTION__ << "(" << success << ", " + << duration.InMilliseconds() << ")"; + } + + bool OnNewConfig(const AudioDecoderConfig& audio_config, + const VideoDecoderConfig& video_config, + const StreamParser::TextTrackConfigMap& text_config) { + DVLOG(1) << __FUNCTION__ << "(" << audio_config.IsValidConfig() << ", " + << video_config.IsValidConfig() << ")"; + EXPECT_TRUE(audio_config.IsValidConfig()); + EXPECT_FALSE(video_config.IsValidConfig()); + return true; + } + + std::string BufferQueueToString(const StreamParser::BufferQueue& buffers) { + std::stringstream ss; + + ss << "{"; + for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); + itr != buffers.end(); + ++itr) { + ss << " " << (*itr)->timestamp().InMilliseconds(); + if ((*itr)->IsKeyframe()) + ss << "K"; + } + ss << " }"; + + return ss.str(); + } + + bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, + const StreamParser::BufferQueue& video_buffers, + const StreamParser::TextBufferQueueMap& text_map) { + EXPECT_FALSE(audio_buffers.empty()); + EXPECT_TRUE(video_buffers.empty()); + + // TODO(wolenetz/acolwell): Add text track support to more MSE parsers. See + // http://crbug.com/336926. + EXPECT_TRUE(text_map.empty()); + + std::string buffers_str = BufferQueueToString(audio_buffers); + DVLOG(1) << __FUNCTION__ << " : " << buffers_str; + results_stream_ << buffers_str; + return true; + } + + void OnKeyNeeded(const std::string& type, + const std::vector<uint8>& init_data) { + DVLOG(1) << __FUNCTION__ << "(" << type << ", " << init_data.size() << ")"; + } + + void OnNewSegment() { + DVLOG(1) << __FUNCTION__; + results_stream_ << "NewSegment"; + } + + void OnEndOfSegment() { + DVLOG(1) << __FUNCTION__; + results_stream_ << "EndOfSegment"; + } + + void InitializeParser() { + parser_.Init( + base::Bind(&MP3StreamParserTest::OnInitDone, base::Unretained(this)), + base::Bind(&MP3StreamParserTest::OnNewConfig, base::Unretained(this)), + base::Bind(&MP3StreamParserTest::OnNewBuffers, base::Unretained(this)), + true, + base::Bind(&MP3StreamParserTest::OnKeyNeeded, base::Unretained(this)), + base::Bind(&MP3StreamParserTest::OnNewSegment, base::Unretained(this)), + base::Bind(&MP3StreamParserTest::OnEndOfSegment, + base::Unretained(this)), + LogCB()); + } + + std::string ParseFile(const std::string& filename, int append_bytes) { + results_stream_.clear(); + InitializeParser(); + + scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); + EXPECT_TRUE( + AppendDataInPieces(buffer->data(), buffer->data_size(), append_bytes)); + return results_stream_.str(); + } +}; + +// Test parsing with small prime sized chunks to smoke out "power of +// 2" field size assumptions. +TEST_F(MP3StreamParserTest, UnalignedAppend) { + std::string expected = + "NewSegment" + "{ 0K }" + "{ 26K }" + "{ 52K }" + "{ 78K }" + "{ 104K }" + "{ 130K }" + "{ 156K }" + "{ 182K }" + "EndOfSegment" + "NewSegment" + "{ 208K }" + "{ 235K }" + "{ 261K }" + "EndOfSegment" + "NewSegment" + "{ 287K }" + "{ 313K }" + "EndOfSegment"; + EXPECT_EQ(expected, ParseFile("sfx.mp3", 17)); +} + +// Test parsing with a larger piece size to verify that multiple buffers +// are passed to |new_buffer_cb_|. +TEST_F(MP3StreamParserTest, UnalignedAppend512) { + std::string expected = + "NewSegment" + "{ 0K }" + "{ 26K 52K 78K 104K }" + "EndOfSegment" + "NewSegment" + "{ 130K 156K 182K }" + "{ 208K 235K 261K 287K }" + "{ 313K }" + "EndOfSegment"; + EXPECT_EQ(expected, ParseFile("sfx.mp3", 512)); +} + +} // namespace media diff --git a/media/formats/mp4/aac.cc b/media/formats/mp4/aac.cc index c6be6be..fedb33f 100644 --- a/media/formats/mp4/aac.cc +++ b/media/formats/mp4/aac.cc @@ -9,9 +9,39 @@ #include "base/logging.h" #include "media/base/bit_reader.h" #include "media/formats/mp4/rcheck.h" -#include "media/formats/mpeg/adts_constants.h" + +// The following conversion table is extracted from ISO 14496 Part 3 - +// Table 1.16 - Sampling Frequency Index. +static const int kFrequencyMap[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, + 22050, 16000, 12000, 11025, 8000, 7350 +}; namespace media { + +static ChannelLayout ConvertChannelConfigToLayout(uint8 channel_config) { + switch (channel_config) { + case 1: + return CHANNEL_LAYOUT_MONO; + case 2: + return CHANNEL_LAYOUT_STEREO; + case 3: + return CHANNEL_LAYOUT_SURROUND; + case 4: + return CHANNEL_LAYOUT_4_0; + case 5: + return CHANNEL_LAYOUT_5_0; + case 6: + return CHANNEL_LAYOUT_5_1; + case 8: + return CHANNEL_LAYOUT_7_1; + default: + break; + } + + return CHANNEL_LAYOUT_UNSUPPORTED; +} + namespace mp4 { AAC::AAC() @@ -92,25 +122,24 @@ bool AAC::Parse(const std::vector<uint8>& data) { } if (frequency_ == 0) { - RCHECK(frequency_index_ < kADTSFrequencyTableSize); - frequency_ = kADTSFrequencyTable[frequency_index_]; + RCHECK(frequency_index_ < arraysize(kFrequencyMap)); + frequency_ = kFrequencyMap[frequency_index_]; } if (extension_frequency_ == 0 && extension_frequency_index != 0xff) { - RCHECK(extension_frequency_index < kADTSFrequencyTableSize); - extension_frequency_ = kADTSFrequencyTable[extension_frequency_index]; + RCHECK(extension_frequency_index < arraysize(kFrequencyMap)); + extension_frequency_ = kFrequencyMap[extension_frequency_index]; } // When Parametric Stereo is on, mono will be played as stereo. - if (ps_present && channel_config_ == 1) { + if (ps_present && channel_config_ == 1) channel_layout_ = CHANNEL_LAYOUT_STEREO; - } else { - RCHECK(channel_layout_ < kADTSChannelLayoutTableSize); - channel_layout_ = kADTSChannelLayoutTable[channel_config_]; - } + else + channel_layout_ = ConvertChannelConfigToLayout(channel_config_); - return frequency_ != 0 && channel_layout_ != CHANNEL_LAYOUT_NONE && - profile_ >= 1 && profile_ <= 4; + return frequency_ != 0 && channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED && + profile_ >= 1 && profile_ <= 4 && frequency_index_ != 0xf && + channel_config_ <= 7; } int AAC::GetOutputSamplesPerSecond(bool sbr_in_mimetype) const { @@ -139,7 +168,7 @@ ChannelLayout AAC::GetChannelLayout(bool sbr_in_mimetype) const { } bool AAC::ConvertEsdsToADTS(std::vector<uint8>* buffer) const { - size_t size = buffer->size() + kADTSHeaderMinSize; + size_t size = buffer->size() + kADTSHeaderSize; DCHECK(profile_ >= 1 && profile_ <= 4 && frequency_index_ != 0xf && channel_config_ <= 7); @@ -150,7 +179,7 @@ bool AAC::ConvertEsdsToADTS(std::vector<uint8>* buffer) const { std::vector<uint8>& adts = *buffer; - adts.insert(buffer->begin(), kADTSHeaderMinSize, 0); + adts.insert(buffer->begin(), kADTSHeaderSize, 0); adts[0] = 0xff; adts[1] = 0xf1; adts[2] = ((profile_ - 1) << 6) + (frequency_index_ << 2) + diff --git a/media/formats/mp4/aac.h b/media/formats/mp4/aac.h index 0b1d950..333d621 100644 --- a/media/formats/mp4/aac.h +++ b/media/formats/mp4/aac.h @@ -59,6 +59,9 @@ class MEDIA_EXPORT AAC { } #endif + // Size in bytes of the ADTS header added by ConvertEsdsToADTS(). + static const size_t kADTSHeaderSize = 7; + private: bool SkipDecoderGASpecificConfig(BitReader* bit_reader) const; bool SkipErrorSpecificConfig() const; diff --git a/media/formats/mp4/aac_unittest.cc b/media/formats/mp4/aac_unittest.cc index d3ca839..6c2e797 100644 --- a/media/formats/mp4/aac_unittest.cc +++ b/media/formats/mp4/aac_unittest.cc @@ -85,7 +85,7 @@ TEST(AACTest, SixChannelTest) { EXPECT_TRUE(aac.Parse(data)); EXPECT_EQ(aac.GetOutputSamplesPerSecond(false), 48000); - EXPECT_EQ(aac.GetChannelLayout(false), CHANNEL_LAYOUT_5_1_BACK); + EXPECT_EQ(aac.GetChannelLayout(false), CHANNEL_LAYOUT_5_1); } TEST(AACTest, DataTooShortTest) { diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index 809bd82..e6de37e 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc @@ -17,7 +17,6 @@ #include "media/formats/mp4/box_reader.h" #include "media/formats/mp4/es_descriptor.h" #include "media/formats/mp4/rcheck.h" -#include "media/formats/mpeg/adts_constants.h" namespace media { namespace mp4 { @@ -385,11 +384,11 @@ bool MP4StreamParser::PrepareAACBuffer( // not required to use subsample encryption, so we may need to add an entry. if (subsamples->empty()) { SubsampleEntry entry; - entry.clear_bytes = kADTSHeaderMinSize; - entry.cypher_bytes = frame_buf->size() - kADTSHeaderMinSize; + entry.clear_bytes = AAC::kADTSHeaderSize; + entry.cypher_bytes = frame_buf->size() - AAC::kADTSHeaderSize; subsamples->push_back(entry); } else { - (*subsamples)[0].clear_bytes += kADTSHeaderMinSize; + (*subsamples)[0].clear_bytes += AAC::kADTSHeaderSize; } return true; } diff --git a/media/formats/mpeg/adts_constants.cc b/media/formats/mpeg/adts_constants.cc deleted file mode 100644 index bc89890..0000000 --- a/media/formats/mpeg/adts_constants.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/formats/mpeg/adts_constants.h" - -#include "base/macros.h" - -namespace media { - -// The following conversion table is extracted from ISO 14496 Part 3 - -// Table 1.16 - Sampling Frequency Index. -const int kADTSFrequencyTable[] = {96000, 88200, 64000, 48000, 44100, - 32000, 24000, 22050, 16000, 12000, - 11025, 8000, 7350}; -const size_t kADTSFrequencyTableSize = arraysize(kADTSFrequencyTable); - -// The following conversion table is extracted from ISO 14496 Part 3 - -// Table 1.17 - Channel Configuration. -const media::ChannelLayout kADTSChannelLayoutTable[] = { - media::CHANNEL_LAYOUT_NONE, media::CHANNEL_LAYOUT_MONO, - media::CHANNEL_LAYOUT_STEREO, media::CHANNEL_LAYOUT_SURROUND, - media::CHANNEL_LAYOUT_4_0, media::CHANNEL_LAYOUT_5_0_BACK, - media::CHANNEL_LAYOUT_5_1_BACK, media::CHANNEL_LAYOUT_7_1}; -const size_t kADTSChannelLayoutTableSize = arraysize(kADTSChannelLayoutTable); - -} // namespace media diff --git a/media/formats/mpeg/adts_constants.h b/media/formats/mpeg/adts_constants.h deleted file mode 100644 index e080766..0000000 --- a/media/formats/mpeg/adts_constants.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_FORMATS_MPEG_ADTS_CONSTANTS_H_ -#define MEDIA_FORMATS_MPEG_ADTS_CONSTANTS_H_ - -#include <stddef.h> - -#include "media/base/channel_layout.h" -#include "media/base/media_export.h" - -namespace media { - -enum { - kADTSHeaderMinSize = 7, - kSamplesPerAACFrame = 1024, -}; - -MEDIA_EXPORT extern const int kADTSFrequencyTable[]; -MEDIA_EXPORT extern const size_t kADTSFrequencyTableSize; - -MEDIA_EXPORT extern const media::ChannelLayout kADTSChannelLayoutTable[]; -MEDIA_EXPORT extern const size_t kADTSChannelLayoutTableSize; - -} // namespace media - -#endif // MEDIA_FORMATS_MPEG_ADTS_CONSTANTS_H_
\ No newline at end of file diff --git a/media/formats/mpeg/adts_stream_parser.cc b/media/formats/mpeg/adts_stream_parser.cc deleted file mode 100644 index 0f5e280..0000000 --- a/media/formats/mpeg/adts_stream_parser.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/formats/mpeg/adts_stream_parser.h" - -#include "media/formats/mpeg/adts_constants.h" - -namespace media { - -static const uint32 kADTSStartCodeMask = 0xfff00000; - -ADTSStreamParser::ADTSStreamParser() - : MPEGAudioStreamParserBase(kADTSStartCodeMask, kCodecAAC) {} - -ADTSStreamParser::~ADTSStreamParser() {} - -int ADTSStreamParser::ParseFrameHeader(const uint8* data, - int size, - int* frame_size, - int* sample_rate, - ChannelLayout* channel_layout, - int* sample_count) const { - DCHECK(data); - DCHECK_GE(size, 0); - DCHECK(frame_size); - - if (size < 8) - return 0; - - BitReader reader(data, size); - int sync; - int version; - int layer; - int protection_absent; - int profile; - size_t sample_rate_index; - size_t channel_layout_index; - int frame_length; - size_t num_data_blocks; - int unused; - - if (!reader.ReadBits(12, &sync) || - !reader.ReadBits(1, &version) || - !reader.ReadBits(2, &layer) || - !reader.ReadBits(1, &protection_absent) || - !reader.ReadBits(2, &profile) || - !reader.ReadBits(4, &sample_rate_index) || - !reader.ReadBits(1, &unused) || - !reader.ReadBits(3, &channel_layout_index) || - !reader.ReadBits(4, &unused) || - !reader.ReadBits(13, &frame_length) || - !reader.ReadBits(11, &unused) || - !reader.ReadBits(2, &num_data_blocks) || - (!protection_absent && !reader.ReadBits(16, &unused))) { - return -1; - } - - DVLOG(2) << "Header data :" << std::hex - << " sync 0x" << sync - << " version 0x" << version - << " layer 0x" << layer - << " profile 0x" << profile - << " sample_rate_index 0x" << sample_rate_index - << " channel_layout_index 0x" << channel_layout_index; - - const int bytes_read = reader.bits_read() / 8; - if (sync != 0xfff || layer != 0 || frame_length < bytes_read || - sample_rate_index >= kADTSFrequencyTableSize || - channel_layout_index >= kADTSChannelLayoutTableSize) { - MEDIA_LOG(log_cb()) << "Invalid header data :" << std::hex - << " sync 0x" << sync - << " version 0x" << version - << " layer 0x" << layer - << " sample_rate_index 0x" << sample_rate_index - << " channel_layout_index 0x" << channel_layout_index; - return -1; - } - - if (sample_rate) - *sample_rate = kADTSFrequencyTable[sample_rate_index]; - - if (frame_size) - *frame_size = frame_length; - - if (sample_count) - *sample_count = (num_data_blocks + 1) * kSamplesPerAACFrame; - - if (channel_layout) - *channel_layout = kADTSChannelLayoutTable[channel_layout_index]; - - return bytes_read; -} - -} // namespace media diff --git a/media/formats/mpeg/adts_stream_parser.h b/media/formats/mpeg/adts_stream_parser.h deleted file mode 100644 index 26ebcc9..0000000 --- a/media/formats/mpeg/adts_stream_parser.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_FORMATS_MPEG_ADTS_STREAM_PARSER_H_ -#define MEDIA_FORMATS_MPEG_ADTS_STREAM_PARSER_H_ - -#include "base/basictypes.h" -#include "media/base/media_export.h" -#include "media/formats/mpeg/mpeg_audio_stream_parser_base.h" - -namespace media { - -class MEDIA_EXPORT ADTSStreamParser : public MPEGAudioStreamParserBase { - public: - ADTSStreamParser(); - virtual ~ADTSStreamParser(); - - private: - // MPEGAudioStreamParserBase overrides. - virtual int ParseFrameHeader(const uint8* data, - int size, - int* frame_size, - int* sample_rate, - ChannelLayout* channel_layout, - int* sample_count) const OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(ADTSStreamParser); -}; - -} // namespace media - -#endif // MEDIA_FORMATS_MPEG_ADTS_STREAM_PARSER_H_ diff --git a/media/formats/mpeg/adts_stream_parser_unittest.cc b/media/formats/mpeg/adts_stream_parser_unittest.cc deleted file mode 100644 index d0bedbe..0000000 --- a/media/formats/mpeg/adts_stream_parser_unittest.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/formats/common/stream_parser_test_base.h" -#include "media/formats/mpeg/adts_stream_parser.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { - -class ADTSStreamParserTest : public StreamParserTestBase, public testing::Test { - public: - ADTSStreamParserTest() - : StreamParserTestBase( - scoped_ptr<StreamParser>(new ADTSStreamParser()).Pass()) {} - virtual ~ADTSStreamParserTest() {} -}; - -// Test parsing with small prime sized chunks to smoke out "power of -// 2" field size assumptions. -TEST_F(ADTSStreamParserTest, UnalignedAppend) { - const std::string expected = - "NewSegment" - "{ 0K }" - "{ 23K }" - "{ 46K }" - "{ 69K }" - "{ 92K }" - "{ 116K }" - "{ 139K }" - "{ 162K }" - "{ 185K }" - "EndOfSegment" - "NewSegment" - "{ 208K }" - "{ 232K }" - "{ 255K }" - "{ 278K }" - "{ 301K }" - "EndOfSegment"; - EXPECT_EQ(expected, ParseFile("sfx.adts", 17)); -} - -// Test parsing with a larger piece size to verify that multiple buffers -// are passed to |new_buffer_cb_|. -TEST_F(ADTSStreamParserTest, UnalignedAppend512) { - const std::string expected = - "NewSegment" - "{ 0K 23K 46K }" - "{ 69K 92K 116K 139K 162K }" - "{ 185K 208K 232K 255K 278K }" - "EndOfSegment" - "NewSegment" - "{ 301K }" - "EndOfSegment"; - EXPECT_EQ(expected, ParseFile("sfx.adts", 512)); -} - -} // namespace media diff --git a/media/formats/mpeg/mp3_stream_parser.cc b/media/formats/mpeg/mp3_stream_parser.cc deleted file mode 100644 index 74d2f7d..0000000 --- a/media/formats/mpeg/mp3_stream_parser.cc +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/formats/mpeg/mp3_stream_parser.h" - -namespace media { - -static const uint32 kMP3StartCodeMask = 0xffe00000; - -// Map that determines which bitrate_index & channel_mode combinations -// are allowed. -// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -static const bool kIsAllowed[17][4] = { - { true, true, true, true }, // free - { true, false, false, false }, // 32 - { true, false, false, false }, // 48 - { true, false, false, false }, // 56 - { true, true, true, true }, // 64 - { true, false, false, false }, // 80 - { true, true, true, true }, // 96 - { true, true, true, true }, // 112 - { true, true, true, true }, // 128 - { true, true, true, true }, // 160 - { true, true, true, true }, // 192 - { false, true, true, true }, // 224 - { false, true, true, true }, // 256 - { false, true, true, true }, // 320 - { false, true, true, true }, // 384 - { false, false, false, false } // bad -}; - -// Maps version and layer information in the frame header -// into an index for the |kBitrateMap|. -// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -static const int kVersionLayerMap[4][4] = { - // { reserved, L3, L2, L1 } - { 5, 4, 4, 3 }, // MPEG 2.5 - { 5, 5, 5, 5 }, // reserved - { 5, 4, 4, 3 }, // MPEG 2 - { 5, 2, 1, 0 } // MPEG 1 -}; - -// Maps the bitrate index field in the header and an index -// from |kVersionLayerMap| to a frame bitrate. -// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -static const int kBitrateMap[16][6] = { - // { V1L1, V1L2, V1L3, V2L1, V2L2 & V2L3, reserved } - { 0, 0, 0, 0, 0, 0 }, - { 32, 32, 32, 32, 8, 0 }, - { 64, 48, 40, 48, 16, 0 }, - { 96, 56, 48, 56, 24, 0 }, - { 128, 64, 56, 64, 32, 0 }, - { 160, 80, 64, 80, 40, 0 }, - { 192, 96, 80, 96, 48, 0 }, - { 224, 112, 96, 112, 56, 0 }, - { 256, 128, 112, 128, 64, 0 }, - { 288, 160, 128, 144, 80, 0 }, - { 320, 192, 160, 160, 96, 0 }, - { 352, 224, 192, 176, 112, 0 }, - { 384, 256, 224, 192, 128, 0 }, - { 416, 320, 256, 224, 144, 0 }, - { 448, 384, 320, 256, 160, 0 }, - { 0, 0, 0, 0, 0} -}; - -// Maps the sample rate index and version fields from the frame header -// to a sample rate. -// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -static const int kSampleRateMap[4][4] = { - // { V2.5, reserved, V2, V1 } - { 11025, 0, 22050, 44100 }, - { 12000, 0, 24000, 48000 }, - { 8000, 0, 16000, 32000 }, - { 0, 0, 0, 0 } -}; - -// Frame header field constants. -static const int kVersion2 = 2; -static const int kVersionReserved = 1; -static const int kVersion2_5 = 0; -static const int kLayerReserved = 0; -static const int kLayer1 = 3; -static const int kLayer2 = 2; -static const int kLayer3 = 1; -static const int kBitrateFree = 0; -static const int kBitrateBad = 0xf; -static const int kSampleRateReserved = 3; - -MP3StreamParser::MP3StreamParser() - : MPEGAudioStreamParserBase(kMP3StartCodeMask, kCodecMP3) {} - -MP3StreamParser::~MP3StreamParser() {} - -int MP3StreamParser::ParseFrameHeader(const uint8* data, - int size, - int* frame_size, - int* sample_rate, - ChannelLayout* channel_layout, - int* sample_count) const { - DCHECK(data); - DCHECK_GE(size, 0); - DCHECK(frame_size); - - if (size < 4) - return 0; - - BitReader reader(data, size); - int sync; - int version; - int layer; - int is_protected; - int bitrate_index; - int sample_rate_index; - int has_padding; - int is_private; - int channel_mode; - int other_flags; - - if (!reader.ReadBits(11, &sync) || - !reader.ReadBits(2, &version) || - !reader.ReadBits(2, &layer) || - !reader.ReadBits(1, &is_protected) || - !reader.ReadBits(4, &bitrate_index) || - !reader.ReadBits(2, &sample_rate_index) || - !reader.ReadBits(1, &has_padding) || - !reader.ReadBits(1, &is_private) || - !reader.ReadBits(2, &channel_mode) || - !reader.ReadBits(6, &other_flags)) { - return -1; - } - - DVLOG(2) << "Header data :" << std::hex - << " sync 0x" << sync - << " version 0x" << version - << " layer 0x" << layer - << " bitrate_index 0x" << bitrate_index - << " sample_rate_index 0x" << sample_rate_index - << " channel_mode 0x" << channel_mode; - - if (sync != 0x7ff || - version == kVersionReserved || - layer == kLayerReserved || - bitrate_index == kBitrateFree || bitrate_index == kBitrateBad || - sample_rate_index == kSampleRateReserved) { - MEDIA_LOG(log_cb()) << "Invalid header data :" << std::hex - << " sync 0x" << sync - << " version 0x" << version - << " layer 0x" << layer - << " bitrate_index 0x" << bitrate_index - << " sample_rate_index 0x" << sample_rate_index - << " channel_mode 0x" << channel_mode; - return -1; - } - - if (layer == kLayer2 && kIsAllowed[bitrate_index][channel_mode]) { - MEDIA_LOG(log_cb()) << "Invalid (bitrate_index, channel_mode) combination :" - << std::hex - << " bitrate_index " << bitrate_index - << " channel_mode " << channel_mode; - return -1; - } - - int bitrate = kBitrateMap[bitrate_index][kVersionLayerMap[version][layer]]; - - if (bitrate == 0) { - MEDIA_LOG(log_cb()) << "Invalid bitrate :" << std::hex - << " version " << version - << " layer " << layer - << " bitrate_index " << bitrate_index; - return -1; - } - - DVLOG(2) << " bitrate " << bitrate; - - int frame_sample_rate = kSampleRateMap[sample_rate_index][version]; - if (frame_sample_rate == 0) { - MEDIA_LOG(log_cb()) << "Invalid sample rate :" << std::hex - << " version " << version - << " sample_rate_index " << sample_rate_index; - return -1; - } - - if (sample_rate) - *sample_rate = frame_sample_rate; - - // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf - // Table 2.1.5 - int samples_per_frame; - switch (layer) { - case kLayer1: - samples_per_frame = 384; - break; - - case kLayer2: - samples_per_frame = 1152; - break; - - case kLayer3: - if (version == kVersion2 || version == kVersion2_5) - samples_per_frame = 576; - else - samples_per_frame = 1152; - break; - - default: - return -1; - } - - if (sample_count) - *sample_count = samples_per_frame; - - // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf - // Text just below Table 2.1.5. - if (layer == kLayer1) { - // This formulation is a slight variation on the equation below, - // but has slightly different truncation characteristics to deal - // with the fact that Layer 1 has 4 byte "slots" instead of single - // byte ones. - *frame_size = 4 * (12 * bitrate * 1000 / frame_sample_rate); - } else { - *frame_size = - ((samples_per_frame / 8) * bitrate * 1000) / frame_sample_rate; - } - - if (has_padding) - *frame_size += (layer == kLayer1) ? 4 : 1; - - if (channel_layout) { - // Map Stereo(0), Joint Stereo(1), and Dual Channel (2) to - // CHANNEL_LAYOUT_STEREO and Single Channel (3) to CHANNEL_LAYOUT_MONO. - *channel_layout = - (channel_mode == 3) ? CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO; - } - - return 4; -} - -} // namespace media diff --git a/media/formats/mpeg/mp3_stream_parser.h b/media/formats/mpeg/mp3_stream_parser.h deleted file mode 100644 index 209d263..0000000 --- a/media/formats/mpeg/mp3_stream_parser.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_FORMATS_MPEG_MP3_STREAM_PARSER_H_ -#define MEDIA_FORMATS_MPEG_MP3_STREAM_PARSER_H_ - -#include "base/basictypes.h" -#include "media/base/media_export.h" -#include "media/formats/mpeg/mpeg_audio_stream_parser_base.h" - -namespace media { - -class MEDIA_EXPORT MP3StreamParser : public MPEGAudioStreamParserBase { - public: - MP3StreamParser(); - virtual ~MP3StreamParser(); - - private: - // MPEGAudioStreamParserBase overrides. - virtual int ParseFrameHeader(const uint8* data, - int size, - int* frame_size, - int* sample_rate, - ChannelLayout* channel_layout, - int* sample_count) const OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(MP3StreamParser); -}; - -} // namespace media - -#endif // MEDIA_FORMATS_MPEG_MP3_STREAM_PARSER_H_ diff --git a/media/formats/mpeg/mp3_stream_parser_unittest.cc b/media/formats/mpeg/mp3_stream_parser_unittest.cc deleted file mode 100644 index eefadc5..0000000 --- a/media/formats/mpeg/mp3_stream_parser_unittest.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/formats/common/stream_parser_test_base.h" -#include "media/formats/mpeg/mp3_stream_parser.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { - -class MP3StreamParserTest : public StreamParserTestBase, public testing::Test { - public: - MP3StreamParserTest() - : StreamParserTestBase( - scoped_ptr<StreamParser>(new MP3StreamParser()).Pass()) {} - virtual ~MP3StreamParserTest() {} -}; - -// Test parsing with small prime sized chunks to smoke out "power of -// 2" field size assumptions. -TEST_F(MP3StreamParserTest, UnalignedAppend) { - const std::string expected = - "NewSegment" - "{ 0K }" - "{ 26K }" - "{ 52K }" - "{ 78K }" - "{ 104K }" - "{ 130K }" - "{ 156K }" - "{ 182K }" - "EndOfSegment" - "NewSegment" - "{ 208K }" - "{ 235K }" - "{ 261K }" - "EndOfSegment" - "NewSegment" - "{ 287K }" - "{ 313K }" - "EndOfSegment"; - EXPECT_EQ(expected, ParseFile("sfx.mp3", 17)); -} - -// Test parsing with a larger piece size to verify that multiple buffers -// are passed to |new_buffer_cb_|. -TEST_F(MP3StreamParserTest, UnalignedAppend512) { - const std::string expected = - "NewSegment" - "{ 0K }" - "{ 26K 52K 78K 104K }" - "EndOfSegment" - "NewSegment" - "{ 130K 156K 182K }" - "{ 208K 235K 261K 287K }" - "{ 313K }" - "EndOfSegment"; - EXPECT_EQ(expected, ParseFile("sfx.mp3", 512)); -} - -} // namespace media diff --git a/media/media.gyp b/media/media.gyp index 6638f5b..2fc8898 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -855,6 +855,8 @@ 'formats/mp2t/ts_section_pmt.h', 'formats/mp2t/ts_section_psi.cc', 'formats/mp2t/ts_section_psi.h', + 'formats/mp3/mp3_stream_parser.cc', + 'formats/mp3/mp3_stream_parser.h', 'formats/mp4/aac.cc', 'formats/mp4/aac.h', 'formats/mp4/avc.cc', @@ -871,14 +873,6 @@ 'formats/mp4/mp4_stream_parser.h', 'formats/mp4/track_run_iterator.cc', 'formats/mp4/track_run_iterator.h', - 'formats/mpeg/adts_constants.cc', - 'formats/mpeg/adts_constants.h', - 'formats/mpeg/adts_stream_parser.cc', - 'formats/mpeg/adts_stream_parser.h', - 'formats/mpeg/mp3_stream_parser.cc', - 'formats/mpeg/mp3_stream_parser.h', - 'formats/mpeg/mpeg_audio_stream_parser_base.cc', - 'formats/mpeg/mpeg_audio_stream_parser_base.h', ], }], ['toolkit_uses_gtk==1', { @@ -1140,17 +1134,14 @@ }], ['proprietary_codecs==1', { 'sources': [ - 'formats/common/stream_parser_test_base.cc', - 'formats/common/stream_parser_test_base.h', 'formats/mp2t/mp2t_stream_parser_unittest.cc', + 'formats/mp3/mp3_stream_parser_unittest.cc', 'formats/mp4/aac_unittest.cc', 'formats/mp4/avc_unittest.cc', 'formats/mp4/box_reader_unittest.cc', 'formats/mp4/es_descriptor_unittest.cc', 'formats/mp4/mp4_stream_parser_unittest.cc', 'formats/mp4/track_run_iterator_unittest.cc', - 'formats/mpeg/adts_stream_parser_unittest.cc', - 'formats/mpeg/mp3_stream_parser_unittest.cc', ], }], # TODO(wolenetz): Fix size_t to int truncations in win64. See |