- add sources.
[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/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"
19
20 using ::testing::_;
21 using ::testing::StrictMock;
22
23 namespace media {
24
25 ACTION_P(InvokeReadPacket, test) {
26   test->ReadPacket(arg0);
27 }
28
29 class FFmpegAudioDecoderTest : public testing::Test {
30  public:
31   FFmpegAudioDecoderTest()
32       : decoder_(new FFmpegAudioDecoder(message_loop_.message_loop_proxy())),
33         demuxer_(new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)) {
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
57   virtual ~FFmpegAudioDecoderTest() {}
58
59   void Initialize() {
60     AudioDecoderConfig config(kCodecVorbis,
61                               kSampleFormatPlanarF32,
62                               CHANNEL_LAYOUT_STEREO,
63                               44100,
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_)));
72
73     message_loop_.RunUntilIdle();
74   }
75
76   void ReadPacket(const DemuxerStream::ReadCB& read_cb) {
77     CHECK(!encoded_audio_.empty()) << "ReadPacket() called too many times";
78
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);
84   }
85
86   void Read() {
87     decoder_->Read(base::Bind(
88         &FFmpegAudioDecoderTest::DecodeFinished, base::Unretained(this)));
89     message_loop_.RunUntilIdle();
90   }
91
92   void DecodeFinished(AudioDecoder::Status status,
93                       const scoped_refptr<AudioBuffer>& buffer) {
94     decoded_audio_.push_back(buffer);
95   }
96
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());
102   }
103
104   void ExpectEndOfStream(size_t i) {
105     EXPECT_LT(i, decoded_audio_.size());
106     EXPECT_TRUE(decoded_audio_[i]->end_of_stream());
107   }
108
109   base::MessageLoop message_loop_;
110   scoped_ptr<FFmpegAudioDecoder> decoder_;
111   scoped_ptr<StrictMock<MockDemuxerStream> > demuxer_;
112   MockStatisticsCB statistics_cb_;
113
114   scoped_refptr<DecoderBuffer> vorbis_extradata_;
115
116   std::deque<scoped_refptr<DecoderBuffer> > encoded_audio_;
117   std::deque<scoped_refptr<AudioBuffer> > decoded_audio_;
118 };
119
120 TEST_F(FFmpegAudioDecoderTest, Initialize) {
121   Initialize();
122
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());
127 }
128
129 TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) {
130   Initialize();
131
132   // Vorbis requires N+1 packets to produce audio data for N packets.
133   //
134   // This will should result in the demuxer receiving three reads for two
135   // requests to produce audio samples.
136   EXPECT_CALL(*demuxer_, Read(_))
137       .Times(5)
138       .WillRepeatedly(InvokeReadPacket(this));
139   EXPECT_CALL(statistics_cb_, OnStatistics(_))
140       .Times(4);
141
142   Read();
143   Read();
144   Read();
145
146   ASSERT_EQ(3u, decoded_audio_.size());
147   ExpectDecodedAudio(0, 0, 2902);
148   ExpectDecodedAudio(1, 2902, 13061);
149   ExpectDecodedAudio(2, 15963, 23220);
150
151   // Call one more time to trigger EOS.
152   Read();
153   ASSERT_EQ(4u, decoded_audio_.size());
154   ExpectEndOfStream(3);
155 }
156
157 TEST_F(FFmpegAudioDecoderTest, ReadAbort) {
158   Initialize();
159
160   encoded_audio_.clear();
161   encoded_audio_.push_back(NULL);
162
163   EXPECT_CALL(*demuxer_, Read(_))
164       .WillOnce(InvokeReadPacket(this));
165   Read();
166
167   EXPECT_EQ(decoded_audio_.size(), 1u);
168   EXPECT_TRUE(decoded_audio_[0].get() ==  NULL);
169 }
170
171 }  // namespace media