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

Side by Side Diff: media/filters/video_renderer_impl_unittest.cc

Issue 297553002: Add callback in VideoDecoder and AudioDecoder to return decoded frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
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 <utility> 5 #include <utility>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/debug/stack_trace.h" 10 #include "base/debug/stack_trace.h"
(...skipping 14 matching lines...) Expand all
25 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
26 26
27 using ::testing::_; 27 using ::testing::_;
28 using ::testing::AnyNumber; 28 using ::testing::AnyNumber;
29 using ::testing::AtLeast; 29 using ::testing::AtLeast;
30 using ::testing::InSequence; 30 using ::testing::InSequence;
31 using ::testing::Invoke; 31 using ::testing::Invoke;
32 using ::testing::NiceMock; 32 using ::testing::NiceMock;
33 using ::testing::NotNull; 33 using ::testing::NotNull;
34 using ::testing::Return; 34 using ::testing::Return;
35 using ::testing::SaveArg;
35 using ::testing::StrictMock; 36 using ::testing::StrictMock;
36 37
37 namespace media { 38 namespace media {
38 39
39 ACTION_P(RunClosure, closure) { 40 ACTION_P(RunClosure, closure) {
40 closure.Run(); 41 closure.Run();
41 } 42 }
42 43
43 MATCHER_P(HasTimestamp, ms, "") { 44 MATCHER_P(HasTimestamp, ms, "") {
44 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds(); 45 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds();
(...skipping 15 matching lines...) Expand all
60 new VideoRendererImpl(message_loop_.message_loop_proxy(), 61 new VideoRendererImpl(message_loop_.message_loop_proxy(),
61 decoders.Pass(), 62 decoders.Pass(),
62 media::SetDecryptorReadyCB(), 63 media::SetDecryptorReadyCB(),
63 base::Bind(&StrictMock<MockDisplayCB>::Display, 64 base::Bind(&StrictMock<MockDisplayCB>::Display,
64 base::Unretained(&mock_display_cb_)), 65 base::Unretained(&mock_display_cb_)),
65 true)); 66 true));
66 67
67 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal()); 68 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal());
68 69
69 // We expect these to be called but we don't care how/when. 70 // We expect these to be called but we don't care how/when.
70 EXPECT_CALL(demuxer_stream_, Read(_)) 71 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly(
71 .WillRepeatedly(RunCallback<0>(DemuxerStream::kOk, 72 RunCallback<0>(DemuxerStream::kOk,
72 DecoderBuffer::CreateEOSBuffer())); 73 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))));
73 EXPECT_CALL(*decoder_, Stop()) 74 EXPECT_CALL(*decoder_, Stop())
74 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::StopRequested)); 75 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::StopRequested));
75 EXPECT_CALL(statistics_cb_object_, OnStatistics(_)) 76 EXPECT_CALL(statistics_cb_object_, OnStatistics(_))
76 .Times(AnyNumber()); 77 .Times(AnyNumber());
77 EXPECT_CALL(*this, OnTimeUpdate(_)) 78 EXPECT_CALL(*this, OnTimeUpdate(_))
78 .Times(AnyNumber()); 79 .Times(AnyNumber());
79 } 80 }
80 81
81 virtual ~VideoRendererImplTest() {} 82 virtual ~VideoRendererImplTest() {}
82 83
83 // Callbacks passed into Initialize(). 84 // Callbacks passed into Initialize().
84 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta)); 85 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta));
85 86
86 void Initialize() { 87 void Initialize() {
87 InitializeWithLowDelay(false); 88 InitializeWithLowDelay(false);
88 } 89 }
89 90
90 void InitializeWithLowDelay(bool low_delay) { 91 void InitializeWithLowDelay(bool low_delay) {
91 // Monitor decodes from the decoder. 92 // Monitor decodes from the decoder.
92 EXPECT_CALL(*decoder_, Decode(_, _)) 93 EXPECT_CALL(*decoder_, Decode(_, _))
93 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FrameRequested)); 94 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::DecodeRequested));
94 95
95 EXPECT_CALL(*decoder_, Reset(_)) 96 EXPECT_CALL(*decoder_, Reset(_))
96 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FlushRequested)); 97 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FlushRequested));
97 98
98 InSequence s; 99 InSequence s;
99 100
100 EXPECT_CALL(*decoder_, Initialize(_, _, _))
101 .WillOnce(RunCallback<2>(PIPELINE_OK));
102
103 // Set playback rate before anything else happens. 101 // Set playback rate before anything else happens.
104 renderer_->SetPlaybackRate(1.0f); 102 renderer_->SetPlaybackRate(1.0f);
105 103
106 // Initialize, we shouldn't have any reads. 104 // Initialize, we shouldn't have any reads.
107 InitializeRenderer(PIPELINE_OK, low_delay); 105 InitializeRenderer(PIPELINE_OK, low_delay);
108 } 106 }
109 107
110 void InitializeRenderer(PipelineStatus expected, bool low_delay) { 108 void InitializeRenderer(PipelineStatus expected, bool low_delay) {
111 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected)); 109 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected));
112 WaitableMessageLoopEvent event; 110 WaitableMessageLoopEvent event;
113 CallInitialize(event.GetPipelineStatusCB(), low_delay); 111 CallInitialize(event.GetPipelineStatusCB(), low_delay, expected);
114 event.RunAndWaitForStatus(expected); 112 event.RunAndWaitForStatus(expected);
115 } 113 }
116 114
117 void CallInitialize(const PipelineStatusCB& status_cb, bool low_delay) { 115 void CallInitialize(const PipelineStatusCB& status_cb,
116 bool low_delay,
117 PipelineStatus decoder_status) {
118 EXPECT_CALL(*decoder_, Initialize(_, _, _, _)).WillOnce(
119 DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(decoder_status)));
118 renderer_->Initialize( 120 renderer_->Initialize(
119 &demuxer_stream_, 121 &demuxer_stream_,
120 low_delay, 122 low_delay,
121 status_cb, 123 status_cb,
122 base::Bind(&MockStatisticsCB::OnStatistics, 124 base::Bind(&MockStatisticsCB::OnStatistics,
123 base::Unretained(&statistics_cb_object_)), 125 base::Unretained(&statistics_cb_object_)),
124 base::Bind(&VideoRendererImplTest::OnTimeUpdate, 126 base::Bind(&VideoRendererImplTest::OnTimeUpdate,
125 base::Unretained(this)), 127 base::Unretained(this)),
126 ended_event_.GetClosure(), 128 ended_event_.GetClosure(),
127 error_event_.GetPipelineStatusCB(), 129 error_event_.GetPipelineStatusCB(),
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 base::TimeDelta::FromMilliseconds(timestamp_in_ms)); 214 base::TimeDelta::FromMilliseconds(timestamp_in_ms));
213 decode_results_.push_back(std::make_pair(VideoDecoder::kOk, frame)); 215 decode_results_.push_back(std::make_pair(VideoDecoder::kOk, frame));
214 continue; 216 continue;
215 } 217 }
216 218
217 CHECK(false) << "Unrecognized decoder buffer token: " << tokens[i]; 219 CHECK(false) << "Unrecognized decoder buffer token: " << tokens[i];
218 } 220 }
219 } 221 }
220 222
221 bool IsReadPending() { 223 bool IsReadPending() {
222 return !read_cb_.is_null(); 224 return !decode_cb_.is_null();
223 } 225 }
224 226
225 void WaitForError(PipelineStatus expected) { 227 void WaitForError(PipelineStatus expected) {
226 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); 228 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected));
227 error_event_.RunAndWaitForStatus(expected); 229 error_event_.RunAndWaitForStatus(expected);
228 } 230 }
229 231
230 void WaitForEnded() { 232 void WaitForEnded() {
231 SCOPED_TRACE("WaitForEnded()"); 233 SCOPED_TRACE("WaitForEnded()");
232 ended_event_.RunAndWait(); 234 ended_event_.RunAndWait();
233 } 235 }
234 236
235 void WaitForPendingRead() { 237 void WaitForPendingRead() {
236 SCOPED_TRACE("WaitForPendingRead()"); 238 SCOPED_TRACE("WaitForPendingRead()");
237 if (!read_cb_.is_null()) 239 if (!decode_cb_.is_null())
238 return; 240 return;
239 241
240 DCHECK(wait_for_pending_read_cb_.is_null()); 242 DCHECK(wait_for_pending_decode_cb_.is_null());
241 243
242 WaitableMessageLoopEvent event; 244 WaitableMessageLoopEvent event;
243 wait_for_pending_read_cb_ = event.GetClosure(); 245 wait_for_pending_decode_cb_ = event.GetClosure();
244 event.RunAndWait(); 246 event.RunAndWait();
245 247
246 DCHECK(!read_cb_.is_null()); 248 DCHECK(!decode_cb_.is_null());
247 DCHECK(wait_for_pending_read_cb_.is_null()); 249 DCHECK(wait_for_pending_decode_cb_.is_null());
248 } 250 }
249 251
250 void SatisfyPendingRead() { 252 void SatisfyPendingRead() {
251 CHECK(!read_cb_.is_null()); 253 CHECK(!decode_cb_.is_null());
252 CHECK(!decode_results_.empty()); 254 CHECK(!decode_results_.empty());
253 255
254 base::Closure closure = base::Bind( 256 // Post tasks for OutputCB and DecodeCB.
255 read_cb_, decode_results_.front().first, 257 scoped_refptr<VideoFrame> frame = decode_results_.front().second;
256 decode_results_.front().second); 258 if (frame)
257 259 message_loop_.PostTask(FROM_HERE, base::Bind(output_cb_, frame));
258 read_cb_.Reset(); 260 message_loop_.PostTask(
261 FROM_HERE, base::Bind(base::ResetAndReturn(&decode_cb_),
262 decode_results_.front().first));
259 decode_results_.pop_front(); 263 decode_results_.pop_front();
260
261 message_loop_.PostTask(FROM_HERE, closure);
262 } 264 }
263 265
264 void AdvanceTimeInMs(int time_ms) { 266 void AdvanceTimeInMs(int time_ms) {
265 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 267 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
266 base::AutoLock l(lock_); 268 base::AutoLock l(lock_);
267 time_ += base::TimeDelta::FromMilliseconds(time_ms); 269 time_ += base::TimeDelta::FromMilliseconds(time_ms);
268 DCHECK_LE(time_.InMicroseconds(), GetDuration().InMicroseconds()); 270 DCHECK_LE(time_.InMicroseconds(), GetDuration().InMicroseconds());
269 } 271 }
270 272
271 protected: 273 protected:
(...skipping 13 matching lines...) Expand all
285 private: 287 private:
286 base::TimeDelta GetTime() { 288 base::TimeDelta GetTime() {
287 base::AutoLock l(lock_); 289 base::AutoLock l(lock_);
288 return time_; 290 return time_;
289 } 291 }
290 292
291 base::TimeDelta GetDuration() { 293 base::TimeDelta GetDuration() {
292 return base::TimeDelta::FromMilliseconds(kVideoDurationInMs); 294 return base::TimeDelta::FromMilliseconds(kVideoDurationInMs);
293 } 295 }
294 296
295 void FrameRequested(const scoped_refptr<DecoderBuffer>& buffer, 297 void DecodeRequested(const scoped_refptr<DecoderBuffer>& buffer,
296 const VideoDecoder::DecodeCB& read_cb) { 298 const VideoDecoder::DecodeCB& decode_cb) {
297 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 299 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
298 CHECK(read_cb_.is_null()); 300 CHECK(decode_cb_.is_null());
299 read_cb_ = read_cb; 301 decode_cb_ = decode_cb;
300 302
301 // Wake up WaitForPendingRead() if needed. 303 // Wake up WaitForPendingRead() if needed.
302 if (!wait_for_pending_read_cb_.is_null()) 304 if (!wait_for_pending_decode_cb_.is_null())
303 base::ResetAndReturn(&wait_for_pending_read_cb_).Run(); 305 base::ResetAndReturn(&wait_for_pending_decode_cb_).Run();
304 306
305 if (decode_results_.empty()) 307 if (decode_results_.empty())
306 return; 308 return;
307 309
308 SatisfyPendingRead(); 310 SatisfyPendingRead();
309 } 311 }
310 312
311 void FlushRequested(const base::Closure& callback) { 313 void FlushRequested(const base::Closure& callback) {
312 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 314 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
313 decode_results_.clear(); 315 decode_results_.clear();
314 if (!read_cb_.is_null()) { 316 if (!decode_cb_.is_null()) {
315 QueueFrames("abort"); 317 QueueFrames("abort");
316 SatisfyPendingRead(); 318 SatisfyPendingRead();
317 } 319 }
318 320
319 message_loop_.PostTask(FROM_HERE, callback); 321 message_loop_.PostTask(FROM_HERE, callback);
320 } 322 }
321 323
322 void StopRequested() { 324 void StopRequested() {
323 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 325 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
324 decode_results_.clear(); 326 decode_results_.clear();
325 if (!read_cb_.is_null()) { 327 if (!decode_cb_.is_null()) {
326 QueueFrames("abort"); 328 QueueFrames("abort");
327 SatisfyPendingRead(); 329 SatisfyPendingRead();
328 } 330 }
329 } 331 }
330 332
331 base::MessageLoop message_loop_; 333 base::MessageLoop message_loop_;
332 334
333 // Used to protect |time_|. 335 // Used to protect |time_|.
334 base::Lock lock_; 336 base::Lock lock_;
335 base::TimeDelta time_; 337 base::TimeDelta time_;
336 338
337 // Used for satisfying reads. 339 // Used for satisfying reads.
338 VideoDecoder::DecodeCB read_cb_; 340 VideoDecoder::OutputCB output_cb_;
341 VideoDecoder::DecodeCB decode_cb_;
339 base::TimeDelta next_frame_timestamp_; 342 base::TimeDelta next_frame_timestamp_;
340 343
341 WaitableMessageLoopEvent error_event_; 344 WaitableMessageLoopEvent error_event_;
342 WaitableMessageLoopEvent ended_event_; 345 WaitableMessageLoopEvent ended_event_;
343 346
344 // Run during FrameRequested() to unblock WaitForPendingRead(). 347 // Run during DecodeRequested() to unblock WaitForPendingRead().
345 base::Closure wait_for_pending_read_cb_; 348 base::Closure wait_for_pending_decode_cb_;
346 349
347 std::deque<std::pair< 350 std::deque<std::pair<
348 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_; 351 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_;
349 352
350 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest); 353 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
351 }; 354 };
352 355
353 TEST_F(VideoRendererImplTest, DoNothing) { 356 TEST_F(VideoRendererImplTest, DoNothing) {
354 // Test that creation and deletion doesn't depend on calls to Initialize() 357 // Test that creation and deletion doesn't depend on calls to Initialize()
355 // and/or Stop(). 358 // and/or Stop().
(...skipping 15 matching lines...) Expand all
371 Preroll(0, PIPELINE_OK); 374 Preroll(0, PIPELINE_OK);
372 Shutdown(); 375 Shutdown();
373 } 376 }
374 377
375 static void ExpectNotCalled(PipelineStatus) { 378 static void ExpectNotCalled(PipelineStatus) {
376 base::debug::StackTrace stack; 379 base::debug::StackTrace stack;
377 ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString(); 380 ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString();
378 } 381 }
379 382
380 TEST_F(VideoRendererImplTest, StopWhileInitializing) { 383 TEST_F(VideoRendererImplTest, StopWhileInitializing) {
381 EXPECT_CALL(*decoder_, Initialize(_, _, _)) 384 CallInitialize(base::Bind(&ExpectNotCalled), false, PIPELINE_OK);
382 .WillOnce(RunCallback<2>(PIPELINE_OK));
383 CallInitialize(base::Bind(&ExpectNotCalled), false);
384 Stop(); 385 Stop();
385 386
386 // ~VideoRendererImpl() will CHECK() if we left anything initialized. 387 // ~VideoRendererImpl() will CHECK() if we left anything initialized.
387 } 388 }
388 389
389 TEST_F(VideoRendererImplTest, StopWhileFlushing) { 390 TEST_F(VideoRendererImplTest, StopWhileFlushing) {
390 Initialize(); 391 Initialize();
391 renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK)); 392 renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK));
392 Stop(); 393 Stop();
393 394
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 TEST_F(VideoRendererImplTest, AbortPendingRead_Preroll) { 619 TEST_F(VideoRendererImplTest, AbortPendingRead_Preroll) {
619 Initialize(); 620 Initialize();
620 QueueFrames("0 10 abort"); 621 QueueFrames("0 10 abort");
621 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0))); 622 EXPECT_CALL(mock_display_cb_, Display(HasTimestamp(0)));
622 Preroll(0, PIPELINE_OK); 623 Preroll(0, PIPELINE_OK);
623 Shutdown(); 624 Shutdown();
624 } 625 }
625 626
626 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { 627 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) {
627 InSequence s; 628 InSequence s;
628
629 EXPECT_CALL(*decoder_, Initialize(_, _, _))
630 .WillOnce(RunCallback<2>(DECODER_ERROR_NOT_SUPPORTED));
631 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED, false); 629 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED, false);
632
633 Stop(); 630 Stop();
634 } 631 }
635 632
636 } // namespace media 633 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698