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 CopyAndResetCB(seek_cb_).Run(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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
570 | 578 |
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; |
Ami GONE FROM CHROMIUM
2011/05/12 20:42:16
Typically the reason we have this sort of stack va
acolwell GONE FROM CHROMIUM
2011/05/12 22:30:40
Done.
| |
589 FilterStatusCB status_cb; | |
590 | |
581 switch (state_) { | 591 switch (state_) { |
582 case kUninitialized: | 592 case kUninitialized: |
583 case kPrerolled: | 593 case kPrerolled: |
584 case kPaused: | 594 case kPaused: |
585 case kFlushed: | 595 case kFlushed: |
586 case kEnded: | 596 case kEnded: |
587 case kPlaying: | 597 case kPlaying: |
588 break; | 598 break; |
589 | 599 |
590 case kFlushing: | 600 case kFlushing: |
591 CHECK(flush_callback_.get()); | 601 CHECK(flush_callback_.get()); |
592 callback.swap(flush_callback_); | 602 callback.swap(flush_callback_); |
593 break; | 603 break; |
594 | 604 |
595 case kSeeking: | 605 case kSeeking: { |
596 CHECK(seek_callback_.get()); | 606 CHECK(!seek_cb_.is_null()); |
597 callback.swap(seek_callback_); | 607 status_cb = CopyAndResetCB(seek_cb_); |
Ami GONE FROM CHROMIUM
2011/05/12 20:42:16
std::swap() fits in better here, esp. if you take
acolwell GONE FROM CHROMIUM
2011/05/12 22:30:40
Done.
| |
598 break; | 608 } break; |
Ami GONE FROM CHROMIUM
2011/05/12 20:42:16
braces should be unnecessary.
acolwell GONE FROM CHROMIUM
2011/05/12 22:30:40
Done.
| |
599 | 609 |
600 case kStopped: | 610 case kStopped: |
601 NOTREACHED() << "Should not error if stopped."; | 611 NOTREACHED() << "Should not error if stopped."; |
602 return; | 612 return; |
603 | 613 |
604 case kError: | 614 case kError: |
605 return; | 615 return; |
606 } | 616 } |
607 state_ = kError; | 617 state_ = kError; |
618 | |
619 if (!status_cb.is_null()) { | |
620 status_cb.Run(status); | |
621 return; | |
622 } | |
623 | |
608 host()->SetError(status); | 624 host()->SetError(status); |
Ami GONE FROM CHROMIUM
2011/05/12 20:42:16
Is it really right to not set the host's error sta
acolwell GONE FROM CHROMIUM
2011/05/12 22:30:40
Yes. Calling host()->SetError() is the old style o
Ami GONE FROM CHROMIUM
2011/05/12 22:49:25
I understand this, but I'm questioning whether the
acolwell GONE FROM CHROMIUM
2011/05/13 00:49:10
Sorry I wasn't clear. Yes this is safe because in
| |
609 | 625 |
610 if (callback.get()) | 626 if (callback.get()) |
611 callback->Run(); | 627 callback->Run(); |
612 } | 628 } |
613 | 629 |
614 } // namespace media | 630 } // namespace media |
OLD | NEW |