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_impl.h" | 5 #include "media/filters/audio_renderer_impl.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 received_end_of_stream_(false), | 60 received_end_of_stream_(false), |
61 rendered_end_of_stream_(false), | 61 rendered_end_of_stream_(false), |
62 weak_factory_(this) { | 62 weak_factory_(this) { |
63 audio_buffer_stream_->set_splice_observer(base::Bind( | 63 audio_buffer_stream_->set_splice_observer(base::Bind( |
64 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 64 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); |
65 audio_buffer_stream_->set_config_change_observer(base::Bind( | 65 audio_buffer_stream_->set_config_change_observer(base::Bind( |
66 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 66 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); |
67 } | 67 } |
68 | 68 |
69 AudioRendererImpl::~AudioRendererImpl() { | 69 AudioRendererImpl::~AudioRendererImpl() { |
70 // Stop() should have been called and |algorithm_| should have been destroyed. | 70 DVLOG(1) << __FUNCTION__; |
71 DCHECK(state_ == kUninitialized || state_ == kStopped); | 71 DCHECK(task_runner_->BelongsToCurrentThread()); |
72 DCHECK(!algorithm_.get()); | 72 |
73 // If Render() is in progress, this call will wait for Render() to finish. | |
74 // After this call, the |sink_| will not call back into |this| anymore. | |
75 sink_->Stop(); | |
DaleCurtis
2014/07/22 00:15:48
Correct, once this returns no further calls to the
| |
76 | |
77 if (!init_cb_.is_null()) | |
78 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
73 } | 79 } |
74 | 80 |
75 void AudioRendererImpl::StartRendering() { | 81 void AudioRendererImpl::StartRendering() { |
76 DVLOG(1) << __FUNCTION__; | 82 DVLOG(1) << __FUNCTION__; |
77 DCHECK(task_runner_->BelongsToCurrentThread()); | 83 DCHECK(task_runner_->BelongsToCurrentThread()); |
78 DCHECK(!rendering_); | 84 DCHECK(!rendering_); |
79 rendering_ = true; | 85 rendering_ = true; |
80 | 86 |
81 base::AutoLock auto_lock(lock_); | 87 base::AutoLock auto_lock(lock_); |
82 // Wait for an eventual call to SetPlaybackRate() to start rendering. | 88 // Wait for an eventual call to SetPlaybackRate() to start rendering. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 DCHECK_EQ(state_, kFlushed); | 173 DCHECK_EQ(state_, kFlushed); |
168 | 174 |
169 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, | 175 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, |
170 weak_factory_.GetWeakPtr())); | 176 weak_factory_.GetWeakPtr())); |
171 } | 177 } |
172 | 178 |
173 void AudioRendererImpl::ResetDecoderDone() { | 179 void AudioRendererImpl::ResetDecoderDone() { |
174 DCHECK(task_runner_->BelongsToCurrentThread()); | 180 DCHECK(task_runner_->BelongsToCurrentThread()); |
175 { | 181 { |
176 base::AutoLock auto_lock(lock_); | 182 base::AutoLock auto_lock(lock_); |
177 if (state_ == kStopped) | |
178 return; | |
179 | 183 |
180 DCHECK_EQ(state_, kFlushed); | 184 DCHECK_EQ(state_, kFlushed); |
181 DCHECK(!flush_cb_.is_null()); | 185 DCHECK(!flush_cb_.is_null()); |
182 | 186 |
183 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); | 187 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
184 received_end_of_stream_ = false; | 188 received_end_of_stream_ = false; |
185 rendered_end_of_stream_ = false; | 189 rendered_end_of_stream_ = false; |
186 | 190 |
187 // Flush() may have been called while underflowed/not fully buffered. | 191 // Flush() may have been called while underflowed/not fully buffered. |
188 if (buffering_state_ != BUFFERING_HAVE_NOTHING) | 192 if (buffering_state_ != BUFFERING_HAVE_NOTHING) |
189 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 193 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
190 | 194 |
191 splicer_->Reset(); | 195 splicer_->Reset(); |
192 if (buffer_converter_) | 196 if (buffer_converter_) |
193 buffer_converter_->Reset(); | 197 buffer_converter_->Reset(); |
194 algorithm_->FlushBuffers(); | 198 algorithm_->FlushBuffers(); |
195 } | 199 } |
196 | 200 |
197 // Changes in buffering state are always posted. Flush callback must only be | 201 // Changes in buffering state are always posted. Flush callback must only be |
198 // run after buffering state has been set back to nothing. | 202 // run after buffering state has been set back to nothing. |
199 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); | 203 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); |
200 } | 204 } |
201 | 205 |
202 void AudioRendererImpl::Stop(const base::Closure& callback) { | |
203 DVLOG(1) << __FUNCTION__; | |
204 DCHECK(task_runner_->BelongsToCurrentThread()); | |
205 DCHECK(!callback.is_null()); | |
206 | |
207 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | |
208 // task-running guards that check |state_| with DCHECK(). | |
209 | |
210 { | |
211 base::AutoLock auto_lock(lock_); | |
212 | |
213 if (state_ == kStopped) { | |
214 task_runner_->PostTask(FROM_HERE, callback); | |
215 return; | |
216 } | |
217 | |
218 ChangeState_Locked(kStopped); | |
219 algorithm_.reset(); | |
220 time_cb_.Reset(); | |
221 flush_cb_.Reset(); | |
222 } | |
223 | |
224 if (sink_) { | |
225 sink_->Stop(); | |
226 sink_ = NULL; | |
227 } | |
228 | |
229 audio_buffer_stream_.reset(); | |
230 task_runner_->PostTask(FROM_HERE, callback); | |
231 } | |
232 | |
233 void AudioRendererImpl::StartPlaying() { | 206 void AudioRendererImpl::StartPlaying() { |
234 DVLOG(1) << __FUNCTION__; | 207 DVLOG(1) << __FUNCTION__; |
235 DCHECK(task_runner_->BelongsToCurrentThread()); | 208 DCHECK(task_runner_->BelongsToCurrentThread()); |
236 | 209 |
237 base::AutoLock auto_lock(lock_); | 210 base::AutoLock auto_lock(lock_); |
238 DCHECK(!sink_playing_); | 211 DCHECK(!sink_playing_); |
239 DCHECK_EQ(state_, kFlushed); | 212 DCHECK_EQ(state_, kFlushed); |
240 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 213 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
241 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 214 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
242 | 215 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 statistics_cb, | 285 statistics_cb, |
313 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 286 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
314 weak_factory_.GetWeakPtr())); | 287 weak_factory_.GetWeakPtr())); |
315 } | 288 } |
316 | 289 |
317 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 290 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
318 DCHECK(task_runner_->BelongsToCurrentThread()); | 291 DCHECK(task_runner_->BelongsToCurrentThread()); |
319 | 292 |
320 base::AutoLock auto_lock(lock_); | 293 base::AutoLock auto_lock(lock_); |
321 | 294 |
322 if (state_ == kStopped) { | |
323 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
324 return; | |
325 } | |
326 | |
327 if (!success) { | 295 if (!success) { |
328 state_ = kUninitialized; | 296 state_ = kUninitialized; |
329 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 297 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
330 return; | 298 return; |
331 } | 299 } |
332 | 300 |
333 if (!audio_parameters_.IsValid()) { | 301 if (!audio_parameters_.IsValid()) { |
334 ChangeState_Locked(kUninitialized); | 302 ChangeState_Locked(kUninitialized); |
335 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 303 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
336 return; | 304 return; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 if (trim_time > base::TimeDelta()) { | 415 if (trim_time > base::TimeDelta()) { |
448 buffer->TrimStart(buffer->frame_count() * | 416 buffer->TrimStart(buffer->frame_count() * |
449 (static_cast<double>(trim_time.InMicroseconds()) / | 417 (static_cast<double>(trim_time.InMicroseconds()) / |
450 buffer->duration().InMicroseconds())); | 418 buffer->duration().InMicroseconds())); |
451 } | 419 } |
452 // If the entire buffer was trimmed, request a new one. | 420 // If the entire buffer was trimmed, request a new one. |
453 if (!buffer->frame_count()) | 421 if (!buffer->frame_count()) |
454 return true; | 422 return true; |
455 } | 423 } |
456 | 424 |
457 if (state_ != kUninitialized && state_ != kStopped) | 425 if (state_ != kUninitialized) |
458 algorithm_->EnqueueBuffer(buffer); | 426 algorithm_->EnqueueBuffer(buffer); |
459 } | 427 } |
460 | 428 |
461 switch (state_) { | 429 switch (state_) { |
462 case kUninitialized: | 430 case kUninitialized: |
463 case kInitializing: | 431 case kInitializing: |
464 case kFlushing: | 432 case kFlushing: |
465 NOTREACHED(); | 433 NOTREACHED(); |
466 return false; | 434 return false; |
467 | 435 |
468 case kFlushed: | 436 case kFlushed: |
469 DCHECK(!pending_read_); | 437 DCHECK(!pending_read_); |
470 return false; | 438 return false; |
471 | 439 |
472 case kPlaying: | 440 case kPlaying: |
473 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { | 441 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { |
474 if (buffering_state_ == BUFFERING_HAVE_NOTHING) | 442 if (buffering_state_ == BUFFERING_HAVE_NOTHING) |
475 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); | 443 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); |
476 return false; | 444 return false; |
477 } | 445 } |
478 return true; | 446 return true; |
479 | |
480 case kStopped: | |
481 return false; | |
482 } | 447 } |
483 return false; | 448 return false; |
484 } | 449 } |
485 | 450 |
486 void AudioRendererImpl::AttemptRead() { | 451 void AudioRendererImpl::AttemptRead() { |
487 base::AutoLock auto_lock(lock_); | 452 base::AutoLock auto_lock(lock_); |
488 AttemptRead_Locked(); | 453 AttemptRead_Locked(); |
489 } | 454 } |
490 | 455 |
491 void AudioRendererImpl::AttemptRead_Locked() { | 456 void AudioRendererImpl::AttemptRead_Locked() { |
492 DCHECK(task_runner_->BelongsToCurrentThread()); | 457 DCHECK(task_runner_->BelongsToCurrentThread()); |
493 lock_.AssertAcquired(); | 458 lock_.AssertAcquired(); |
494 | 459 |
495 if (!CanRead_Locked()) | 460 if (!CanRead_Locked()) |
496 return; | 461 return; |
497 | 462 |
498 pending_read_ = true; | 463 pending_read_ = true; |
499 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, | 464 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, |
500 weak_factory_.GetWeakPtr())); | 465 weak_factory_.GetWeakPtr())); |
501 } | 466 } |
502 | 467 |
503 bool AudioRendererImpl::CanRead_Locked() { | 468 bool AudioRendererImpl::CanRead_Locked() { |
504 lock_.AssertAcquired(); | 469 lock_.AssertAcquired(); |
505 | 470 |
506 switch (state_) { | 471 switch (state_) { |
507 case kUninitialized: | 472 case kUninitialized: |
508 case kInitializing: | 473 case kInitializing: |
509 case kFlushing: | 474 case kFlushing: |
510 case kFlushed: | 475 case kFlushed: |
511 case kStopped: | |
512 return false; | 476 return false; |
513 | 477 |
514 case kPlaying: | 478 case kPlaying: |
515 break; | 479 break; |
516 } | 480 } |
517 | 481 |
518 return !pending_read_ && !received_end_of_stream_ && | 482 return !pending_read_ && !received_end_of_stream_ && |
519 !algorithm_->IsQueueFull(); | 483 !algorithm_->IsQueueFull(); |
520 } | 484 } |
521 | 485 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
668 DoFlush_Locked(); | 632 DoFlush_Locked(); |
669 return; | 633 return; |
670 } | 634 } |
671 | 635 |
672 error_cb_.Run(status); | 636 error_cb_.Run(status); |
673 base::ResetAndReturn(&flush_cb_).Run(); | 637 base::ResetAndReturn(&flush_cb_).Run(); |
674 return; | 638 return; |
675 | 639 |
676 case kFlushed: | 640 case kFlushed: |
677 case kPlaying: | 641 case kPlaying: |
678 case kStopped: | |
679 if (status != PIPELINE_OK) | 642 if (status != PIPELINE_OK) |
680 error_cb_.Run(status); | 643 error_cb_.Run(status); |
681 return; | 644 return; |
682 } | 645 } |
683 } | 646 } |
684 | 647 |
685 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 648 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
686 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 649 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
687 lock_.AssertAcquired(); | 650 lock_.AssertAcquired(); |
688 state_ = new_state; | 651 state_ = new_state; |
(...skipping 21 matching lines...) Expand all Loading... | |
710 << buffering_state; | 673 << buffering_state; |
711 DCHECK_NE(buffering_state_, buffering_state); | 674 DCHECK_NE(buffering_state_, buffering_state); |
712 lock_.AssertAcquired(); | 675 lock_.AssertAcquired(); |
713 buffering_state_ = buffering_state; | 676 buffering_state_ = buffering_state; |
714 | 677 |
715 task_runner_->PostTask(FROM_HERE, | 678 task_runner_->PostTask(FROM_HERE, |
716 base::Bind(buffering_state_cb_, buffering_state_)); | 679 base::Bind(buffering_state_cb_, buffering_state_)); |
717 } | 680 } |
718 | 681 |
719 } // namespace media | 682 } // namespace media |
OLD | NEW |