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.
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"
16 using ::testing::Invoke
;
17 using ::testing::Return
;
18 using ::testing::SaveArg
;
19 using ::testing::WithArgs
;
23 // TODO(wuchengli): add MockSharedMemroy so more functions can be tested.
24 class RTCVideoDecoderTest
: public ::testing::Test
,
25 webrtc::DecodedImageCallback
{
28 : mock_gpu_factories_(new media::MockGpuVideoAcceleratorFactories
),
29 vda_thread_("vda_thread"),
30 idle_waiter_(false, false) {
31 memset(&codec_
, 0, sizeof(codec_
));
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(_
, _
))
46 .WillRepeatedly(Return(true));
47 EXPECT_CALL(*mock_vda_
, Destroy()).Times(1);
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.
60 virtual int32_t Decoded(webrtc::I420VideoFrame
& decoded_image
) OVERRIDE
{
62 EXPECT_EQ(vda_task_runner_
, base::MessageLoopProxy::current());
63 return WEBRTC_VIDEO_CODEC_OK
;
66 void CreateDecoder(webrtc::VideoCodecType codec_type
) {
67 VLOG(2) << "CreateDecoder";
68 codec_
.codecType
= codec_type
;
70 RTCVideoDecoder::Create(codec_type
, mock_gpu_factories_
);
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));
80 void NotifyResetDone() {
81 VLOG(2) << "NotifyResetDone";
82 vda_task_runner_
->PostTask(
84 base::Bind(&RTCVideoDecoder::NotifyResetDone
,
85 base::Unretained(rtc_decoder_
.get())));
89 VLOG(2) << "RunUntilIdle";
90 vda_task_runner_
->PostTask(FROM_HERE
,
91 base::Bind(&base::WaitableEvent::Signal
,
92 base::Unretained(&idle_waiter_
)));
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_
;
104 scoped_refptr
<base::SingleThreadTaskRunner
> vda_task_runner_
;
107 base::WaitableEvent idle_waiter_
;
110 TEST_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());
117 TEST_F(RTCVideoDecoderTest
, CreateAndInitSucceedsForH264Codec
) {
118 CreateDecoder(webrtc::kVideoCodecH264
);
119 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->InitDecode(&codec_
, 1));
122 TEST_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));
128 TEST_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));
135 TEST_F(RTCVideoDecoderTest
, DecodeReturnsErrorOnIncompleteFrame
) {
136 CreateDecoder(webrtc::kVideoCodecVP8
);
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));
144 TEST_F(RTCVideoDecoderTest
, DecodeReturnsErrorOnMissingFrames
) {
145 CreateDecoder(webrtc::kVideoCodecVP8
);
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));
154 TEST_F(RTCVideoDecoderTest
, ResetReturnsOk
) {
155 CreateDecoder(webrtc::kVideoCodecVP8
);
157 EXPECT_CALL(*mock_vda_
, Reset())
158 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone
));
159 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Reset());
162 TEST_F(RTCVideoDecoderTest
, ReleaseReturnsOk
) {
163 CreateDecoder(webrtc::kVideoCodecVP8
);
165 EXPECT_CALL(*mock_vda_
, Reset())
166 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone
));
167 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Release());
170 TEST_F(RTCVideoDecoderTest
, InitDecodeAfterRelease
) {
171 CreateDecoder(webrtc::kVideoCodecVP8
);
172 EXPECT_CALL(*mock_vda_
, Reset())
173 .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone
));
175 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Release());
177 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Release());
180 TEST_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));
190 EXPECT_FALSE(rtc_decoder_
->IsBufferAfterReset(0, 0));
191 EXPECT_TRUE(rtc_decoder_
->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST
));
193 rtc_decoder_
->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF
- 2));
195 rtc_decoder_
->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF
+ 2));
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
));
206 TEST_F(RTCVideoDecoderTest
, IsFirstBufferAfterReset
) {
207 CreateDecoder(webrtc::kVideoCodecVP8
);
209 rtc_decoder_
->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID
));
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));
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
));
223 EXPECT_FALSE(rtc_decoder_
->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST
,
224 RTCVideoDecoder::ID_LAST
));
226 rtc_decoder_
->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST
));
228 rtc_decoder_
->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST
));