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 |