| Index: chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
|
| diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
|
| index 0430d330b69ef74c5e9805ed227392c2ff70f111..e38074ea331a10a9d6144affcfa6277733bca390 100644
|
| --- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
|
| +++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
|
| @@ -17,7 +17,6 @@
|
| #include "base/memory/weak_ptr.h"
|
| #include "base/numerics/saturated_arithmetic.h"
|
| #include "base/single_thread_task_runner.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| #include "base/threading/platform_thread.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "chromecast/base/chromecast_switches.h"
|
| @@ -126,50 +125,6 @@ int64_t TimespecToMicroseconds(struct timespec time) {
|
| time.tv_nsec / 1000;
|
| }
|
|
|
| -bool GetSwitchValueAsInt(const std::string& switch_name,
|
| - int default_value,
|
| - int* value) {
|
| - DCHECK(value);
|
| - *value = default_value;
|
| - if (!base::CommandLine::InitializedForCurrentProcess()) {
|
| - LOG(WARNING) << "No CommandLine for current process.";
|
| - return false;
|
| - }
|
| - const base::CommandLine* command_line =
|
| - base::CommandLine::ForCurrentProcess();
|
| - if (!command_line->HasSwitch(switch_name)) {
|
| - return false;
|
| - }
|
| -
|
| - int arg_value;
|
| - if (!base::StringToInt(command_line->GetSwitchValueASCII(switch_name),
|
| - &arg_value)) {
|
| - LOG(DFATAL) << "--" << switch_name << " only accepts integers as arguments";
|
| - return false;
|
| - }
|
| - *value = arg_value;
|
| - return true;
|
| -}
|
| -
|
| -bool GetSwitchValueAsNonNegativeInt(const std::string& switch_name,
|
| - int default_value,
|
| - int* value) {
|
| - DCHECK_GE(default_value, 0) << "--" << switch_name
|
| - << " must have a non-negative default value";
|
| - DCHECK(value);
|
| -
|
| - if (!GetSwitchValueAsInt(switch_name, default_value, value)) {
|
| - return false;
|
| - }
|
| -
|
| - if (*value < 0) {
|
| - LOG(DFATAL) << "--" << switch_name << " must have a non-negative value";
|
| - *value = default_value;
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| void VectorAccumulate(const int32_t* source, size_t size, int32_t* dest) {
|
| for (size_t i = 0; i < size; ++i) {
|
| dest[i] = base::SaturatedAddition(source[i], dest[i]);
|
| @@ -190,6 +145,10 @@ base::LazyInstance<StreamMixerAlsaInstance>::DestructorAtExit g_mixer_instance =
|
|
|
| } // namespace
|
|
|
| +float StreamMixerAlsa::VolumeInfo::GetEffectiveVolume() {
|
| + return std::min(volume, limit);
|
| +}
|
| +
|
| // static
|
| bool StreamMixerAlsa::single_threaded_for_test_ = false;
|
|
|
| @@ -214,7 +173,6 @@ StreamMixerAlsa::StreamMixerAlsa()
|
| pcm_status_(nullptr),
|
| pcm_format_(SND_PCM_FORMAT_UNKNOWN),
|
| alsa_buffer_size_(0),
|
| - alsa_period_explicitly_set(false),
|
| alsa_period_size_(0),
|
| alsa_start_threshold_(0),
|
| alsa_avail_min_(0),
|
| @@ -240,9 +198,8 @@ StreamMixerAlsa::StreamMixerAlsa()
|
| switches::kAlsaOutputDevice);
|
| }
|
|
|
| - int fixed_samples_per_second;
|
| - GetSwitchValueAsNonNegativeInt(switches::kAlsaFixedOutputSampleRate,
|
| - kInvalidSampleRate, &fixed_samples_per_second);
|
| + int fixed_samples_per_second = GetSwitchValueNonNegativeInt(
|
| + switches::kAlsaFixedOutputSampleRate, kInvalidSampleRate);
|
| if (fixed_samples_per_second != kInvalidSampleRate) {
|
| LOG(INFO) << "Setting fixed sample rate to " << fixed_samples_per_second;
|
| }
|
| @@ -259,18 +216,19 @@ StreamMixerAlsa::StreamMixerAlsa()
|
| filter_groups_.push_back(base::MakeUnique<FilterGroup>(
|
| std::unordered_set<std::string>(
|
| {::media::AudioDeviceDescription::kCommunicationsDeviceId}),
|
| - AudioFilterFactory::COMMUNICATION_AUDIO_FILTER));
|
| + AudioFilterFactory::COMMUNICATION_AUDIO_FILTER,
|
| + AudioContentType::kMedia));
|
| filter_groups_.push_back(base::MakeUnique<FilterGroup>(
|
| std::unordered_set<std::string>({kAlarmAudioDeviceId}),
|
| - AudioFilterFactory::ALARM_AUDIO_FILTER));
|
| + AudioFilterFactory::ALARM_AUDIO_FILTER, AudioContentType::kAlarm));
|
| filter_groups_.push_back(base::MakeUnique<FilterGroup>(
|
| std::unordered_set<std::string>({kTtsAudioDeviceId}),
|
| - AudioFilterFactory::TTS_AUDIO_FILTER));
|
| + AudioFilterFactory::TTS_AUDIO_FILTER, AudioContentType::kCommunication));
|
| filter_groups_.push_back(base::MakeUnique<FilterGroup>(
|
| std::unordered_set<std::string>(
|
| {::media::AudioDeviceDescription::kDefaultDeviceId,
|
| kLocalAudioDeviceId, ""}),
|
| - AudioFilterFactory::MEDIA_AUDIO_FILTER));
|
| + AudioFilterFactory::MEDIA_AUDIO_FILTER, AudioContentType::kMedia));
|
|
|
| DefineAlsaParameters();
|
| }
|
| @@ -281,52 +239,42 @@ void StreamMixerAlsa::ResetTaskRunnerForTest() {
|
|
|
| void StreamMixerAlsa::DefineAlsaParameters() {
|
| // Get the ALSA output configuration from the command line.
|
| - int buffer_size;
|
| - GetSwitchValueAsNonNegativeInt(switches::kAlsaOutputBufferSize,
|
| - kDefaultOutputBufferSizeFrames, &buffer_size);
|
| - alsa_buffer_size_ = buffer_size;
|
| -
|
| - int period_size;
|
| - if (GetSwitchValueAsNonNegativeInt(switches::kAlsaOutputPeriodSize,
|
| - alsa_buffer_size_ / 16, &period_size)) {
|
| - if (period_size >= buffer_size) {
|
| - LOG(DFATAL) << "ALSA period size must be smaller than the buffer size";
|
| - period_size = buffer_size / 2;
|
| - } else {
|
| - alsa_period_explicitly_set = true;
|
| - }
|
| + alsa_buffer_size_ = GetSwitchValueNonNegativeInt(
|
| + switches::kAlsaOutputBufferSize, kDefaultOutputBufferSizeFrames);
|
| +
|
| + alsa_period_size_ = GetSwitchValueNonNegativeInt(
|
| + switches::kAlsaOutputPeriodSize, alsa_buffer_size_ / 16);
|
| + if (alsa_period_size_ >= alsa_buffer_size_) {
|
| + LOG(DFATAL) << "ALSA period size must be smaller than the buffer size";
|
| + alsa_period_size_ = alsa_buffer_size_ / 2;
|
| }
|
| - alsa_period_size_ = period_size;
|
|
|
| - int start_threshold;
|
| - GetSwitchValueAsNonNegativeInt(switches::kAlsaOutputStartThreshold,
|
| - (buffer_size / period_size) * period_size,
|
| - &start_threshold);
|
| - if (start_threshold > buffer_size) {
|
| + alsa_start_threshold_ = GetSwitchValueNonNegativeInt(
|
| + switches::kAlsaOutputStartThreshold,
|
| + (alsa_buffer_size_ / alsa_period_size_) * alsa_period_size_);
|
| + if (alsa_start_threshold_ > alsa_buffer_size_) {
|
| LOG(DFATAL) << "ALSA start threshold must be no larger than "
|
| << "the buffer size";
|
| - start_threshold = (buffer_size / period_size) * period_size;
|
| + alsa_start_threshold_ =
|
| + (alsa_buffer_size_ / alsa_period_size_) * alsa_period_size_;
|
| }
|
| - alsa_start_threshold_ = start_threshold;
|
|
|
| // By default, allow the transfer when at least period_size samples can be
|
| // processed.
|
| - int avail_min;
|
| - GetSwitchValueAsNonNegativeInt(switches::kAlsaOutputAvailMin, period_size,
|
| - &avail_min);
|
| - if (avail_min > buffer_size) {
|
| + alsa_avail_min_ = GetSwitchValueNonNegativeInt(switches::kAlsaOutputAvailMin,
|
| + alsa_period_size_);
|
| + if (alsa_avail_min_ > alsa_buffer_size_) {
|
| LOG(DFATAL) << "ALSA avail min must be no larger than the buffer size";
|
| - avail_min = alsa_period_size_;
|
| + alsa_avail_min_ = alsa_period_size_;
|
| }
|
| - alsa_avail_min_ = avail_min;
|
|
|
| // --accept-resource-provider should imply a check close timeout of 0.
|
| int default_close_timeout = chromecast::GetSwitchValueBoolean(
|
| switches::kAcceptResourceProvider, false)
|
| ? 0
|
| : kDefaultCheckCloseTimeoutMs;
|
| - GetSwitchValueAsInt(switches::kAlsaCheckCloseTimeout, default_close_timeout,
|
| - &check_close_timeout_);
|
| + check_close_timeout_ = GetSwitchValueInt(switches::kAlsaCheckCloseTimeout,
|
| + default_close_timeout);
|
| }
|
|
|
| unsigned int StreamMixerAlsa::DetermineOutputRate(unsigned int requested_rate) {
|
| @@ -442,11 +390,7 @@ int StreamMixerAlsa::SetAlsaPlaybackParams() {
|
| << " frames). This may lead to an increase in "
|
| "either audio latency or audio underruns.";
|
|
|
| - // Always try to use the value for period_size that was passed in on the
|
| - // command line, if any.
|
| - if (!alsa_period_explicitly_set) {
|
| - alsa_period_size_ = alsa_buffer_size_ / 16;
|
| - } else if (alsa_period_size_ >= alsa_buffer_size_) {
|
| + if (alsa_period_size_ >= alsa_buffer_size_) {
|
| snd_pcm_uframes_t new_period_size = alsa_buffer_size_ / 2;
|
| LOG(DFATAL) << "Configured period size (" << alsa_period_size_
|
| << ") is >= actual buffer size (" << alsa_buffer_size_
|
| @@ -660,6 +604,14 @@ void StreamMixerAlsa::AddInput(std::unique_ptr<InputQueue> input) {
|
| CheckChangeOutputRate(input->input_samples_per_second());
|
| }
|
|
|
| + auto type = input->content_type();
|
| + if (input->primary()) {
|
| + input->SetContentTypeVolume(volume_info_[type].GetEffectiveVolume());
|
| + } else {
|
| + input->SetContentTypeVolume(volume_info_[type].volume);
|
| + }
|
| + input->SetMuted(volume_info_[type].muted);
|
| +
|
| check_close_timer_->Stop();
|
| switch (state_) {
|
| case kStateUninitialized:
|
| @@ -967,5 +919,57 @@ void StreamMixerAlsa::RemoveLoopbackAudioObserver(
|
| observer->OnRemoved();
|
| }
|
|
|
| +void StreamMixerAlsa::SetVolume(AudioContentType type, float level) {
|
| + RUN_ON_MIXER_THREAD(&StreamMixerAlsa::SetVolume, type, level);
|
| + volume_info_[type].volume = level;
|
| + float effective_volume = volume_info_[type].GetEffectiveVolume();
|
| + for (auto&& input : inputs_) {
|
| + if (input->content_type() == type) {
|
| + if (input->primary()) {
|
| + input->SetContentTypeVolume(effective_volume);
|
| + } else {
|
| + // Volume limits don't apply to effects streams.
|
| + input->SetContentTypeVolume(level);
|
| + }
|
| + }
|
| + }
|
| +
|
| + for (auto&& filter : filter_groups_) {
|
| + if (filter->content_type() == type) {
|
| + filter->set_volume(effective_volume);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void StreamMixerAlsa::SetMuted(AudioContentType type, bool muted) {
|
| + RUN_ON_MIXER_THREAD(&StreamMixerAlsa::SetMuted, type, muted);
|
| + volume_info_[type].muted = muted;
|
| + for (auto&& input : inputs_) {
|
| + if (input->content_type() == type) {
|
| + input->SetMuted(muted);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void StreamMixerAlsa::SetOutputLimit(AudioContentType type, float limit) {
|
| + RUN_ON_MIXER_THREAD(&StreamMixerAlsa::SetOutputLimit, type, limit);
|
| + LOG(INFO) << "Set volume limit for " << static_cast<int>(type) << " to "
|
| + << limit;
|
| + volume_info_[type].limit = limit;
|
| + float effective_volume = volume_info_[type].GetEffectiveVolume();
|
| + for (auto&& input : inputs_) {
|
| + // Volume limits don't apply to effects streams.
|
| + if (input->primary() && input->content_type() == type) {
|
| + input->SetContentTypeVolume(effective_volume);
|
| + }
|
| + }
|
| +
|
| + for (auto&& filter : filter_groups_) {
|
| + if (filter->content_type() == type) {
|
| + filter->set_volume(effective_volume);
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace media
|
| } // namespace chromecast
|
|
|