1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <deque> 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/run_loop.h" 10 #include "base/strings/stringprintf.h" 11 #include "media/base/audio_buffer.h" 12 #include "media/base/decoder_buffer.h" 13 #include "media/base/mock_filters.h" 14 #include "media/base/test_data_util.h" 15 #include "media/base/test_helpers.h" 16 #include "media/ffmpeg/ffmpeg_common.h" 17 #include "media/filters/ffmpeg_audio_decoder.h" 18 #include "media/filters/ffmpeg_glue.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 using ::testing::_; 22 using ::testing::StrictMock; 23 24 namespace media { 25 26 class FFmpegAudioDecoderTest : public testing::Test { 27 public: 28 FFmpegAudioDecoderTest() 29 : decoder_(new FFmpegAudioDecoder(message_loop_.message_loop_proxy(), 30 LogCB())), 31 pending_decode_(false), 32 pending_reset_(false), 33 last_decode_status_(AudioDecoder::kOk) { 34 FFmpegGlue::InitializeFFmpeg(); 35 36 vorbis_extradata_ = ReadTestDataFile("vorbis-extradata"); 37 38 // Refer to media/test/data/README for details on vorbis test data. 39 for (int i = 0; i < 4; ++i) { 40 scoped_refptr<DecoderBuffer> buffer = 41 ReadTestDataFile(base::StringPrintf("vorbis-packet-%d", i)); 42 43 if (i < 3) { 44 buffer->set_timestamp(base::TimeDelta()); 45 } else { 46 buffer->set_timestamp(base::TimeDelta::FromMicroseconds(2902)); 47 } 48 49 buffer->set_duration(base::TimeDelta()); 50 encoded_audio_.push_back(buffer); 51 } 52 53 // Push in an EOS buffer. 54 encoded_audio_.push_back(DecoderBuffer::CreateEOSBuffer()); 55 56 Initialize(); 57 } 58 59 virtual ~FFmpegAudioDecoderTest() { 60 EXPECT_FALSE(pending_decode_); 61 EXPECT_FALSE(pending_reset_); 62 } 63 64 void Initialize() { 65 AudioDecoderConfig config(kCodecVorbis, 66 kSampleFormatPlanarF32, 67 CHANNEL_LAYOUT_STEREO, 68 44100, 69 vorbis_extradata_->data(), 70 vorbis_extradata_->data_size(), 71 false); // Not encrypted. 72 decoder_->Initialize(config, 73 NewExpectedStatusCB(PIPELINE_OK), 74 base::Bind(&FFmpegAudioDecoderTest::OnDecoderOutput, 75 base::Unretained(this))); 76 base::RunLoop().RunUntilIdle(); 77 } 78 79 void SatisfyPendingDecode() { 80 base::RunLoop().RunUntilIdle(); 81 } 82 83 void Decode() { 84 pending_decode_ = true; 85 scoped_refptr<DecoderBuffer> buffer(encoded_audio_.front()); 86 encoded_audio_.pop_front(); 87 decoder_->Decode(buffer, 88 base::Bind(&FFmpegAudioDecoderTest::DecodeFinished, 89 base::Unretained(this))); 90 base::RunLoop().RunUntilIdle(); 91 EXPECT_FALSE(pending_decode_); 92 EXPECT_EQ(AudioDecoder::kOk, last_decode_status_); 93 } 94 95 void Reset() { 96 pending_reset_ = true; 97 decoder_->Reset(base::Bind( 98 &FFmpegAudioDecoderTest::ResetFinished, base::Unretained(this))); 99 base::RunLoop().RunUntilIdle(); 100 } 101 102 void Stop() { 103 decoder_->Stop(); 104 base::RunLoop().RunUntilIdle(); 105 } 106 107 void OnDecoderOutput(const scoped_refptr<AudioBuffer>& buffer) { 108 EXPECT_FALSE(buffer->end_of_stream()); 109 decoded_audio_.push_back(buffer); 110 } 111 112 void DecodeFinished(AudioDecoder::Status status) { 113 EXPECT_TRUE(pending_decode_); 114 pending_decode_ = false; 115 116 last_decode_status_ = status; 117 } 118 119 void ResetFinished() { 120 EXPECT_TRUE(pending_reset_); 121 // Reset should always finish after Decode. 122 EXPECT_FALSE(pending_decode_); 123 124 pending_reset_ = false; 125 } 126 127 void ExpectDecodedAudio(size_t i, int64 timestamp, int64 duration) { 128 EXPECT_LT(i, decoded_audio_.size()); 129 EXPECT_EQ(timestamp, decoded_audio_[i]->timestamp().InMicroseconds()); 130 EXPECT_EQ(duration, decoded_audio_[i]->duration().InMicroseconds()); 131 } 132 133 base::MessageLoop message_loop_; 134 scoped_ptr<FFmpegAudioDecoder> decoder_; 135 bool pending_decode_; 136 bool pending_reset_; 137 138 scoped_refptr<DecoderBuffer> vorbis_extradata_; 139 140 std::deque<scoped_refptr<DecoderBuffer> > encoded_audio_; 141 std::deque<scoped_refptr<AudioBuffer> > decoded_audio_; 142 AudioDecoder::Status last_decode_status_; 143 }; 144 145 TEST_F(FFmpegAudioDecoderTest, Initialize) { 146 AudioDecoderConfig config(kCodecVorbis, 147 kSampleFormatPlanarF32, 148 CHANNEL_LAYOUT_STEREO, 149 44100, 150 vorbis_extradata_->data(), 151 vorbis_extradata_->data_size(), 152 false); // Not encrypted. 153 Stop(); 154 } 155 156 TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) { 157 // Vorbis requires N+1 packets to produce audio data for N packets. 158 // 159 // This will should result in the demuxer receiving three reads for two 160 // requests to produce audio samples. 161 Decode(); 162 Decode(); 163 Decode(); 164 Decode(); 165 166 ASSERT_EQ(3u, decoded_audio_.size()); 167 ExpectDecodedAudio(0, 0, 2902); 168 ExpectDecodedAudio(1, 2902, 13061); 169 ExpectDecodedAudio(2, 15963, 23219); 170 171 // Call one more time with EOS. 172 Decode(); 173 ASSERT_EQ(3u, decoded_audio_.size()); 174 Stop(); 175 } 176 177 TEST_F(FFmpegAudioDecoderTest, PendingDecode_Stop) { 178 Decode(); 179 Stop(); 180 SatisfyPendingDecode(); 181 } 182 183 TEST_F(FFmpegAudioDecoderTest, PendingDecode_Reset) { 184 Decode(); 185 Reset(); 186 SatisfyPendingDecode(); 187 Stop(); 188 } 189 190 TEST_F(FFmpegAudioDecoderTest, PendingDecode_ResetStop) { 191 Decode(); 192 Reset(); 193 Stop(); 194 SatisfyPendingDecode(); 195 } 196 197 } // namespace media 198