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..8d9bfea14f44327a9f53cc77ae3237154695eaa4 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]); |
@@ -214,7 +169,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), |
@@ -222,6 +176,13 @@ StreamMixerAlsa::StreamMixerAlsa() |
retry_write_frames_timer_(new base::Timer(false, false)), |
check_close_timeout_(kDefaultCheckCloseTimeoutMs), |
check_close_timer_(new base::Timer(false, false)) { |
+ for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm, |
slan
2017/03/13 22:09:51
Perhaps we should use a static assert in here to m
kmackay
2017/03/14 00:20:59
Done.
|
+ AudioContentType::kCommunication}) { |
+ volume_[type] = 1.0f; |
+ volume_limit_[type] = 1.0f; |
+ muted_[type] = false; |
+ } |
+ |
if (single_threaded_for_test_) { |
mixer_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
} else { |
@@ -240,9 +201,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 +219,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 +242,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 +393,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 +607,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(std::min(volume_limit_[type], volume_[type])); |
+ } else { |
+ input->SetContentTypeVolume(volume_[type]); |
+ } |
+ input->SetMuted(muted_[type]); |
+ |
check_close_timer_->Stop(); |
switch (state_) { |
case kStateUninitialized: |
@@ -967,5 +922,57 @@ void StreamMixerAlsa::RemoveLoopbackAudioObserver( |
observer->OnRemoved(); |
} |
+void StreamMixerAlsa::SetVolume(AudioContentType type, float level) { |
+ RUN_ON_MIXER_THREAD(&StreamMixerAlsa::SetVolume, type, level); |
+ volume_[type] = level; |
+ float effective_volume = std::min(volume_limit_[type], level); |
slan
2017/03/13 22:09:51
Regarding my earlier comment about using a VolumeC
kmackay
2017/03/14 00:20:59
Done.
|
+ 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); |
+ muted_[type] = 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_limit_[type] = limit; |
+ float effective_volume = std::min(volume_[type], limit); |
+ 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 |