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/renderers/audio_renderer_impl.h" | 5 #include "media/renderers/audio_renderer_impl.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 const scoped_refptr<MediaLog>& media_log) | 53 const scoped_refptr<MediaLog>& media_log) |
| 54 : task_runner_(task_runner), | 54 : task_runner_(task_runner), |
| 55 expecting_config_changes_(false), | 55 expecting_config_changes_(false), |
| 56 sink_(sink), | 56 sink_(sink), |
| 57 audio_buffer_stream_( | 57 audio_buffer_stream_( |
| 58 new AudioBufferStream(task_runner, std::move(decoders), media_log)), | 58 new AudioBufferStream(task_runner, std::move(decoders), media_log)), |
| 59 hardware_config_(hardware_config), | 59 hardware_config_(hardware_config), |
| 60 media_log_(media_log), | 60 media_log_(media_log), |
| 61 tick_clock_(new base::DefaultTickClock()), | 61 tick_clock_(new base::DefaultTickClock()), |
| 62 last_audio_memory_usage_(0), | 62 last_audio_memory_usage_(0), |
| 63 last_decoded_sample_rate_(0), | |
| 63 playback_rate_(0.0), | 64 playback_rate_(0.0), |
| 64 state_(kUninitialized), | 65 state_(kUninitialized), |
| 65 buffering_state_(BUFFERING_HAVE_NOTHING), | 66 buffering_state_(BUFFERING_HAVE_NOTHING), |
| 66 rendering_(false), | 67 rendering_(false), |
| 67 sink_playing_(false), | 68 sink_playing_(false), |
| 68 pending_read_(false), | 69 pending_read_(false), |
| 69 received_end_of_stream_(false), | 70 received_end_of_stream_(false), |
| 70 rendered_end_of_stream_(false), | 71 rendered_end_of_stream_(false), |
| 71 weak_factory_(this) { | 72 weak_factory_(this) { |
| 72 audio_buffer_stream_->set_splice_observer(base::Bind( | 73 audio_buffer_stream_->set_splice_observer(base::Bind( |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 #if defined(OS_CHROMEOS) | 379 #if defined(OS_CHROMEOS) |
| 379 // On ChromeOS let the OS level resampler handle resampling unless the | 380 // On ChromeOS let the OS level resampler handle resampling unless the |
| 380 // initial sample rate is too low; this allows support for sample rate | 381 // initial sample rate is too low; this allows support for sample rate |
| 381 // adaptations where necessary. | 382 // adaptations where necessary. |
| 382 if (stream->audio_decoder_config().samples_per_second() >= 44100) { | 383 if (stream->audio_decoder_config().samples_per_second() >= 44100) { |
| 383 sample_rate = stream->audio_decoder_config().samples_per_second(); | 384 sample_rate = stream->audio_decoder_config().samples_per_second(); |
| 384 preferred_buffer_size = 0; // No preference. | 385 preferred_buffer_size = 0; // No preference. |
| 385 } | 386 } |
| 386 #endif | 387 #endif |
| 387 | 388 |
| 389 int stream_channel_count = ChannelLayoutToChannelCount(stream->audio_decoder _config().channel_layout()); | |
| 390 int fiveptone_channel_count = ChannelLayoutToChannelCount(CHANNEL_LAYOUT_5_1 ); | |
| 391 | |
| 392 // The layout we pass to |audio_parameters_| will be used for the lifetime | |
| 393 // of this audio renderer, regardless of changes to hardware and/or stream | |
| 394 // properties. Below we choose the max of stream layout vs. hardware layout | |
| 395 // to leave room for changes to the hardware and/or stream (i.e. avoid | |
| 396 // premature down-mixing). | |
| 397 // If stream_channels < hw_channels: | |
| 398 // Taking max means we up-mix to hardware layout. If stream later changes | |
| 399 // to have more channels, we aren't locked into down-mixing to the | |
| 400 // initial layout. | |
| 401 // If stream_channels > hw_channels: | |
| 402 // We choose to output stream's layout, meaning mixing is a no-op for the | |
| 403 // renderer. Browser-side will down-mix to the hardware config. If the | |
| 404 // hardware later changes to equal stream channels, browser-side will stop | |
| 405 // down-mixing and use the data from all stream channels. | |
| 406 ChannelLayout renderer_channel_layout = CHANNEL_LAYOUT_NONE; | |
| 407 | |
| 408 // WORRY: IF STREAM CHANGES, WHERE DOES MIXER LEARN OF THE NEW INPUT CHANNEL COU NT? | |
|
chcunningham
2016/03/17 21:48:19
This happens in AudioBufferConverter::AddBuffer. E
| |
| 409 // WORRY: WHERE IS BROWSER LEARNING OF NEW HW CHANNEL COUNT IF SOMETHING GETS PL UGGED IN? WHERE IS BROWSER-SIDE MIXER? | |
|
chcunningham
2016/03/17 21:48:19
The HW channel count is updated via audio_device_l
| |
| 410 // TODO ABOVE: ADD CRBUGS TO COMMENT. ADD TODO FOR TO BE ABLE TO CHANGE LAYOUTS ON FLY | |
| 411 // TODO BELOW: TRY USING INTERMEDIATE hw_layout = discrete ? 5.1 : hw_params TO SIMPLIFY CODE. | |
| 412 | |
| 413 | |
| 414 // We don't know how to mix for DISCRETE layouts (fancy multichannel | |
| 415 // hardware). Instead we choose the max of 5.1 and the stream layout with | |
| 416 // the hope that the OS will know best how to up-mix to the DISCRETE layout. | |
| 417 // Choosing the max avoids pre-maturely down-mixing. | |
| 418 if (hw_params.channel_layout() == CHANNEL_LAYOUT_DISCRETE) { | |
|
DaleCurtis
2016/03/18 00:16:23
Why not just always use the discrete layout in thi
chcunningham
2016/03/25 01:41:16
We chatted - thing is we aren't confident that we
| |
| 419 renderer_channel_layout = stream_channel_count < fiveptone_channel_count ? | |
| 420 CHANNEL_LAYOUT_5_1 : stream->audio_decoder_config().channel_layout(); | |
| 421 } else { | |
| 422 // For all non-discrete layouts we know how to up-mix to the hardware | |
| 423 // layout. Using the max of stream and hardware channel counts avoids | |
| 424 // premature down-mixing should either the stream or hardware later change | |
| 425 // to have more channels. | |
| 426 renderer_channel_layout = stream_channel_count < ChannelLayoutToChannelCou nt(hw_params.channel_layout()) ? | |
| 427 hw_params.channel_layout() : stream->audio_decoder_config().channel_la yout(); | |
| 428 } | |
| 429 | |
| 388 audio_parameters_.Reset( | 430 audio_parameters_.Reset( |
| 389 hw_params.format(), | 431 hw_params.format(), |
| 390 // Always use the source's channel layout to avoid premature downmixing | 432 renderer_channel_layout, |
| 391 // (http://crbug.com/379288), platform specific issues around channel | 433 sample_rate, |
| 392 // layouts (http://crbug.com/266674), and unnecessary upmixing overhead. | |
| 393 stream->audio_decoder_config().channel_layout(), sample_rate, | |
| 394 hw_params.bits_per_sample(), | 434 hw_params.bits_per_sample(), |
| 395 AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, | 435 AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, |
| 396 preferred_buffer_size)); | 436 preferred_buffer_size)); |
| 397 } | 437 } |
| 398 | 438 |
| 399 audio_clock_.reset( | 439 audio_clock_.reset( |
| 400 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate())); | 440 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate())); |
| 401 | 441 |
| 402 audio_buffer_stream_->Initialize( | 442 audio_buffer_stream_->Initialize( |
| 403 stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 443 stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 DCHECK_EQ(status, AudioBufferStream::OK); | 523 DCHECK_EQ(status, AudioBufferStream::OK); |
| 484 DCHECK(buffer.get()); | 524 DCHECK(buffer.get()); |
| 485 | 525 |
| 486 if (state_ == kFlushing) { | 526 if (state_ == kFlushing) { |
| 487 ChangeState_Locked(kFlushed); | 527 ChangeState_Locked(kFlushed); |
| 488 DoFlush_Locked(); | 528 DoFlush_Locked(); |
| 489 return; | 529 return; |
| 490 } | 530 } |
| 491 | 531 |
| 492 if (expecting_config_changes_) { | 532 if (expecting_config_changes_) { |
| 533 if (buffer->sample_rate() != last_decoded_sample_rate_) { | |
| 534 DVLOG(1) << __FUNCTION__ << " Updating audio sample_rate." | |
| 535 << " ts:" << buffer->timestamp().InMicroseconds() | |
| 536 << " old:" << last_decoded_sample_rate_ | |
| 537 << " new:" << buffer->sample_rate(); | |
| 538 OnConfigChange(); | |
| 539 } | |
| 540 last_decoded_sample_rate_ = buffer->sample_rate(); | |
| 541 | |
| 493 DCHECK(buffer_converter_); | 542 DCHECK(buffer_converter_); |
| 494 buffer_converter_->AddInput(buffer); | 543 buffer_converter_->AddInput(buffer); |
| 495 while (buffer_converter_->HasNextBuffer()) { | 544 while (buffer_converter_->HasNextBuffer()) { |
| 496 if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) { | 545 if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) { |
| 497 HandleAbortedReadOrDecodeError(true); | 546 HandleAbortedReadOrDecodeError(true); |
| 498 return; | 547 return; |
| 499 } | 548 } |
| 500 } | 549 } |
| 501 } else { | 550 } else { |
| 502 if (!splicer_->AddInput(buffer)) { | 551 if (!splicer_->AddInput(buffer)) { |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 << buffering_state; | 898 << buffering_state; |
| 850 DCHECK_NE(buffering_state_, buffering_state); | 899 DCHECK_NE(buffering_state_, buffering_state); |
| 851 lock_.AssertAcquired(); | 900 lock_.AssertAcquired(); |
| 852 buffering_state_ = buffering_state; | 901 buffering_state_ = buffering_state; |
| 853 | 902 |
| 854 task_runner_->PostTask(FROM_HERE, | 903 task_runner_->PostTask(FROM_HERE, |
| 855 base::Bind(buffering_state_cb_, buffering_state_)); | 904 base::Bind(buffering_state_cb_, buffering_state_)); |
| 856 } | 905 } |
| 857 | 906 |
| 858 } // namespace media | 907 } // namespace media |
| OLD | NEW |