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 |