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 |