| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/threading/platform_thread.h" | 7 #include "base/threading/platform_thread.h" |
| 8 #include "media/base/buffers.h" | 8 #include "media/base/buffers.h" |
| 9 #include "media/base/callback.h" | 9 #include "media/base/callback.h" |
| 10 #include "media/base/filter_host.h" | 10 #include "media/base/filter_host.h" |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 | 122 |
| 123 // Signal the subclass we're stopping. | 123 // Signal the subclass we're stopping. |
| 124 OnStop(callback); | 124 OnStop(callback); |
| 125 } | 125 } |
| 126 | 126 |
| 127 void VideoRendererBase::SetPlaybackRate(float playback_rate) { | 127 void VideoRendererBase::SetPlaybackRate(float playback_rate) { |
| 128 base::AutoLock auto_lock(lock_); | 128 base::AutoLock auto_lock(lock_); |
| 129 playback_rate_ = playback_rate; | 129 playback_rate_ = playback_rate; |
| 130 } | 130 } |
| 131 | 131 |
| 132 void VideoRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) { | 132 void VideoRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
| 133 base::AutoLock auto_lock(lock_); | 133 bool run_callback = false; |
| 134 // There is a race condition between filters to receive SeekTask(). | |
| 135 // It turns out we could receive buffer from decoder before seek() | |
| 136 // is called on us. so we do the following: | |
| 137 // kFlushed => ( Receive first buffer or Seek() ) => kSeeking and | |
| 138 // kSeeking => ( Receive enough buffers) => kPrerolled. ) | |
| 139 DCHECK(kPrerolled == state_ || kFlushed == state_ || kSeeking == state_); | |
| 140 | 134 |
| 141 if (state_ == kPrerolled) { | 135 { |
| 142 // Already get enough buffers from decoder. | 136 base::AutoLock auto_lock(lock_); |
| 143 callback->Run(); | 137 // There is a race condition between filters to receive SeekTask(). |
| 144 delete callback; | 138 // It turns out we could receive buffer from decoder before seek() |
| 145 } else { | 139 // is called on us. so we do the following: |
| 146 // Otherwise we are either kFlushed or kSeeking, but without enough buffers; | 140 // kFlushed => ( Receive first buffer or Seek() ) => kSeeking and |
| 147 // we should save the callback function and call it later. | 141 // kSeeking => ( Receive enough buffers) => kPrerolled. ) |
| 148 state_ = kSeeking; | 142 DCHECK(kPrerolled == state_ || kFlushed == state_ || kSeeking == state_); |
| 149 seek_callback_.reset(callback); | 143 DCHECK(!cb.is_null()); |
| 144 DCHECK(seek_cb_.is_null()); |
| 145 |
| 146 if (state_ == kPrerolled) { |
| 147 // Already get enough buffers from decoder. |
| 148 run_callback = true; |
| 149 |
| 150 } else { |
| 151 // Otherwise we are either kFlushed or kSeeking, but without enough |
| 152 // buffers we should save the callback function and call it later. |
| 153 state_ = kSeeking; |
| 154 seek_cb_ = cb; |
| 155 } |
| 156 |
| 157 seek_timestamp_ = time; |
| 158 ScheduleRead_Locked(); |
| 150 } | 159 } |
| 151 | 160 |
| 152 seek_timestamp_ = time; | 161 if (run_callback) |
| 153 ScheduleRead_Locked(); | 162 cb.Run(PIPELINE_OK); |
| 154 } | 163 } |
| 155 | 164 |
| 156 void VideoRendererBase::Initialize(VideoDecoder* decoder, | 165 void VideoRendererBase::Initialize(VideoDecoder* decoder, |
| 157 FilterCallback* callback, | 166 FilterCallback* callback, |
| 158 StatisticsCallback* stats_callback) { | 167 StatisticsCallback* stats_callback) { |
| 159 base::AutoLock auto_lock(lock_); | 168 base::AutoLock auto_lock(lock_); |
| 160 DCHECK(decoder); | 169 DCHECK(decoder); |
| 161 DCHECK(callback); | 170 DCHECK(callback); |
| 162 DCHECK(stats_callback); | 171 DCHECK(stats_callback); |
| 163 DCHECK_EQ(kUninitialized, state_); | 172 DCHECK_EQ(kUninitialized, state_); |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 first_frame = frames_queue_ready_.front(); | 464 first_frame = frames_queue_ready_.front(); |
| 456 if (!first_frame->IsEndOfStream()) { | 465 if (!first_frame->IsEndOfStream()) { |
| 457 frames_queue_ready_.pop_front(); | 466 frames_queue_ready_.pop_front(); |
| 458 current_frame_ = first_frame; | 467 current_frame_ = first_frame; |
| 459 } | 468 } |
| 460 new_frame_available = true; | 469 new_frame_available = true; |
| 461 | 470 |
| 462 // If we reach prerolled state before Seek() is called by pipeline, | 471 // If we reach prerolled state before Seek() is called by pipeline, |
| 463 // |seek_callback_| is not set, we will return immediately during | 472 // |seek_callback_| is not set, we will return immediately during |
| 464 // when Seek() is eventually called. | 473 // when Seek() is eventually called. |
| 465 if ((seek_callback_.get())) { | 474 if (!seek_cb_.is_null()) { |
| 466 seek_callback_->Run(); | 475 ResetAndRunCB(&seek_cb_, PIPELINE_OK); |
| 467 seek_callback_.reset(); | |
| 468 } | 476 } |
| 469 } | 477 } |
| 470 } else if (state_ == kFlushing && pending_reads_ == 0 && !pending_paint_) { | 478 } else if (state_ == kFlushing && pending_reads_ == 0 && !pending_paint_) { |
| 471 OnFlushDone(); | 479 OnFlushDone(); |
| 472 } | 480 } |
| 473 | 481 |
| 474 if (new_frame_available) { | 482 if (new_frame_available) { |
| 475 base::AutoUnlock auto_unlock(lock_); | 483 base::AutoUnlock auto_unlock(lock_); |
| 476 OnFrameAvailable(); | 484 OnFrameAvailable(); |
| 477 } | 485 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 // Scale our sleep based on the playback rate. | 579 // Scale our sleep based on the playback rate. |
| 572 // TODO(scherkus): floating point badness and degrade gracefully. | 580 // TODO(scherkus): floating point badness and degrade gracefully. |
| 573 return base::TimeDelta::FromMicroseconds( | 581 return base::TimeDelta::FromMicroseconds( |
| 574 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); | 582 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); |
| 575 } | 583 } |
| 576 | 584 |
| 577 void VideoRendererBase::EnterErrorState_Locked(PipelineStatus status) { | 585 void VideoRendererBase::EnterErrorState_Locked(PipelineStatus status) { |
| 578 lock_.AssertAcquired(); | 586 lock_.AssertAcquired(); |
| 579 | 587 |
| 580 scoped_ptr<FilterCallback> callback; | 588 scoped_ptr<FilterCallback> callback; |
| 581 switch (state_) { | 589 State old_state = state_; |
| 590 state_ = kError; |
| 591 |
| 592 switch (old_state) { |
| 582 case kUninitialized: | 593 case kUninitialized: |
| 583 case kPrerolled: | 594 case kPrerolled: |
| 584 case kPaused: | 595 case kPaused: |
| 585 case kFlushed: | 596 case kFlushed: |
| 586 case kEnded: | 597 case kEnded: |
| 587 case kPlaying: | 598 case kPlaying: |
| 588 break; | 599 break; |
| 589 | 600 |
| 590 case kFlushing: | 601 case kFlushing: |
| 591 CHECK(flush_callback_.get()); | 602 CHECK(flush_callback_.get()); |
| 592 callback.swap(flush_callback_); | 603 callback.swap(flush_callback_); |
| 593 break; | 604 break; |
| 594 | 605 |
| 595 case kSeeking: | 606 case kSeeking: |
| 596 CHECK(seek_callback_.get()); | 607 CHECK(!seek_cb_.is_null()); |
| 597 callback.swap(seek_callback_); | 608 ResetAndRunCB(&seek_cb_, status); |
| 609 return; |
| 598 break; | 610 break; |
| 599 | 611 |
| 600 case kStopped: | 612 case kStopped: |
| 601 NOTREACHED() << "Should not error if stopped."; | 613 NOTREACHED() << "Should not error if stopped."; |
| 602 return; | 614 return; |
| 603 | 615 |
| 604 case kError: | 616 case kError: |
| 605 return; | 617 return; |
| 606 } | 618 } |
| 607 state_ = kError; | 619 |
| 608 host()->SetError(status); | 620 host()->SetError(status); |
| 609 | 621 |
| 610 if (callback.get()) | 622 if (callback.get()) |
| 611 callback->Run(); | 623 callback->Run(); |
| 612 } | 624 } |
| 613 | 625 |
| 614 } // namespace media | 626 } // namespace media |
| OLD | NEW |