Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: chromecast/media/cma/backend/alsa/audio_decoder_alsa.cc

Issue 2612353003: [Chromecast] Fix AudioVideoPipelineDeviceTest failures (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698