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/bind.h"
6#include "base/message_loop/message_loop.h"
7#include "base/synchronization/waitable_event.h"
8#include "base/threading/thread.h"
9#include "content/renderer/media/rtc_video_decoder.h"
10#include "media/base/gmock_callback_support.h"
11#include "media/filters/mock_gpu_video_accelerator_factories.h"
12#include "media/video/mock_video_decode_accelerator.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15using ::testing::_;
16using ::testing::Invoke;
17using ::testing::Return;
18using ::testing::SaveArg;
19using ::testing::WithArgs;
20
21namespace content {
22
23// TODO(wuchengli): add MockSharedMemroy so more functions can be tested.
24class RTCVideoDecoderTest : public ::testing::Test,
25                            webrtc::DecodedImageCallback {
26 public:
27  RTCVideoDecoderTest()
28      : mock_gpu_factories_(new media::MockGpuVideoAcceleratorFactories),
29        vda_thread_("vda_thread"),
30        idle_waiter_(false, false) {
31    memset(&codec_, 0, sizeof(codec_));
32  }
33
34  virtual void SetUp() OVERRIDE {
35    ASSERT_TRUE(vda_thread_.Start());
36    vda_task_runner_ = vda_thread_.message_loop_proxy();
37    mock_vda_ = new media::MockVideoDecodeAccelerator;
38    EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner())
39        .WillRepeatedly(Return(vda_task_runner_));
40    EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
41        .WillRepeatedly(Return(mock_vda_));
42    EXPECT_CALL(*mock_gpu_factories_.get(), CreateSharedMemory(_))
43        .WillRepeatedly(Return(static_cast<base::SharedMemory*>(NULL)));
44    EXPECT_CALL(*mock_vda_, Initialize(_, _))
45        .Times(1)
46        .WillRepeatedly(Return(true));
47    EXPECT_CALL(*mock_vda_, Destroy()).Times(1);
48  }
49
50  virtual void TearDown() OVERRIDE {
51    VLOG(2) << "TearDown";
52    EXPECT_TRUE(vda_thread_.IsRunning());
53    RunUntilIdle();  // Wait until all callbascks complete.
54    vda_task_runner_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
55    // Make sure the decoder is released before stopping the thread.
56    RunUntilIdle();
57    vda_thread_.Stop();
58  }
59
60  virtual int32_t Decoded(webrtc::I420VideoFrame& decoded_image) OVERRIDE {
61    VLOG(2) << "Decoded";
62    EXPECT_EQ(vda_task_runner_, base::MessageLoopProxy::current());
63    return WEBRTC_VIDEO_CODEC_OK;
64  }
65
66  void CreateDecoder(webrtc::VideoCodecType codec_type) {
67    VLOG(2) << "CreateDecoder";
68    codec_.codecType = codec_type;
69    rtc_decoder_ =
70        RTCVideoDecoder::Create(codec_type, mock_gpu_factories_);
71  }
72
73  void Initialize() {
74    VLOG(2) << "Initialize";
75    EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
76    EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
77              rtc_decoder_->RegisterDecodeCompleteCallback(this));
78  }
79
80  void NotifyResetDone() {
81    VLOG(2) << "NotifyResetDone";
82    vda_task_runner_->PostTask(
83        FROM_HERE,
84        base::Bind(&RTCVideoDecoder::NotifyResetDone,
85                   base::Unretained(rtc_decoder_.get())));
86  }
87
88  void RunUntilIdle() {
89    VLOG(2) << "RunUntilIdle";
90    vda_task_runner_->PostTask(FROM_HERE,
91                               base::Bind(&base::WaitableEvent::Signal,
92                                          base::Unretained(&idle_waiter_)));
93    idle_waiter_.Wait();
94  }
95
96 protected:
97  scoped_refptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
98  media::MockVideoDecodeAccelerator* mock_vda_;
99  scoped_ptr<RTCVideoDecoder> rtc_decoder_;
100  webrtc::VideoCodec codec_;
101  base::Thread vda_thread_;
102
103 private:
104  scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_;
105
106  base::Lock lock_;
107  base::WaitableEvent idle_waiter_;
108};
109
110TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
111  CreateDecoder(webrtc::kVideoCodecVP8);
112  scoped_ptr<RTCVideoDecoder> null_rtc_decoder(
113      RTCVideoDecoder::Create(webrtc::kVideoCodecI420, mock_gpu_factories_));
114  EXPECT_EQ(NULL, null_rtc_decoder.get());
115}
116
117TEST_F(RTCVideoDecoderTest, CreateAndInitSucceedsForH264Codec) {
118  CreateDecoder(webrtc::kVideoCodecH264);
119  EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
120}
121
122TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
123  CreateDecoder(webrtc::kVideoCodecVP8);
124  codec_.codecSpecific.VP8.feedbackModeOn = true;
125  EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
126}
127
128TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
129  CreateDecoder(webrtc::kVideoCodecVP8);
130  webrtc::EncodedImage input_image;
131  EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
132            rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
133}
134
135TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
136  CreateDecoder(webrtc::kVideoCodecVP8);
137  Initialize();
138  webrtc::EncodedImage input_image;
139  input_image._completeFrame = false;
140  EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
141            rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
142}
143
144TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
145  CreateDecoder(webrtc::kVideoCodecVP8);
146  Initialize();
147  webrtc::EncodedImage input_image;
148  input_image._completeFrame = true;
149  bool missingFrames = true;
150  EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
151            rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0));
152}
153
154TEST_F(RTCVideoDecoderTest, ResetReturnsOk) {
155  CreateDecoder(webrtc::kVideoCodecVP8);
156  Initialize();
157  EXPECT_CALL(*mock_vda_, Reset())
158      .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
159  EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Reset());
160}
161
162TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
163  CreateDecoder(webrtc::kVideoCodecVP8);
164  Initialize();
165  EXPECT_CALL(*mock_vda_, Reset())
166      .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
167  EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
168}
169
170TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
171  CreateDecoder(webrtc::kVideoCodecVP8);
172  EXPECT_CALL(*mock_vda_, Reset())
173      .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
174  Initialize();
175  EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
176  Initialize();
177  EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
178}
179
180TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
181  CreateDecoder(webrtc::kVideoCodecVP8);
182  EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
183  EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
184                                               RTCVideoDecoder::ID_INVALID));
185  EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2,
186                                                RTCVideoDecoder::ID_HALF + 2));
187  EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2,
188                                               RTCVideoDecoder::ID_HALF - 2));
189
190  EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0));
191  EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
192  EXPECT_FALSE(
193      rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2));
194  EXPECT_TRUE(
195      rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2));
196
197  EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0));
198  EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
199                                                RTCVideoDecoder::ID_HALF - 2));
200  EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
201                                               RTCVideoDecoder::ID_HALF + 2));
202  EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
203                                                RTCVideoDecoder::ID_LAST));
204}
205
206TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
207  CreateDecoder(webrtc::kVideoCodecVP8);
208  EXPECT_TRUE(
209      rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
210  EXPECT_FALSE(
211      rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_INVALID));
212  EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(0, 0));
213  EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(1, 0));
214  EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(2, 0));
215
216  EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_HALF,
217                                                     RTCVideoDecoder::ID_HALF));
218  EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(
219      RTCVideoDecoder::ID_HALF + 1, RTCVideoDecoder::ID_HALF));
220  EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(
221      RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF));
222
223  EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST,
224                                                     RTCVideoDecoder::ID_LAST));
225  EXPECT_TRUE(
226      rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
227  EXPECT_FALSE(
228      rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
229}
230
231}  // content
232