Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / media / filters / ffmpeg_audio_decoder_unittest.cc
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 ACTION_P(InvokeReadPacket, test) {
27   test->ReadPacket(arg0);
28 }
29
30 ACTION_P(EnterPendingDemuxerReadState, test) {
31   test->EnterPendingDemuxerRead(arg0);
32 }
33
34 class FFmpegAudioDecoderTest : public testing::Test {
35  public:
36   FFmpegAudioDecoderTest()
37       : decoder_(new FFmpegAudioDecoder(message_loop_.message_loop_proxy())),
38         demuxer_(new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)),
39         pending_read_(false),
40         pending_reset_(false),
41         pending_stop_(false) {
42     FFmpegGlue::InitializeFFmpeg();
43
44     vorbis_extradata_ = ReadTestDataFile("vorbis-extradata");
45
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));
50
51       if (i < 3) {
52         buffer->set_timestamp(base::TimeDelta());
53       } else {
54         buffer->set_timestamp(base::TimeDelta::FromMicroseconds(2902));
55       }
56
57       buffer->set_duration(base::TimeDelta());
58       encoded_audio_.push_back(buffer);
59     }
60
61     // Push in an EOS buffer.
62     encoded_audio_.push_back(DecoderBuffer::CreateEOSBuffer());
63
64     Initialize();
65   }
66
67   virtual ~FFmpegAudioDecoderTest() {
68     EXPECT_FALSE(pending_read_);
69     EXPECT_FALSE(pending_reset_);
70     EXPECT_FALSE(pending_stop_);
71   }
72
73   void Initialize() {
74     AudioDecoderConfig config(kCodecVorbis,
75                               kSampleFormatPlanarF32,
76                               CHANNEL_LAYOUT_STEREO,
77                               44100,
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();
87   }
88
89   void SetupPendingReadTest() {
90     encoded_audio_.clear();
91     encoded_audio_.push_back(NULL);
92     EXPECT_CALL(*demuxer_, Read(_))
93         .WillOnce(EnterPendingDemuxerReadState(this));
94   }
95
96   void ReadPacket(const DemuxerStream::ReadCB& read_cb) {
97     CHECK(!encoded_audio_.empty()) << "ReadPacket() called too many times";
98
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);
104   }
105
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;
111   }
112
113   void SatisfyPendingRead() {
114     DCHECK(pending_read_ && !pending_demuxer_read_cb_.is_null());
115     ReadPacket(pending_demuxer_read_cb_);
116     base::RunLoop().RunUntilIdle();
117   }
118
119   void Read() {
120     pending_read_ = true;
121     decoder_->Read(base::Bind(
122         &FFmpegAudioDecoderTest::ReadFinished, base::Unretained(this)));
123     base::RunLoop().RunUntilIdle();
124   }
125
126   void Reset() {
127     pending_reset_ = true;
128     decoder_->Reset(base::Bind(
129         &FFmpegAudioDecoderTest::ResetFinished, base::Unretained(this)));
130     base::RunLoop().RunUntilIdle();
131   }
132
133   void Stop() {
134     pending_stop_ = true;
135     decoder_->Stop(base::Bind(
136         &FFmpegAudioDecoderTest::StopFinished, base::Unretained(this)));
137     base::RunLoop().RunUntilIdle();
138   }
139
140   void ReadFinished(AudioDecoder::Status status,
141                       const scoped_refptr<AudioBuffer>& buffer) {
142     EXPECT_TRUE(pending_read_);
143     pending_read_ = false;
144
145     decoded_audio_.push_back(buffer);
146
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);
151       return;
152     }
153
154     EXPECT_EQ(status, AudioDecoder::kOk);
155   }
156
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;
162   }
163
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_);
169
170     pending_stop_ = false;
171   }
172
173   void ResetFinished() {
174     EXPECT_TRUE(pending_reset_);
175     // Reset should always finish after Read.
176     EXPECT_FALSE(pending_read_);
177
178     pending_reset_ = false;
179   }
180
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());
186   }
187
188   void ExpectEndOfStream(size_t i) {
189     EXPECT_LT(i, decoded_audio_.size());
190     EXPECT_TRUE(decoded_audio_[i]->end_of_stream());
191   }
192
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_;
198   bool pending_read_;
199   bool pending_reset_;
200   bool pending_stop_;
201
202   scoped_refptr<DecoderBuffer> vorbis_extradata_;
203
204   std::deque<scoped_refptr<DecoderBuffer> > encoded_audio_;
205   std::deque<scoped_refptr<AudioBuffer> > decoded_audio_;
206 };
207
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());
213 }
214
215 TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) {
216   // Vorbis requires N+1 packets to produce audio data for N packets.
217   //
218   // This will should result in the demuxer receiving three reads for two
219   // requests to produce audio samples.
220   EXPECT_CALL(*demuxer_, Read(_))
221       .Times(5)
222       .WillRepeatedly(InvokeReadPacket(this));
223   EXPECT_CALL(statistics_cb_, OnStatistics(_))
224       .Times(4);
225
226   Read();
227   Read();
228   Read();
229
230   ASSERT_EQ(3u, decoded_audio_.size());
231   ExpectDecodedAudio(0, 0, 2902);
232   ExpectDecodedAudio(1, 2902, 13061);
233   ExpectDecodedAudio(2, 15963, 23220);
234
235   // Call one more time to trigger EOS.
236   Read();
237   ASSERT_EQ(4u, decoded_audio_.size());
238   ExpectEndOfStream(3);
239 }
240
241 TEST_F(FFmpegAudioDecoderTest, ReadAbort) {
242   encoded_audio_.clear();
243   encoded_audio_.push_back(NULL);
244   EXPECT_CALL(*demuxer_, Read(_))
245       .WillOnce(InvokeReadPacket(this));
246   Read();
247
248   EXPECT_EQ(decoded_audio_.size(), 1u);
249   EXPECT_TRUE(decoded_audio_[0].get() ==  NULL);
250 }
251
252 TEST_F(FFmpegAudioDecoderTest, PendingRead_Stop) {
253   SetupPendingReadTest();
254   Read();
255   Stop();
256   DCHECK(pending_read_ && pending_stop_);
257   SatisfyPendingRead();
258 }
259
260 TEST_F(FFmpegAudioDecoderTest, PendingRead_Reset) {
261   SetupPendingReadTest();
262   Read();
263   Reset();
264   DCHECK(pending_read_ && pending_reset_);
265   SatisfyPendingRead();
266 }
267
268 TEST_F(FFmpegAudioDecoderTest, PendingRead_ResetStop) {
269   SetupPendingReadTest();
270   Read();
271   Reset();
272   Stop();
273   DCHECK(pending_read_ && pending_reset_ && pending_stop_);
274   SatisfyPendingRead();
275 }
276
277 }  // namespace media