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

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

Issue 2418613002: Proxy RtcVideoDecoder calls to a media::VideoDecoder.
Patch Set: Comments addressed and unittests updated. Created 4 years, 1 month 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
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/run_loop.h"
10 #include "base/single_thread_task_runner.h" 11 #include "base/single_thread_task_runner.h"
11 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
13 #include "base/test/test_simple_task_runner.h"
12 #include "base/threading/thread.h" 14 #include "base/threading/thread.h"
13 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
14 #include "content/renderer/media/gpu/rtc_video_decoder.h" 16 #include "content/renderer/media/gpu/rtc_video_decoder.h"
15 #include "media/base/gmock_callback_support.h" 17 #include "media/base/gmock_callback_support.h"
18 #include "media/base/mock_filters.h"
19 #include "media/filters/fake_video_decoder.h"
16 #include "media/renderers/mock_gpu_video_accelerator_factories.h" 20 #include "media/renderers/mock_gpu_video_accelerator_factories.h"
17 #include "media/video/mock_video_decode_accelerator.h" 21 #include "media/video/mock_video_decode_accelerator.h"
18 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
19 23
20 #if defined(OS_WIN) 24 #if defined(OS_WIN)
21 #include "base/command_line.h" 25 #include "base/command_line.h"
22 #include "content/public/common/content_switches.h" 26 #include "content/public/common/content_switches.h"
23 #endif // defined(OS_WIN) 27 #endif // defined(OS_WIN)
24 28
25 using ::testing::_; 29 using ::testing::_;
26 using ::testing::Invoke; 30 using ::testing::Invoke;
27 using ::testing::Return; 31 using ::testing::Return;
28 using ::testing::SaveArg; 32 using ::testing::SaveArg;
29 using ::testing::Values; 33 using ::testing::Values;
30 using ::testing::WithArgs; 34 using ::testing::WithArgs;
31 35
32 namespace content { 36 namespace content {
33 37
34 namespace { 38 namespace {
35 39
36 static const int kMinResolutionWidth = 16; 40 const int kVideoFrameWidth = 1280;
37 static const int kMinResolutionHeight = 16; 41 const int kVideoFrameHeight = 720;
38 static const int kMaxResolutionWidth = 1920; 42
39 static const int kMaxResolutionHeight = 1088; 43 const int kMaxParallelVideoDecoderRequests = 4;
44
45 void OnBytesDecoded(int numbytes) {}
46
47 // This class creates and manages a thread to which tasks may be posted, and
48 // which exposes BlockUntilTaskRunnerIdle(), allowing callers on other threads
49 // to block until the thread this idle.
50 // This is accomplished via two task runners on the underlying thread. Tasks may
51 // be posted to the one returned by task_runner(), while another, which is
52 // private to the implementation, pumps and controls the first. To the caller,
53 // this interface appears as a Thread on which one can block.
54 class ThreadHelper {
55 public:
56 explicit ThreadHelper(const std::string& thread_name);
57 ~ThreadHelper();
58
59 // Start the underlying thread. Return true on success. After this call,
60 // task_runner() will return a valid base::SingleThreadTaskRunner.
61 bool Start();
62
63 // Return true if the underlying thread is running, false otherwise.
64 bool IsRunning();
65
66 // Block the calling thread until task_runner() is idle. If tasks are posted
67 // to the task_runner() during execution of other tasks, those will run too.
68 // Thus, this call may never return.
69 void BlockUntilTaskRunnerIdle();
70
71 // Stop the underlying thread. task_runner() will return nullptr after this
72 // is called.
73 void Stop();
74
75 // Tasks may be posted to this task_runner. Will when this is not running,
76 // returns nullptr.
77 scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
78 return postable_task_runner_;
79 }
80
81 private:
82 void StartPumping();
83 void Pump();
84 void StopPumping();
85
86 base::Thread thread_;
87 base::WaitableEvent waiter_;
88 bool pumping_ = false;
89 scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_;
90 scoped_refptr<base::TestSimpleTaskRunner> postable_task_runner_;
91
92 DISALLOW_COPY_AND_ASSIGN(ThreadHelper);
93 };
94
95 ThreadHelper::ThreadHelper(const std::string& thread_name)
96 : thread_(thread_name),
97 waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
98 base::WaitableEvent::InitialState::NOT_SIGNALED) {}
99
100 ThreadHelper::~ThreadHelper() {
101 if (thread_.IsRunning())
102 Stop();
103 }
104
105 bool ThreadHelper::Start() {
106 if (!thread_.Start())
107 return false;
108 control_task_runner_ = thread_.task_runner();
109 control_task_runner_->PostTask(
110 FROM_HERE,
111 base::Bind(&ThreadHelper::StartPumping, base::Unretained(this)));
112 waiter_.Wait();
113 return true;
114 }
115
116 bool ThreadHelper::IsRunning() {
117 return thread_.IsRunning();
118 }
119
120 void ThreadHelper::BlockUntilTaskRunnerIdle() {
121 waiter_.Wait();
122 }
123
124 void ThreadHelper::Stop() {
125 BlockUntilTaskRunnerIdle();
126 control_task_runner_->PostTask(
127 FROM_HERE,
128 base::Bind(&ThreadHelper::StopPumping, base::Unretained(this)));
129 waiter_.Wait();
130 thread_.Stop();
131 }
132
133 // Start pumping the task_runner(), so that it executes tasks. Called in
134 // Start(). Must be called on the |control_task_runner_|.
135 void ThreadHelper::StartPumping() {
136 DCHECK(!postable_task_runner_);
137 postable_task_runner_ = new base::TestSimpleTaskRunner();
138 thread_.message_loop()->SetTaskRunner(postable_task_runner_);
139
140 // Start pumping.
141 pumping_ = true;
142 Pump();
143 }
144
145 // Recurring task which causes tasks posted to task_runner() to run.
146 // BlockUntilTaskRunnerIdle() will block the calling thread while this is
147 // running. Must be called on the |control_task_runner_|.
148 void ThreadHelper::Pump() {
149 postable_task_runner_->RunUntilIdle();
150 if (pumping_) {
151 control_task_runner_->PostDelayedTask(
152 FROM_HERE, base::Bind(&ThreadHelper::Pump, base::Unretained(this)),
153 base::TimeDelta::FromMilliseconds(10));
154 }
155 waiter_.Signal();
156 }
157
158 // Stop pumping the task_runner(). Called in Stop(). Must be called on the
159 // control_task_runner_|.
160 void ThreadHelper::StopPumping() {
161 thread_.message_loop()->SetTaskRunner(control_task_runner_);
162 pumping_ = false;
163 }
40 164
41 } // namespace 165 } // namespace
42 166
43 // TODO(wuchengli): add MockSharedMemory so more functions can be tested. 167 // TODO(wuchengli): add MockSharedMemory so more functions can be tested.
44 class RTCVideoDecoderTest 168 class RTCVideoDecoderTest
45 : public ::testing::TestWithParam<webrtc::VideoCodecType>, 169 : public ::testing::TestWithParam<webrtc::VideoCodecType>,
46 webrtc::DecodedImageCallback { 170 webrtc::DecodedImageCallback {
47 public: 171 public:
48 RTCVideoDecoderTest() 172 RTCVideoDecoderTest()
49 : mock_gpu_factories_( 173 : fake_video_decoder_(nullptr), video_decoder_thread_("decoder_thread") {
50 new media::MockGpuVideoAcceleratorFactories(nullptr)),
51 vda_thread_("vda_thread"),
52 idle_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
53 base::WaitableEvent::InitialState::NOT_SIGNALED) {
54 memset(&codec_, 0, sizeof(codec_)); 174 memset(&codec_, 0, sizeof(codec_));
55 } 175 }
56 176
57 void SetUp() override { 177 void SetUp() override {
58 ASSERT_TRUE(vda_thread_.Start()); 178 ASSERT_TRUE(video_decoder_thread_.Start());
59 vda_task_runner_ = vda_thread_.task_runner(); 179 video_decoder_task_runner_ = video_decoder_thread_.task_runner();
60 mock_vda_ = new media::MockVideoDecodeAccelerator;
61 180
62 media::VideoDecodeAccelerator::SupportedProfile supported_profile; 181 // If any frames are passed in, they should match these values.
63 supported_profile.min_resolution.SetSize(kMinResolutionWidth, 182 codec_.width = kVideoFrameWidth;
64 kMinResolutionHeight); 183 codec_.height = kVideoFrameWidth;
65 supported_profile.max_resolution.SetSize(kMaxResolutionWidth,
66 kMaxResolutionHeight);
67 supported_profile.profile = media::H264PROFILE_MAIN;
68 capabilities_.supported_profiles.push_back(supported_profile);
69 supported_profile.profile = media::VP8PROFILE_ANY;
70 capabilities_.supported_profiles.push_back(supported_profile);
71
72 EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner())
73 .WillRepeatedly(Return(vda_task_runner_));
74 EXPECT_CALL(*mock_gpu_factories_.get(),
75 GetVideoDecodeAcceleratorCapabilities())
76 .WillRepeatedly(Return(capabilities_));
77 EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
78 .WillRepeatedly(Return(mock_vda_));
79 EXPECT_CALL(*mock_vda_, Initialize(_, _))
80 .Times(1)
81 .WillRepeatedly(Return(true));
82 EXPECT_CALL(*mock_vda_, Destroy()).Times(1);
83 184
84 #if defined(OS_WIN) 185 #if defined(OS_WIN)
85 base::CommandLine::ForCurrentProcess()->AppendSwitch( 186 base::CommandLine::ForCurrentProcess()->AppendSwitch(
86 switches::kEnableWin7WebRtcHWH264Decoding); 187 switches::kEnableWin7WebRtcHWH264Decoding);
87 #endif // defined(OS_WIN) 188 #endif // defined(OS_WIN)
88 } 189 }
89 190
90 void TearDown() override { 191 void TearDown() override {
91 DVLOG(2) << "TearDown"; 192 DVLOG(2) << "TearDown";
92 EXPECT_TRUE(vda_thread_.IsRunning()); 193 EXPECT_TRUE(video_decoder_thread_.IsRunning());
93 RunUntilIdle(); // Wait until all callbascks complete. 194 RTCVideoDecoder::Destroy(rtc_decoder_.release(),
94 vda_task_runner_->DeleteSoon(FROM_HERE, rtc_decoder_.release()); 195 video_decoder_task_runner_);
95 // Make sure the decoder is released before stopping the thread. 196 // Make sure the decoder is released before stopping the thread.
96 RunUntilIdle(); 197 RunUntilIdle();
97 vda_thread_.Stop(); 198 video_decoder_thread_.Stop();
98 } 199 }
99 200
100 int32_t Decoded(webrtc::VideoFrame& decoded_image) override { 201 int32_t Decoded(webrtc::VideoFrame& decoded_image) override {
101 DVLOG(2) << "Decoded"; 202 DVLOG(2) << "Decoded";
102 EXPECT_EQ(vda_task_runner_, base::ThreadTaskRunnerHandle::Get()); 203 EXPECT_EQ(video_decoder_task_runner_, base::ThreadTaskRunnerHandle::Get());
103 return WEBRTC_VIDEO_CODEC_OK; 204 return WEBRTC_VIDEO_CODEC_OK;
104 } 205 }
105 206
106 void CreateDecoder(webrtc::VideoCodecType codec_type) { 207 void CreateDecoder(webrtc::VideoCodecType codec_type) {
107 DVLOG(2) << "CreateDecoder"; 208 DVLOG(2) << "CreateDecoder";
209
210 // If a decoder already exists, delete the old one.
211 if (rtc_decoder_) {
212 RTCVideoDecoder::Destroy(rtc_decoder_.release(),
213 video_decoder_task_runner_);
214 }
215
108 codec_.codecType = codec_type; 216 codec_.codecType = codec_type;
109 rtc_decoder_ = 217 rtc_decoder_ = RTCVideoDecoder::Create(
110 RTCVideoDecoder::Create(codec_type, mock_gpu_factories_.get()); 218 codec_type, base::Bind(&RTCVideoDecoderTest::CreateFakeVideoDecoder,
219 base::Unretained(this)),
220 video_decoder_task_runner_);
221 RunUntilIdle();
111 } 222 }
112 223
113 void Initialize() { 224 void Initialize() {
114 DVLOG(2) << "Initialize"; 225 DVLOG(2) << "Initialize";
226 DCHECK(rtc_decoder_);
115 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1)); 227 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
116 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, 228 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
117 rtc_decoder_->RegisterDecodeCompleteCallback(this)); 229 rtc_decoder_->RegisterDecodeCompleteCallback(this));
118 } 230 }
119 231
120 void NotifyResetDone() { 232 // This function blocks the calling thread until |video_decoder_thread_| is
121 DVLOG(2) << "NotifyResetDone"; 233 // idle.
122 vda_task_runner_->PostTask(
123 FROM_HERE,
124 base::Bind(&RTCVideoDecoder::NotifyResetDone,
125 base::Unretained(rtc_decoder_.get())));
126 }
127
128 void NotifyError(media::VideoDecodeAccelerator::Error error) {
129 DVLOG(2) << "NotifyError";
130 vda_task_runner_->PostTask(
131 FROM_HERE,
132 base::Bind(&RTCVideoDecoder::NotifyError,
133 base::Unretained(rtc_decoder_.get()), error));
134 }
135
136 void RunUntilIdle() { 234 void RunUntilIdle() {
137 DVLOG(2) << "RunUntilIdle"; 235 DVLOG(2) << "RunUntilIdle";
138 vda_task_runner_->PostTask(FROM_HERE, 236 video_decoder_thread_.BlockUntilTaskRunnerIdle();
139 base::Bind(&base::WaitableEvent::Signal,
140 base::Unretained(&idle_waiter_)));
141 idle_waiter_.Wait();
142 }
143
144 void SetUpResetVDA() {
145 mock_vda_after_reset_ = new media::MockVideoDecodeAccelerator;
146 EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
147 .WillRepeatedly(Return(mock_vda_after_reset_));
148 EXPECT_CALL(*mock_vda_after_reset_, Initialize(_, _))
149 .Times(1)
150 .WillRepeatedly(Return(true));
151 EXPECT_CALL(*mock_vda_after_reset_, Destroy()).Times(1);
152 } 237 }
153 238
154 protected: 239 protected:
155 std::unique_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_; 240 media::FakeVideoDecoder* fake_video_decoder_;
156 media::MockVideoDecodeAccelerator* mock_vda_;
157 media::MockVideoDecodeAccelerator* mock_vda_after_reset_;
158 std::unique_ptr<RTCVideoDecoder> rtc_decoder_; 241 std::unique_ptr<RTCVideoDecoder> rtc_decoder_;
159 webrtc::VideoCodec codec_; 242 webrtc::VideoCodec codec_;
160 base::Thread vda_thread_; 243 scoped_refptr<base::SingleThreadTaskRunner> video_decoder_task_runner_;
161 media::VideoDecodeAccelerator::Capabilities capabilities_;
162 244
163 private: 245 private:
164 scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_; 246 std::unique_ptr<media::VideoDecoder> CreateFakeVideoDecoder() {
247 std::unique_ptr<media::FakeVideoDecoder> fake_decoder(
248 new media::FakeVideoDecoder(0, /* decode_delay */
249 kMaxParallelVideoDecoderRequests,
250 base::Bind(&OnBytesDecoded)));
251 fake_video_decoder_ = fake_decoder.get();
252 return fake_decoder;
253 }
165 254
166 base::Lock lock_; 255 ThreadHelper video_decoder_thread_;
167 base::WaitableEvent idle_waiter_;
168 }; 256 };
169 257
170 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) { 258 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
259 // VP8 is supported, so |rtc_decoder_| should be non-null.
171 CreateDecoder(webrtc::kVideoCodecVP8); 260 CreateDecoder(webrtc::kVideoCodecVP8);
172 std::unique_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create( 261 EXPECT_NE(nullptr, rtc_decoder_.get());
173 webrtc::kVideoCodecI420, mock_gpu_factories_.get())); 262
174 EXPECT_EQ(NULL, null_rtc_decoder.get()); 263 // I420 is not supported, so |rtc_decoder_| should be null.
264 CreateDecoder(webrtc::kVideoCodecI420);
265 EXPECT_EQ(nullptr, rtc_decoder_.get());
175 } 266 }
176 267
177 TEST_P(RTCVideoDecoderTest, CreateAndInitSucceeds) { 268 TEST_P(RTCVideoDecoderTest, CreateAndInitSucceedsForSupportedCodec) {
178 const webrtc::VideoCodecType codec_type = GetParam(); 269 const webrtc::VideoCodecType codec_type = GetParam();
179 CreateDecoder(codec_type); 270 CreateDecoder(codec_type);
271 ASSERT_NE(nullptr, rtc_decoder_.get());
180 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1)); 272 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
181 } 273 }
182 274
183 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) { 275 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
184 CreateDecoder(webrtc::kVideoCodecVP8); 276 CreateDecoder(webrtc::kVideoCodecVP8);
185 codec_.codecSpecific.VP8.feedbackModeOn = true; 277 codec_.codecSpecific.VP8.feedbackModeOn = true;
186 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1)); 278 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
187 } 279 }
188 280
189 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) { 281 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
(...skipping 19 matching lines...) Expand all
209 input_image._completeFrame = true; 301 input_image._completeFrame = true;
210 bool missingFrames = true; 302 bool missingFrames = true;
211 EXPECT_EQ( 303 EXPECT_EQ(
212 WEBRTC_VIDEO_CODEC_ERROR, 304 WEBRTC_VIDEO_CODEC_ERROR,
213 rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0)); 305 rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0));
214 } 306 }
215 307
216 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { 308 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
217 CreateDecoder(webrtc::kVideoCodecVP8); 309 CreateDecoder(webrtc::kVideoCodecVP8);
218 Initialize(); 310 Initialize();
219 EXPECT_CALL(*mock_vda_, Reset()) 311
220 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone)); 312 // TODO(slan): Mock Reset() call here.
313
221 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release()); 314 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
222 } 315 }
223 316
224 TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) { 317 TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
225 CreateDecoder(webrtc::kVideoCodecVP8); 318 CreateDecoder(webrtc::kVideoCodecVP8);
226 EXPECT_CALL(*mock_vda_, Reset())
227 .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
228 Initialize(); 319 Initialize();
320
229 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release()); 321 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
230 Initialize(); 322 Initialize();
323
231 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release()); 324 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
232 } 325 }
233 326
234 TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
235 CreateDecoder(webrtc::kVideoCodecVP8);
236 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
237 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
238 RTCVideoDecoder::ID_INVALID));
239 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2,
240 RTCVideoDecoder::ID_HALF + 2));
241 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2,
242 RTCVideoDecoder::ID_HALF - 2));
243
244 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0));
245 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
246 EXPECT_FALSE(
247 rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2));
248 EXPECT_TRUE(
249 rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2));
250
251 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0));
252 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
253 RTCVideoDecoder::ID_HALF - 2));
254 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
255 RTCVideoDecoder::ID_HALF + 2));
256 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
257 RTCVideoDecoder::ID_LAST));
258 }
259
260 TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
261 CreateDecoder(webrtc::kVideoCodecVP8);
262 EXPECT_TRUE(
263 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
264 EXPECT_FALSE(
265 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_INVALID));
266 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(0, 0));
267 EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(1, 0));
268 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(2, 0));
269
270 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_HALF,
271 RTCVideoDecoder::ID_HALF));
272 EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(
273 RTCVideoDecoder::ID_HALF + 1, RTCVideoDecoder::ID_HALF));
274 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(
275 RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF));
276
277 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST,
278 RTCVideoDecoder::ID_LAST));
279 EXPECT_TRUE(
280 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
281 EXPECT_FALSE(
282 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
283 }
284
285 // Tests/Verifies that |rtc_encoder_| drops incoming frames and its error 327 // Tests/Verifies that |rtc_encoder_| drops incoming frames and its error
286 // counter is increased when in an error condition. 328 // counter is increased when in an error condition.
287 TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForTesting) { 329 TEST_P(RTCVideoDecoderTest, GetDecoderErrorCounterForTesting) {
288 const webrtc::VideoCodecType codec_type = GetParam(); 330 const webrtc::VideoCodecType codec_type = GetParam();
289 CreateDecoder(codec_type); 331 CreateDecoder(codec_type);
290 Initialize(); 332 Initialize();
291 333
292 webrtc::EncodedImage input_image; 334 // Hold the next decode, so that we can trigger an error.
335 ASSERT_NE(nullptr, fake_video_decoder_);
336 video_decoder_task_runner_->PostTask(
337 FROM_HERE, base::Bind(&media::FakeVideoDecoder::HoldDecode,
338 base::Unretained(fake_video_decoder_)));
339 RunUntilIdle();
340
341 // Send a valid key frame to the decoder.
342 uint8_t buffer[kVideoFrameWidth * kVideoFrameHeight];
343 webrtc::EncodedImage input_image(buffer, sizeof(buffer), sizeof(buffer));
293 input_image._completeFrame = true; 344 input_image._completeFrame = true;
294 input_image._encodedWidth = kMinResolutionWidth; 345 input_image._encodedWidth = kVideoFrameWidth;
295 input_image._encodedHeight = kMaxResolutionHeight; 346 input_image._encodedHeight = kVideoFrameHeight;
347 input_image._frameType = webrtc::kVideoFrameKey;
348 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
349 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
350
351 // Simulate an error from the decoder. This will run the held decode callback
352 // with DECODE_ERROR.
353 video_decoder_task_runner_->PostTask(
354 FROM_HERE, base::Bind(&media::FakeVideoDecoder::SimulateError,
355 base::Unretained(fake_video_decoder_)));
356 RunUntilIdle();
357 EXPECT_EQ(1, rtc_decoder_->GetDecoderErrorCounterForTesting());
358
359 // We will continue to push this frame, but each one will not be a key frame.
296 input_image._frameType = webrtc::kVideoFrameDelta; 360 input_image._frameType = webrtc::kVideoFrameDelta;
297 input_image._length = kMinResolutionWidth * kMaxResolutionHeight; 361
362 // This should trigger a Reset() on the decoder.
298 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, 363 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
299 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); 364 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
300 RunUntilIdle(); 365 EXPECT_EQ(1, rtc_decoder_->GetDecoderErrorCounterForTesting());
301
302 // Notify the decoder about a platform error.
303 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
304 RunUntilIdle();
305 EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
306
307 // Expect decode call to reset decoder, and set up a new VDA to track it.
308 SetUpResetVDA();
309 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
310 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
311 EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
312 366
313 // Decoder expects a keyframe after reset, so drops any other frames. However, 367 // Decoder expects a keyframe after reset, so drops any other frames. However,
314 // we should still increment the error counter. 368 // we should still increment the error counter.
315 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, 369 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
316 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); 370 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
317 EXPECT_EQ(2, rtc_decoder_->GetVDAErrorCounterForTesting()); 371 EXPECT_EQ(2, rtc_decoder_->GetDecoderErrorCounterForTesting());
372 }
373
374 // Verify that there are never more than GetMaxDecodeRequests() issued to the
375 // decoder concurrently.
376 TEST_F(RTCVideoDecoderTest, MaxNumberOfRequestsIsNotExceeded) {
377 CreateDecoder(webrtc::kVideoCodecVP8);
378 Initialize();
379
380 // Hold incoming decode requests.
381 ASSERT_NE(nullptr, fake_video_decoder_);
382 video_decoder_task_runner_->PostTask(
383 FROM_HERE, base::Bind(&media::FakeVideoDecoder::HoldDecode,
384 base::Unretained(fake_video_decoder_)));
385 RunUntilIdle();
386
387 uint8_t buffer[kVideoFrameWidth * kVideoFrameHeight];
388 webrtc::EncodedImage input_image(buffer, sizeof(buffer), sizeof(buffer));
389 input_image._completeFrame = true;
390 input_image._encodedWidth = kVideoFrameWidth;
391 input_image._encodedHeight = kVideoFrameHeight;
392 input_image._frameType = webrtc::kVideoFrameKey;
393
394 // Determine how many concurrent decode requests the remote decoder can
395 // handle, and send more than that into the RTCVideoDecoder. Frames
396 // should buffer until the remote decoder calls back.
397 const int numRequests = fake_video_decoder_->GetMaxDecodeRequests();
398 EXPECT_EQ(kMaxParallelVideoDecoderRequests, numRequests);
399 for (int i = 0; i < numRequests + 1; ++i) {
400 if (i > 0)
401 input_image._frameType = webrtc::kVideoFrameDelta;
402 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
403 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
404 }
405 RunUntilIdle();
406
407 // Release the pending decodes.
408 video_decoder_task_runner_->PostTask(
409 FROM_HERE, base::Bind(&media::FakeVideoDecoder::SatisfyDecode,
410 base::Unretained(fake_video_decoder_)));
411 RunUntilIdle();
318 } 412 }
319 413
320 INSTANTIATE_TEST_CASE_P(CodecProfiles, 414 INSTANTIATE_TEST_CASE_P(CodecProfiles,
321 RTCVideoDecoderTest, 415 RTCVideoDecoderTest,
322 Values(webrtc::kVideoCodecVP8, 416 Values(webrtc::kVideoCodecVP8,
417 webrtc::kVideoCodecVP9,
323 webrtc::kVideoCodecH264)); 418 webrtc::kVideoCodecH264));
324 419
325 } // content 420 } // content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698