1// Copyright 2013 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 "base/basictypes.h"
6#include "base/bind.h"
7#include "base/message_loop/message_loop.h"
8#include "media/base/decoder_buffer.h"
9#include "media/base/mock_filters.h"
10#include "media/base/test_helpers.h"
11#include "media/base/video_frame.h"
12#include "media/filters/fake_video_decoder.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace media {
16
17static const int kTotalBuffers = 12;
18static const int kDurationMs = 30;
19
20struct FakeVideoDecoderTestParams {
21  FakeVideoDecoderTestParams(int decoding_delay, int max_decode_requests)
22      : decoding_delay(decoding_delay),
23        max_decode_requests(max_decode_requests) {}
24  int decoding_delay;
25  int max_decode_requests;
26};
27
28class FakeVideoDecoderTest
29    : public testing::Test,
30      public testing::WithParamInterface<FakeVideoDecoderTestParams> {
31 public:
32  FakeVideoDecoderTest()
33      : decoder_(new FakeVideoDecoder(GetParam().decoding_delay,
34                                      GetParam().max_decode_requests)),
35        num_input_buffers_(0),
36        num_decoded_frames_(0),
37        last_decode_status_(VideoDecoder::kOk),
38        pending_decode_requests_(0),
39        is_reset_pending_(false) {}
40
41  virtual ~FakeVideoDecoderTest() {
42    Destroy();
43  }
44
45  void InitializeWithConfig(const VideoDecoderConfig& config) {
46    decoder_->Initialize(
47        config, false, NewExpectedStatusCB(PIPELINE_OK),
48        base::Bind(&FakeVideoDecoderTest::FrameReady, base::Unretained(this)));
49    message_loop_.RunUntilIdle();
50    current_config_ = config;
51  }
52
53  void Initialize() {
54    InitializeWithConfig(TestVideoConfig::Normal());
55  }
56
57  void EnterPendingInitState() {
58    decoder_->HoldNextInit();
59    Initialize();
60  }
61
62  void SatisfyInit() {
63    decoder_->SatisfyInit();
64    message_loop_.RunUntilIdle();
65  }
66
67  // Callback for VideoDecoder::Decode().
68  void DecodeDone(VideoDecoder::Status status) {
69    DCHECK_GT(pending_decode_requests_, 0);
70    --pending_decode_requests_;
71    last_decode_status_ = status;
72  }
73
74  void FrameReady(const scoped_refptr<VideoFrame>& frame) {
75    DCHECK(!frame->end_of_stream());
76    last_decoded_frame_ = frame;
77    num_decoded_frames_++;
78  }
79
80  enum CallbackResult {
81    PENDING,
82    OK,
83    NOT_ENOUGH_DATA,
84    ABORTED
85  };
86
87  void ExpectReadResult(CallbackResult result) {
88    switch (result) {
89      case PENDING:
90        EXPECT_GT(pending_decode_requests_, 0);
91        break;
92      case OK:
93        EXPECT_EQ(0, pending_decode_requests_);
94        ASSERT_EQ(VideoDecoder::kOk, last_decode_status_);
95        ASSERT_TRUE(last_decoded_frame_.get());
96        break;
97      case NOT_ENOUGH_DATA:
98        EXPECT_EQ(0, pending_decode_requests_);
99        ASSERT_EQ(VideoDecoder::kOk, last_decode_status_);
100        ASSERT_FALSE(last_decoded_frame_.get());
101        break;
102      case ABORTED:
103        EXPECT_EQ(0, pending_decode_requests_);
104        ASSERT_EQ(VideoDecoder::kAborted, last_decode_status_);
105        EXPECT_FALSE(last_decoded_frame_.get());
106        break;
107    }
108  }
109
110  void Decode() {
111    scoped_refptr<DecoderBuffer> buffer;
112
113    if (num_input_buffers_ < kTotalBuffers) {
114      buffer = CreateFakeVideoBufferForTest(
115          current_config_,
116          base::TimeDelta::FromMilliseconds(kDurationMs * num_input_buffers_),
117          base::TimeDelta::FromMilliseconds(kDurationMs));
118    } else {
119      buffer = DecoderBuffer::CreateEOSBuffer();
120    }
121
122    ++num_input_buffers_;
123    ++pending_decode_requests_;
124
125    decoder_->Decode(
126        buffer,
127        base::Bind(&FakeVideoDecoderTest::DecodeDone, base::Unretained(this)));
128    message_loop_.RunUntilIdle();
129  }
130
131  void ReadOneFrame() {
132    last_decoded_frame_ = NULL;
133    do {
134      Decode();
135    } while (!last_decoded_frame_.get() && pending_decode_requests_ == 0);
136  }
137
138  void ReadAllFrames() {
139    do {
140      Decode();
141    } while (num_input_buffers_ <= kTotalBuffers); // All input buffers + EOS.
142  }
143
144  void EnterPendingReadState() {
145    // Pass the initial NOT_ENOUGH_DATA stage.
146    ReadOneFrame();
147    decoder_->HoldDecode();
148    ReadOneFrame();
149    ExpectReadResult(PENDING);
150  }
151
152  void SatisfyDecodeAndExpect(CallbackResult result) {
153    decoder_->SatisfyDecode();
154    message_loop_.RunUntilIdle();
155    ExpectReadResult(result);
156  }
157
158  void SatisfyRead() {
159    SatisfyDecodeAndExpect(OK);
160  }
161
162  // Callback for VideoDecoder::Reset().
163  void OnDecoderReset() {
164    DCHECK(is_reset_pending_);
165    is_reset_pending_ = false;
166  }
167
168  void ExpectResetResult(CallbackResult result) {
169    switch (result) {
170      case PENDING:
171        EXPECT_TRUE(is_reset_pending_);
172        break;
173      case OK:
174        EXPECT_FALSE(is_reset_pending_);
175        break;
176      default:
177        NOTREACHED();
178    }
179  }
180
181  void ResetAndExpect(CallbackResult result) {
182    is_reset_pending_ = true;
183    decoder_->Reset(base::Bind(&FakeVideoDecoderTest::OnDecoderReset,
184                               base::Unretained(this)));
185    message_loop_.RunUntilIdle();
186    ExpectResetResult(result);
187  }
188
189  void EnterPendingResetState() {
190    decoder_->HoldNextReset();
191    ResetAndExpect(PENDING);
192  }
193
194  void SatisfyReset() {
195    decoder_->SatisfyReset();
196    message_loop_.RunUntilIdle();
197    ExpectResetResult(OK);
198  }
199
200  void Destroy() {
201    decoder_.reset();
202    message_loop_.RunUntilIdle();
203
204    // All pending callbacks must have been fired.
205    DCHECK_EQ(pending_decode_requests_, 0);
206    DCHECK(!is_reset_pending_);
207  }
208
209  base::MessageLoop message_loop_;
210  VideoDecoderConfig current_config_;
211
212  scoped_ptr<FakeVideoDecoder> decoder_;
213
214  int num_input_buffers_;
215  int num_decoded_frames_;
216
217  // Callback result/status.
218  VideoDecoder::Status last_decode_status_;
219  scoped_refptr<VideoFrame> last_decoded_frame_;
220  int pending_decode_requests_;
221  bool is_reset_pending_;
222
223 private:
224  DISALLOW_COPY_AND_ASSIGN(FakeVideoDecoderTest);
225};
226
227INSTANTIATE_TEST_CASE_P(NoParallelDecode,
228                        FakeVideoDecoderTest,
229                        ::testing::Values(FakeVideoDecoderTestParams(9, 1),
230                                          FakeVideoDecoderTestParams(0, 1)));
231INSTANTIATE_TEST_CASE_P(ParallelDecode,
232                        FakeVideoDecoderTest,
233                        ::testing::Values(FakeVideoDecoderTestParams(9, 3),
234                                          FakeVideoDecoderTestParams(0, 3)));
235
236TEST_P(FakeVideoDecoderTest, Initialize) {
237  Initialize();
238}
239
240TEST_P(FakeVideoDecoderTest, Read_AllFrames) {
241  Initialize();
242  ReadAllFrames();
243  EXPECT_EQ(kTotalBuffers, num_decoded_frames_);
244}
245
246TEST_P(FakeVideoDecoderTest, Read_DecodingDelay) {
247  Initialize();
248
249  while (num_input_buffers_ < kTotalBuffers) {
250    ReadOneFrame();
251    EXPECT_EQ(num_input_buffers_,
252              num_decoded_frames_ + GetParam().decoding_delay);
253  }
254}
255
256TEST_P(FakeVideoDecoderTest, Read_ZeroDelay) {
257  decoder_.reset(new FakeVideoDecoder(0, 1));
258  Initialize();
259
260  while (num_input_buffers_ < kTotalBuffers) {
261    ReadOneFrame();
262    EXPECT_EQ(num_input_buffers_, num_decoded_frames_);
263  }
264}
265
266TEST_P(FakeVideoDecoderTest, Read_Pending_NotEnoughData) {
267  if (GetParam().decoding_delay < 1)
268    return;
269
270  Initialize();
271  decoder_->HoldDecode();
272  ReadOneFrame();
273  ExpectReadResult(PENDING);
274  SatisfyDecodeAndExpect(NOT_ENOUGH_DATA);
275
276  // Verify that FrameReady() hasn't been called.
277  EXPECT_FALSE(last_decoded_frame_.get());
278}
279
280TEST_P(FakeVideoDecoderTest, Read_Pending_OK) {
281  Initialize();
282  EnterPendingReadState();
283  SatisfyDecodeAndExpect(OK);
284}
285
286TEST_P(FakeVideoDecoderTest, Read_Parallel) {
287  if (GetParam().max_decode_requests < 2)
288    return;
289
290  Initialize();
291  decoder_->HoldDecode();
292  for (int i = 0; i < GetParam().max_decode_requests; ++i) {
293    ReadOneFrame();
294    ExpectReadResult(PENDING);
295  }
296  EXPECT_EQ(GetParam().max_decode_requests, pending_decode_requests_);
297  SatisfyDecodeAndExpect(
298      GetParam().max_decode_requests > GetParam().decoding_delay
299          ? OK
300          : NOT_ENOUGH_DATA);
301}
302
303TEST_P(FakeVideoDecoderTest, ReadWithHold_DecodingDelay) {
304  Initialize();
305
306  // Hold all decodes and satisfy one decode at a time.
307  decoder_->HoldDecode();
308  int num_decodes_satisfied = 0;
309  while (num_decoded_frames_ == 0) {
310    while (pending_decode_requests_ < decoder_->GetMaxDecodeRequests())
311      Decode();
312    decoder_->SatisfySingleDecode();
313    ++num_decodes_satisfied;
314    message_loop_.RunUntilIdle();
315  }
316
317  DCHECK_EQ(num_decoded_frames_, 1);
318  DCHECK_EQ(num_decodes_satisfied, GetParam().decoding_delay + 1);
319}
320
321TEST_P(FakeVideoDecoderTest, Reinitialize) {
322  Initialize();
323  ReadOneFrame();
324  InitializeWithConfig(TestVideoConfig::Large());
325  ReadOneFrame();
326}
327
328// Reinitializing the decoder during the middle of the decoding process can
329// cause dropped frames.
330TEST_P(FakeVideoDecoderTest, Reinitialize_FrameDropped) {
331  if (GetParam().decoding_delay < 1)
332    return;
333
334  Initialize();
335  ReadOneFrame();
336  Initialize();
337  ReadAllFrames();
338  EXPECT_LT(num_decoded_frames_, kTotalBuffers);
339}
340
341TEST_P(FakeVideoDecoderTest, Reset) {
342  Initialize();
343  ReadOneFrame();
344  ResetAndExpect(OK);
345}
346
347TEST_P(FakeVideoDecoderTest, Reset_DuringPendingRead) {
348  Initialize();
349  EnterPendingReadState();
350  ResetAndExpect(PENDING);
351  SatisfyDecodeAndExpect(ABORTED);
352}
353
354TEST_P(FakeVideoDecoderTest, Reset_Pending) {
355  Initialize();
356  EnterPendingResetState();
357  SatisfyReset();
358}
359
360TEST_P(FakeVideoDecoderTest, Reset_PendingDuringPendingRead) {
361  Initialize();
362  EnterPendingReadState();
363  EnterPendingResetState();
364  SatisfyDecodeAndExpect(ABORTED);
365  SatisfyReset();
366}
367
368TEST_P(FakeVideoDecoderTest, Destroy) {
369  Initialize();
370  ReadOneFrame();
371  ExpectReadResult(OK);
372  Destroy();
373}
374
375TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingInitialization) {
376  EnterPendingInitState();
377  Destroy();
378}
379
380TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingRead) {
381  Initialize();
382  EnterPendingReadState();
383  Destroy();
384}
385
386TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingReset) {
387  Initialize();
388  EnterPendingResetState();
389  Destroy();
390}
391
392TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingReadAndPendingReset) {
393  Initialize();
394  EnterPendingReadState();
395  EnterPendingResetState();
396  Destroy();
397}
398
399}  // namespace media
400