Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(378)

Side by Side Diff: content/renderer/media/rtc_video_decoder_unittest.cc

Issue 1817573004: Handle HW decode failures in RTCVideoDecoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/renderer/media/rtc_video_decoder.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdint.h> 5 #include <stdint.h>
6 #include <string.h> 6 #include <string.h>
7 7
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
11 #include "base/synchronization/waitable_event.h" 11 #include "base/synchronization/waitable_event.h"
12 #include "base/thread_task_runner_handle.h" 12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/thread.h" 13 #include "base/threading/thread.h"
14 #include "content/renderer/media/rtc_video_decoder.h" 14 #include "content/renderer/media/rtc_video_decoder.h"
15 #include "media/base/gmock_callback_support.h" 15 #include "media/base/gmock_callback_support.h"
16 #include "media/renderers/mock_gpu_video_accelerator_factories.h" 16 #include "media/renderers/mock_gpu_video_accelerator_factories.h"
17 #include "media/video/mock_video_decode_accelerator.h" 17 #include "media/video/mock_video_decode_accelerator.h"
18 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
19 19
20 using ::testing::_; 20 using ::testing::_;
21 using ::testing::Invoke; 21 using ::testing::Invoke;
22 using ::testing::Return; 22 using ::testing::Return;
23 using ::testing::SaveArg; 23 using ::testing::SaveArg;
24 using ::testing::Values;
24 using ::testing::WithArgs; 25 using ::testing::WithArgs;
25 26
26 namespace content { 27 namespace content {
27 28
28 // TODO(wuchengli): add MockSharedMemroy so more functions can be tested. 29 namespace {
29 class RTCVideoDecoderTest : public ::testing::Test, 30
30 webrtc::DecodedImageCallback { 31 static const int kMinResolutionWidth = 16;
32 static const int kMinResolutionHeight = 16;
33 static const int kMaxResolutionWidth = 1920;
34 static const int kMaxResolutionHeight = 1088;
35
36 } // namespace
37
38 // TODO(wuchengli): add MockSharedMemory so more functions can be tested.
39 class RTCVideoDecoderTest
40 : public ::testing::TestWithParam<webrtc::VideoCodecType>,
41 webrtc::DecodedImageCallback {
31 public: 42 public:
32 RTCVideoDecoderTest() 43 RTCVideoDecoderTest()
33 : mock_gpu_factories_( 44 : mock_gpu_factories_(
34 new media::MockGpuVideoAcceleratorFactories(nullptr)), 45 new media::MockGpuVideoAcceleratorFactories(nullptr)),
35 vda_thread_("vda_thread"), 46 vda_thread_("vda_thread"),
36 idle_waiter_(false, false) { 47 idle_waiter_(false, false) {
37 memset(&codec_, 0, sizeof(codec_)); 48 memset(&codec_, 0, sizeof(codec_));
38 } 49 }
39 50
40 void SetUp() override { 51 void SetUp() override {
41 ASSERT_TRUE(vda_thread_.Start()); 52 ASSERT_TRUE(vda_thread_.Start());
42 vda_task_runner_ = vda_thread_.task_runner(); 53 vda_task_runner_ = vda_thread_.task_runner();
43 mock_vda_ = new media::MockVideoDecodeAccelerator; 54 mock_vda_ = new media::MockVideoDecodeAccelerator;
44 55
45 media::VideoDecodeAccelerator::SupportedProfile supported_profile; 56 media::VideoDecodeAccelerator::SupportedProfile supported_profile;
46 supported_profile.min_resolution.SetSize(16, 16); 57 supported_profile.min_resolution.SetSize(kMinResolutionWidth,
47 supported_profile.max_resolution.SetSize(1920, 1088); 58 kMinResolutionHeight);
59 supported_profile.max_resolution.SetSize(kMaxResolutionWidth,
60 kMaxResolutionHeight);
48 supported_profile.profile = media::H264PROFILE_MAIN; 61 supported_profile.profile = media::H264PROFILE_MAIN;
49 capabilities_.supported_profiles.push_back(supported_profile); 62 capabilities_.supported_profiles.push_back(supported_profile);
50 supported_profile.profile = media::VP8PROFILE_ANY; 63 supported_profile.profile = media::VP8PROFILE_ANY;
51 capabilities_.supported_profiles.push_back(supported_profile); 64 capabilities_.supported_profiles.push_back(supported_profile);
52 65
53 EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner()) 66 EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner())
54 .WillRepeatedly(Return(vda_task_runner_)); 67 .WillRepeatedly(Return(vda_task_runner_));
55 EXPECT_CALL(*mock_gpu_factories_.get(), 68 EXPECT_CALL(*mock_gpu_factories_.get(),
56 GetVideoDecodeAcceleratorCapabilities()) 69 GetVideoDecodeAcceleratorCapabilities())
57 .WillRepeatedly(Return(capabilities_)); 70 .WillRepeatedly(Return(capabilities_));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 } 107 }
95 108
96 void NotifyResetDone() { 109 void NotifyResetDone() {
97 DVLOG(2) << "NotifyResetDone"; 110 DVLOG(2) << "NotifyResetDone";
98 vda_task_runner_->PostTask( 111 vda_task_runner_->PostTask(
99 FROM_HERE, 112 FROM_HERE,
100 base::Bind(&RTCVideoDecoder::NotifyResetDone, 113 base::Bind(&RTCVideoDecoder::NotifyResetDone,
101 base::Unretained(rtc_decoder_.get()))); 114 base::Unretained(rtc_decoder_.get())));
102 } 115 }
103 116
117 void NotifyError(media::VideoDecodeAccelerator::Error error) {
118 DVLOG(2) << "NotifyError";
119 vda_task_runner_->PostTask(
120 FROM_HERE,
121 base::Bind(&RTCVideoDecoder::NotifyError,
122 base::Unretained(rtc_decoder_.get()), error));
123 }
124
104 void RunUntilIdle() { 125 void RunUntilIdle() {
105 DVLOG(2) << "RunUntilIdle"; 126 DVLOG(2) << "RunUntilIdle";
106 vda_task_runner_->PostTask(FROM_HERE, 127 vda_task_runner_->PostTask(FROM_HERE,
107 base::Bind(&base::WaitableEvent::Signal, 128 base::Bind(&base::WaitableEvent::Signal,
108 base::Unretained(&idle_waiter_))); 129 base::Unretained(&idle_waiter_)));
109 idle_waiter_.Wait(); 130 idle_waiter_.Wait();
110 } 131 }
111 132
133 void SetUpResetVDA() {
134 mock_vda_after_reset_ = new media::MockVideoDecodeAccelerator;
135 EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
136 .WillRepeatedly(Return(mock_vda_after_reset_));
137 EXPECT_CALL(*mock_vda_after_reset_, Initialize(_, _))
138 .Times(1)
139 .WillRepeatedly(Return(true));
140 EXPECT_CALL(*mock_vda_after_reset_, Destroy()).Times(1);
141 }
142
112 protected: 143 protected:
113 scoped_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_; 144 scoped_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
114 media::MockVideoDecodeAccelerator* mock_vda_; 145 media::MockVideoDecodeAccelerator* mock_vda_;
146 media::MockVideoDecodeAccelerator* mock_vda_after_reset_;
115 scoped_ptr<RTCVideoDecoder> rtc_decoder_; 147 scoped_ptr<RTCVideoDecoder> rtc_decoder_;
116 webrtc::VideoCodec codec_; 148 webrtc::VideoCodec codec_;
117 base::Thread vda_thread_; 149 base::Thread vda_thread_;
118 media::VideoDecodeAccelerator::Capabilities capabilities_; 150 media::VideoDecodeAccelerator::Capabilities capabilities_;
119 151
120 private: 152 private:
121 scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_; 153 scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_;
122 154
123 base::Lock lock_; 155 base::Lock lock_;
124 base::WaitableEvent idle_waiter_; 156 base::WaitableEvent idle_waiter_;
125 }; 157 };
126 158
127 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) { 159 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
128 CreateDecoder(webrtc::kVideoCodecVP8); 160 CreateDecoder(webrtc::kVideoCodecVP8);
129 scoped_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create( 161 scoped_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create(
130 webrtc::kVideoCodecI420, mock_gpu_factories_.get())); 162 webrtc::kVideoCodecI420, mock_gpu_factories_.get()));
131 EXPECT_EQ(NULL, null_rtc_decoder.get()); 163 EXPECT_EQ(NULL, null_rtc_decoder.get());
132 } 164 }
133 165
134 TEST_F(RTCVideoDecoderTest, CreateAndInitSucceedsForH264Codec) { 166 TEST_P(RTCVideoDecoderTest, CreateAndInitSucceeds) {
135 CreateDecoder(webrtc::kVideoCodecH264); 167 const webrtc::VideoCodecType codec_type = GetParam();
168 CreateDecoder(codec_type);
136 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1)); 169 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
137 } 170 }
138 171
139 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) { 172 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
140 CreateDecoder(webrtc::kVideoCodecVP8); 173 CreateDecoder(webrtc::kVideoCodecVP8);
141 codec_.codecSpecific.VP8.feedbackModeOn = true; 174 codec_.codecSpecific.VP8.feedbackModeOn = true;
142 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1)); 175 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
143 } 176 }
144 177
145 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) { 178 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
146 CreateDecoder(webrtc::kVideoCodecVP8); 179 CreateDecoder(webrtc::kVideoCodecVP8);
147 webrtc::EncodedImage input_image; 180 webrtc::EncodedImage input_image;
148 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, 181 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
149 rtc_decoder_->Decode(input_image, false, NULL, NULL, 0)); 182 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
150 } 183 }
151 184
152 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) { 185 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
153 CreateDecoder(webrtc::kVideoCodecVP8); 186 CreateDecoder(webrtc::kVideoCodecVP8);
154 Initialize(); 187 Initialize();
155 webrtc::EncodedImage input_image; 188 webrtc::EncodedImage input_image;
156 input_image._completeFrame = false; 189 input_image._completeFrame = false;
157 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, 190 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
158 rtc_decoder_->Decode(input_image, false, NULL, NULL, 0)); 191 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
159 } 192 }
160 193
161 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) { 194 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
162 CreateDecoder(webrtc::kVideoCodecVP8); 195 CreateDecoder(webrtc::kVideoCodecVP8);
163 Initialize(); 196 Initialize();
164 webrtc::EncodedImage input_image; 197 webrtc::EncodedImage input_image;
165 input_image._completeFrame = true; 198 input_image._completeFrame = true;
166 bool missingFrames = true; 199 bool missingFrames = true;
167 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, 200 EXPECT_EQ(
168 rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0)); 201 WEBRTC_VIDEO_CODEC_ERROR,
202 rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0));
169 } 203 }
170 204
171 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { 205 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
172 CreateDecoder(webrtc::kVideoCodecVP8); 206 CreateDecoder(webrtc::kVideoCodecVP8);
173 Initialize(); 207 Initialize();
174 EXPECT_CALL(*mock_vda_, Reset()) 208 EXPECT_CALL(*mock_vda_, Reset())
175 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone)); 209 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
176 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release()); 210 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
177 } 211 }
178 212
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF)); 264 RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF));
231 265
232 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST, 266 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST,
233 RTCVideoDecoder::ID_LAST)); 267 RTCVideoDecoder::ID_LAST));
234 EXPECT_TRUE( 268 EXPECT_TRUE(
235 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST)); 269 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
236 EXPECT_FALSE( 270 EXPECT_FALSE(
237 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST)); 271 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
238 } 272 }
239 273
274
275 TEST_P(RTCVideoDecoderTest, DecodeResetsAfterError) {
276 const webrtc::VideoCodecType codec_type = GetParam();
277 CreateDecoder(codec_type);
278 Initialize();
279
280 webrtc::EncodedImage input_image;
281 input_image._completeFrame = true;
282 input_image._encodedWidth = kMinResolutionWidth;
283 input_image._encodedHeight = kMaxResolutionHeight;
284 input_image._frameType = webrtc::kVideoFrameDelta;
285 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
286 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
287 RunUntilIdle();
288
289 // Notify the decoder about a platform error.
290 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
291 RunUntilIdle();
292
293 // Expect decode call to reset decoder, and set up a new VDA to track it.
294 SetUpResetVDA();
295 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
296 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
297 }
298
299 INSTANTIATE_TEST_CASE_P(CodecProfiles,
300 RTCVideoDecoderTest,
301 Values(webrtc::kVideoCodecVP8,
302 webrtc::kVideoCodecH264));
303
240 } // content 304 } // content
OLDNEW
« no previous file with comments | « content/renderer/media/rtc_video_decoder.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698