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> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/callback.h" | 13 #include "base/callback.h" |
| 14 #include "base/callback_helpers.h" | 14 #include "base/callback_helpers.h" |
| 15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/power_monitor/power_monitor.h" | 17 #include "base/power_monitor/power_monitor.h" |
| 18 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
| 19 #include "base/time/default_tick_clock.h" | 19 #include "base/time/default_tick_clock.h" |
| 20 #include "build/build_config.h" | 20 #include "build/build_config.h" |
| 21 #include "media/base/audio_buffer.h" | 21 #include "media/base/audio_buffer.h" |
| 22 #include "media/base/audio_buffer_converter.h" | 22 #include "media/base/audio_buffer_converter.h" |
| 23 #include "media/base/audio_latency.h" | 23 #include "media/base/audio_latency.h" |
| 24 #include "media/base/bind_to_current_loop.h" | 24 #include "media/base/bind_to_current_loop.h" |
| 25 #include "media/base/channel_mixing_matrix.h" | 25 #include "media/base/channel_mixing_matrix.h" |
| 26 #include "media/base/demuxer_stream.h" | 26 #include "media/base/demuxer_stream.h" |
| 27 #include "media/base/media_client.h" | |
| 27 #include "media/base/media_log.h" | 28 #include "media/base/media_log.h" |
| 28 #include "media/base/media_switches.h" | 29 #include "media/base/media_switches.h" |
| 29 #include "media/base/renderer_client.h" | 30 #include "media/base/renderer_client.h" |
| 30 #include "media/base/timestamp_constants.h" | 31 #include "media/base/timestamp_constants.h" |
| 31 #include "media/filters/audio_clock.h" | 32 #include "media/filters/audio_clock.h" |
| 32 #include "media/filters/decrypting_demuxer_stream.h" | 33 #include "media/filters/decrypting_demuxer_stream.h" |
| 33 | 34 |
| 34 namespace media { | 35 namespace media { |
| 35 | 36 |
| 37 static const int kMaxFramesPerCompressedAudioBuffer = 4096; | |
|
DaleCurtis
2017/06/15 21:46:33
Needs explanation; possibly should be stored in Au
AndyWu
2017/08/02 01:43:41
Done.
| |
| 38 | |
| 36 AudioRendererImpl::AudioRendererImpl( | 39 AudioRendererImpl::AudioRendererImpl( |
| 37 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 40 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 38 media::AudioRendererSink* sink, | 41 media::AudioRendererSink* sink, |
| 39 const CreateAudioDecodersCB& create_audio_decoders_cb, | 42 const CreateAudioDecodersCB& create_audio_decoders_cb, |
| 40 MediaLog* media_log) | 43 MediaLog* media_log) |
| 41 : task_runner_(task_runner), | 44 : task_runner_(task_runner), |
| 42 expecting_config_changes_(false), | 45 expecting_config_changes_(false), |
| 43 sink_(sink), | 46 sink_(sink), |
| 44 media_log_(media_log), | 47 media_log_(media_log), |
| 45 client_(nullptr), | 48 client_(nullptr), |
| 46 tick_clock_(new base::DefaultTickClock()), | 49 tick_clock_(new base::DefaultTickClock()), |
| 47 last_audio_memory_usage_(0), | 50 last_audio_memory_usage_(0), |
| 48 last_decoded_sample_rate_(0), | 51 last_decoded_sample_rate_(0), |
| 49 last_decoded_channel_layout_(CHANNEL_LAYOUT_NONE), | 52 last_decoded_channel_layout_(CHANNEL_LAYOUT_NONE), |
| 50 is_encrypted_(false), | 53 is_encrypted_(false), |
| 51 last_decoded_channels_(0), | 54 last_decoded_channels_(0), |
| 52 playback_rate_(0.0), | 55 playback_rate_(0.0), |
| 53 state_(kUninitialized), | 56 state_(kUninitialized), |
| 54 create_audio_decoders_cb_(create_audio_decoders_cb), | 57 create_audio_decoders_cb_(create_audio_decoders_cb), |
| 55 buffering_state_(BUFFERING_HAVE_NOTHING), | 58 buffering_state_(BUFFERING_HAVE_NOTHING), |
| 56 rendering_(false), | 59 rendering_(false), |
| 57 sink_playing_(false), | 60 sink_playing_(false), |
| 58 pending_read_(false), | 61 pending_read_(false), |
| 59 received_end_of_stream_(false), | 62 received_end_of_stream_(false), |
| 60 rendered_end_of_stream_(false), | 63 rendered_end_of_stream_(false), |
| 61 is_suspending_(false), | 64 is_suspending_(false), |
| 65 is_passthrough_(false), | |
| 66 last_reported_media_time_(kNoTimestamp), | |
| 62 weak_factory_(this) { | 67 weak_factory_(this) { |
| 63 DCHECK(create_audio_decoders_cb_); | 68 DCHECK(create_audio_decoders_cb_); |
| 64 // Tests may not have a power monitor. | 69 // Tests may not have a power monitor. |
| 65 base::PowerMonitor* monitor = base::PowerMonitor::Get(); | 70 base::PowerMonitor* monitor = base::PowerMonitor::Get(); |
| 66 if (!monitor) | 71 if (!monitor) |
| 67 return; | 72 return; |
| 68 | 73 |
| 69 // PowerObserver's must be added and removed from the same thread, but we | 74 // PowerObserver's must be added and removed from the same thread, but we |
| 70 // won't remove the observer until we're destructed on |task_runner_| so we | 75 // won't remove the observer until we're destructed on |task_runner_| so we |
| 71 // must post it here if we're on the wrong thread. | 76 // must post it here if we're on the wrong thread. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 172 | 177 |
| 173 base::AutoLock auto_lock(lock_); | 178 base::AutoLock auto_lock(lock_); |
| 174 DCHECK(!rendering_); | 179 DCHECK(!rendering_); |
| 175 DCHECK_EQ(state_, kFlushed); | 180 DCHECK_EQ(state_, kFlushed); |
| 176 | 181 |
| 177 start_timestamp_ = time; | 182 start_timestamp_ = time; |
| 178 ended_timestamp_ = kInfiniteDuration; | 183 ended_timestamp_ = kInfiniteDuration; |
| 179 last_render_time_ = stop_rendering_time_ = base::TimeTicks(); | 184 last_render_time_ = stop_rendering_time_ = base::TimeTicks(); |
| 180 first_packet_timestamp_ = kNoTimestamp; | 185 first_packet_timestamp_ = kNoTimestamp; |
| 181 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate())); | 186 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate())); |
| 187 last_reported_media_time_ = kNoTimestamp; | |
| 182 } | 188 } |
| 183 | 189 |
| 184 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { | 190 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { |
| 185 base::AutoLock auto_lock(lock_); | 191 base::AutoLock auto_lock(lock_); |
| 186 | 192 |
| 187 // Return the current time based on the known extents of the rendered audio | 193 // Return the current time based on the known extents of the rendered audio |
| 188 // data plus an estimate based on the last time those values were calculated. | 194 // data plus an estimate based on the last time those values were calculated. |
| 189 base::TimeDelta current_media_time = audio_clock_->front_timestamp(); | 195 base::TimeDelta current_media_time = audio_clock_->front_timestamp(); |
| 190 if (!last_render_time_.is_null()) { | 196 if (!last_render_time_.is_null()) { |
| 191 current_media_time += | 197 current_media_time += |
| 192 (tick_clock_->NowTicks() - last_render_time_) * playback_rate_; | 198 (tick_clock_->NowTicks() - last_render_time_) * playback_rate_; |
| 193 if (current_media_time > audio_clock_->back_timestamp()) | 199 if (current_media_time > audio_clock_->back_timestamp()) |
| 194 current_media_time = audio_clock_->back_timestamp(); | 200 current_media_time = audio_clock_->back_timestamp(); |
| 195 } | 201 } |
| 196 | 202 |
| 197 return current_media_time; | 203 // Clamp current media time to the last reported value, this prevents higher |
|
DaleCurtis
2017/06/15 21:46:33
We already do this in PipelineImpl.
AndyWu
2017/08/02 01:43:41
Hi Chris, do you agree to remove this logic?
chcunningham
2017/08/04 19:26:40
Yep, should be fine. It used to live here, but had
AndyWu
2017/08/04 21:45:52
Thanks for your feedback.
| |
| 204 // level clients from seeing time go backwards. This may happen when seeking | |
| 205 // a passthrough audio stream, since we are unable to trim a compressed audio | |
| 206 // buffer. | |
| 207 if (last_reported_media_time_ < current_media_time) | |
| 208 last_reported_media_time_ = current_media_time; | |
| 209 | |
| 210 return last_reported_media_time_; | |
| 198 } | 211 } |
| 199 | 212 |
| 200 bool AudioRendererImpl::GetWallClockTimes( | 213 bool AudioRendererImpl::GetWallClockTimes( |
| 201 const std::vector<base::TimeDelta>& media_timestamps, | 214 const std::vector<base::TimeDelta>& media_timestamps, |
| 202 std::vector<base::TimeTicks>* wall_clock_times) { | 215 std::vector<base::TimeTicks>* wall_clock_times) { |
| 203 base::AutoLock auto_lock(lock_); | 216 base::AutoLock auto_lock(lock_); |
| 204 DCHECK(wall_clock_times->empty()); | 217 DCHECK(wall_clock_times->empty()); |
| 205 | 218 |
| 206 // When playback is paused (rate is zero), assume a rate of 1.0. | 219 // When playback is paused (rate is zero), assume a rate of 1.0. |
| 207 const double playback_rate = playback_rate_ ? playback_rate_ : 1.0; | 220 const double playback_rate = playback_rate_ ? playback_rate_ : 1.0; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 362 | 375 |
| 363 audio_buffer_stream_->set_config_change_observer(base::Bind( | 376 audio_buffer_stream_->set_config_change_observer(base::Bind( |
| 364 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 377 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); |
| 365 | 378 |
| 366 // Always post |init_cb_| because |this| could be destroyed if initialization | 379 // Always post |init_cb_| because |this| could be destroyed if initialization |
| 367 // failed. | 380 // failed. |
| 368 init_cb_ = BindToCurrentLoop(init_cb); | 381 init_cb_ = BindToCurrentLoop(init_cb); |
| 369 | 382 |
| 370 auto output_device_info = sink_->GetOutputDeviceInfo(); | 383 auto output_device_info = sink_->GetOutputDeviceInfo(); |
| 371 const AudioParameters& hw_params = output_device_info.output_params(); | 384 const AudioParameters& hw_params = output_device_info.output_params(); |
| 385 AudioCodec codec = stream->audio_decoder_config().codec(); | |
| 386 MediaClient* media_client = GetMediaClient(); | |
|
DaleCurtis
2017/06/15 21:46:33
if (auto* mc = GetMediaClient())
is_passthrough_
AndyWu
2017/08/02 01:43:41
Done.
| |
| 387 is_passthrough_ = | |
| 388 media_client && media_client->IsSupportedBitstreamAudioCodec(codec); | |
| 372 expecting_config_changes_ = stream->SupportsConfigChanges(); | 389 expecting_config_changes_ = stream->SupportsConfigChanges(); |
| 373 | 390 |
| 374 bool use_stream_params = !expecting_config_changes_ || !hw_params.IsValid() || | 391 bool use_stream_params = !expecting_config_changes_ || !hw_params.IsValid() || |
| 375 hw_params.format() == AudioParameters::AUDIO_FAKE || | 392 hw_params.format() == AudioParameters::AUDIO_FAKE || |
| 376 !sink_->IsOptimizedForHardwareParameters(); | 393 !sink_->IsOptimizedForHardwareParameters(); |
| 377 | 394 |
| 378 if (stream->audio_decoder_config().channel_layout() == | 395 if (stream->audio_decoder_config().channel_layout() == |
| 379 CHANNEL_LAYOUT_DISCRETE && | 396 CHANNEL_LAYOUT_DISCRETE && |
| 380 sink_->IsOptimizedForHardwareParameters()) { | 397 sink_->IsOptimizedForHardwareParameters()) { |
| 381 use_stream_params = false; | 398 use_stream_params = false; |
| 382 } | 399 } |
| 383 | 400 |
| 384 if (use_stream_params) { | 401 if (is_passthrough_) { |
| 402 AudioParameters::Format format = AudioParameters::AUDIO_FAKE; | |
| 403 if (codec == kCodecAC3) { | |
| 404 format = AudioParameters::AUDIO_BITSTREAM_AC3; | |
| 405 } else if (codec == kCodecEAC3) { | |
| 406 format = AudioParameters::AUDIO_BITSTREAM_EAC3; | |
| 407 } else { | |
| 408 NOTREACHED(); | |
| 409 } | |
| 410 | |
| 411 const int buffer_size = kMaxFramesPerCompressedAudioBuffer * | |
| 412 stream->audio_decoder_config().bytes_per_frame(); | |
| 413 | |
| 414 audio_parameters_.Reset( | |
| 415 format, stream->audio_decoder_config().channel_layout(), | |
| 416 stream->audio_decoder_config().samples_per_second(), | |
| 417 stream->audio_decoder_config().bits_per_channel(), buffer_size); | |
| 418 buffer_converter_.reset(); | |
| 419 } else if (use_stream_params) { | |
| 385 // The actual buffer size is controlled via the size of the AudioBus | 420 // The actual buffer size is controlled via the size of the AudioBus |
| 386 // provided to Render(), but we should choose a value here based on hardware | 421 // provided to Render(), but we should choose a value here based on hardware |
| 387 // parameters if possible since it affects the initial buffer size used by | 422 // parameters if possible since it affects the initial buffer size used by |
| 388 // the algorithm. Too little will cause underflow on Bluetooth devices. | 423 // the algorithm. Too little will cause underflow on Bluetooth devices. |
| 389 int buffer_size = | 424 int buffer_size = |
| 390 std::max(stream->audio_decoder_config().samples_per_second() / 100, | 425 std::max(stream->audio_decoder_config().samples_per_second() / 100, |
| 391 hw_params.IsValid() ? hw_params.frames_per_buffer() : 0); | 426 hw_params.IsValid() ? hw_params.frames_per_buffer() : 0); |
| 392 audio_parameters_.Reset(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 427 audio_parameters_.Reset(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 393 stream->audio_decoder_config().channel_layout(), | 428 stream->audio_decoder_config().channel_layout(), |
| 394 stream->audio_decoder_config().samples_per_second(), | 429 stream->audio_decoder_config().samples_per_second(), |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 | 697 |
| 663 AttemptRead_Locked(); | 698 AttemptRead_Locked(); |
| 664 } | 699 } |
| 665 | 700 |
| 666 bool AudioRendererImpl::HandleDecodedBuffer_Locked( | 701 bool AudioRendererImpl::HandleDecodedBuffer_Locked( |
| 667 const scoped_refptr<AudioBuffer>& buffer) { | 702 const scoped_refptr<AudioBuffer>& buffer) { |
| 668 lock_.AssertAcquired(); | 703 lock_.AssertAcquired(); |
| 669 if (buffer->end_of_stream()) { | 704 if (buffer->end_of_stream()) { |
| 670 received_end_of_stream_ = true; | 705 received_end_of_stream_ = true; |
| 671 } else { | 706 } else { |
| 672 if (state_ == kPlaying) { | 707 if (buffer->IsBitstreamFormat() && state_ == kPlaying) { |
| 673 if (IsBeforeStartTime(buffer)) | 708 if (IsBeforeStartTime(buffer)) |
| 674 return true; | 709 return true; |
| 675 | 710 |
| 711 // Adjust the start time since we are unable to trim a compressed audio | |
| 712 // buffer. | |
| 713 if (buffer->timestamp() < start_timestamp_ && | |
|
DaleCurtis
2017/06/15 21:46:33
I'd just skip this and seek to the first full buff
AndyWu
2017/08/02 01:43:41
Done.
| |
| 714 (buffer->timestamp() + buffer->duration()) > start_timestamp_) { | |
| 715 start_timestamp_ = buffer->timestamp(); | |
| 716 audio_clock_.reset(new AudioClock(buffer->timestamp(), | |
| 717 audio_parameters_.sample_rate())); | |
| 718 } | |
| 719 } else if (state_ == kPlaying) { | |
| 720 if (IsBeforeStartTime(buffer)) | |
| 721 return true; | |
| 722 | |
| 676 // Trim off any additional time before the start timestamp. | 723 // Trim off any additional time before the start timestamp. |
| 677 const base::TimeDelta trim_time = start_timestamp_ - buffer->timestamp(); | 724 const base::TimeDelta trim_time = start_timestamp_ - buffer->timestamp(); |
| 678 if (trim_time > base::TimeDelta()) { | 725 if (trim_time > base::TimeDelta()) { |
| 679 buffer->TrimStart(buffer->frame_count() * | 726 buffer->TrimStart(buffer->frame_count() * |
| 680 (static_cast<double>(trim_time.InMicroseconds()) / | 727 (static_cast<double>(trim_time.InMicroseconds()) / |
| 681 buffer->duration().InMicroseconds())); | 728 buffer->duration().InMicroseconds())); |
| 682 buffer->set_timestamp(start_timestamp_); | 729 buffer->set_timestamp(start_timestamp_); |
| 683 } | 730 } |
| 684 // If the entire buffer was trimmed, request a new one. | 731 // If the entire buffer was trimmed, request a new one. |
| 685 if (!buffer->frame_count()) | 732 if (!buffer->frame_count()) |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 } | 808 } |
| 762 | 809 |
| 763 void AudioRendererImpl::SetPlaybackRate(double playback_rate) { | 810 void AudioRendererImpl::SetPlaybackRate(double playback_rate) { |
| 764 DVLOG(1) << __func__ << "(" << playback_rate << ")"; | 811 DVLOG(1) << __func__ << "(" << playback_rate << ")"; |
| 765 DCHECK(task_runner_->BelongsToCurrentThread()); | 812 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 766 DCHECK_GE(playback_rate, 0); | 813 DCHECK_GE(playback_rate, 0); |
| 767 DCHECK(sink_.get()); | 814 DCHECK(sink_.get()); |
| 768 | 815 |
| 769 base::AutoLock auto_lock(lock_); | 816 base::AutoLock auto_lock(lock_); |
| 770 | 817 |
| 818 if (is_passthrough_ && playback_rate != 0 && playback_rate != 1) { | |
| 819 MEDIA_LOG(ERROR, media_log_) | |
|
DaleCurtis
2017/06/15 21:46:32
WARNING or INFO, no need for ERROR.
AndyWu
2017/08/02 01:43:41
Done.
| |
| 820 << "Unsupported playback rate when outputing compressed bitstream." | |
| 821 << " Playback Rate: " << playback_rate; | |
| 822 return; | |
| 823 } | |
| 824 | |
| 771 // We have two cases here: | 825 // We have two cases here: |
| 772 // Play: current_playback_rate == 0 && playback_rate != 0 | 826 // Play: current_playback_rate == 0 && playback_rate != 0 |
| 773 // Pause: current_playback_rate != 0 && playback_rate == 0 | 827 // Pause: current_playback_rate != 0 && playback_rate == 0 |
| 774 double current_playback_rate = playback_rate_; | 828 double current_playback_rate = playback_rate_; |
| 775 playback_rate_ = playback_rate; | 829 playback_rate_ = playback_rate; |
| 776 | 830 |
| 777 if (!rendering_) | 831 if (!rendering_) |
| 778 return; | 832 return; |
| 779 | 833 |
| 780 if (current_playback_rate == 0 && playback_rate != 0) { | 834 if (current_playback_rate == 0 && playback_rate != 0) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 792 const scoped_refptr<AudioBuffer>& buffer) { | 846 const scoped_refptr<AudioBuffer>& buffer) { |
| 793 DCHECK_EQ(state_, kPlaying); | 847 DCHECK_EQ(state_, kPlaying); |
| 794 return buffer.get() && !buffer->end_of_stream() && | 848 return buffer.get() && !buffer->end_of_stream() && |
| 795 (buffer->timestamp() + buffer->duration()) < start_timestamp_; | 849 (buffer->timestamp() + buffer->duration()) < start_timestamp_; |
| 796 } | 850 } |
| 797 | 851 |
| 798 int AudioRendererImpl::Render(base::TimeDelta delay, | 852 int AudioRendererImpl::Render(base::TimeDelta delay, |
| 799 base::TimeTicks delay_timestamp, | 853 base::TimeTicks delay_timestamp, |
| 800 int prior_frames_skipped, | 854 int prior_frames_skipped, |
| 801 AudioBus* audio_bus) { | 855 AudioBus* audio_bus) { |
| 802 const int frames_requested = audio_bus->frames(); | 856 int frames_requested = audio_bus->frames(); |
| 803 DVLOG(4) << __func__ << " delay:" << delay | 857 DVLOG(4) << __func__ << " delay:" << delay |
| 804 << " prior_frames_skipped:" << prior_frames_skipped | 858 << " prior_frames_skipped:" << prior_frames_skipped |
| 805 << " frames_requested:" << frames_requested; | 859 << " frames_requested:" << frames_requested; |
| 806 | 860 |
| 807 int frames_written = 0; | 861 int frames_written = 0; |
| 808 { | 862 { |
| 809 base::AutoLock auto_lock(lock_); | 863 base::AutoLock auto_lock(lock_); |
| 810 last_render_time_ = tick_clock_->NowTicks(); | 864 last_render_time_ = tick_clock_->NowTicks(); |
| 811 | 865 |
| 812 int64_t frames_delayed = AudioTimestampHelper::TimeToFrames( | 866 int64_t frames_delayed = AudioTimestampHelper::TimeToFrames( |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 831 return 0; | 885 return 0; |
| 832 } | 886 } |
| 833 | 887 |
| 834 // Mute audio by returning 0 when not playing. | 888 // Mute audio by returning 0 when not playing. |
| 835 if (state_ != kPlaying) { | 889 if (state_ != kPlaying) { |
| 836 audio_clock_->WroteAudio(0, frames_requested, frames_delayed, | 890 audio_clock_->WroteAudio(0, frames_requested, frames_delayed, |
| 837 playback_rate_); | 891 playback_rate_); |
| 838 return 0; | 892 return 0; |
| 839 } | 893 } |
| 840 | 894 |
| 841 // Delay playback by writing silence if we haven't reached the first | 895 if (is_passthrough_ && algorithm_->frames_buffered() > 0) { |
| 842 // timestamp yet; this can occur if the video starts before the audio. | 896 frames_written += algorithm_->FillBuffer(audio_bus, 0, frames_requested, |
|
chcunningham
2017/06/14 20:03:08
special passthrough logic needs "why" documentatio
DaleCurtis
2017/06/15 21:46:33
FYI, this is going to be wrong in cases where the
AndyWu
2017/08/02 01:43:41
Done.
AndyWu
2017/08/02 01:43:41
Done.
| |
| 843 if (algorithm_->frames_buffered() > 0) { | 897 playback_rate_); |
| 898 frames_requested = frames_written; | |
| 899 } else if (algorithm_->frames_buffered() > 0) { | |
| 900 // Delay playback by writing silence if we haven't reached the first | |
| 901 // timestamp yet; this can occur if the video starts before the audio. | |
| 844 CHECK_NE(first_packet_timestamp_, kNoTimestamp); | 902 CHECK_NE(first_packet_timestamp_, kNoTimestamp); |
| 845 CHECK_GE(first_packet_timestamp_, base::TimeDelta()); | 903 CHECK_GE(first_packet_timestamp_, base::TimeDelta()); |
| 846 const base::TimeDelta play_delay = | 904 const base::TimeDelta play_delay = |
| 847 first_packet_timestamp_ - audio_clock_->back_timestamp(); | 905 first_packet_timestamp_ - audio_clock_->back_timestamp(); |
| 848 if (play_delay > base::TimeDelta()) { | 906 if (play_delay > base::TimeDelta()) { |
| 849 DCHECK_EQ(frames_written, 0); | 907 DCHECK_EQ(frames_written, 0); |
| 850 | 908 |
| 851 // Don't multiply |play_delay| out since it can be a huge value on | 909 // Don't multiply |play_delay| out since it can be a huge value on |
| 852 // poorly encoded media and multiplying by the sample rate could cause | 910 // poorly encoded media and multiplying by the sample rate could cause |
| 853 // the value to overflow. | 911 // the value to overflow. |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1023 // All channels with a zero mix are muted and can be ignored. | 1081 // All channels with a zero mix are muted and can be ignored. |
| 1024 std::vector<bool> channel_mask(audio_parameters_.channels(), false); | 1082 std::vector<bool> channel_mask(audio_parameters_.channels(), false); |
| 1025 for (size_t ch = 0; ch < matrix.size(); ++ch) { | 1083 for (size_t ch = 0; ch < matrix.size(); ++ch) { |
| 1026 channel_mask[ch] = std::any_of(matrix[ch].begin(), matrix[ch].end(), | 1084 channel_mask[ch] = std::any_of(matrix[ch].begin(), matrix[ch].end(), |
| 1027 [](float mix) { return !!mix; }); | 1085 [](float mix) { return !!mix; }); |
| 1028 } | 1086 } |
| 1029 algorithm_->SetChannelMask(std::move(channel_mask)); | 1087 algorithm_->SetChannelMask(std::move(channel_mask)); |
| 1030 } | 1088 } |
| 1031 | 1089 |
| 1032 } // namespace media | 1090 } // namespace media |
| OLD | NEW |