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

Unified Diff: media/filters/audio_renderer_base.cc

Issue 9295020: Fix ChunkDemuxer seek deadlock (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comments and added VideoRendererBase & FFmpegVideoDecoder unit tests. Created 8 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: media/filters/audio_renderer_base.cc
diff --git a/media/filters/audio_renderer_base.cc b/media/filters/audio_renderer_base.cc
index 049a39a1005856fc38032ddc3da4b879636bccf5..c7f556290b62d171b49f9da6d5c35725b7534364 100644
--- a/media/filters/audio_renderer_base.cc
+++ b/media/filters/audio_renderer_base.cc
@@ -67,6 +67,7 @@ void AudioRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) {
base::AutoLock auto_lock(lock_);
DCHECK_EQ(kPaused, state_);
DCHECK(!pending_read_) << "Pending read must complete before seeking";
+ DCHECK(pause_callback_.is_null());
DCHECK(seek_cb_.is_null());
state_ = kSeeking;
seek_cb_ = cb;
@@ -144,46 +145,43 @@ void AudioRendererBase::DecodedAudioReady(scoped_refptr<Buffer> buffer) {
CHECK(pending_read_);
pending_read_ = false;
- // TODO(scherkus): this happens due to a race, primarily because Stop() is a
- // synchronous call when it should be asynchronous and accept a callback.
- // Refer to http://crbug.com/16059
- if (state_ == kStopped) {
- return;
- }
-
- // Don't enqueue an end-of-stream buffer because it has no data, otherwise
- // discard decoded audio data until we reach our desired seek timestamp.
- if (buffer->IsEndOfStream()) {
+ if (buffer && buffer->IsEndOfStream()) {
recieved_end_of_stream_ = true;
- // Transition to kPlaying if we are currently handling an underflow since no
- // more data will be arriving.
+ // Transition to kPlaying if we are currently handling an underflow since
+ // no more data will be arriving.
if (state_ == kUnderflow || state_ == kRebuffering)
state_ = kPlaying;
- } else if (state_ == kSeeking && !buffer->IsEndOfStream() &&
- (buffer->GetTimestamp() + buffer->GetDuration()) <
- seek_timestamp_) {
- ScheduleRead_Locked();
- } else {
- // Note: Calling this may schedule more reads.
- algorithm_->EnqueueBuffer(buffer);
}
- // Check for our preroll complete condition.
- if (state_ == kSeeking) {
- DCHECK(!seek_cb_.is_null());
- if (algorithm_->IsQueueFull() || recieved_end_of_stream_) {
- // Transition into paused whether we have data in |algorithm_| or not.
- // FillBuffer() will play silence if there's nothing to fill.
- state_ = kPaused;
- ResetAndRunCB(&seek_cb_, PIPELINE_OK);
- }
- } else if (state_ == kPaused && !pending_read_) {
- // No more pending read! We're now officially "paused".
- if (!pause_callback_.is_null()) {
- pause_callback_.Run();
- pause_callback_.Reset();
- }
+ switch (state_) {
+ case kUninitialized:
+ NOTREACHED();
+ break;
Ami GONE FROM CHROMIUM 2012/01/29 22:12:38 s/break/return/ here and everywhere below, for uni
acolwell GONE FROM CHROMIUM 2012/01/30 00:14:14 Done.
+ case kPaused:
+ EnqueueBuffer(buffer);
+ DCHECK(!pending_read_);
+ ResetAndRunCB(&pause_callback_);
Ami GONE FROM CHROMIUM 2012/01/29 22:12:38 Before your CL the code could handle receiving mul
acolwell GONE FROM CHROMIUM 2012/01/30 00:14:14 That was because algorithm->EnqueueBuffer() could
+ break;
+ case kSeeking:
+ if (IsBeforeSeekTime(buffer)) {
+ ScheduleRead_Locked();
+ return;
+ }
+ EnqueueBuffer(buffer);
+ if (!buffer || buffer->IsEndOfStream() || algorithm_->IsQueueFull()) {
Ami GONE FROM CHROMIUM 2012/01/29 22:12:38 That the first two clauses repeat the test in Enqu
acolwell GONE FROM CHROMIUM 2012/01/30 00:14:14 Removed EB and just put the conditional checks in
+ state_ = kPaused;
+ ResetAndRunCB(&seek_cb_, PIPELINE_OK);
+ return;
+ }
+ break;
+ case kPlaying:
+ case kUnderflow:
+ case kRebuffering:
+ EnqueueBuffer(buffer);
+ break;
+ case kStopped:
+ return;
}
}
@@ -271,7 +269,7 @@ uint32 AudioRendererBase::FillBuffer(uint8* dest,
void AudioRendererBase::ScheduleRead_Locked() {
lock_.AssertAcquired();
- if (pending_read_)
+ if (pending_read_ || state_ == kPaused)
return;
pending_read_ = true;
decoder_->Read(read_cb_);
@@ -287,4 +285,14 @@ float AudioRendererBase::GetPlaybackRate() {
return algorithm_->playback_rate();
}
+bool AudioRendererBase::IsBeforeSeekTime(const scoped_refptr<Buffer>& buffer) {
+ return (state_ == kSeeking) && buffer && !buffer->IsEndOfStream() &&
+ (buffer->GetTimestamp() + buffer->GetDuration()) < seek_timestamp_;
+}
+
+void AudioRendererBase::EnqueueBuffer(const scoped_refptr<Buffer>& buffer) {
+ if (buffer && !buffer->IsEndOfStream())
+ algorithm_->EnqueueBuffer(buffer);
+}
+
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698