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 "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/callback.h" | 6 #include "base/callback.h" |
7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
8 #include "base/threading/platform_thread.h" | 8 #include "base/threading/platform_thread.h" |
9 #include "media/base/buffers.h" | 9 #include "media/base/buffers.h" |
10 #include "media/base/filter_host.h" | 10 #include "media/base/filter_host.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 base::AutoLock auto_lock(lock_); | 47 base::AutoLock auto_lock(lock_); |
48 DCHECK(state_ != kUninitialized || state_ == kError); | 48 DCHECK(state_ != kUninitialized || state_ == kError); |
49 state_ = kPaused; | 49 state_ = kPaused; |
50 callback.Run(); | 50 callback.Run(); |
51 } | 51 } |
52 | 52 |
53 void VideoRendererBase::Flush(const base::Closure& callback) { | 53 void VideoRendererBase::Flush(const base::Closure& callback) { |
54 base::AutoLock auto_lock(lock_); | 54 base::AutoLock auto_lock(lock_); |
55 DCHECK_EQ(state_, kPaused); | 55 DCHECK_EQ(state_, kPaused); |
56 flush_cb_ = callback; | 56 flush_cb_ = callback; |
57 state_ = kFlushing; | 57 state_ = kFlushingDecoder; |
58 | 58 |
59 AttemptFlush_Locked(); | 59 // We must unlock here because the callback might run within the Flush() |
60 // call. | |
scherkus (not reviewing)
2012/04/25 03:33:58
should we have semantics similar to VideoDecoder::
acolwell GONE FROM CHROMIUM
2012/04/25 17:41:44
Yes. I think that is a good idea. I created a bug
| |
61 base::AutoUnlock auto_unlock(lock_); | |
62 decoder_->Flush(base::Bind(&VideoRendererBase::OnDecoderFlushDone, this)); | |
60 } | 63 } |
61 | 64 |
62 void VideoRendererBase::Stop(const base::Closure& callback) { | 65 void VideoRendererBase::Stop(const base::Closure& callback) { |
63 if (state_ == kStopped) { | 66 if (state_ == kStopped) { |
64 callback.Run(); | 67 callback.Run(); |
65 return; | 68 return; |
66 } | 69 } |
67 | 70 |
68 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; | 71 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; |
69 { | 72 { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 DCHECK(!pending_paint_); | 338 DCHECK(!pending_paint_); |
336 pending_paint_with_last_available_ = false; | 339 pending_paint_with_last_available_ = false; |
337 } else { | 340 } else { |
338 DCHECK(!frame); | 341 DCHECK(!frame); |
339 } | 342 } |
340 | 343 |
341 // We had cleared the |pending_paint_| flag, there are chances that current | 344 // We had cleared the |pending_paint_| flag, there are chances that current |
342 // frame is timed-out. We will wake up our main thread to advance the current | 345 // frame is timed-out. We will wake up our main thread to advance the current |
343 // frame when this is true. | 346 // frame when this is true. |
344 frame_available_.Signal(); | 347 frame_available_.Signal(); |
348 if (state_ == kFlushingDecoder) | |
349 return; | |
350 | |
345 if (state_ == kFlushing) { | 351 if (state_ == kFlushing) { |
346 AttemptFlush_Locked(); | 352 AttemptFlush_Locked(); |
347 } else if (state_ == kError || state_ == kStopped) { | 353 return; |
354 } | |
355 | |
356 if (state_ == kError || state_ == kStopped) { | |
348 DoStopOrError_Locked(); | 357 DoStopOrError_Locked(); |
349 } | 358 } |
350 } | 359 } |
351 | 360 |
352 void VideoRendererBase::FrameReady(scoped_refptr<VideoFrame> frame) { | 361 void VideoRendererBase::FrameReady(scoped_refptr<VideoFrame> frame) { |
353 base::AutoLock auto_lock(lock_); | 362 base::AutoLock auto_lock(lock_); |
354 DCHECK_NE(state_, kUninitialized); | 363 DCHECK_NE(state_, kUninitialized); |
355 | 364 |
356 CHECK(pending_read_); | 365 CHECK(pending_read_); |
357 pending_read_ = false; | 366 pending_read_ = false; |
358 | 367 |
359 // Already-queued Decoder ReadCB's can fire after various state transitions | 368 // Already-queued Decoder ReadCB's can fire after various state transitions |
360 // have happened; in that case just drop those frames immediately. | 369 // have happened; in that case just drop those frames immediately. |
361 if (state_ == kStopped || state_ == kError || state_ == kFlushed) | 370 if (state_ == kStopped || state_ == kError || state_ == kFlushed || |
371 state_ == kFlushingDecoder) | |
362 return; | 372 return; |
363 | 373 |
364 if (state_ == kFlushing) { | 374 if (state_ == kFlushing) { |
365 AttemptFlush_Locked(); | 375 AttemptFlush_Locked(); |
366 return; | 376 return; |
367 } | 377 } |
368 | 378 |
369 if (!frame) { | 379 if (!frame) { |
370 if (state_ != kSeeking) | 380 if (state_ != kSeeking) |
371 return; | 381 return; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 paint_cb_.Run(); | 449 paint_cb_.Run(); |
440 } | 450 } |
441 } | 451 } |
442 | 452 |
443 void VideoRendererBase::AttemptRead_Locked() { | 453 void VideoRendererBase::AttemptRead_Locked() { |
444 lock_.AssertAcquired(); | 454 lock_.AssertAcquired(); |
445 DCHECK_NE(kEnded, state_); | 455 DCHECK_NE(kEnded, state_); |
446 | 456 |
447 if (pending_read_ || | 457 if (pending_read_ || |
448 NumFrames_Locked() == limits::kMaxVideoFrames || | 458 NumFrames_Locked() == limits::kMaxVideoFrames || |
449 (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream())) { | 459 (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream()) || |
450 return; | 460 state_ == kFlushingDecoder || |
451 } | 461 state_ == kFlushing) { |
462 return; | |
463 } | |
452 | 464 |
453 pending_read_ = true; | 465 pending_read_ = true; |
454 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this)); | 466 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this)); |
455 } | 467 } |
456 | 468 |
469 void VideoRendererBase::OnDecoderFlushDone() { | |
470 base::AutoLock auto_lock(lock_); | |
471 DCHECK_EQ(kFlushingDecoder, state_); | |
472 DCHECK(!pending_read_); | |
473 | |
474 state_ = kFlushing; | |
475 AttemptFlush_Locked(); | |
476 } | |
477 | |
457 void VideoRendererBase::AttemptFlush_Locked() { | 478 void VideoRendererBase::AttemptFlush_Locked() { |
458 lock_.AssertAcquired(); | 479 lock_.AssertAcquired(); |
459 DCHECK_EQ(kFlushing, state_); | 480 DCHECK_EQ(kFlushing, state_); |
460 | 481 |
461 // Get rid of any ready frames. | 482 // Get rid of any ready frames. |
462 ready_frames_.clear(); | 483 ready_frames_.clear(); |
463 | 484 |
464 if (!pending_paint_ && !pending_read_) { | 485 if (!pending_paint_ && !pending_read_) { |
465 state_ = kFlushed; | 486 state_ = kFlushed; |
466 current_frame_ = NULL; | 487 current_frame_ = NULL; |
467 | 488 base::ResetAndReturn(&flush_cb_).Run(); |
468 base::Closure flush_cb = flush_cb_; | |
469 flush_cb_.Reset(); | |
470 decoder_->Flush(flush_cb); | |
471 } | 489 } |
472 } | 490 } |
473 | 491 |
474 base::TimeDelta VideoRendererBase::CalculateSleepDuration( | 492 base::TimeDelta VideoRendererBase::CalculateSleepDuration( |
475 const scoped_refptr<VideoFrame>& next_frame, | 493 const scoped_refptr<VideoFrame>& next_frame, |
476 float playback_rate) { | 494 float playback_rate) { |
477 // Determine the current and next presentation timestamps. | 495 // Determine the current and next presentation timestamps. |
478 base::TimeDelta now = host()->GetTime(); | 496 base::TimeDelta now = host()->GetTime(); |
479 base::TimeDelta this_pts = current_frame_->GetTimestamp(); | 497 base::TimeDelta this_pts = current_frame_->GetTimestamp(); |
480 base::TimeDelta next_pts; | 498 base::TimeDelta next_pts; |
(...skipping 20 matching lines...) Expand all Loading... | |
501 | 519 |
502 int VideoRendererBase::NumFrames_Locked() const { | 520 int VideoRendererBase::NumFrames_Locked() const { |
503 lock_.AssertAcquired(); | 521 lock_.AssertAcquired(); |
504 int outstanding_frames = | 522 int outstanding_frames = |
505 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + | 523 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + |
506 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); | 524 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); |
507 return ready_frames_.size() + outstanding_frames; | 525 return ready_frames_.size() + outstanding_frames; |
508 } | 526 } |
509 | 527 |
510 } // namespace media | 528 } // namespace media |
OLD | NEW |