Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/filters/audio_renderer_base.h" | 5 #include "media/filters/audio_renderer_base.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 } | 60 } |
| 61 if (!callback.is_null()) { | 61 if (!callback.is_null()) { |
| 62 callback.Run(); | 62 callback.Run(); |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 | 65 |
| 66 void AudioRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 66 void AudioRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
| 67 base::AutoLock auto_lock(lock_); | 67 base::AutoLock auto_lock(lock_); |
| 68 DCHECK_EQ(kPaused, state_); | 68 DCHECK_EQ(kPaused, state_); |
| 69 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 69 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
| 70 DCHECK(pause_callback_.is_null()); | |
| 70 DCHECK(seek_cb_.is_null()); | 71 DCHECK(seek_cb_.is_null()); |
| 71 state_ = kSeeking; | 72 state_ = kSeeking; |
| 72 seek_cb_ = cb; | 73 seek_cb_ = cb; |
| 73 seek_timestamp_ = time; | 74 seek_timestamp_ = time; |
| 74 | 75 |
| 75 // Throw away everything and schedule our reads. | 76 // Throw away everything and schedule our reads. |
| 76 last_fill_buffer_time_ = base::TimeDelta(); | 77 last_fill_buffer_time_ = base::TimeDelta(); |
| 77 recieved_end_of_stream_ = false; | 78 recieved_end_of_stream_ = false; |
| 78 rendered_end_of_stream_ = false; | 79 rendered_end_of_stream_ = false; |
| 79 | 80 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 } | 138 } |
| 138 | 139 |
| 139 void AudioRendererBase::DecodedAudioReady(scoped_refptr<Buffer> buffer) { | 140 void AudioRendererBase::DecodedAudioReady(scoped_refptr<Buffer> buffer) { |
| 140 base::AutoLock auto_lock(lock_); | 141 base::AutoLock auto_lock(lock_); |
| 141 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying || | 142 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying || |
| 142 state_ == kUnderflow || state_ == kRebuffering || state_ == kStopped); | 143 state_ == kUnderflow || state_ == kRebuffering || state_ == kStopped); |
| 143 | 144 |
| 144 CHECK(pending_read_); | 145 CHECK(pending_read_); |
| 145 pending_read_ = false; | 146 pending_read_ = false; |
| 146 | 147 |
| 147 // TODO(scherkus): this happens due to a race, primarily because Stop() is a | 148 if (buffer && buffer->IsEndOfStream()) { |
| 148 // synchronous call when it should be asynchronous and accept a callback. | 149 recieved_end_of_stream_ = true; |
| 149 // Refer to http://crbug.com/16059 | 150 |
| 150 if (state_ == kStopped) { | 151 // Transition to kPlaying if we are currently handling an underflow since |
| 151 return; | 152 // no more data will be arriving. |
| 153 if (state_ == kUnderflow || state_ == kRebuffering) | |
| 154 state_ = kPlaying; | |
| 152 } | 155 } |
| 153 | 156 |
| 154 // Don't enqueue an end-of-stream buffer because it has no data, otherwise | 157 switch (state_) { |
| 155 // discard decoded audio data until we reach our desired seek timestamp. | 158 case kUninitialized: |
| 156 if (buffer->IsEndOfStream()) { | 159 NOTREACHED(); |
| 157 recieved_end_of_stream_ = true; | 160 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.
| |
| 158 | 161 case kPaused: |
| 159 // Transition to kPlaying if we are currently handling an underflow since no | 162 EnqueueBuffer(buffer); |
| 160 // more data will be arriving. | 163 DCHECK(!pending_read_); |
| 161 if (state_ == kUnderflow || state_ == kRebuffering) | 164 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
| |
| 162 state_ = kPlaying; | 165 break; |
| 163 } else if (state_ == kSeeking && !buffer->IsEndOfStream() && | 166 case kSeeking: |
| 164 (buffer->GetTimestamp() + buffer->GetDuration()) < | 167 if (IsBeforeSeekTime(buffer)) { |
| 165 seek_timestamp_) { | 168 ScheduleRead_Locked(); |
| 166 ScheduleRead_Locked(); | 169 return; |
| 167 } else { | 170 } |
| 168 // Note: Calling this may schedule more reads. | 171 EnqueueBuffer(buffer); |
| 169 algorithm_->EnqueueBuffer(buffer); | 172 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
| |
| 170 } | 173 state_ = kPaused; |
| 171 | 174 ResetAndRunCB(&seek_cb_, PIPELINE_OK); |
| 172 // Check for our preroll complete condition. | 175 return; |
| 173 if (state_ == kSeeking) { | 176 } |
| 174 DCHECK(!seek_cb_.is_null()); | 177 break; |
| 175 if (algorithm_->IsQueueFull() || recieved_end_of_stream_) { | 178 case kPlaying: |
| 176 // Transition into paused whether we have data in |algorithm_| or not. | 179 case kUnderflow: |
| 177 // FillBuffer() will play silence if there's nothing to fill. | 180 case kRebuffering: |
| 178 state_ = kPaused; | 181 EnqueueBuffer(buffer); |
| 179 ResetAndRunCB(&seek_cb_, PIPELINE_OK); | 182 break; |
| 180 } | 183 case kStopped: |
| 181 } else if (state_ == kPaused && !pending_read_) { | 184 return; |
| 182 // No more pending read! We're now officially "paused". | |
| 183 if (!pause_callback_.is_null()) { | |
| 184 pause_callback_.Run(); | |
| 185 pause_callback_.Reset(); | |
| 186 } | |
| 187 } | 185 } |
| 188 } | 186 } |
| 189 | 187 |
| 190 uint32 AudioRendererBase::FillBuffer(uint8* dest, | 188 uint32 AudioRendererBase::FillBuffer(uint8* dest, |
| 191 uint32 dest_len, | 189 uint32 dest_len, |
| 192 const base::TimeDelta& playback_delay, | 190 const base::TimeDelta& playback_delay, |
| 193 bool buffers_empty) { | 191 bool buffers_empty) { |
| 194 // The timestamp of the last buffer written during the last call to | 192 // The timestamp of the last buffer written during the last call to |
| 195 // FillBuffer(). | 193 // FillBuffer(). |
| 196 base::TimeDelta last_fill_buffer_time; | 194 base::TimeDelta last_fill_buffer_time; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 } | 262 } |
| 265 | 263 |
| 266 if (!underflow_cb.is_null()) | 264 if (!underflow_cb.is_null()) |
| 267 underflow_cb.Run(); | 265 underflow_cb.Run(); |
| 268 | 266 |
| 269 return dest_written; | 267 return dest_written; |
| 270 } | 268 } |
| 271 | 269 |
| 272 void AudioRendererBase::ScheduleRead_Locked() { | 270 void AudioRendererBase::ScheduleRead_Locked() { |
| 273 lock_.AssertAcquired(); | 271 lock_.AssertAcquired(); |
| 274 if (pending_read_) | 272 if (pending_read_ || state_ == kPaused) |
| 275 return; | 273 return; |
| 276 pending_read_ = true; | 274 pending_read_ = true; |
| 277 decoder_->Read(read_cb_); | 275 decoder_->Read(read_cb_); |
| 278 } | 276 } |
| 279 | 277 |
| 280 void AudioRendererBase::SetPlaybackRate(float playback_rate) { | 278 void AudioRendererBase::SetPlaybackRate(float playback_rate) { |
| 281 base::AutoLock auto_lock(lock_); | 279 base::AutoLock auto_lock(lock_); |
| 282 algorithm_->SetPlaybackRate(playback_rate); | 280 algorithm_->SetPlaybackRate(playback_rate); |
| 283 } | 281 } |
| 284 | 282 |
| 285 float AudioRendererBase::GetPlaybackRate() { | 283 float AudioRendererBase::GetPlaybackRate() { |
| 286 base::AutoLock auto_lock(lock_); | 284 base::AutoLock auto_lock(lock_); |
| 287 return algorithm_->playback_rate(); | 285 return algorithm_->playback_rate(); |
| 288 } | 286 } |
| 289 | 287 |
| 288 bool AudioRendererBase::IsBeforeSeekTime(const scoped_refptr<Buffer>& buffer) { | |
| 289 return (state_ == kSeeking) && buffer && !buffer->IsEndOfStream() && | |
| 290 (buffer->GetTimestamp() + buffer->GetDuration()) < seek_timestamp_; | |
| 291 } | |
| 292 | |
| 293 void AudioRendererBase::EnqueueBuffer(const scoped_refptr<Buffer>& buffer) { | |
| 294 if (buffer && !buffer->IsEndOfStream()) | |
| 295 algorithm_->EnqueueBuffer(buffer); | |
| 296 } | |
| 297 | |
| 290 } // namespace media | 298 } // namespace media |
| OLD | NEW |