Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: media/filters/video_renderer_base.cc

Issue 6969026: Convert Filter::Seek() to use new callback system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add files in content/renderer/media Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698