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 |