Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "chromecast/media/cma/backend/alsa/audio_decoder_alsa.h" | 5 #include "chromecast/media/cma/backend/alsa/audio_decoder_alsa.h" |
| 6 | 6 |
| 7 #include <time.h> | 7 #include <time.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 } | 211 } |
| 212 | 212 |
| 213 bool AudioDecoderAlsa::SetConfig(const AudioConfig& config) { | 213 bool AudioDecoderAlsa::SetConfig(const AudioConfig& config) { |
| 214 TRACE_FUNCTION_ENTRY0(); | 214 TRACE_FUNCTION_ENTRY0(); |
| 215 DCHECK(task_runner_->BelongsToCurrentThread()); | 215 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 216 if (!IsValidConfig(config)) { | 216 if (!IsValidConfig(config)) { |
| 217 LOG(ERROR) << "Invalid audio config passed to SetConfig"; | 217 LOG(ERROR) << "Invalid audio config passed to SetConfig"; |
| 218 return false; | 218 return false; |
| 219 } | 219 } |
| 220 | 220 |
| 221 if (!rate_shifter_ || | 221 bool changed_sample_rate = |
| 222 config.samples_per_second != config_.samples_per_second) { | 222 (config.samples_per_second != config_.samples_per_second); |
| 223 | |
| 224 if (!rate_shifter_ || changed_sample_rate) { | |
| 223 CreateRateShifter(config.samples_per_second); | 225 CreateRateShifter(config.samples_per_second); |
| 224 } | 226 } |
| 225 | 227 |
| 226 if (mixer_input_ && config.samples_per_second != config_.samples_per_second) { | 228 if (mixer_input_ && changed_sample_rate) { |
| 227 // Destroy the old input first to ensure that the mixer output sample rate | 229 // Destroy the old input first to ensure that the mixer output sample rate |
| 228 // is updated. | 230 // is updated. |
| 229 mixer_input_.reset(); | 231 mixer_input_.reset(); |
| 230 mixer_input_.reset(new StreamMixerAlsaInput( | 232 mixer_input_.reset(new StreamMixerAlsaInput( |
| 231 this, config.samples_per_second, backend_->Primary())); | 233 this, config.samples_per_second, backend_->Primary())); |
| 232 mixer_input_->SetVolumeMultiplier(volume_multiplier_); | 234 mixer_input_->SetVolumeMultiplier(volume_multiplier_); |
| 233 pending_output_frames_ = kNoPendingOutput; | 235 pending_output_frames_ = kNoPendingOutput; |
| 234 } | 236 } |
| 235 | 237 |
| 236 config_ = config; | 238 config_ = config; |
| 237 decoder_.reset(); | 239 decoder_.reset(); |
| 238 CreateDecoder(); | 240 CreateDecoder(); |
| 239 | 241 |
| 240 if (pending_buffer_complete_ && !rate_shifter_->IsQueueFull()) { | 242 if (pending_buffer_complete_ && changed_sample_rate) { |
|
slan
2017/01/06 01:14:47
This code is now liable to call OnPushBufferComple
kmackay
2017/01/06 01:21:04
In this case, the rate shifter was just (re)create
| |
| 241 pending_buffer_complete_ = false; | 243 pending_buffer_complete_ = false; |
| 242 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | 244 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); |
| 243 } | 245 } |
| 244 return true; | 246 return true; |
| 245 } | 247 } |
| 246 | 248 |
| 247 void AudioDecoderAlsa::CreateDecoder() { | 249 void AudioDecoderAlsa::CreateDecoder() { |
| 248 DCHECK(!decoder_); | 250 DCHECK(!decoder_); |
| 249 DCHECK(IsValidConfig(config_)); | 251 DCHECK(IsValidConfig(config_)); |
| 250 | 252 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 } | 333 } |
| 332 if (mixer_error_) { | 334 if (mixer_error_) { |
| 333 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferFailed); | 335 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferFailed); |
| 334 return; | 336 return; |
| 335 } | 337 } |
| 336 | 338 |
| 337 Statistics delta; | 339 Statistics delta; |
| 338 delta.decoded_bytes = input_bytes; | 340 delta.decoded_bytes = input_bytes; |
| 339 UpdateStatistics(delta); | 341 UpdateStatistics(delta); |
| 340 | 342 |
| 343 pending_buffer_complete_ = true; | |
| 341 if (decoded->end_of_stream()) { | 344 if (decoded->end_of_stream()) { |
| 342 got_eos_ = true; | 345 got_eos_ = true; |
| 343 } else { | 346 } else { |
| 344 int input_frames = decoded->data_size() / (kNumChannels * sizeof(float)); | 347 int input_frames = decoded->data_size() / (kNumChannels * sizeof(float)); |
| 345 | 348 |
| 346 DCHECK(!rate_shifter_info_.empty()); | 349 DCHECK(!rate_shifter_info_.empty()); |
| 347 RateShifterInfo* rate_info = &rate_shifter_info_.front(); | 350 RateShifterInfo* rate_info = &rate_shifter_info_.front(); |
| 348 // Bypass rate shifter if the rate is 1.0, and there are no frames queued | 351 // Bypass rate shifter if the rate is 1.0, and there are no frames queued |
| 349 // in the rate shifter. | 352 // in the rate shifter. |
| 350 if (rate_info->rate == 1.0 && rate_shifter_->frames_buffered() == 0 && | 353 if (rate_info->rate == 1.0 && rate_shifter_->frames_buffered() == 0 && |
| 351 pending_output_frames_ == kNoPendingOutput) { | 354 pending_output_frames_ == kNoPendingOutput) { |
| 352 DCHECK_EQ(rate_info->output_frames, rate_info->input_frames); | 355 DCHECK_EQ(rate_info->output_frames, rate_info->input_frames); |
| 353 pending_buffer_complete_ = true; | |
| 354 pending_output_frames_ = input_frames; | 356 pending_output_frames_ = input_frames; |
| 355 if (got_eos_) { | 357 if (got_eos_) { |
| 356 DCHECK(!pushed_eos_); | 358 DCHECK(!pushed_eos_); |
| 357 pushed_eos_ = true; | 359 pushed_eos_ = true; |
| 358 } | 360 } |
| 359 mixer_input_->WritePcm(decoded); | 361 mixer_input_->WritePcm(decoded); |
| 360 return; | 362 return; |
| 361 } | 363 } |
| 362 | 364 |
| 363 // Otherwise, queue data into the rate shifter, and then try to push the | 365 // Otherwise, queue data into the rate shifter, and then try to push the |
| 364 // rate-shifted data. | 366 // rate-shifted data. |
| 365 const uint8_t* channels[kNumChannels] = { | 367 const uint8_t* channels[kNumChannels] = { |
| 366 decoded->data(), decoded->data() + input_frames * sizeof(float)}; | 368 decoded->data(), decoded->data() + input_frames * sizeof(float)}; |
| 367 scoped_refptr<::media::AudioBuffer> buffer = ::media::AudioBuffer::CopyFrom( | 369 scoped_refptr<::media::AudioBuffer> buffer = ::media::AudioBuffer::CopyFrom( |
| 368 ::media::kSampleFormatPlanarF32, ::media::CHANNEL_LAYOUT_STEREO, | 370 ::media::kSampleFormatPlanarF32, ::media::CHANNEL_LAYOUT_STEREO, |
| 369 kNumChannels, config_.samples_per_second, input_frames, channels, | 371 kNumChannels, config_.samples_per_second, input_frames, channels, |
| 370 base::TimeDelta()); | 372 base::TimeDelta()); |
| 371 rate_shifter_->EnqueueBuffer(buffer); | 373 rate_shifter_->EnqueueBuffer(buffer); |
| 372 rate_shifter_info_.back().input_frames += input_frames; | 374 rate_shifter_info_.back().input_frames += input_frames; |
| 373 } | 375 } |
| 374 | 376 |
| 375 PushRateShifted(); | 377 PushRateShifted(); |
| 376 DCHECK(!rate_shifter_info_.empty()); | 378 DCHECK(!rate_shifter_info_.empty()); |
| 377 // Can't check got_eos_ here, since it may have already been reset by a call | 379 CheckBufferComplete(); |
| 378 // to Stop(). | 380 } |
| 379 if (decoded->end_of_stream() || (!rate_shifter_->IsQueueFull() && | 381 |
| 380 rate_shifter_info_.front().rate != 1.0)) { | 382 void AudioDecoderAlsa::CheckBufferComplete() { |
| 383 if (!pending_buffer_complete_) { | |
| 384 return; | |
| 385 } | |
| 386 | |
| 387 bool rate_shifter_queue_full = rate_shifter_->IsQueueFull(); | |
| 388 DCHECK(!rate_shifter_info_.empty()); | |
| 389 if (rate_shifter_info_.front().rate == 1.0) { | |
| 390 // If the current rate is 1.0, drain any data in the rate shifter before | |
| 391 // calling PushBufferComplete, so that the next PushBuffer call can skip the | |
| 392 // rate shifter entirely. | |
| 393 rate_shifter_queue_full = (rate_shifter_->frames_buffered() > 0 || | |
| 394 pending_output_frames_ != kNoPendingOutput); | |
| 395 } | |
| 396 | |
| 397 if (pushed_eos_ || !rate_shifter_queue_full) { | |
| 398 pending_buffer_complete_ = false; | |
| 381 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | 399 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); |
| 382 } else { | |
| 383 pending_buffer_complete_ = true; | |
| 384 } | 400 } |
| 385 } | 401 } |
| 386 | 402 |
| 387 void AudioDecoderAlsa::PushRateShifted() { | 403 void AudioDecoderAlsa::PushRateShifted() { |
| 388 DCHECK(mixer_input_); | 404 DCHECK(mixer_input_); |
| 389 | 405 |
| 390 if (pending_output_frames_ != kNoPendingOutput) { | 406 if (pushed_eos_ || pending_output_frames_ != kNoPendingOutput) { |
| 391 return; | 407 return; |
| 392 } | 408 } |
| 393 | 409 |
| 394 if (got_eos_) { | 410 if (got_eos_) { |
| 395 // Push some silence into the rate shifter so we can get out any remaining | 411 // Push some silence into the rate shifter so we can get out any remaining |
| 396 // rate-shifted data. | 412 // rate-shifted data. |
| 397 rate_shifter_->EnqueueBuffer(::media::AudioBuffer::CreateEmptyBuffer( | 413 rate_shifter_->EnqueueBuffer(::media::AudioBuffer::CreateEmptyBuffer( |
| 398 ::media::CHANNEL_LAYOUT_STEREO, kNumChannels, | 414 ::media::CHANNEL_LAYOUT_STEREO, kNumChannels, |
| 399 config_.samples_per_second, kSilenceBufferFrames, base::TimeDelta())); | 415 config_.samples_per_second, kSilenceBufferFrames, base::TimeDelta())); |
| 400 } | 416 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 } | 501 } |
| 486 | 502 |
| 487 void AudioDecoderAlsa::OnWritePcmCompletion(BufferStatus status, | 503 void AudioDecoderAlsa::OnWritePcmCompletion(BufferStatus status, |
| 488 const RenderingDelay& delay) { | 504 const RenderingDelay& delay) { |
| 489 TRACE_FUNCTION_ENTRY0(); | 505 TRACE_FUNCTION_ENTRY0(); |
| 490 DCHECK(task_runner_->BelongsToCurrentThread()); | 506 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 491 DCHECK_EQ(MediaPipelineBackendAlsa::kBufferSuccess, status); | 507 DCHECK_EQ(MediaPipelineBackendAlsa::kBufferSuccess, status); |
| 492 pending_output_frames_ = kNoPendingOutput; | 508 pending_output_frames_ = kNoPendingOutput; |
| 493 last_mixer_delay_ = delay; | 509 last_mixer_delay_ = delay; |
| 494 | 510 |
| 495 if (pushed_eos_) { | 511 task_runner_->PostTask(FROM_HERE, base::Bind(&AudioDecoderAlsa::PushMorePcm, |
| 496 if (pending_buffer_complete_) { | 512 weak_factory_.GetWeakPtr())); |
| 497 pending_buffer_complete_ = false; | |
| 498 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | |
| 499 } | |
| 500 delegate_->OnEndOfStream(); | |
| 501 } else { | |
| 502 task_runner_->PostTask(FROM_HERE, base::Bind(&AudioDecoderAlsa::PushMorePcm, | |
| 503 weak_factory_.GetWeakPtr())); | |
| 504 } | |
| 505 } | 513 } |
| 506 | 514 |
| 507 void AudioDecoderAlsa::PushMorePcm() { | 515 void AudioDecoderAlsa::PushMorePcm() { |
| 508 PushRateShifted(); | 516 PushRateShifted(); |
| 509 | 517 |
| 510 DCHECK(!rate_shifter_info_.empty()); | 518 DCHECK(!rate_shifter_info_.empty()); |
| 511 if (pending_buffer_complete_) { | 519 CheckBufferComplete(); |
| 512 double rate = rate_shifter_info_.front().rate; | 520 |
| 513 if ((rate == 1.0 && pending_output_frames_ == kNoPendingOutput) || | 521 if (pushed_eos_) { |
| 514 (rate != 1.0 && !rate_shifter_->IsQueueFull())) { | 522 delegate_->OnEndOfStream(); |
| 515 pending_buffer_complete_ = false; | |
| 516 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess); | |
| 517 } | |
| 518 } | 523 } |
| 519 } | 524 } |
| 520 | 525 |
| 521 void AudioDecoderAlsa::OnMixerError(MixerError error) { | 526 void AudioDecoderAlsa::OnMixerError(MixerError error) { |
| 522 TRACE_FUNCTION_ENTRY0(); | 527 TRACE_FUNCTION_ENTRY0(); |
| 523 DCHECK(task_runner_->BelongsToCurrentThread()); | 528 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 524 if (error != MixerError::kInputIgnored) | 529 if (error != MixerError::kInputIgnored) |
| 525 LOG(ERROR) << "Mixer error occurred."; | 530 LOG(ERROR) << "Mixer error occurred."; |
| 526 mixer_error_ = true; | 531 mixer_error_ = true; |
| 527 delegate_->OnDecoderError(); | 532 delegate_->OnDecoderError(); |
| 528 } | 533 } |
| 529 | 534 |
| 530 } // namespace media | 535 } // namespace media |
| 531 } // namespace chromecast | 536 } // namespace chromecast |
| OLD | NEW |