OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/filters/video_renderer_base.h" | 5 #include "media/filters/video_renderer_base.h" |
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/message_loop.h" | 10 #include "base/message_loop.h" |
11 #include "base/threading/platform_thread.h" | 11 #include "base/threading/platform_thread.h" |
12 #include "media/base/buffers.h" | 12 #include "media/base/buffers.h" |
13 #include "media/base/limits.h" | 13 #include "media/base/limits.h" |
14 #include "media/base/pipeline.h" | 14 #include "media/base/pipeline.h" |
15 #include "media/base/video_frame.h" | 15 #include "media/base/video_frame.h" |
16 #include "media/filters/decrypting_demuxer_stream.h" | 16 #include "media/filters/decrypting_demuxer_stream.h" |
17 #include "media/filters/video_decoder_selector.h" | 17 #include "media/filters/video_decoder_selector.h" |
18 | 18 |
19 namespace media { | 19 namespace media { |
20 | 20 |
21 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { | 21 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { |
22 return base::TimeDelta::FromMilliseconds(250); | 22 return base::TimeDelta::FromMilliseconds(250); |
23 } | 23 } |
24 | 24 |
25 VideoRendererBase::VideoRendererBase( | 25 VideoRendererBase::VideoRendererBase( |
26 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 26 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
27 const SetDecryptorReadyCB& set_decryptor_ready_cb, | 27 const SetDecryptorReadyCB& set_decryptor_ready_cb, |
28 const base::Closure& paint_cb, | 28 const PaintCB& paint_cb, |
29 const SetOpaqueCB& set_opaque_cb, | 29 const SetOpaqueCB& set_opaque_cb, |
30 bool drop_frames) | 30 bool drop_frames) |
31 : message_loop_(message_loop), | 31 : message_loop_(message_loop), |
32 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 32 set_decryptor_ready_cb_(set_decryptor_ready_cb), |
33 frame_available_(&lock_), | 33 frame_available_(&lock_), |
34 state_(kUninitialized), | 34 state_(kUninitialized), |
35 thread_(base::kNullThreadHandle), | 35 thread_(base::kNullThreadHandle), |
36 pending_read_(false), | 36 pending_read_(false), |
37 pending_paint_(false), | |
38 pending_paint_with_last_available_(false), | |
39 drop_frames_(drop_frames), | 37 drop_frames_(drop_frames), |
40 playback_rate_(0), | 38 playback_rate_(0), |
41 paint_cb_(paint_cb), | 39 paint_cb_(paint_cb), |
42 set_opaque_cb_(set_opaque_cb) { | 40 set_opaque_cb_(set_opaque_cb), |
41 last_timestamp_(kNoTimestamp()) { | |
43 DCHECK(!paint_cb_.is_null()); | 42 DCHECK(!paint_cb_.is_null()); |
44 } | 43 } |
45 | 44 |
46 void VideoRendererBase::Play(const base::Closure& callback) { | 45 void VideoRendererBase::Play(const base::Closure& callback) { |
47 DCHECK(message_loop_->BelongsToCurrentThread()); | 46 DCHECK(message_loop_->BelongsToCurrentThread()); |
48 base::AutoLock auto_lock(lock_); | 47 base::AutoLock auto_lock(lock_); |
49 DCHECK_EQ(kPrerolled, state_); | 48 DCHECK_EQ(kPrerolled, state_); |
50 state_ = kPlaying; | 49 state_ = kPlaying; |
51 callback.Run(); | 50 callback.Run(); |
52 } | 51 } |
(...skipping 23 matching lines...) Expand all Loading... | |
76 } | 75 } |
77 | 76 |
78 void VideoRendererBase::ResetDecoder() { | 77 void VideoRendererBase::ResetDecoder() { |
79 DCHECK(message_loop_->BelongsToCurrentThread()); | 78 DCHECK(message_loop_->BelongsToCurrentThread()); |
80 base::AutoLock auto_lock(lock_); | 79 base::AutoLock auto_lock(lock_); |
81 decoder_->Reset(base::Bind(&VideoRendererBase::OnDecoderResetDone, this)); | 80 decoder_->Reset(base::Bind(&VideoRendererBase::OnDecoderResetDone, this)); |
82 } | 81 } |
83 | 82 |
84 void VideoRendererBase::Stop(const base::Closure& callback) { | 83 void VideoRendererBase::Stop(const base::Closure& callback) { |
85 DCHECK(message_loop_->BelongsToCurrentThread()); | 84 DCHECK(message_loop_->BelongsToCurrentThread()); |
86 if (state_ == kUninitialized || state_ == kStopped) { | 85 if (state_ == kUninitialized || state_ == kStopped) { |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
I'm pretty sure these checks should be done under
scherkus (not reviewing)
2013/02/01 22:45:25
Done.
| |
87 callback.Run(); | 86 callback.Run(); |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
message_loop_->PostTask(FROM_HERE, callback) ?
scherkus (not reviewing)
2013/02/01 22:45:25
I'm going to hold off on cleaning up VRB threading
| |
88 return; | 87 return; |
89 } | 88 } |
90 | 89 |
91 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; | 90 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; |
92 { | 91 { |
93 base::AutoLock auto_lock(lock_); | 92 base::AutoLock auto_lock(lock_); |
94 state_ = kStopped; | 93 state_ = kStopped; |
95 | 94 |
96 statistics_cb_.Reset(); | 95 statistics_cb_.Reset(); |
97 max_time_cb_.Reset(); | 96 max_time_cb_.Reset(); |
98 if (!pending_paint_ && !pending_paint_with_last_available_) | 97 DoStopOrError_Locked(); |
99 DoStopOrError_Locked(); | |
100 | 98 |
101 // Clean up our thread if present. | 99 // Clean up our thread if present. |
102 if (thread_ != base::kNullThreadHandle) { | 100 if (thread_ != base::kNullThreadHandle) { |
103 // Signal the thread since it's possible to get stopped with the video | 101 // Signal the thread since it's possible to get stopped with the video |
104 // thread waiting for a read to complete. | 102 // thread waiting for a read to complete. |
105 frame_available_.Signal(); | 103 frame_available_.Signal(); |
106 thread_to_join = thread_; | 104 thread_to_join = thread_; |
107 thread_ = base::kNullThreadHandle; | 105 thread_ = base::kNullThreadHandle; |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
nit: std::swap(thread_to_join, thread_)
scherkus (not reviewing)
2013/02/01 22:45:25
Done.
| |
108 } | 106 } |
109 } | 107 } |
110 if (thread_to_join != base::kNullThreadHandle) | 108 if (thread_to_join != base::kNullThreadHandle) |
111 base::PlatformThread::Join(thread_to_join); | 109 base::PlatformThread::Join(thread_to_join); |
112 | 110 |
113 if (decrypting_demuxer_stream_) { | 111 if (decrypting_demuxer_stream_) { |
114 decrypting_demuxer_stream_->Reset(base::Bind( | 112 decrypting_demuxer_stream_->Reset(base::Bind( |
115 &VideoRendererBase::StopDecoder, this, callback)); | 113 &VideoRendererBase::StopDecoder, this, callback)); |
116 return; | 114 return; |
117 } | 115 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
274 frame_available_.TimedWait(kIdleTimeDelta); | 272 frame_available_.TimedWait(kIdleTimeDelta); |
275 continue; | 273 continue; |
276 } | 274 } |
277 | 275 |
278 // Remain idle until we have the next frame ready for rendering. | 276 // Remain idle until we have the next frame ready for rendering. |
279 if (ready_frames_.empty()) { | 277 if (ready_frames_.empty()) { |
280 frame_available_.TimedWait(kIdleTimeDelta); | 278 frame_available_.TimedWait(kIdleTimeDelta); |
281 continue; | 279 continue; |
282 } | 280 } |
283 | 281 |
284 // Remain idle until we've initialized |current_frame_| via prerolling. | 282 // This can happen if our preroll only contains end of stream frames. |
285 if (!current_frame_) { | 283 if (ready_frames_.front()->IsEndOfStream()) { |
286 // This can happen if our preroll only contains end of stream frames. | 284 state_ = kEnded; |
287 if (ready_frames_.front()->IsEndOfStream()) { | 285 ended_cb_.Run(); |
288 state_ = kEnded; | 286 ready_frames_.clear(); |
289 ended_cb_.Run(); | |
290 ready_frames_.clear(); | |
291 | 287 |
292 // No need to sleep here as we idle when |state_ != kPlaying|. | 288 // No need to sleep here as we idle when |state_ != kPlaying|. |
293 continue; | |
294 } | |
295 | |
296 frame_available_.TimedWait(kIdleTimeDelta); | |
297 continue; | 289 continue; |
298 } | 290 } |
299 | 291 |
300 // Calculate how long until we should advance the frame, which is | 292 // Calculate how long until we should advance the frame, which is |
301 // typically negative but for playback rates < 1.0f may be long enough | 293 // typically negative but for playback rates < 1.0f may be long enough |
302 // that it makes more sense to idle and check again. | 294 // that it makes more sense to idle and check again. |
303 base::TimeDelta remaining_time = | 295 base::TimeDelta remaining_time = |
304 CalculateSleepDuration(ready_frames_.front(), playback_rate_); | 296 CalculateSleepDuration(ready_frames_.front(), playback_rate_); |
305 | 297 |
306 // Sleep up to a maximum of our idle time until we're within the time to | 298 // Sleep up to a maximum of our idle time until we're within the time to |
307 // render the next frame. | 299 // render the next frame. |
308 if (remaining_time.InMicroseconds() > 0) { | 300 if (remaining_time.InMicroseconds() > 0) { |
309 remaining_time = std::min(remaining_time, kIdleTimeDelta); | 301 remaining_time = std::min(remaining_time, kIdleTimeDelta); |
310 frame_available_.TimedWait(remaining_time); | 302 frame_available_.TimedWait(remaining_time); |
311 continue; | 303 continue; |
312 } | 304 } |
313 | 305 |
314 | |
315 // We're almost there! | |
316 // | |
317 // At this point we've rendered |current_frame_| for the proper amount | |
318 // of time and also have the next frame that ready for rendering. | |
319 | |
320 | |
321 // If the next frame is end of stream then we are truly at the end of the | |
322 // video stream. | |
323 // | |
324 // TODO(scherkus): deduplicate this end of stream check after we get rid of | |
325 // |current_frame_|. | |
326 if (ready_frames_.front()->IsEndOfStream()) { | |
327 state_ = kEnded; | |
328 ended_cb_.Run(); | |
329 ready_frames_.clear(); | |
330 | |
331 // No need to sleep here as we idle when |state_ != kPlaying|. | |
332 continue; | |
333 } | |
334 | |
335 // We cannot update |current_frame_| until we've completed the pending | |
336 // paint. Furthermore, the pending paint might be really slow: check to | |
337 // see if we have any ready frames that we can drop if they've already | |
338 // expired. | |
339 if (pending_paint_) { | |
340 while (!ready_frames_.empty()) { | |
341 // Can't drop anything if we're at the end. | |
342 if (ready_frames_.front()->IsEndOfStream()) | |
343 break; | |
344 | |
345 base::TimeDelta remaining_time = | |
346 ready_frames_.front()->GetTimestamp() - get_time_cb_.Run(); | |
347 | |
348 // Still a chance we can render the frame! | |
349 if (remaining_time.InMicroseconds() > 0) | |
350 break; | |
351 | |
352 if (!drop_frames_) | |
353 break; | |
354 | |
355 // Frame dropped: read again. | |
356 ++frames_dropped; | |
357 ready_frames_.pop_front(); | |
358 message_loop_->PostTask(FROM_HERE, base::Bind( | |
359 &VideoRendererBase::AttemptRead, this)); | |
360 } | |
361 // Continue waiting for the current paint to finish. | |
362 frame_available_.TimedWait(kIdleTimeDelta); | |
363 continue; | |
364 } | |
365 | |
366 | |
367 // Congratulations! You've made it past the video frame timing gauntlet. | 306 // Congratulations! You've made it past the video frame timing gauntlet. |
368 // | 307 // |
369 // We can now safely update the current frame, request another frame, and | 308 // At this point enough time has passed that the next frame that ready for |
370 // signal to the client that a new frame is available. | 309 // rendering. |
371 DCHECK(!pending_paint_); | 310 PaintWithNextReadyFrame(); |
372 DCHECK(!ready_frames_.empty()); | |
373 SetCurrentFrameToNextReadyFrame(); | |
374 message_loop_->PostTask(FROM_HERE, base::Bind( | 311 message_loop_->PostTask(FROM_HERE, base::Bind( |
375 &VideoRendererBase::AttemptRead, this)); | 312 &VideoRendererBase::AttemptRead, this)); |
376 | |
377 base::AutoUnlock auto_unlock(lock_); | |
378 paint_cb_.Run(); | |
379 } | 313 } |
380 } | 314 } |
381 | 315 |
382 void VideoRendererBase::SetCurrentFrameToNextReadyFrame() { | 316 void VideoRendererBase::PaintWithNextReadyFrame() { |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
nit: Add _Locked() & corresponding assert since th
scherkus (not reviewing)
2013/02/01 22:45:25
Done.
| |
383 current_frame_ = ready_frames_.front(); | 317 scoped_refptr<VideoFrame> next_frame = ready_frames_.front(); |
384 ready_frames_.pop_front(); | 318 ready_frames_.pop_front(); |
385 | 319 |
386 // Notify the pipeline of natural_size() changes. | 320 // Notify the pipeline of natural_size() changes. |
387 const gfx::Size& natural_size = current_frame_->natural_size(); | 321 const gfx::Size& natural_size = next_frame->natural_size(); |
388 if (natural_size != last_natural_size_) { | 322 if (natural_size != last_natural_size_) { |
389 size_changed_cb_.Run(natural_size); | 323 size_changed_cb_.Run(natural_size); |
390 last_natural_size_ = natural_size; | 324 last_natural_size_ = natural_size; |
391 } | 325 } |
392 } | |
393 | 326 |
394 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { | 327 paint_cb_.Run(next_frame); |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
This calls the callback under lock now. Are you su
scherkus (not reviewing)
2013/02/01 22:45:25
Yes. Previously it was terrifying because the most
| |
395 base::AutoLock auto_lock(lock_); | |
396 DCHECK(!pending_paint_ && !pending_paint_with_last_available_); | |
397 | |
398 if ((!current_frame_ || current_frame_->IsEndOfStream()) && | |
399 (!last_available_frame_ || last_available_frame_->IsEndOfStream())) { | |
400 *frame_out = NULL; | |
401 return; | |
402 } | |
403 | |
404 // We should have initialized and have the current frame. | |
405 DCHECK_NE(state_, kUninitialized); | |
406 DCHECK_NE(state_, kStopped); | |
407 DCHECK_NE(state_, kError); | |
408 | |
409 if (current_frame_) { | |
410 *frame_out = current_frame_; | |
411 last_available_frame_ = current_frame_; | |
412 pending_paint_ = true; | |
413 } else { | |
414 DCHECK(last_available_frame_); | |
415 *frame_out = last_available_frame_; | |
416 pending_paint_with_last_available_ = true; | |
417 } | |
418 } | |
419 | |
420 void VideoRendererBase::PutCurrentFrame(scoped_refptr<VideoFrame> frame) { | |
421 base::AutoLock auto_lock(lock_); | |
422 | |
423 // Note that we do not claim |pending_paint_| when we return NULL frame, in | |
424 // that case, |current_frame_| could be changed before PutCurrentFrame. | |
425 if (pending_paint_) { | |
426 DCHECK_EQ(current_frame_, frame); | |
427 DCHECK(!pending_paint_with_last_available_); | |
428 pending_paint_ = false; | |
429 } else if (pending_paint_with_last_available_) { | |
430 DCHECK_EQ(last_available_frame_, frame); | |
431 DCHECK(!pending_paint_); | |
432 pending_paint_with_last_available_ = false; | |
433 } else { | |
434 DCHECK(!frame); | |
435 } | |
436 | |
437 // We had cleared the |pending_paint_| flag, there are chances that current | |
438 // frame is timed-out. We will wake up our main thread to advance the current | |
439 // frame when this is true. | |
440 frame_available_.Signal(); | |
441 if (state_ == kFlushingDecoder) | |
442 return; | |
443 | |
444 if (state_ == kFlushing) { | |
445 AttemptFlush_Locked(); | |
446 return; | |
447 } | |
448 | |
449 if (state_ == kError || state_ == kStopped) { | |
450 DoStopOrError_Locked(); | |
451 } | |
452 } | 328 } |
453 | 329 |
454 VideoRendererBase::~VideoRendererBase() { | 330 VideoRendererBase::~VideoRendererBase() { |
455 base::AutoLock auto_lock(lock_); | 331 base::AutoLock auto_lock(lock_); |
456 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; | 332 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; |
457 } | 333 } |
458 | 334 |
459 void VideoRendererBase::FrameReady(VideoDecoder::Status status, | 335 void VideoRendererBase::FrameReady(VideoDecoder::Status status, |
460 const scoped_refptr<VideoFrame>& frame) { | 336 const scoped_refptr<VideoFrame>& frame) { |
461 base::AutoLock auto_lock(lock_); | 337 base::AutoLock auto_lock(lock_); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
525 // purposes: | 401 // purposes: |
526 // 1) Prerolling while paused | 402 // 1) Prerolling while paused |
527 // 2) Keeps decoding going if video rendering thread starts falling behind | 403 // 2) Keeps decoding going if video rendering thread starts falling behind |
528 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) { | 404 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) { |
529 AttemptRead_Locked(); | 405 AttemptRead_Locked(); |
530 return; | 406 return; |
531 } | 407 } |
532 | 408 |
533 // If we're at capacity or end of stream while prerolling we need to | 409 // If we're at capacity or end of stream while prerolling we need to |
534 // transition to prerolled. | 410 // transition to prerolled. |
535 if (state_ == kPrerolling) { | 411 if (state_ == kPrerolling) { |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
nit: reverse check and unindent?
scherkus (not reviewing)
2013/02/01 22:45:25
Done.
| |
536 DCHECK(!current_frame_); | |
537 state_ = kPrerolled; | 412 state_ = kPrerolled; |
538 | 413 |
539 // Because we might remain in the prerolled state for an undetermined amount | 414 // Because we might remain in the prerolled state for an undetermined amount |
540 // of time (i.e., we were not playing before we started prerolling), we'll | 415 // of time (i.e., we were not playing before we started prerolling), we'll |
541 // manually update the current frame and notify the subclass below. | 416 // manually update the current frame and notify the subclass below. |
542 if (!ready_frames_.front()->IsEndOfStream()) | 417 if (!ready_frames_.front()->IsEndOfStream()) |
543 SetCurrentFrameToNextReadyFrame(); | 418 PaintWithNextReadyFrame(); |
544 | 419 |
545 // ...and we're done prerolling! | 420 // ...and we're done prerolling! |
546 DCHECK(!preroll_cb_.is_null()); | |
547 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); | 421 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); |
548 | 422 |
423 #if 0 | |
424 // XXX do we still need this!? | |
scherkus (not reviewing)
2013/01/31 17:54:05
PWNRF() fires the paint_cb_ ... I suppose this mig
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
Not sure. What did we use to paint in the case whe
scherkus (not reviewing)
2013/02/01 22:45:25
current_frame_ would have been null, so SkCanvasVi
| |
549 base::AutoUnlock ul(lock_); | 425 base::AutoUnlock ul(lock_); |
550 paint_cb_.Run(); | 426 paint_cb_.Run(); |
427 #endif | |
551 } | 428 } |
552 } | 429 } |
553 | 430 |
554 void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) { | 431 void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) { |
555 // Adjust the incoming frame if its rendering stop time is past the duration | 432 // Adjust the incoming frame if its rendering stop time is past the duration |
556 // of the video itself. This is typically the last frame of the video and | 433 // of the video itself. This is typically the last frame of the video and |
557 // occurs if the container specifies a duration that isn't a multiple of the | 434 // occurs if the container specifies a duration that isn't a multiple of the |
558 // frame rate. Another way for this to happen is for the container to state a | 435 // frame rate. Another way for this to happen is for the container to state a |
559 // smaller duration than the largest packet timestamp. | 436 // smaller duration than the largest packet timestamp. |
560 base::TimeDelta duration = get_duration_cb_.Run(); | 437 base::TimeDelta duration = get_duration_cb_.Run(); |
561 if (frame->IsEndOfStream()) { | 438 if (frame->IsEndOfStream()) { |
562 base::TimeDelta end_timestamp = kNoTimestamp(); | 439 base::TimeDelta end_timestamp = kNoTimestamp(); |
563 if (!ready_frames_.empty()) { | 440 if (!ready_frames_.empty()) { |
564 end_timestamp = std::min( | 441 end_timestamp = std::min( |
565 duration, | 442 duration, |
566 ready_frames_.back()->GetTimestamp() + kMaxLastFrameDuration()); | 443 ready_frames_.back()->GetTimestamp() + kMaxLastFrameDuration()); |
567 } else if (current_frame_) { | 444 } else if (last_timestamp_ != kNoTimestamp()) { |
568 end_timestamp = | 445 end_timestamp = |
569 std::min(duration, | 446 std::min(duration, last_timestamp_ + kMaxLastFrameDuration()); |
570 current_frame_->GetTimestamp() + kMaxLastFrameDuration()); | |
571 } | 447 } |
572 frame->SetTimestamp(end_timestamp); | 448 frame->SetTimestamp(end_timestamp); |
573 } else if (frame->GetTimestamp() > duration) { | 449 } else if (frame->GetTimestamp() > duration) { |
574 frame->SetTimestamp(duration); | 450 frame->SetTimestamp(duration); |
575 } | 451 } |
576 | 452 |
577 ready_frames_.push_back(frame); | 453 ready_frames_.push_back(frame); |
578 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames); | 454 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames); |
579 | 455 |
580 base::TimeDelta max_clock_time = | 456 base::TimeDelta max_clock_time = |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 AttemptFlush_Locked(); | 505 AttemptFlush_Locked(); |
630 } | 506 } |
631 | 507 |
632 void VideoRendererBase::AttemptFlush_Locked() { | 508 void VideoRendererBase::AttemptFlush_Locked() { |
633 lock_.AssertAcquired(); | 509 lock_.AssertAcquired(); |
634 DCHECK_EQ(kFlushing, state_); | 510 DCHECK_EQ(kFlushing, state_); |
635 | 511 |
636 prerolling_delayed_frame_ = NULL; | 512 prerolling_delayed_frame_ = NULL; |
637 ready_frames_.clear(); | 513 ready_frames_.clear(); |
638 | 514 |
639 if (!pending_paint_ && !pending_read_) { | 515 if (!pending_read_) { |
640 state_ = kFlushed; | 516 state_ = kFlushed; |
641 current_frame_ = NULL; | 517 last_timestamp_ = kNoTimestamp(); |
642 base::ResetAndReturn(&flush_cb_).Run(); | 518 base::ResetAndReturn(&flush_cb_).Run(); |
643 } | 519 } |
644 } | 520 } |
645 | 521 |
646 base::TimeDelta VideoRendererBase::CalculateSleepDuration( | 522 base::TimeDelta VideoRendererBase::CalculateSleepDuration( |
647 const scoped_refptr<VideoFrame>& next_frame, | 523 const scoped_refptr<VideoFrame>& next_frame, |
648 float playback_rate) { | 524 float playback_rate) { |
649 // Determine the current and next presentation timestamps. | 525 // Determine the current and next presentation timestamps. |
650 base::TimeDelta now = get_time_cb_.Run(); | 526 base::TimeDelta now = get_time_cb_.Run(); |
651 base::TimeDelta next_pts = next_frame->GetTimestamp(); | 527 base::TimeDelta next_pts = next_frame->GetTimestamp(); |
652 | 528 |
653 // Scale our sleep based on the playback rate. | 529 // Scale our sleep based on the playback rate. |
654 base::TimeDelta sleep = next_pts - now; | 530 base::TimeDelta sleep = next_pts - now; |
655 return base::TimeDelta::FromMicroseconds( | 531 return base::TimeDelta::FromMicroseconds( |
656 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); | 532 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); |
657 } | 533 } |
658 | 534 |
659 void VideoRendererBase::DoStopOrError_Locked() { | 535 void VideoRendererBase::DoStopOrError_Locked() { |
660 DCHECK(!pending_paint_); | |
661 DCHECK(!pending_paint_with_last_available_); | |
662 lock_.AssertAcquired(); | 536 lock_.AssertAcquired(); |
663 current_frame_ = NULL; | 537 last_timestamp_ = kNoTimestamp(); |
664 last_available_frame_ = NULL; | |
665 ready_frames_.clear(); | 538 ready_frames_.clear(); |
666 } | 539 } |
667 | 540 |
668 int VideoRendererBase::NumFrames_Locked() const { | 541 int VideoRendererBase::NumFrames_Locked() const { |
669 lock_.AssertAcquired(); | 542 lock_.AssertAcquired(); |
670 int outstanding_frames = | 543 return ready_frames_.size(); |
671 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + | |
672 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); | |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
o.O I'm not going to miss this.
| |
673 return ready_frames_.size() + outstanding_frames; | |
674 } | 544 } |
675 | 545 |
676 } // namespace media | 546 } // namespace media |
OLD | NEW |