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 (sink_) { | |
74 // If Render() is in process, this call will wait for Render() to finish. | |
scherkus (not reviewing)
2014/07/21 23:38:20
s/process/progress/?
xhwang
2014/07/21 23:56:33
Done.
| |
75 // After this call, the |sink_| will not call back into |this| anymore. | |
76 sink_->Stop(); | |
77 sink_ = NULL; | |
scherkus (not reviewing)
2014/07/21 23:38:20
is this required to force the ref-count to zero? i
xhwang
2014/07/21 23:56:33
Probably not needed. The ref-count will be dropped
| |
78 } | |
79 | |
80 if (!init_cb_.is_null()) | |
81 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
73 } | 82 } |
74 | 83 |
75 void AudioRendererImpl::StartRendering() { | 84 void AudioRendererImpl::StartRendering() { |
76 DVLOG(1) << __FUNCTION__; | 85 DVLOG(1) << __FUNCTION__; |
77 DCHECK(task_runner_->BelongsToCurrentThread()); | 86 DCHECK(task_runner_->BelongsToCurrentThread()); |
78 DCHECK(!rendering_); | 87 DCHECK(!rendering_); |
79 rendering_ = true; | 88 rendering_ = true; |
80 | 89 |
81 base::AutoLock auto_lock(lock_); | 90 base::AutoLock auto_lock(lock_); |
82 // Wait for an eventual call to SetPlaybackRate() to start rendering. | 91 // Wait for an eventual call to SetPlaybackRate() to start rendering. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 DCHECK_EQ(state_, kFlushed); | 165 DCHECK_EQ(state_, kFlushed); |
157 | 166 |
158 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, | 167 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, |
159 weak_factory_.GetWeakPtr())); | 168 weak_factory_.GetWeakPtr())); |
160 } | 169 } |
161 | 170 |
162 void AudioRendererImpl::ResetDecoderDone() { | 171 void AudioRendererImpl::ResetDecoderDone() { |
163 DCHECK(task_runner_->BelongsToCurrentThread()); | 172 DCHECK(task_runner_->BelongsToCurrentThread()); |
164 { | 173 { |
165 base::AutoLock auto_lock(lock_); | 174 base::AutoLock auto_lock(lock_); |
166 if (state_ == kStopped) | |
167 return; | |
168 | 175 |
169 DCHECK_EQ(state_, kFlushed); | 176 DCHECK_EQ(state_, kFlushed); |
170 DCHECK(!flush_cb_.is_null()); | 177 DCHECK(!flush_cb_.is_null()); |
171 | 178 |
172 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); | 179 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
173 received_end_of_stream_ = false; | 180 received_end_of_stream_ = false; |
174 rendered_end_of_stream_ = false; | 181 rendered_end_of_stream_ = false; |
175 | 182 |
176 // Flush() may have been called while underflowed/not fully buffered. | 183 // Flush() may have been called while underflowed/not fully buffered. |
177 if (buffering_state_ != BUFFERING_HAVE_NOTHING) | 184 if (buffering_state_ != BUFFERING_HAVE_NOTHING) |
178 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 185 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
179 | 186 |
180 splicer_->Reset(); | 187 splicer_->Reset(); |
181 if (buffer_converter_) | 188 if (buffer_converter_) |
182 buffer_converter_->Reset(); | 189 buffer_converter_->Reset(); |
183 algorithm_->FlushBuffers(); | 190 algorithm_->FlushBuffers(); |
184 } | 191 } |
185 | 192 |
186 // Changes in buffering state are always posted. Flush callback must only be | 193 // Changes in buffering state are always posted. Flush callback must only be |
187 // run after buffering state has been set back to nothing. | 194 // run after buffering state has been set back to nothing. |
188 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); | 195 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); |
189 } | 196 } |
190 | 197 |
191 void AudioRendererImpl::Stop(const base::Closure& callback) { | |
192 DVLOG(1) << __FUNCTION__; | |
193 DCHECK(task_runner_->BelongsToCurrentThread()); | |
194 DCHECK(!callback.is_null()); | |
195 | |
196 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | |
197 // task-running guards that check |state_| with DCHECK(). | |
198 | |
199 { | |
200 base::AutoLock auto_lock(lock_); | |
201 | |
202 if (state_ == kStopped) { | |
203 task_runner_->PostTask(FROM_HERE, callback); | |
204 return; | |
205 } | |
206 | |
207 ChangeState_Locked(kStopped); | |
208 algorithm_.reset(); | |
209 time_cb_.Reset(); | |
210 flush_cb_.Reset(); | |
211 } | |
212 | |
213 if (sink_) { | |
214 sink_->Stop(); | |
215 sink_ = NULL; | |
216 } | |
217 | |
218 audio_buffer_stream_.reset(); | |
219 task_runner_->PostTask(FROM_HERE, callback); | |
220 } | |
221 | |
222 void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { | 198 void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { |
223 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; | 199 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; |
224 DCHECK(task_runner_->BelongsToCurrentThread()); | 200 DCHECK(task_runner_->BelongsToCurrentThread()); |
225 | 201 |
226 base::AutoLock auto_lock(lock_); | 202 base::AutoLock auto_lock(lock_); |
227 DCHECK(!sink_playing_); | 203 DCHECK(!sink_playing_); |
228 DCHECK_EQ(state_, kFlushed); | 204 DCHECK_EQ(state_, kFlushed); |
229 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 205 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
230 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 206 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
231 | 207 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 statistics_cb, | 279 statistics_cb, |
304 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 280 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
305 weak_factory_.GetWeakPtr())); | 281 weak_factory_.GetWeakPtr())); |
306 } | 282 } |
307 | 283 |
308 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 284 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
309 DCHECK(task_runner_->BelongsToCurrentThread()); | 285 DCHECK(task_runner_->BelongsToCurrentThread()); |
310 | 286 |
311 base::AutoLock auto_lock(lock_); | 287 base::AutoLock auto_lock(lock_); |
312 | 288 |
313 if (state_ == kStopped) { | |
314 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
315 return; | |
316 } | |
317 | |
318 if (!success) { | 289 if (!success) { |
319 state_ = kUninitialized; | 290 state_ = kUninitialized; |
320 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 291 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
321 return; | 292 return; |
322 } | 293 } |
323 | 294 |
324 if (!audio_parameters_.IsValid()) { | 295 if (!audio_parameters_.IsValid()) { |
325 ChangeState_Locked(kUninitialized); | 296 ChangeState_Locked(kUninitialized); |
326 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 297 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
327 return; | 298 return; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 if (trim_time > base::TimeDelta()) { | 409 if (trim_time > base::TimeDelta()) { |
439 buffer->TrimStart(buffer->frame_count() * | 410 buffer->TrimStart(buffer->frame_count() * |
440 (static_cast<double>(trim_time.InMicroseconds()) / | 411 (static_cast<double>(trim_time.InMicroseconds()) / |
441 buffer->duration().InMicroseconds())); | 412 buffer->duration().InMicroseconds())); |
442 } | 413 } |
443 // If the entire buffer was trimmed, request a new one. | 414 // If the entire buffer was trimmed, request a new one. |
444 if (!buffer->frame_count()) | 415 if (!buffer->frame_count()) |
445 return true; | 416 return true; |
446 } | 417 } |
447 | 418 |
448 if (state_ != kUninitialized && state_ != kStopped) | 419 if (state_ != kUninitialized) |
449 algorithm_->EnqueueBuffer(buffer); | 420 algorithm_->EnqueueBuffer(buffer); |
450 } | 421 } |
451 | 422 |
452 switch (state_) { | 423 switch (state_) { |
453 case kUninitialized: | 424 case kUninitialized: |
454 case kInitializing: | 425 case kInitializing: |
455 case kFlushing: | 426 case kFlushing: |
456 NOTREACHED(); | 427 NOTREACHED(); |
457 return false; | 428 return false; |
458 | 429 |
459 case kFlushed: | 430 case kFlushed: |
460 DCHECK(!pending_read_); | 431 DCHECK(!pending_read_); |
461 return false; | 432 return false; |
462 | 433 |
463 case kPlaying: | 434 case kPlaying: |
464 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { | 435 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { |
465 if (buffering_state_ == BUFFERING_HAVE_NOTHING) | 436 if (buffering_state_ == BUFFERING_HAVE_NOTHING) |
466 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); | 437 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); |
467 return false; | 438 return false; |
468 } | 439 } |
469 return true; | 440 return true; |
470 | |
471 case kStopped: | |
472 return false; | |
473 } | 441 } |
474 return false; | 442 return false; |
475 } | 443 } |
476 | 444 |
477 void AudioRendererImpl::AttemptRead() { | 445 void AudioRendererImpl::AttemptRead() { |
478 base::AutoLock auto_lock(lock_); | 446 base::AutoLock auto_lock(lock_); |
479 AttemptRead_Locked(); | 447 AttemptRead_Locked(); |
480 } | 448 } |
481 | 449 |
482 void AudioRendererImpl::AttemptRead_Locked() { | 450 void AudioRendererImpl::AttemptRead_Locked() { |
483 DCHECK(task_runner_->BelongsToCurrentThread()); | 451 DCHECK(task_runner_->BelongsToCurrentThread()); |
484 lock_.AssertAcquired(); | 452 lock_.AssertAcquired(); |
485 | 453 |
486 if (!CanRead_Locked()) | 454 if (!CanRead_Locked()) |
487 return; | 455 return; |
488 | 456 |
489 pending_read_ = true; | 457 pending_read_ = true; |
490 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, | 458 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, |
491 weak_factory_.GetWeakPtr())); | 459 weak_factory_.GetWeakPtr())); |
492 } | 460 } |
493 | 461 |
494 bool AudioRendererImpl::CanRead_Locked() { | 462 bool AudioRendererImpl::CanRead_Locked() { |
495 lock_.AssertAcquired(); | 463 lock_.AssertAcquired(); |
496 | 464 |
497 switch (state_) { | 465 switch (state_) { |
498 case kUninitialized: | 466 case kUninitialized: |
499 case kInitializing: | 467 case kInitializing: |
500 case kFlushing: | 468 case kFlushing: |
501 case kFlushed: | 469 case kFlushed: |
502 case kStopped: | |
503 return false; | 470 return false; |
504 | 471 |
505 case kPlaying: | 472 case kPlaying: |
506 break; | 473 break; |
507 } | 474 } |
508 | 475 |
509 return !pending_read_ && !received_end_of_stream_ && | 476 return !pending_read_ && !received_end_of_stream_ && |
510 !algorithm_->IsQueueFull(); | 477 !algorithm_->IsQueueFull(); |
511 } | 478 } |
512 | 479 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
659 DoFlush_Locked(); | 626 DoFlush_Locked(); |
660 return; | 627 return; |
661 } | 628 } |
662 | 629 |
663 error_cb_.Run(status); | 630 error_cb_.Run(status); |
664 base::ResetAndReturn(&flush_cb_).Run(); | 631 base::ResetAndReturn(&flush_cb_).Run(); |
665 return; | 632 return; |
666 | 633 |
667 case kFlushed: | 634 case kFlushed: |
668 case kPlaying: | 635 case kPlaying: |
669 case kStopped: | |
670 if (status != PIPELINE_OK) | 636 if (status != PIPELINE_OK) |
671 error_cb_.Run(status); | 637 error_cb_.Run(status); |
672 return; | 638 return; |
673 } | 639 } |
674 } | 640 } |
675 | 641 |
676 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 642 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
677 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 643 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
678 lock_.AssertAcquired(); | 644 lock_.AssertAcquired(); |
679 state_ = new_state; | 645 state_ = new_state; |
(...skipping 21 matching lines...) Expand all Loading... | |
701 << buffering_state; | 667 << buffering_state; |
702 DCHECK_NE(buffering_state_, buffering_state); | 668 DCHECK_NE(buffering_state_, buffering_state); |
703 lock_.AssertAcquired(); | 669 lock_.AssertAcquired(); |
704 buffering_state_ = buffering_state; | 670 buffering_state_ = buffering_state; |
705 | 671 |
706 task_runner_->PostTask(FROM_HERE, | 672 task_runner_->PostTask(FROM_HERE, |
707 base::Bind(buffering_state_cb_, buffering_state_)); | 673 base::Bind(buffering_state_cb_, buffering_state_)); |
708 } | 674 } |
709 | 675 |
710 } // namespace media | 676 } // namespace media |
OLD | NEW |