| 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 return; |
| 158 | 161 case kPaused: |
| 159 // Transition to kPlaying if we are currently handling an underflow since no | 162 if (buffer && !buffer->IsEndOfStream()) |
| 160 // more data will be arriving. | 163 algorithm_->EnqueueBuffer(buffer); |
| 161 if (state_ == kUnderflow || state_ == kRebuffering) | 164 DCHECK(!pending_read_); |
| 162 state_ = kPlaying; | 165 ResetAndRunCB(&pause_callback_); |
| 163 } else if (state_ == kSeeking && !buffer->IsEndOfStream() && | 166 return; |
| 164 (buffer->GetTimestamp() + buffer->GetDuration()) < | 167 case kSeeking: |
| 165 seek_timestamp_) { | 168 if (IsBeforeSeekTime(buffer)) { |
| 166 ScheduleRead_Locked(); | 169 ScheduleRead_Locked(); |
| 167 } else { | 170 return; |
| 168 // Note: Calling this may schedule more reads. | 171 } |
| 169 algorithm_->EnqueueBuffer(buffer); | 172 if (buffer && !buffer->IsEndOfStream()) { |
| 170 } | 173 algorithm_->EnqueueBuffer(buffer); |
| 171 | 174 if (!algorithm_->IsQueueFull()) |
| 172 // Check for our preroll complete condition. | 175 return; |
| 173 if (state_ == kSeeking) { | 176 } |
| 174 DCHECK(!seek_cb_.is_null()); | |
| 175 if (algorithm_->IsQueueFull() || recieved_end_of_stream_) { | |
| 176 // Transition into paused whether we have data in |algorithm_| or not. | |
| 177 // FillBuffer() will play silence if there's nothing to fill. | |
| 178 state_ = kPaused; | 177 state_ = kPaused; |
| 179 ResetAndRunCB(&seek_cb_, PIPELINE_OK); | 178 ResetAndRunCB(&seek_cb_, PIPELINE_OK); |
| 180 } | 179 return; |
| 181 } else if (state_ == kPaused && !pending_read_) { | 180 case kPlaying: |
| 182 // No more pending read! We're now officially "paused". | 181 case kUnderflow: |
| 183 if (!pause_callback_.is_null()) { | 182 case kRebuffering: |
| 184 pause_callback_.Run(); | 183 if (buffer && !buffer->IsEndOfStream()) |
| 185 pause_callback_.Reset(); | 184 algorithm_->EnqueueBuffer(buffer); |
| 186 } | 185 return; |
| 186 case kStopped: |
| 187 return; |
| 187 } | 188 } |
| 188 } | 189 } |
| 189 | 190 |
| 190 uint32 AudioRendererBase::FillBuffer(uint8* dest, | 191 uint32 AudioRendererBase::FillBuffer(uint8* dest, |
| 191 uint32 dest_len, | 192 uint32 dest_len, |
| 192 const base::TimeDelta& playback_delay) { | 193 const base::TimeDelta& playback_delay) { |
| 193 // The timestamp of the last buffer written during the last call to | 194 // The timestamp of the last buffer written during the last call to |
| 194 // FillBuffer(). | 195 // FillBuffer(). |
| 195 base::TimeDelta last_fill_buffer_time; | 196 base::TimeDelta last_fill_buffer_time; |
| 196 size_t dest_written = 0; | 197 size_t dest_written = 0; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 void AudioRendererBase::SignalEndOfStream() { | 272 void AudioRendererBase::SignalEndOfStream() { |
| 272 DCHECK(recieved_end_of_stream_); | 273 DCHECK(recieved_end_of_stream_); |
| 273 if (!rendered_end_of_stream_) { | 274 if (!rendered_end_of_stream_) { |
| 274 rendered_end_of_stream_ = true; | 275 rendered_end_of_stream_ = true; |
| 275 host()->NotifyEnded(); | 276 host()->NotifyEnded(); |
| 276 } | 277 } |
| 277 } | 278 } |
| 278 | 279 |
| 279 void AudioRendererBase::ScheduleRead_Locked() { | 280 void AudioRendererBase::ScheduleRead_Locked() { |
| 280 lock_.AssertAcquired(); | 281 lock_.AssertAcquired(); |
| 281 if (pending_read_) | 282 if (pending_read_ || state_ == kPaused) |
| 282 return; | 283 return; |
| 283 pending_read_ = true; | 284 pending_read_ = true; |
| 284 decoder_->Read(read_cb_); | 285 decoder_->Read(read_cb_); |
| 285 } | 286 } |
| 286 | 287 |
| 287 void AudioRendererBase::SetPlaybackRate(float playback_rate) { | 288 void AudioRendererBase::SetPlaybackRate(float playback_rate) { |
| 288 base::AutoLock auto_lock(lock_); | 289 base::AutoLock auto_lock(lock_); |
| 289 algorithm_->SetPlaybackRate(playback_rate); | 290 algorithm_->SetPlaybackRate(playback_rate); |
| 290 } | 291 } |
| 291 | 292 |
| 292 float AudioRendererBase::GetPlaybackRate() { | 293 float AudioRendererBase::GetPlaybackRate() { |
| 293 base::AutoLock auto_lock(lock_); | 294 base::AutoLock auto_lock(lock_); |
| 294 return algorithm_->playback_rate(); | 295 return algorithm_->playback_rate(); |
| 295 } | 296 } |
| 296 | 297 |
| 298 bool AudioRendererBase::IsBeforeSeekTime(const scoped_refptr<Buffer>& buffer) { |
| 299 return (state_ == kSeeking) && buffer && !buffer->IsEndOfStream() && |
| 300 (buffer->GetTimestamp() + buffer->GetDuration()) < seek_timestamp_; |
| 301 } |
| 302 |
| 297 } // namespace media | 303 } // namespace media |
| OLD | NEW |