Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / filters / opus_audio_decoder_unittest.cc
1 // Copyright 2014 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 "media/base/audio_buffer.h"
11 #include "media/base/decoder_buffer.h"
12 #include "media/base/test_data_util.h"
13 #include "media/base/test_helpers.h"
14 #include "media/ffmpeg/ffmpeg_common.h"
15 #include "media/filters/audio_file_reader.h"
16 #include "media/filters/in_memory_url_protocol.h"
17 #include "media/filters/opus_audio_decoder.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace media {
21
22 class OpusAudioDecoderTest : public testing::Test {
23  public:
24   OpusAudioDecoderTest()
25       : decoder_(new OpusAudioDecoder(message_loop_.message_loop_proxy())),
26         pending_decode_(false),
27         pending_reset_(false) {
28     // Load the test data file.
29     data_ = ReadTestDataFile("bear-opus.ogg");
30     protocol_.reset(
31         new InMemoryUrlProtocol(data_->data(), data_->data_size(), false));
32     reader_.reset(new AudioFileReader(protocol_.get()));
33     reader_->Open();
34
35     AudioDecoderConfig config;
36     AVCodecContextToAudioDecoderConfig(
37         reader_->codec_context_for_testing(), false, &config, false);
38     decoder_->Initialize(config, NewExpectedStatusCB(PIPELINE_OK));
39     base::RunLoop().RunUntilIdle();
40   }
41
42   virtual ~OpusAudioDecoderTest() {
43     EXPECT_FALSE(pending_decode_);
44     EXPECT_FALSE(pending_reset_);
45   }
46
47  protected:
48   void SatisfyPendingDecode() { base::RunLoop().RunUntilIdle(); }
49
50   void SendEndOfStream() {
51     pending_decode_ = true;
52     decoder_->Decode(DecoderBuffer::CreateEOSBuffer(),
53                      base::Bind(&OpusAudioDecoderTest::DecodeFinished,
54                                 base::Unretained(this)));
55     base::RunLoop().RunUntilIdle();
56   }
57
58   void Decode() {
59     pending_decode_ = true;
60
61     AVPacket packet;
62     ASSERT_TRUE(reader_->ReadPacketForTesting(&packet));
63     scoped_refptr<DecoderBuffer> buffer =
64         DecoderBuffer::CopyFrom(packet.data, packet.size);
65     buffer->set_timestamp(ConvertFromTimeBase(
66         reader_->codec_context_for_testing()->time_base, packet.pts));
67     buffer->set_duration(ConvertFromTimeBase(
68         reader_->codec_context_for_testing()->time_base, packet.duration));
69     decoder_->Decode(buffer,
70                      base::Bind(&OpusAudioDecoderTest::DecodeFinished,
71                                 base::Unretained(this)));
72     av_free_packet(&packet);
73     base::RunLoop().RunUntilIdle();
74   }
75
76   void Reset() {
77     pending_reset_ = true;
78     decoder_->Reset(base::Bind(&OpusAudioDecoderTest::ResetFinished,
79                                base::Unretained(this)));
80     base::RunLoop().RunUntilIdle();
81   }
82
83   void Stop() {
84     decoder_->Stop();
85     base::RunLoop().RunUntilIdle();
86   }
87
88   void DecodeFinished(AudioDecoder::Status status,
89                       const scoped_refptr<AudioBuffer>& buffer) {
90     EXPECT_TRUE(pending_decode_);
91     pending_decode_ = false;
92
93     if (status == AudioDecoder::kNotEnoughData) {
94       EXPECT_TRUE(buffer.get() == NULL);
95       Decode();
96       return;
97     }
98
99     decoded_audio_.push_back(buffer);
100
101     // If we hit a NULL buffer or have a pending reset, we expect an abort.
102     if (buffer.get() == NULL || pending_reset_) {
103       EXPECT_TRUE(buffer.get() == NULL);
104       EXPECT_EQ(status, AudioDecoder::kAborted);
105       return;
106     }
107
108     EXPECT_EQ(status, AudioDecoder::kOk);
109   }
110
111   void ResetFinished() {
112     EXPECT_TRUE(pending_reset_);
113     // Reset should always finish after Decode.
114     EXPECT_FALSE(pending_decode_);
115
116     pending_reset_ = false;
117   }
118
119   void ExpectDecodedAudio(size_t i, int64 timestamp, int64 duration) {
120     EXPECT_LT(i, decoded_audio_.size());
121     EXPECT_EQ(timestamp, decoded_audio_[i]->timestamp().InMicroseconds());
122     EXPECT_EQ(duration, decoded_audio_[i]->duration().InMicroseconds());
123     EXPECT_FALSE(decoded_audio_[i]->end_of_stream());
124   }
125
126   void ExpectEndOfStream(size_t i) {
127     EXPECT_LT(i, decoded_audio_.size());
128     EXPECT_TRUE(decoded_audio_[i]->end_of_stream());
129   }
130
131   size_t decoded_audio_size() const {
132     return decoded_audio_.size();
133   }
134
135  private:
136   base::MessageLoop message_loop_;
137   scoped_refptr<DecoderBuffer> data_;
138   scoped_ptr<InMemoryUrlProtocol> protocol_;
139   scoped_ptr<AudioFileReader> reader_;
140
141   scoped_ptr<OpusAudioDecoder> decoder_;
142   bool pending_decode_;
143   bool pending_reset_;
144
145   std::deque<scoped_refptr<AudioBuffer> > decoded_audio_;
146
147   DISALLOW_COPY_AND_ASSIGN(OpusAudioDecoderTest);
148 };
149
150 TEST_F(OpusAudioDecoderTest, Initialize) {
151   Stop();
152 }
153
154 TEST_F(OpusAudioDecoderTest, ProduceAudioSamples) {
155   Decode();
156   Decode();
157   Decode();
158
159   ASSERT_EQ(3u, decoded_audio_size());
160   ExpectDecodedAudio(0, 0, 3500);
161   ExpectDecodedAudio(1, 3500, 10000);
162   ExpectDecodedAudio(2, 13500, 10000);
163
164   // Call one more time to trigger EOS.
165   SendEndOfStream();
166   ASSERT_EQ(4u, decoded_audio_size());
167   ExpectEndOfStream(3);
168   Stop();
169 }
170
171 TEST_F(OpusAudioDecoderTest, DecodeAbort) {
172   Decode();
173   Stop();
174 }
175
176 TEST_F(OpusAudioDecoderTest, PendingDecode_Stop) {
177   Decode();
178   Stop();
179   SatisfyPendingDecode();
180 }
181
182 TEST_F(OpusAudioDecoderTest, PendingDecode_Reset) {
183   Decode();
184   Reset();
185   SatisfyPendingDecode();
186   Stop();
187 }
188
189 TEST_F(OpusAudioDecoderTest, PendingDecode_ResetStop) {
190   Decode();
191   Reset();
192   Stop();
193   SatisfyPendingDecode();
194 }
195
196 }  // namespace media