| // Copyright 2013 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/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) { |
| EXPECT_FALSE(audio_buffers.empty()); |
| EXPECT_TRUE(video_buffers.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)), |
| StreamParser::NewTextBuffersCB(), |
| 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 |