Chromium Code Reviews| 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 "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 case kUnderflow: | 270 case kUnderflow: |
| 271 case kRebuffering: | 271 case kRebuffering: |
| 272 if (buffer && !buffer->IsEndOfStream()) | 272 if (buffer && !buffer->IsEndOfStream()) |
| 273 algorithm_->EnqueueBuffer(buffer); | 273 algorithm_->EnqueueBuffer(buffer); |
| 274 return; | 274 return; |
| 275 case kStopped: | 275 case kStopped: |
| 276 return; | 276 return; |
| 277 } | 277 } |
| 278 } | 278 } |
| 279 | 279 |
| 280 void AudioRendererImpl::SignalEndOfStream() { | |
| 281 DCHECK(received_end_of_stream_); | |
| 282 if (!rendered_end_of_stream_) { | |
| 283 rendered_end_of_stream_ = true; | |
| 284 host()->NotifyEnded(); | |
| 285 } | |
| 286 } | |
| 287 | |
| 288 void AudioRendererImpl::ScheduleRead_Locked() { | 280 void AudioRendererImpl::ScheduleRead_Locked() { |
| 289 lock_.AssertAcquired(); | 281 lock_.AssertAcquired(); |
| 290 if (pending_read_ || state_ == kPaused) | 282 if (pending_read_ || state_ == kPaused) |
| 291 return; | 283 return; |
| 292 pending_read_ = true; | 284 pending_read_ = true; |
| 293 decoder_->Read(read_cb_); | 285 decoder_->Read(read_cb_); |
| 294 } | 286 } |
| 295 | 287 |
| 296 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { | 288 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { |
| 297 DCHECK_LE(0.0f, playback_rate); | 289 DCHECK_LE(0.0f, playback_rate); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 // the subclass can restart the conversation. | 391 // the subclass can restart the conversation. |
| 400 // | 392 // |
| 401 // This should get handled by the subclass http://crbug.com/106600 | 393 // This should get handled by the subclass http://crbug.com/106600 |
| 402 const uint32 kZeroLength = 8192; | 394 const uint32 kZeroLength = 8192; |
| 403 size_t zeros_to_write = | 395 size_t zeros_to_write = |
| 404 std::min(kZeroLength, requested_frames * bytes_per_frame_); | 396 std::min(kZeroLength, requested_frames * bytes_per_frame_); |
| 405 memset(dest, 0, zeros_to_write); | 397 memset(dest, 0, zeros_to_write); |
| 406 return zeros_to_write / bytes_per_frame_; | 398 return zeros_to_write / bytes_per_frame_; |
| 407 } | 399 } |
| 408 | 400 |
| 409 // Use three conditions to determine the end of playback: | 401 // We use the following conditions to determine end of playback: |
| 410 // 1. Algorithm needs more audio data. | 402 // 1) Algorithm needs more audio data |
| 411 // 2. We've received an end of stream buffer. | 403 // 2) We received an end of stream buffer |
| 412 // (received_end_of_stream_ == true) | 404 // 3) We haven't already signalled that we've ended |
| 413 // 3. Browser process has no audio data being played. | 405 // 4) Our estimated earliest end time has expired |
| 414 // There is no way to check that condition that would work for all | |
| 415 // derived classes, so call virtual method that would either render | |
| 416 // end of stream or schedule such rendering. | |
| 417 // | 406 // |
| 418 // Three conditions determine when an underflow occurs: | 407 // TODO(enal): we should replace (4) with a check that the browser has no |
| 419 // 1. Algorithm has no audio data. | 408 // more audio data or at least use a delayed callback. |
| 420 // 2. Currently in the kPlaying state. | 409 // |
| 421 // 3. Have not received an end of stream buffer. | 410 // We use the following conditions to determine underflow: |
| 422 if (algorithm_->NeedsMoreData()) { | 411 // 1) Algorithm needs more audio data |
| 423 if (received_end_of_stream_) { | 412 // 2) We have NOT received an end of stream buffer |
| 424 // TODO(enal): schedule callback instead of polling. | 413 // 3) We are in the kPlaying state |
| 425 if (base::Time::Now() >= earliest_end_time_) | 414 // |
| 426 SignalEndOfStream(); | 415 // Otherwise fill the buffer with whatever data we can send to the device. |
| 427 } else if (state_ == kPlaying) { | 416 if (algorithm_->NeedsMoreData() && received_end_of_stream_ && |
| 428 state_ = kUnderflow; | 417 !rendered_end_of_stream_ && base::Time::Now() >= earliest_end_time_) { |
| 429 underflow_cb = underflow_cb_; | 418 rendered_end_of_stream_ = true; |
| 430 } | 419 host()->NotifyEnded(); |
| 420 } else if (algorithm_->NeedsMoreData() && !received_end_of_stream_ && | |
| 421 state_ == kPlaying) { | |
| 422 state_ = kUnderflow; | |
| 423 underflow_cb = underflow_cb_; | |
| 424 } else if (!algorithm_->NeedsMoreData()) { | |
| 425 frames_written = algorithm_->FillBuffer(dest, requested_frames); | |
| 426 DCHECK_GT(frames_written, 0u); | |
| 431 } else { | 427 } else { |
| 432 // Otherwise fill the buffer. | 428 // ATTN VRK: What should we do here? I can leave an empty else branch |
| 433 frames_written = algorithm_->FillBuffer(dest, requested_frames); | 429 // here, or we can be comfortable calling FillBuffer() + remove DCHECK |
| 430 // even if NeedsMoreData() returns false. | |
|
vrk (LEFT CHROMIUM)
2012/05/17 04:40:52
Hmmm...
Since all this code is crazy, I think ke
scherkus (not reviewing)
2012/05/19 03:13:08
Done.
| |
| 431 // | |
| 432 // Sample comment: | |
| 433 // | |
| 434 // We can't write any data this cycle. For example, we may have | |
| 435 // sent all available data to the audio device while not reaching | |
| 436 // |earliest_end_time_|. | |
| 434 } | 437 } |
| 435 | 438 |
| 436 // The |audio_time_buffered_| is the ending timestamp of the last frame | 439 // The |audio_time_buffered_| is the ending timestamp of the last frame |
| 437 // buffered at the audio device. |playback_delay| is the amount of time | 440 // buffered at the audio device. |playback_delay| is the amount of time |
| 438 // buffered at the audio device. The current time can be computed by their | 441 // buffered at the audio device. The current time can be computed by their |
| 439 // difference. | 442 // difference. |
| 440 if (audio_time_buffered_ != kNoTimestamp()) { | 443 if (audio_time_buffered_ != kNoTimestamp()) { |
| 441 base::TimeDelta previous_time = current_time_; | 444 base::TimeDelta previous_time = current_time_; |
| 442 current_time_ = audio_time_buffered_ - playback_delay; | 445 current_time_ = audio_time_buffered_ - playback_delay; |
| 443 | 446 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); | 502 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); |
| 500 } | 503 } |
| 501 return base::TimeDelta(); | 504 return base::TimeDelta(); |
| 502 } | 505 } |
| 503 | 506 |
| 504 void AudioRendererImpl::OnRenderError() { | 507 void AudioRendererImpl::OnRenderError() { |
| 505 host()->DisableAudioRenderer(); | 508 host()->DisableAudioRenderer(); |
| 506 } | 509 } |
| 507 | 510 |
| 508 } // namespace media | 511 } // namespace media |
| OLD | NEW |