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