Chromium Code Reviews| 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 |