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

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

Issue 1900233006: [Chromecast] Remove command-line switch to change the number of mixer output channels (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Created 4 years, 8 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/stream_mixer_alsa.h" 5 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <utility> 10 #include <utility>
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 #define POST_TASK_TO_MIXER_THREAD(task, ...) \ 57 #define POST_TASK_TO_MIXER_THREAD(task, ...) \
58 mixer_task_runner_->PostTask( \ 58 mixer_task_runner_->PostTask( \
59 FROM_HERE, base::Bind(task, base::Unretained(this), ##__VA_ARGS__)); 59 FROM_HERE, base::Bind(task, base::Unretained(this), ##__VA_ARGS__));
60 60
61 namespace chromecast { 61 namespace chromecast {
62 namespace media { 62 namespace media {
63 63
64 namespace { 64 namespace {
65 65
66 const char kOutputDeviceDefaultName[] = "default"; 66 const char kOutputDeviceDefaultName[] = "default";
67 const int kDefaultNumOutputChannels = 2; 67 const int kNumOutputChannels = 2;
68 68
69 const int kDefaultOutputBufferSizeFrames = 4096; 69 const int kDefaultOutputBufferSizeFrames = 4096;
70 const bool kPcmRecoverIsSilent = false; 70 const bool kPcmRecoverIsSilent = false;
71 // The number of frames of silence to write (to prevent underrun) when no inputs 71 // The number of frames of silence to write (to prevent underrun) when no inputs
72 // are present. 72 // are present.
73 const int kPreventUnderrunChunkSize = 512; 73 const int kPreventUnderrunChunkSize = 512;
74 const int kDefaultCheckCloseTimeoutMs = 2000; 74 const int kDefaultCheckCloseTimeoutMs = 2000;
75 75
76 // A list of supported sample rates. 76 // A list of supported sample rates.
77 // TODO(jyw): move this up into chromecast/public for 1) documentation and 77 // TODO(jyw): move this up into chromecast/public for 1) documentation and
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 198
199 alsa_device_name_ = kOutputDeviceDefaultName; 199 alsa_device_name_ = kOutputDeviceDefaultName;
200 if (base::CommandLine::InitializedForCurrentProcess() && 200 if (base::CommandLine::InitializedForCurrentProcess() &&
201 base::CommandLine::ForCurrentProcess()->HasSwitch( 201 base::CommandLine::ForCurrentProcess()->HasSwitch(
202 switches::kAlsaOutputDevice)) { 202 switches::kAlsaOutputDevice)) {
203 alsa_device_name_ = 203 alsa_device_name_ =
204 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 204 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
205 switches::kAlsaOutputDevice); 205 switches::kAlsaOutputDevice);
206 } 206 }
207 207
208 GetSwitchValueAsNonNegativeInt(switches::kAlsaNumOutputChannels,
209 kDefaultNumOutputChannels,
210 &num_output_channels_);
211
212 int fixed_samples_per_second; 208 int fixed_samples_per_second;
213 GetSwitchValueAsNonNegativeInt(switches::kAlsaFixedOutputSampleRate, 209 GetSwitchValueAsNonNegativeInt(switches::kAlsaFixedOutputSampleRate,
214 kInvalidSampleRate, &fixed_samples_per_second); 210 kInvalidSampleRate, &fixed_samples_per_second);
215 if (fixed_samples_per_second != kInvalidSampleRate) 211 if (fixed_samples_per_second != kInvalidSampleRate)
216 LOG(INFO) << "Setting fixed sample rate to " << fixed_samples_per_second; 212 LOG(INFO) << "Setting fixed sample rate to " << fixed_samples_per_second;
217
218 fixed_output_samples_per_second_ = fixed_samples_per_second; 213 fixed_output_samples_per_second_ = fixed_samples_per_second;
219 214
220 DefineAlsaParameters(); 215 DefineAlsaParameters();
221 } 216 }
222 217
223 void StreamMixerAlsa::ResetTaskRunnerForTest() { 218 void StreamMixerAlsa::ResetTaskRunnerForTest() {
224 mixer_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 219 mixer_task_runner_ = base::ThreadTaskRunnerHandle::Get();
225 } 220 }
226 221
227 void StreamMixerAlsa::DefineAlsaParameters() { 222 void StreamMixerAlsa::DefineAlsaParameters() {
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 } 703 }
709 704
710 if (active_inputs.empty()) { 705 if (active_inputs.empty()) {
711 // No inputs have any data to provide. 706 // No inputs have any data to provide.
712 if (!inputs_.empty()) 707 if (!inputs_.empty())
713 return false; // If there are some inputs, don't fill with silence. 708 return false; // If there are some inputs, don't fill with silence.
714 709
715 // If we have no inputs, fill with silence to avoid underrun. 710 // If we have no inputs, fill with silence to avoid underrun.
716 chunk_size = kPreventUnderrunChunkSize; 711 chunk_size = kPreventUnderrunChunkSize;
717 if (!mixed_ || mixed_->frames() < chunk_size) 712 if (!mixed_ || mixed_->frames() < chunk_size)
718 mixed_ = ::media::AudioBus::Create(num_output_channels_, chunk_size); 713 mixed_ = ::media::AudioBus::Create(kNumOutputChannels, chunk_size);
719 mixed_->Zero(); 714 mixed_->Zero();
720 WriteMixedPcm(*mixed_, chunk_size); 715 WriteMixedPcm(*mixed_, chunk_size);
721 return true; 716 return true;
722 } 717 }
723 718
724 // If |mixed_| has not been allocated, or it is too small, allocate a buffer. 719 // If |mixed_| has not been allocated, or it is too small, allocate a buffer.
725 if (!mixed_ || mixed_->frames() < chunk_size) 720 if (!mixed_ || mixed_->frames() < chunk_size)
726 mixed_ = ::media::AudioBus::Create(num_output_channels_, chunk_size); 721 mixed_ = ::media::AudioBus::Create(kNumOutputChannels, chunk_size);
727 // If |temp_| has not been allocated, or is too small, allocate a buffer. 722 // If |temp_| has not been allocated, or is too small, allocate a buffer.
728 if (!temp_ || temp_->frames() < chunk_size) 723 if (!temp_ || temp_->frames() < chunk_size)
729 temp_ = ::media::AudioBus::Create(num_output_channels_, chunk_size); 724 temp_ = ::media::AudioBus::Create(kNumOutputChannels, chunk_size);
730 725
731 mixed_->ZeroFramesPartial(0, chunk_size); 726 mixed_->ZeroFramesPartial(0, chunk_size);
732 727
733 // Loop through active inputs, polling them for data, and mixing them. 728 // Loop through active inputs, polling them for data, and mixing them.
734 for (InputQueue* input : active_inputs) { 729 for (InputQueue* input : active_inputs) {
735 input->GetResampledData(temp_.get(), chunk_size); 730 input->GetResampledData(temp_.get(), chunk_size);
736 for (int c = 0; c < num_output_channels_; ++c) { 731 for (int c = 0; c < kNumOutputChannels; ++c) {
737 float volume_scalar = input->volume_multiplier(); 732 float volume_scalar = input->volume_multiplier();
738 DCHECK(volume_scalar >= 0.0 && volume_scalar <= 1.0) << volume_scalar; 733 DCHECK(volume_scalar >= 0.0 && volume_scalar <= 1.0) << volume_scalar;
739 ::media::vector_math::FMAC(temp_->channel(c), volume_scalar, chunk_size, 734 ::media::vector_math::FMAC(temp_->channel(c), volume_scalar, chunk_size,
740 mixed_->channel(c)); 735 mixed_->channel(c));
741 } 736 }
742 } 737 }
743 738
744 WriteMixedPcm(*mixed_, chunk_size); 739 WriteMixedPcm(*mixed_, chunk_size);
745 return true; 740 return true;
746 } 741 }
747 742
748 ssize_t StreamMixerAlsa::BytesPerOutputFormatSample() { 743 ssize_t StreamMixerAlsa::BytesPerOutputFormatSample() {
749 return alsa_->PcmFormatSize(pcm_format_, 1); 744 return alsa_->PcmFormatSize(pcm_format_, 1);
750 } 745 }
751 746
752 void StreamMixerAlsa::WriteMixedPcm(const ::media::AudioBus& mixed, 747 void StreamMixerAlsa::WriteMixedPcm(const ::media::AudioBus& mixed,
753 int frames) { 748 int frames) {
754 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 749 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
755 CHECK_PCM_INITIALIZED(); 750 CHECK_PCM_INITIALIZED();
756 751
757 size_t interleaved_size = static_cast<size_t>(frames * num_output_channels_) * 752 size_t interleaved_size = static_cast<size_t>(frames * kNumOutputChannels) *
758 BytesPerOutputFormatSample(); 753 BytesPerOutputFormatSample();
759 if (interleaved_.size() < interleaved_size) 754 if (interleaved_.size() < interleaved_size)
760 interleaved_.resize(interleaved_size); 755 interleaved_.resize(interleaved_size);
761 756
762 int64_t expected_playback_time = rendering_delay_.timestamp_microseconds + 757 int64_t expected_playback_time = rendering_delay_.timestamp_microseconds +
763 rendering_delay_.delay_microseconds; 758 rendering_delay_.delay_microseconds;
764 mixed.ToInterleaved(frames, BytesPerOutputFormatSample(), 759 mixed.ToInterleaved(frames, BytesPerOutputFormatSample(),
765 interleaved_.data()); 760 interleaved_.data());
766 for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) { 761 for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) {
767 observer->OnLoopbackAudio(expected_playback_time, kSampleFormatS32, 762 observer->OnLoopbackAudio(expected_playback_time, kSampleFormatS32,
768 output_samples_per_second_, num_output_channels_, 763 output_samples_per_second_, num_output_channels_,
769 interleaved_.data(), interleaved_size); 764 interleaved_.data(), interleaved_size);
770 } 765 }
771 766
772 // If the PCM has been drained it will be in SND_PCM_STATE_SETUP and need 767 // If the PCM has been drained it will be in SND_PCM_STATE_SETUP and need
773 // to be prepared in order for playback to work. 768 // to be prepared in order for playback to work.
774 if (alsa_->PcmState(pcm_) == SND_PCM_STATE_SETUP) 769 if (alsa_->PcmState(pcm_) == SND_PCM_STATE_SETUP)
775 RETURN_REPORT_ERROR(PcmPrepare, pcm_); 770 RETURN_REPORT_ERROR(PcmPrepare, pcm_);
776 771
777 int frames_left = frames; 772 int frames_left = frames;
778 uint8_t* data = &interleaved_[0]; 773 uint8_t* data = &interleaved_[0];
779 while (frames_left) { 774 while (frames_left) {
780 int frames_or_error; 775 int frames_or_error;
781 while ((frames_or_error = alsa_->PcmWritei(pcm_, data, frames_left)) < 0) { 776 while ((frames_or_error = alsa_->PcmWritei(pcm_, data, frames_left)) < 0) {
782 RETURN_REPORT_ERROR(PcmRecover, pcm_, frames_or_error, 777 RETURN_REPORT_ERROR(PcmRecover, pcm_, frames_or_error,
783 kPcmRecoverIsSilent); 778 kPcmRecoverIsSilent);
784 } 779 }
785 frames_left -= frames_or_error; 780 frames_left -= frames_or_error;
786 DCHECK_GE(frames_left, 0); 781 DCHECK_GE(frames_left, 0);
787 data += 782 data += frames_or_error * kNumOutputChannels * BytesPerOutputFormatSample();
788 frames_or_error * num_output_channels_ * BytesPerOutputFormatSample();
789 } 783 }
790 UpdateRenderingDelay(frames); 784 UpdateRenderingDelay(frames);
791 for (auto&& input : inputs_) 785 for (auto&& input : inputs_)
792 input->AfterWriteFrames(rendering_delay_); 786 input->AfterWriteFrames(rendering_delay_);
793 } 787 }
794 788
795 void StreamMixerAlsa::UpdateRenderingDelay(int newly_pushed_frames) { 789 void StreamMixerAlsa::UpdateRenderingDelay(int newly_pushed_frames) {
796 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 790 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
797 CHECK_PCM_INITIALIZED(); 791 CHECK_PCM_INITIALIZED();
798 792
(...skipping 30 matching lines...) Expand all
829 DCHECK(std::find(loopback_observers_.begin(), loopback_observers_.end(), 823 DCHECK(std::find(loopback_observers_.begin(), loopback_observers_.end(),
830 observer) != loopback_observers_.end()); 824 observer) != loopback_observers_.end());
831 loopback_observers_.erase(std::remove(loopback_observers_.begin(), 825 loopback_observers_.erase(std::remove(loopback_observers_.begin(),
832 loopback_observers_.end(), observer), 826 loopback_observers_.end(), observer),
833 loopback_observers_.end()); 827 loopback_observers_.end());
834 observer->OnRemoved(); 828 observer->OnRemoved();
835 } 829 }
836 830
837 } // namespace media 831 } // namespace media
838 } // namespace chromecast 832 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698