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/strings/stringprintf.h"
10 #include "media/base/audio_buffer.h"
11 #include "media/base/decoder_buffer.h"
12 #include "media/base/mock_filters.h"
13 #include "media/base/test_data_util.h"
14 #include "media/base/test_helpers.h"
15 #include "media/ffmpeg/ffmpeg_common.h"
16 #include "media/filters/ffmpeg_audio_decoder.h"
17 #include "media/filters/ffmpeg_glue.h"
18 #include "testing/gtest/include/gtest/gtest.h"
21 using ::testing::StrictMock;
25 ACTION_P(InvokeReadPacket, test) {
26 test->ReadPacket(arg0);
29 class FFmpegAudioDecoderTest : public testing::Test {
31 FFmpegAudioDecoderTest()
32 : decoder_(new FFmpegAudioDecoder(message_loop_.message_loop_proxy())),
33 demuxer_(new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)) {
34 FFmpegGlue::InitializeFFmpeg();
36 vorbis_extradata_ = ReadTestDataFile("vorbis-extradata");
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));
44 buffer->set_timestamp(base::TimeDelta());
46 buffer->set_timestamp(base::TimeDelta::FromMicroseconds(2902));
49 buffer->set_duration(base::TimeDelta());
50 encoded_audio_.push_back(buffer);
53 // Push in an EOS buffer.
54 encoded_audio_.push_back(DecoderBuffer::CreateEOSBuffer());
57 virtual ~FFmpegAudioDecoderTest() {}
60 AudioDecoderConfig config(kCodecVorbis,
61 kSampleFormatPlanarF32,
62 CHANNEL_LAYOUT_STEREO,
64 vorbis_extradata_->data(),
65 vorbis_extradata_->data_size(),
66 false); // Not encrypted.
67 demuxer_->set_audio_decoder_config(config);
68 decoder_->Initialize(demuxer_.get(),
69 NewExpectedStatusCB(PIPELINE_OK),
70 base::Bind(&MockStatisticsCB::OnStatistics,
71 base::Unretained(&statistics_cb_)));
73 message_loop_.RunUntilIdle();
76 void ReadPacket(const DemuxerStream::ReadCB& read_cb) {
77 CHECK(!encoded_audio_.empty()) << "ReadPacket() called too many times";
79 scoped_refptr<DecoderBuffer> buffer(encoded_audio_.front());
80 DemuxerStream::Status status =
81 buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted;
82 encoded_audio_.pop_front();
83 read_cb.Run(status, buffer);
87 decoder_->Read(base::Bind(
88 &FFmpegAudioDecoderTest::DecodeFinished, base::Unretained(this)));
89 message_loop_.RunUntilIdle();
92 void DecodeFinished(AudioDecoder::Status status,
93 const scoped_refptr<AudioBuffer>& buffer) {
94 decoded_audio_.push_back(buffer);
97 void ExpectDecodedAudio(size_t i, int64 timestamp, int64 duration) {
98 EXPECT_LT(i, decoded_audio_.size());
99 EXPECT_EQ(timestamp, decoded_audio_[i]->timestamp().InMicroseconds());
100 EXPECT_EQ(duration, decoded_audio_[i]->duration().InMicroseconds());
101 EXPECT_FALSE(decoded_audio_[i]->end_of_stream());
104 void ExpectEndOfStream(size_t i) {
105 EXPECT_LT(i, decoded_audio_.size());
106 EXPECT_TRUE(decoded_audio_[i]->end_of_stream());
109 base::MessageLoop message_loop_;
110 scoped_ptr<FFmpegAudioDecoder> decoder_;
111 scoped_ptr<StrictMock<MockDemuxerStream> > demuxer_;
112 MockStatisticsCB statistics_cb_;
114 scoped_refptr<DecoderBuffer> vorbis_extradata_;
116 std::deque<scoped_refptr<DecoderBuffer> > encoded_audio_;
117 std::deque<scoped_refptr<AudioBuffer> > decoded_audio_;
120 TEST_F(FFmpegAudioDecoderTest, Initialize) {
123 const AudioDecoderConfig& config = demuxer_->audio_decoder_config();
124 EXPECT_EQ(config.bits_per_channel(), decoder_->bits_per_channel());
125 EXPECT_EQ(config.channel_layout(), decoder_->channel_layout());
126 EXPECT_EQ(config.samples_per_second(), decoder_->samples_per_second());
129 TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) {
132 // Vorbis requires N+1 packets to produce audio data for N packets.
134 // This will should result in the demuxer receiving three reads for two
135 // requests to produce audio samples.
136 EXPECT_CALL(*demuxer_, Read(_))
138 .WillRepeatedly(InvokeReadPacket(this));
139 EXPECT_CALL(statistics_cb_, OnStatistics(_))
146 ASSERT_EQ(3u, decoded_audio_.size());
147 ExpectDecodedAudio(0, 0, 2902);
148 ExpectDecodedAudio(1, 2902, 13061);
149 ExpectDecodedAudio(2, 15963, 23220);
151 // Call one more time to trigger EOS.
153 ASSERT_EQ(4u, decoded_audio_.size());
154 ExpectEndOfStream(3);
157 TEST_F(FFmpegAudioDecoderTest, ReadAbort) {
160 encoded_audio_.clear();
161 encoded_audio_.push_back(NULL);
163 EXPECT_CALL(*demuxer_, Read(_))
164 .WillOnce(InvokeReadPacket(this));
167 EXPECT_EQ(decoded_audio_.size(), 1u);
168 EXPECT_TRUE(decoded_audio_[0].get() == NULL);