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/location.h"
7 #include "base/single_thread_task_runner.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/threading/thread.h"
11 #include "content/renderer/media/rtc_video_decoder.h"
12 #include "media/base/gmock_callback_support.h"
13 #include "media/renderers/mock_gpu_video_accelerator_factories.h"
14 #include "media/video/mock_video_decode_accelerator.h"
15 #include "testing/gtest/include/gtest/gtest.h"
18 using ::testing::Invoke
;
19 using ::testing::Return
;
20 using ::testing::SaveArg
;
21 using ::testing::WithArgs
;
25 // TODO(wuchengli): add MockSharedMemroy so more functions can be tested.
26 class RTCVideoDecoderTest
: public ::testing::Test
,
27 webrtc::DecodedImageCallback
{
30 : mock_gpu_factories_(new media::MockGpuVideoAcceleratorFactories
),
31 vda_thread_("vda_thread"),
32 idle_waiter_(false, false) {
33 memset(&codec_
, 0, sizeof(codec_
));
36 void SetUp() override
{
37 ASSERT_TRUE(vda_thread_
.Start());
38 vda_task_runner_
= vda_thread_
.task_runner();
39 mock_vda_
= new media::MockVideoDecodeAccelerator
;
41 media::VideoDecodeAccelerator::SupportedProfile supported_profile
;
42 supported_profile
.min_resolution
.SetSize(16, 16);
43 supported_profile
.max_resolution
.SetSize(1920, 1088);
44 supported_profile
.profile
= media::H264PROFILE_MAIN
;
45 supported_profiles_
.push_back(supported_profile
);
46 supported_profile
.profile
= media::VP8PROFILE_ANY
;
47 supported_profiles_
.push_back(supported_profile
);
49 EXPECT_CALL(*mock_gpu_factories_
.get(), GetTaskRunner())
50 .WillRepeatedly(Return(vda_task_runner_
));
51 EXPECT_CALL(*mock_gpu_factories_
.get(),
52 GetVideoDecodeAcceleratorSupportedProfiles())
53 .WillRepeatedly(Return(supported_profiles_
));
54 EXPECT_CALL(*mock_gpu_factories_
.get(), DoCreateVideoDecodeAccelerator())
55 .WillRepeatedly(Return(mock_vda_
));
56 EXPECT_CALL(*mock_vda_
, Initialize(_
, _
))
58 .WillRepeatedly(Return(true));
59 EXPECT_CALL(*mock_vda_
, Destroy()).Times(1);
62 void TearDown() override
{
63 DVLOG(2) << "TearDown";
64 EXPECT_TRUE(vda_thread_
.IsRunning());
65 RunUntilIdle(); // Wait until all callbascks complete.
66 vda_task_runner_
->DeleteSoon(FROM_HERE
, rtc_decoder_
.release());
67 // Make sure the decoder is released before stopping the thread.
72 int32_t Decoded(webrtc::VideoFrame
& decoded_image
) override
{
73 DVLOG(2) << "Decoded";
74 EXPECT_EQ(vda_task_runner_
, base::ThreadTaskRunnerHandle::Get());
75 return WEBRTC_VIDEO_CODEC_OK
;
78 void CreateDecoder(webrtc::VideoCodecType codec_type
) {
79 DVLOG(2) << "CreateDecoder";
80 codec_
.codecType
= codec_type
;
82 RTCVideoDecoder::Create(codec_type
, mock_gpu_factories_
);
86 DVLOG(2) << "Initialize";
87 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->InitDecode(&codec_
, 1));
88 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
,
89 rtc_decoder_
->RegisterDecodeCompleteCallback(this));
92 void NotifyResetDone() {
93 DVLOG(2) << "NotifyResetDone";
94 vda_task_runner_
->PostTask(
96 base::Bind(&RTCVideoDecoder::NotifyResetDone
,
97 base::Unretained(rtc_decoder_
.get())));
100 void RunUntilIdle() {
101 DVLOG(2) << "RunUntilIdle";
102 vda_task_runner_
->PostTask(FROM_HERE
,
103 base::Bind(&base::WaitableEvent::Signal
,
104 base::Unretained(&idle_waiter_
)));
109 scoped_refptr
<media::MockGpuVideoAcceleratorFactories
> mock_gpu_factories_
;
110 media::MockVideoDecodeAccelerator
* mock_vda_
;
111 scoped_ptr
<RTCVideoDecoder
> rtc_decoder_
;
112 webrtc::VideoCodec codec_
;
113 base::Thread vda_thread_
;
114 media::VideoDecodeAccelerator::SupportedProfiles supported_profiles_
;
117 scoped_refptr
<base::SingleThreadTaskRunner
> vda_task_runner_
;
120 base::WaitableEvent idle_waiter_
;
123 TEST_F(RTCVideoDecoderTest
, CreateReturnsNullOnUnsupportedCodec
) {
124 CreateDecoder(webrtc::kVideoCodecVP8
);
125 scoped_ptr
<RTCVideoDecoder
> null_rtc_decoder(
126 RTCVideoDecoder::Create(webrtc::kVideoCodecI420
, mock_gpu_factories_
));
127 EXPECT_EQ(NULL
, null_rtc_decoder
.get());
130 TEST_F(RTCVideoDecoderTest
, CreateAndInitSucceedsForH264Codec
) {
131 CreateDecoder(webrtc::kVideoCodecH264
);
132 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->InitDecode(&codec_
, 1));
135 TEST_F(RTCVideoDecoderTest
, InitDecodeReturnsErrorOnFeedbackMode
) {
136 CreateDecoder(webrtc::kVideoCodecVP8
);
137 codec_
.codecSpecific
.VP8
.feedbackModeOn
= true;
138 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR
, rtc_decoder_
->InitDecode(&codec_
, 1));
141 TEST_F(RTCVideoDecoderTest
, DecodeReturnsErrorWithoutInitDecode
) {
142 CreateDecoder(webrtc::kVideoCodecVP8
);
143 webrtc::EncodedImage input_image
;
144 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED
,
145 rtc_decoder_
->Decode(input_image
, false, NULL
, NULL
, 0));
148 TEST_F(RTCVideoDecoderTest
, DecodeReturnsErrorOnIncompleteFrame
) {
149 CreateDecoder(webrtc::kVideoCodecVP8
);
151 webrtc::EncodedImage input_image
;
152 input_image
._completeFrame
= false;
153 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR
,
154 rtc_decoder_
->Decode(input_image
, false, NULL
, NULL
, 0));
157 TEST_F(RTCVideoDecoderTest
, DecodeReturnsErrorOnMissingFrames
) {
158 CreateDecoder(webrtc::kVideoCodecVP8
);
160 webrtc::EncodedImage input_image
;
161 input_image
._completeFrame
= true;
162 bool missingFrames
= true;
163 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR
,
164 rtc_decoder_
->Decode(input_image
, missingFrames
, NULL
, NULL
, 0));
167 TEST_F(RTCVideoDecoderTest
, ResetReturnsOk
) {
168 CreateDecoder(webrtc::kVideoCodecVP8
);
170 EXPECT_CALL(*mock_vda_
, Reset())
171 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone
));
172 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Reset());
175 TEST_F(RTCVideoDecoderTest
, ReleaseReturnsOk
) {
176 CreateDecoder(webrtc::kVideoCodecVP8
);
178 EXPECT_CALL(*mock_vda_
, Reset())
179 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone
));
180 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Release());
183 TEST_F(RTCVideoDecoderTest
, InitDecodeAfterRelease
) {
184 CreateDecoder(webrtc::kVideoCodecVP8
);
185 EXPECT_CALL(*mock_vda_
, Reset())
186 .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone
));
188 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Release());
190 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK
, rtc_decoder_
->Release());
193 TEST_F(RTCVideoDecoderTest
, IsBufferAfterReset
) {
194 CreateDecoder(webrtc::kVideoCodecVP8
);
195 EXPECT_TRUE(rtc_decoder_
->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID
));
196 EXPECT_TRUE(rtc_decoder_
->IsBufferAfterReset(RTCVideoDecoder::ID_LAST
,
197 RTCVideoDecoder::ID_INVALID
));
198 EXPECT_FALSE(rtc_decoder_
->IsBufferAfterReset(RTCVideoDecoder::ID_HALF
- 2,
199 RTCVideoDecoder::ID_HALF
+ 2));
200 EXPECT_TRUE(rtc_decoder_
->IsBufferAfterReset(RTCVideoDecoder::ID_HALF
+ 2,
201 RTCVideoDecoder::ID_HALF
- 2));
203 EXPECT_FALSE(rtc_decoder_
->IsBufferAfterReset(0, 0));
204 EXPECT_TRUE(rtc_decoder_
->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST
));
206 rtc_decoder_
->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF
- 2));
208 rtc_decoder_
->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF
+ 2));
210 EXPECT_FALSE(rtc_decoder_
->IsBufferAfterReset(RTCVideoDecoder::ID_LAST
, 0));
211 EXPECT_FALSE(rtc_decoder_
->IsBufferAfterReset(RTCVideoDecoder::ID_LAST
,
212 RTCVideoDecoder::ID_HALF
- 2));
213 EXPECT_TRUE(rtc_decoder_
->IsBufferAfterReset(RTCVideoDecoder::ID_LAST
,
214 RTCVideoDecoder::ID_HALF
+ 2));
215 EXPECT_FALSE(rtc_decoder_
->IsBufferAfterReset(RTCVideoDecoder::ID_LAST
,
216 RTCVideoDecoder::ID_LAST
));
219 TEST_F(RTCVideoDecoderTest
, IsFirstBufferAfterReset
) {
220 CreateDecoder(webrtc::kVideoCodecVP8
);
222 rtc_decoder_
->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID
));
224 rtc_decoder_
->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_INVALID
));
225 EXPECT_FALSE(rtc_decoder_
->IsFirstBufferAfterReset(0, 0));
226 EXPECT_TRUE(rtc_decoder_
->IsFirstBufferAfterReset(1, 0));
227 EXPECT_FALSE(rtc_decoder_
->IsFirstBufferAfterReset(2, 0));
229 EXPECT_FALSE(rtc_decoder_
->IsFirstBufferAfterReset(RTCVideoDecoder::ID_HALF
,
230 RTCVideoDecoder::ID_HALF
));
231 EXPECT_TRUE(rtc_decoder_
->IsFirstBufferAfterReset(
232 RTCVideoDecoder::ID_HALF
+ 1, RTCVideoDecoder::ID_HALF
));
233 EXPECT_FALSE(rtc_decoder_
->IsFirstBufferAfterReset(
234 RTCVideoDecoder::ID_HALF
+ 2, RTCVideoDecoder::ID_HALF
));
236 EXPECT_FALSE(rtc_decoder_
->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST
,
237 RTCVideoDecoder::ID_LAST
));
239 rtc_decoder_
->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST
));
241 rtc_decoder_
->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST
));