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.
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"
22 using ::testing::StrictMock;
26 ACTION_P(InvokeReadPacket, test) {
27 test->ReadPacket(arg0);
30 ACTION_P(EnterPendingDemuxerReadState, test) {
31 test->EnterPendingDemuxerRead(arg0);
34 class FFmpegAudioDecoderTest : public testing::Test {
36 FFmpegAudioDecoderTest()
37 : decoder_(new FFmpegAudioDecoder(message_loop_.message_loop_proxy())),
38 demuxer_(new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)),
40 pending_reset_(false),
41 pending_stop_(false) {
42 FFmpegGlue::InitializeFFmpeg();
44 vorbis_extradata_ = ReadTestDataFile("vorbis-extradata");
46 // Refer to media/test/data/README for details on vorbis test data.
47 for (int i = 0; i < 4; ++i) {
48 scoped_refptr<DecoderBuffer> buffer =
49 ReadTestDataFile(base::StringPrintf("vorbis-packet-%d", i));
52 buffer->set_timestamp(base::TimeDelta());
54 buffer->set_timestamp(base::TimeDelta::FromMicroseconds(2902));
57 buffer->set_duration(base::TimeDelta());
58 encoded_audio_.push_back(buffer);
61 // Push in an EOS buffer.
62 encoded_audio_.push_back(DecoderBuffer::CreateEOSBuffer());
67 virtual ~FFmpegAudioDecoderTest() {
68 EXPECT_FALSE(pending_read_);
69 EXPECT_FALSE(pending_reset_);
70 EXPECT_FALSE(pending_stop_);
74 AudioDecoderConfig config(kCodecVorbis,
75 kSampleFormatPlanarF32,
76 CHANNEL_LAYOUT_STEREO,
78 vorbis_extradata_->data(),
79 vorbis_extradata_->data_size(),
80 false); // Not encrypted.
81 demuxer_->set_audio_decoder_config(config);
82 decoder_->Initialize(demuxer_.get(),
83 NewExpectedStatusCB(PIPELINE_OK),
84 base::Bind(&MockStatisticsCB::OnStatistics,
85 base::Unretained(&statistics_cb_)));
86 base::RunLoop().RunUntilIdle();
89 void SetupPendingReadTest() {
90 encoded_audio_.clear();
91 encoded_audio_.push_back(NULL);
92 EXPECT_CALL(*demuxer_, Read(_))
93 .WillOnce(EnterPendingDemuxerReadState(this));
96 void ReadPacket(const DemuxerStream::ReadCB& read_cb) {
97 CHECK(!encoded_audio_.empty()) << "ReadPacket() called too many times";
99 scoped_refptr<DecoderBuffer> buffer(encoded_audio_.front());
100 DemuxerStream::Status status =
101 buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted;
102 encoded_audio_.pop_front();
103 read_cb.Run(status, buffer);
106 void EnterPendingDemuxerRead(const DemuxerStream::ReadCB& read_cb) {
107 // We just take note of it and ignore the callback, we'll expect it to be
108 // fired as a result of a Stop/Reset/etc.
109 DCHECK(pending_read_);
110 pending_demuxer_read_cb_ = read_cb;
113 void SatisfyPendingRead() {
114 DCHECK(pending_read_ && !pending_demuxer_read_cb_.is_null());
115 ReadPacket(pending_demuxer_read_cb_);
116 base::RunLoop().RunUntilIdle();
120 pending_read_ = true;
121 decoder_->Read(base::Bind(
122 &FFmpegAudioDecoderTest::ReadFinished, base::Unretained(this)));
123 base::RunLoop().RunUntilIdle();
127 pending_reset_ = true;
128 decoder_->Reset(base::Bind(
129 &FFmpegAudioDecoderTest::ResetFinished, base::Unretained(this)));
130 base::RunLoop().RunUntilIdle();
134 pending_stop_ = true;
135 decoder_->Stop(base::Bind(
136 &FFmpegAudioDecoderTest::StopFinished, base::Unretained(this)));
137 base::RunLoop().RunUntilIdle();
140 void ReadFinished(AudioDecoder::Status status,
141 const scoped_refptr<AudioBuffer>& buffer) {
142 EXPECT_TRUE(pending_read_);
143 pending_read_ = false;
145 decoded_audio_.push_back(buffer);
147 // If we hit a NULL buffer or have a pending reset, we expect an abort.
148 if (buffer.get() == NULL || pending_stop_ || pending_reset_) {
149 EXPECT_TRUE(buffer.get() == NULL);
150 EXPECT_EQ(status, AudioDecoder::kAborted);
154 EXPECT_EQ(status, AudioDecoder::kOk);
157 void PendingReadAborted(AudioDecoder::Status status,
158 const scoped_refptr<AudioBuffer>& buffer) {
159 EXPECT_EQ(status, AudioDecoder::kAborted);
160 EXPECT_TRUE(pending_read_);
161 pending_read_ = false;
164 void StopFinished() {
165 EXPECT_TRUE(pending_stop_);
166 // Stop should always finish after Read and Reset.
167 EXPECT_FALSE(pending_read_);
168 EXPECT_FALSE(pending_reset_);
170 pending_stop_ = false;
173 void ResetFinished() {
174 EXPECT_TRUE(pending_reset_);
175 // Reset should always finish after Read.
176 EXPECT_FALSE(pending_read_);
178 pending_reset_ = false;
181 void ExpectDecodedAudio(size_t i, int64 timestamp, int64 duration) {
182 EXPECT_LT(i, decoded_audio_.size());
183 EXPECT_EQ(timestamp, decoded_audio_[i]->timestamp().InMicroseconds());
184 EXPECT_EQ(duration, decoded_audio_[i]->duration().InMicroseconds());
185 EXPECT_FALSE(decoded_audio_[i]->end_of_stream());
188 void ExpectEndOfStream(size_t i) {
189 EXPECT_LT(i, decoded_audio_.size());
190 EXPECT_TRUE(decoded_audio_[i]->end_of_stream());
193 base::MessageLoop message_loop_;
194 scoped_ptr<FFmpegAudioDecoder> decoder_;
195 scoped_ptr<StrictMock<MockDemuxerStream> > demuxer_;
196 MockStatisticsCB statistics_cb_;
197 DemuxerStream::ReadCB pending_demuxer_read_cb_;
202 scoped_refptr<DecoderBuffer> vorbis_extradata_;
204 std::deque<scoped_refptr<DecoderBuffer> > encoded_audio_;
205 std::deque<scoped_refptr<AudioBuffer> > decoded_audio_;
208 TEST_F(FFmpegAudioDecoderTest, Initialize) {
209 const AudioDecoderConfig& config = demuxer_->audio_decoder_config();
210 EXPECT_EQ(config.bits_per_channel(), decoder_->bits_per_channel());
211 EXPECT_EQ(config.channel_layout(), decoder_->channel_layout());
212 EXPECT_EQ(config.samples_per_second(), decoder_->samples_per_second());
215 TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) {
216 // Vorbis requires N+1 packets to produce audio data for N packets.
218 // This will should result in the demuxer receiving three reads for two
219 // requests to produce audio samples.
220 EXPECT_CALL(*demuxer_, Read(_))
222 .WillRepeatedly(InvokeReadPacket(this));
223 EXPECT_CALL(statistics_cb_, OnStatistics(_))
230 ASSERT_EQ(3u, decoded_audio_.size());
231 ExpectDecodedAudio(0, 0, 2902);
232 ExpectDecodedAudio(1, 2902, 13061);
233 ExpectDecodedAudio(2, 15963, 23220);
235 // Call one more time to trigger EOS.
237 ASSERT_EQ(4u, decoded_audio_.size());
238 ExpectEndOfStream(3);
241 TEST_F(FFmpegAudioDecoderTest, ReadAbort) {
242 encoded_audio_.clear();
243 encoded_audio_.push_back(NULL);
244 EXPECT_CALL(*demuxer_, Read(_))
245 .WillOnce(InvokeReadPacket(this));
248 EXPECT_EQ(decoded_audio_.size(), 1u);
249 EXPECT_TRUE(decoded_audio_[0].get() == NULL);
252 TEST_F(FFmpegAudioDecoderTest, PendingRead_Stop) {
253 SetupPendingReadTest();
256 DCHECK(pending_read_ && pending_stop_);
257 SatisfyPendingRead();
260 TEST_F(FFmpegAudioDecoderTest, PendingRead_Reset) {
261 SetupPendingReadTest();
264 DCHECK(pending_read_ && pending_reset_);
265 SatisfyPendingRead();
268 TEST_F(FFmpegAudioDecoderTest, PendingRead_ResetStop) {
269 SetupPendingReadTest();
273 DCHECK(pending_read_ && pending_reset_ && pending_stop_);
274 SatisfyPendingRead();