Commit bfcb7d68 authored by Ken MacKay's avatar Ken MacKay Committed by Commit Bot

[Chromecast] Add support for power-save mode

After no streams have been playing out audio for a few seconds, trigger
power-save mode. Note that paused streams do not count as playing out
for this purpose.

Bug: internal b/64462358
Change-Id: I6ed4910490705d39e499b5f5e63432f8534993ff
Reviewed-on: https://chromium-review.googlesource.com/807749
Commit-Queue: Kenneth MacKay <kmackay@chromium.org>
Reviewed-by: default avatarLuke Halliwell <halliwell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#522030}
parent 3fc597bc
...@@ -89,6 +89,14 @@ const char kAlsaMuteElementName[] = "alsa-mute-element-name"; ...@@ -89,6 +89,14 @@ const char kAlsaMuteElementName[] = "alsa-mute-element-name";
// specified it will default to the same device as kAlsaVolumeDeviceName. // specified it will default to the same device as kAlsaVolumeDeviceName.
const char kAlsaMuteDeviceName[] = "alsa-mute-device-name"; const char kAlsaMuteDeviceName[] = "alsa-mute-device-name";
// Name of the simple mixer control element that the ALSA-based media library
// should use to toggle powersave mode on the system.
const char kAlsaAmpElementName[] = "alsa-amp-element-name";
// Name of the device the amp mixer should be opened on. If this flag is not
// specified it will default to the same device as kAlsaVolumeDeviceName.
const char kAlsaAmpDeviceName[] = "alsa-amp-device-name";
// Calibrated max output volume dBa for voice content at 1 meter, if known. // Calibrated max output volume dBa for voice content at 1 meter, if known.
const char kMaxOutputVolumeDba1m[] = "max-output-volume-dba1m"; const char kMaxOutputVolumeDba1m[] = "max-output-volume-dba1m";
......
...@@ -52,6 +52,8 @@ extern const char kAlsaVolumeDeviceName[]; ...@@ -52,6 +52,8 @@ extern const char kAlsaVolumeDeviceName[];
extern const char kAlsaVolumeElementName[]; extern const char kAlsaVolumeElementName[];
extern const char kAlsaMuteDeviceName[]; extern const char kAlsaMuteDeviceName[];
extern const char kAlsaMuteElementName[]; extern const char kAlsaMuteElementName[];
extern const char kAlsaAmpDeviceName[];
extern const char kAlsaAmpElementName[];
extern const char kMaxOutputVolumeDba1m[]; extern const char kMaxOutputVolumeDba1m[];
extern const char kAudioOutputChannels[]; extern const char kAudioOutputChannels[];
extern const char kAudioOutputSampleRate[]; extern const char kAudioOutputSampleRate[];
......
...@@ -37,6 +37,7 @@ cast_source_set("backend") { ...@@ -37,6 +37,7 @@ cast_source_set("backend") {
deps = [ deps = [
"//base", "//base",
"//chromecast:chromecast_features", "//chromecast:chromecast_features",
"//chromecast/base/metrics:metrics",
"//chromecast/media:libcast_media", "//chromecast/media:libcast_media",
"//chromecast/media/cma/base", "//chromecast/media/cma/base",
] ]
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "chromecast/base/chromecast_switches.h" #include "chromecast/base/chromecast_switches.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
...@@ -168,9 +167,34 @@ std::string AlsaVolumeControl::GetMuteDeviceName() { ...@@ -168,9 +167,34 @@ std::string AlsaVolumeControl::GetMuteDeviceName() {
return GetVolumeDeviceName(); return GetVolumeDeviceName();
} }
// static
std::string AlsaVolumeControl::GetAmpElementName() {
std::string mixer_element_name =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kAlsaAmpElementName);
if (!mixer_element_name.empty()) {
return mixer_element_name;
}
return std::string();
}
// static
std::string AlsaVolumeControl::GetAmpDeviceName() {
auto* command_line = base::CommandLine::ForCurrentProcess();
std::string mixer_device_name =
command_line->GetSwitchValueASCII(switches::kAlsaAmpDeviceName);
if (!mixer_device_name.empty()) {
return mixer_device_name;
}
// If the amp mixer device was not specified directly, use the same device as
// the volume mixer.
return GetVolumeDeviceName();
}
AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate) AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate)
: delegate_(delegate), : delegate_(delegate),
alsa_(base::MakeUnique<::media::AlsaWrapper>()), alsa_(std::make_unique<::media::AlsaWrapper>()),
volume_mixer_device_name_(GetVolumeDeviceName()), volume_mixer_device_name_(GetVolumeDeviceName()),
volume_mixer_element_name_(GetVolumeElementName()), volume_mixer_element_name_(GetVolumeElementName()),
mute_mixer_device_name_(GetMuteDeviceName()), mute_mixer_device_name_(GetMuteDeviceName()),
...@@ -178,6 +202,8 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate) ...@@ -178,6 +202,8 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate)
volume_mixer_device_name_, volume_mixer_device_name_,
volume_mixer_element_name_, volume_mixer_element_name_,
mute_mixer_device_name_)), mute_mixer_device_name_)),
amp_mixer_device_name_(GetAmpDeviceName()),
amp_mixer_element_name_(GetAmpElementName()),
volume_range_min_(0), volume_range_min_(0),
volume_range_max_(0), volume_range_max_(0),
mute_mixer_ptr_(nullptr) { mute_mixer_ptr_(nullptr) {
...@@ -186,8 +212,10 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate) ...@@ -186,8 +212,10 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate)
<< ", element = " << volume_mixer_element_name_; << ", element = " << volume_mixer_element_name_;
VLOG(1) << "Mute device = " << mute_mixer_device_name_ VLOG(1) << "Mute device = " << mute_mixer_device_name_
<< ", element = " << mute_mixer_element_name_; << ", element = " << mute_mixer_element_name_;
VLOG(1) << "Idle device = " << amp_mixer_device_name_
<< ", element = " << amp_mixer_element_name_;
volume_mixer_ = base::MakeUnique<ScopedAlsaMixer>( volume_mixer_ = std::make_unique<ScopedAlsaMixer>(
alsa_.get(), volume_mixer_device_name_, volume_mixer_element_name_); alsa_.get(), volume_mixer_device_name_, volume_mixer_element_name_);
if (volume_mixer_->element) { if (volume_mixer_->element) {
ALSA_ASSERT(MixerSelemGetPlaybackVolumeRange, volume_mixer_->element, ALSA_ASSERT(MixerSelemGetPlaybackVolumeRange, volume_mixer_->element,
...@@ -200,7 +228,7 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate) ...@@ -200,7 +228,7 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate)
} }
if (mute_mixer_element_name_ != volume_mixer_element_name_) { if (mute_mixer_element_name_ != volume_mixer_element_name_) {
mute_mixer_ = base::MakeUnique<ScopedAlsaMixer>( mute_mixer_ = std::make_unique<ScopedAlsaMixer>(
alsa_.get(), mute_mixer_device_name_, mute_mixer_element_name_); alsa_.get(), mute_mixer_device_name_, mute_mixer_element_name_);
if (mute_mixer_->element) { if (mute_mixer_->element) {
mute_mixer_ptr_ = mute_mixer_.get(); mute_mixer_ptr_ = mute_mixer_.get();
...@@ -214,6 +242,14 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate) ...@@ -214,6 +242,14 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate)
} else { } else {
mute_mixer_ptr_ = volume_mixer_.get(); mute_mixer_ptr_ = volume_mixer_.get();
} }
if (!amp_mixer_element_name_.empty()) {
amp_mixer_ = std::make_unique<ScopedAlsaMixer>(
alsa_.get(), amp_mixer_device_name_, amp_mixer_element_name_);
if (amp_mixer_->element) {
RefreshMixerFds(amp_mixer_.get());
}
}
} }
AlsaVolumeControl::~AlsaVolumeControl() = default; AlsaVolumeControl::~AlsaVolumeControl() = default;
...@@ -271,16 +307,28 @@ bool AlsaVolumeControl::IsMuted() { ...@@ -271,16 +307,28 @@ bool AlsaVolumeControl::IsMuted() {
} }
void AlsaVolumeControl::SetMuted(bool muted) { void AlsaVolumeControl::SetMuted(bool muted) {
if (!mute_mixer_ptr_->element || if (!SetElementMuted(mute_mixer_ptr_, muted)) {
!alsa_->MixerSelemHasPlaybackSwitch(mute_mixer_ptr_->element)) {
LOG(ERROR) << "Mute failed: no mute switch on mixer element."; LOG(ERROR) << "Mute failed: no mute switch on mixer element.";
return; }
}
void AlsaVolumeControl::SetPowerSave(bool power_save_on) {
if (!SetElementMuted(amp_mixer_.get(), power_save_on)) {
LOG(INFO) << "Amp toggle failed: no amp switch on mixer element.";
}
}
bool AlsaVolumeControl::SetElementMuted(ScopedAlsaMixer* mixer, bool muted) {
if (!mixer || !mixer->element ||
!alsa_->MixerSelemHasPlaybackSwitch(mixer->element)) {
return false;
} }
for (int32_t channel = 0; channel <= SND_MIXER_SCHN_LAST; ++channel) { for (int32_t channel = 0; channel <= SND_MIXER_SCHN_LAST; ++channel) {
alsa_->MixerSelemSetPlaybackSwitch( alsa_->MixerSelemSetPlaybackSwitch(
mute_mixer_ptr_->element, mixer->element, static_cast<snd_mixer_selem_channel_id_t>(channel),
static_cast<snd_mixer_selem_channel_id_t>(channel), !muted); !muted);
} }
return true;
} }
void AlsaVolumeControl::RefreshMixerFds(ScopedAlsaMixer* mixer) { void AlsaVolumeControl::RefreshMixerFds(ScopedAlsaMixer* mixer) {
...@@ -291,7 +339,7 @@ void AlsaVolumeControl::RefreshMixerFds(ScopedAlsaMixer* mixer) { ...@@ -291,7 +339,7 @@ void AlsaVolumeControl::RefreshMixerFds(ScopedAlsaMixer* mixer) {
DCHECK_GT(num_fds, 0); DCHECK_GT(num_fds, 0);
for (int i = 0; i < num_fds; ++i) { for (int i = 0; i < num_fds; ++i) {
auto watcher = auto watcher =
base::MakeUnique<base::MessageLoopForIO::FileDescriptorWatcher>( std::make_unique<base::MessageLoopForIO::FileDescriptorWatcher>(
FROM_HERE); FROM_HERE);
base::MessageLoopForIO::current()->WatchFileDescriptor( base::MessageLoopForIO::current()->WatchFileDescriptor(
pfds[i].fd, true /* persistent */, base::MessageLoopForIO::WATCH_READ, pfds[i].fd, true /* persistent */, base::MessageLoopForIO::WATCH_READ,
...@@ -305,6 +353,10 @@ void AlsaVolumeControl::OnFileCanReadWithoutBlocking(int fd) { ...@@ -305,6 +353,10 @@ void AlsaVolumeControl::OnFileCanReadWithoutBlocking(int fd) {
if (mute_mixer_) { if (mute_mixer_) {
alsa_->MixerHandleEvents(mute_mixer_->mixer); alsa_->MixerHandleEvents(mute_mixer_->mixer);
} }
if (amp_mixer_) {
// amixer locks up if we don't call this for unknown reasons.
alsa_->MixerHandleEvents(amp_mixer_->mixer);
}
} }
void AlsaVolumeControl::OnFileCanWriteWithoutBlocking(int fd) { void AlsaVolumeControl::OnFileCanWriteWithoutBlocking(int fd) {
......
...@@ -30,6 +30,7 @@ class AlsaVolumeControl : public SystemVolumeControl, ...@@ -30,6 +30,7 @@ class AlsaVolumeControl : public SystemVolumeControl,
void SetVolume(float level) override; void SetVolume(float level) override;
bool IsMuted() override; bool IsMuted() override;
void SetMuted(bool muted) override; void SetMuted(bool muted) override;
void SetPowerSave(bool power_save_on) override;
private: private:
class ScopedAlsaMixer; class ScopedAlsaMixer;
...@@ -41,10 +42,14 @@ class AlsaVolumeControl : public SystemVolumeControl, ...@@ -41,10 +42,14 @@ class AlsaVolumeControl : public SystemVolumeControl,
const std::string& mixer_element_name, const std::string& mixer_element_name,
const std::string& mute_card_name); const std::string& mute_card_name);
static std::string GetMuteDeviceName(); static std::string GetMuteDeviceName();
static std::string GetAmpElementName();
static std::string GetAmpDeviceName();
static int VolumeOrMuteChangeCallback(snd_mixer_elem_t* elem, static int VolumeOrMuteChangeCallback(snd_mixer_elem_t* elem,
unsigned int mask); unsigned int mask);
bool SetElementMuted(ScopedAlsaMixer* mixer, bool muted);
void RefreshMixerFds(ScopedAlsaMixer* mixer); void RefreshMixerFds(ScopedAlsaMixer* mixer);
// base::MessageLoopForIO::Watcher implementation: // base::MessageLoopForIO::Watcher implementation:
...@@ -52,6 +57,7 @@ class AlsaVolumeControl : public SystemVolumeControl, ...@@ -52,6 +57,7 @@ class AlsaVolumeControl : public SystemVolumeControl,
void OnFileCanWriteWithoutBlocking(int fd) override; void OnFileCanWriteWithoutBlocking(int fd) override;
void OnVolumeOrMuteChanged(); void OnVolumeOrMuteChanged();
Delegate* const delegate_; Delegate* const delegate_;
const std::unique_ptr<::media::AlsaWrapper> alsa_; const std::unique_ptr<::media::AlsaWrapper> alsa_;
...@@ -59,6 +65,8 @@ class AlsaVolumeControl : public SystemVolumeControl, ...@@ -59,6 +65,8 @@ class AlsaVolumeControl : public SystemVolumeControl,
const std::string volume_mixer_element_name_; const std::string volume_mixer_element_name_;
const std::string mute_mixer_device_name_; const std::string mute_mixer_device_name_;
const std::string mute_mixer_element_name_; const std::string mute_mixer_element_name_;
const std::string amp_mixer_device_name_;
const std::string amp_mixer_element_name_;
long volume_range_min_; // NOLINT(runtime/int) long volume_range_min_; // NOLINT(runtime/int)
long volume_range_max_; // NOLINT(runtime/int) long volume_range_max_; // NOLINT(runtime/int)
...@@ -66,6 +74,7 @@ class AlsaVolumeControl : public SystemVolumeControl, ...@@ -66,6 +74,7 @@ class AlsaVolumeControl : public SystemVolumeControl,
std::unique_ptr<ScopedAlsaMixer> volume_mixer_; std::unique_ptr<ScopedAlsaMixer> volume_mixer_;
std::unique_ptr<ScopedAlsaMixer> mute_mixer_; std::unique_ptr<ScopedAlsaMixer> mute_mixer_;
ScopedAlsaMixer* mute_mixer_ptr_; ScopedAlsaMixer* mute_mixer_ptr_;
std::unique_ptr<ScopedAlsaMixer> amp_mixer_;
std::vector<std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher>> std::vector<std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher>>
file_descriptor_watchers_; file_descriptor_watchers_;
......
...@@ -41,5 +41,9 @@ void FuchsiaVolumeControl::SetMuted(bool muted) { ...@@ -41,5 +41,9 @@ void FuchsiaVolumeControl::SetMuted(bool muted) {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
void FuchsiaVolumeControl::SetPowerSave(bool power_save_on) {
NOTIMPLEMENTED();
}
} // namespace media } // namespace media
} // namespace chromecast } // namespace chromecast
...@@ -24,6 +24,7 @@ class FuchsiaVolumeControl : public SystemVolumeControl { ...@@ -24,6 +24,7 @@ class FuchsiaVolumeControl : public SystemVolumeControl {
void SetVolume(float level) override; void SetVolume(float level) override;
bool IsMuted() override; bool IsMuted() override;
void SetMuted(bool muted) override; void SetMuted(bool muted) override;
void SetPowerSave(bool power_save_on) override;
private: private:
DISALLOW_COPY_AND_ASSIGN(FuchsiaVolumeControl); DISALLOW_COPY_AND_ASSIGN(FuchsiaVolumeControl);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/location.h" #include "base/location.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "chromecast/chromecast_features.h" #include "chromecast/chromecast_features.h"
#include "chromecast/media/cma/backend/audio_decoder_wrapper.h" #include "chromecast/media/cma/backend/audio_decoder_wrapper.h"
#include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h" #include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h"
...@@ -28,17 +30,23 @@ ...@@ -28,17 +30,23 @@
namespace chromecast { namespace chromecast {
namespace media { namespace media {
namespace { namespace {
#if BUILDFLAG(IS_CAST_AUDIO_ONLY) #if BUILDFLAG(IS_CAST_AUDIO_ONLY)
constexpr int kAudioDecoderLimit = std::numeric_limits<int>::max(); constexpr int kAudioDecoderLimit = std::numeric_limits<int>::max();
#else #else
constexpr int kAudioDecoderLimit = 1; constexpr int kAudioDecoderLimit = 1;
#endif #endif
constexpr base::TimeDelta kPowerSaveWaitTime = base::TimeDelta::FromSeconds(5);
} // namespace } // namespace
MediaPipelineBackendManager::MediaPipelineBackendManager( MediaPipelineBackendManager::MediaPipelineBackendManager(
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner) scoped_refptr<base::SingleThreadTaskRunner> media_task_runner)
: media_task_runner_(std::move(media_task_runner)), : media_task_runner_(std::move(media_task_runner)),
playing_audio_streams_count_(0),
playing_noneffects_audio_streams_count_(0), playing_noneffects_audio_streams_count_(0),
allow_volume_feedback_observers_( allow_volume_feedback_observers_(
new base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>()), new base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>()),
...@@ -86,9 +94,29 @@ void MediaPipelineBackendManager::DecrementDecoderCount(DecoderType type) { ...@@ -86,9 +94,29 @@ void MediaPipelineBackendManager::DecrementDecoderCount(DecoderType type) {
decoder_count_[type]--; decoder_count_[type]--;
} }
void MediaPipelineBackendManager::UpdatePlayingAudioCount(int change) { void MediaPipelineBackendManager::UpdatePlayingAudioCount(bool sfx,
int change) {
DCHECK(change == -1 || change == 1) << "bad count change: " << change; DCHECK(change == -1 || change == 1) << "bad count change: " << change;
bool had_playing_audio_streams = (playing_audio_streams_count_ > 0);
playing_audio_streams_count_ += change;
DCHECK_GE(playing_audio_streams_count_, 0);
if (VolumeControl::SetPowerSaveMode) {
if (playing_audio_streams_count_ == 0) {
power_save_timer_.Start(FROM_HERE, kPowerSaveWaitTime, this,
&MediaPipelineBackendManager::EnterPowerSaveMode);
} else if (!had_playing_audio_streams && playing_audio_streams_count_ > 0) {
power_save_timer_.Stop();
metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction(
"Cast.Platform.VolumeControl.PowerSaveOff");
VolumeControl::SetPowerSaveMode(false);
}
}
if (sfx) {
return;
}
// Volume feedback sounds are only allowed when there are no non-effects // Volume feedback sounds are only allowed when there are no non-effects
// audio streams playing. // audio streams playing.
bool prev_allow_feedback = (playing_noneffects_audio_streams_count_ == 0); bool prev_allow_feedback = (playing_noneffects_audio_streams_count_ == 0);
...@@ -103,6 +131,14 @@ void MediaPipelineBackendManager::UpdatePlayingAudioCount(int change) { ...@@ -103,6 +131,14 @@ void MediaPipelineBackendManager::UpdatePlayingAudioCount(int change) {
} }
} }
void MediaPipelineBackendManager::EnterPowerSaveMode() {
DCHECK_EQ(playing_audio_streams_count_, 0);
DCHECK(VolumeControl::SetPowerSaveMode);
metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction(
"Cast.Platform.VolumeControl.PowerSaveOn");
VolumeControl::SetPowerSaveMode(true);
}
void MediaPipelineBackendManager::AddAllowVolumeFeedbackObserver( void MediaPipelineBackendManager::AddAllowVolumeFeedbackObserver(
AllowVolumeFeedbackObserver* observer) { AllowVolumeFeedbackObserver* observer) {
allow_volume_feedback_observers_->AddObserver(observer); allow_volume_feedback_observers_->AddObserver(observer);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list_threadsafe.h" #include "base/observer_list_threadsafe.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/timer/timer.h"
#include "chromecast/public/media/media_pipeline_backend.h" #include "chromecast/public/media/media_pipeline_backend.h"
#include "chromecast/public/media/media_pipeline_device_params.h" #include "chromecast/public/media/media_pipeline_device_params.h"
...@@ -129,13 +130,18 @@ class MediaPipelineBackendManager { ...@@ -129,13 +130,18 @@ class MediaPipelineBackendManager {
void DecrementDecoderCount(DecoderType type); void DecrementDecoderCount(DecoderType type);
// Update the count of playing non-effects audio streams. // Update the count of playing non-effects audio streams.
void UpdatePlayingAudioCount(int change); void UpdatePlayingAudioCount(bool sfx, int change);
void EnterPowerSaveMode();
const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
// Total count of decoders created // Total count of decoders created
int decoder_count_[NUM_DECODER_TYPES]; int decoder_count_[NUM_DECODER_TYPES];
// Total number of playing audio streams.
int playing_audio_streams_count_;
// Total number of playing non-effects streams. // Total number of playing non-effects streams.
int playing_noneffects_audio_streams_count_; int playing_noneffects_audio_streams_count_;
...@@ -147,6 +153,8 @@ class MediaPipelineBackendManager { ...@@ -147,6 +153,8 @@ class MediaPipelineBackendManager {
BufferDelegate* buffer_delegate_; BufferDelegate* buffer_delegate_;
base::OneShotTimer power_save_timer_;
base::WeakPtrFactory<MediaPipelineBackendManager> weak_factory_; base::WeakPtrFactory<MediaPipelineBackendManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendManager); DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendManager);
......
...@@ -39,8 +39,8 @@ MediaPipelineBackendWrapper::~MediaPipelineBackendWrapper() { ...@@ -39,8 +39,8 @@ MediaPipelineBackendWrapper::~MediaPipelineBackendWrapper() {
if (playing_) { if (playing_) {
LOG(WARNING) << "Destroying media backend while still in 'playing' state"; LOG(WARNING) << "Destroying media backend while still in 'playing' state";
if (audio_decoder_ && !IsSfx()) { if (audio_decoder_) {
backend_manager_->UpdatePlayingAudioCount(-1); backend_manager_->UpdatePlayingAudioCount(IsSfx(), -1);
} }
} }
} }
...@@ -136,8 +136,8 @@ void MediaPipelineBackendWrapper::SetPlaying(bool playing) { ...@@ -136,8 +136,8 @@ void MediaPipelineBackendWrapper::SetPlaying(bool playing) {
return; return;
} }
playing_ = playing; playing_ = playing;
if (audio_decoder_ && !IsSfx()) { if (audio_decoder_) {
backend_manager_->UpdatePlayingAudioCount(playing_ ? 1 : -1); backend_manager_->UpdatePlayingAudioCount(IsSfx(), (playing_ ? 1 : -1));
} }
} }
......
...@@ -53,6 +53,9 @@ class SystemVolumeControl { ...@@ -53,6 +53,9 @@ class SystemVolumeControl {
// Sets the system mute state to |muted|. // Sets the system mute state to |muted|.
virtual void SetMuted(bool muted) = 0; virtual void SetMuted(bool muted) = 0;
// Sets the system power save state to |power_save_on|.
virtual void SetPowerSave(bool power_save_on) = 0;
private: private:
DISALLOW_COPY_AND_ASSIGN(SystemVolumeControl); DISALLOW_COPY_AND_ASSIGN(SystemVolumeControl);
}; };
......
...@@ -125,8 +125,8 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -125,8 +125,8 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
thread_.StartWithOptions(options); thread_.StartWithOptions(options);
thread_.task_runner()->PostTask( thread_.task_runner()->PostTask(
FROM_HERE, base::Bind(&VolumeControlInternal::InitializeOnThread, FROM_HERE, base::BindOnce(&VolumeControlInternal::InitializeOnThread,
base::Unretained(this))); base::Unretained(this)));
initialize_complete_event_.Wait(); initialize_complete_event_.Wait();
} }
...@@ -152,9 +152,9 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -152,9 +152,9 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
void SetVolume(AudioContentType type, float level) { void SetVolume(AudioContentType type, float level) {
level = std::max(0.0f, std::min(level, 1.0f)); level = std::max(0.0f, std::min(level, 1.0f));
thread_.task_runner()->PostTask( thread_.task_runner()->PostTask(
FROM_HERE, base::Bind(&VolumeControlInternal::SetVolumeOnThread, FROM_HERE, base::BindOnce(&VolumeControlInternal::SetVolumeOnThread,
base::Unretained(this), type, level, base::Unretained(this), type, level,
false /* from_system */)); false /* from_system */));
} }
bool IsMuted(AudioContentType type) { bool IsMuted(AudioContentType type) {
...@@ -164,9 +164,9 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -164,9 +164,9 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
void SetMuted(AudioContentType type, bool muted) { void SetMuted(AudioContentType type, bool muted) {
thread_.task_runner()->PostTask( thread_.task_runner()->PostTask(
FROM_HERE, base::Bind(&VolumeControlInternal::SetMutedOnThread, FROM_HERE, base::BindOnce(&VolumeControlInternal::SetMutedOnThread,
base::Unretained(this), type, muted, base::Unretained(this), type, muted,
false /* from_system */)); false /* from_system */));
} }
void SetOutputLimit(AudioContentType type, float limit) { void SetOutputLimit(AudioContentType type, float limit) {
...@@ -178,6 +178,13 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -178,6 +178,13 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
type, DbFsToScale(VolumeControl::VolumeToDbFS(limit))); type, DbFsToScale(VolumeControl::VolumeToDbFS(limit)));
} }
void SetPowerSaveMode(bool power_save_on) {
thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&VolumeControlInternal::SetPowerSaveModeOnThread,
base::Unretained(this), power_save_on));
}
private: private:
void InitializeOnThread() { void InitializeOnThread() {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
...@@ -276,8 +283,15 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -276,8 +283,15 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
} }
} }
void SetPowerSaveModeOnThread(bool power_save_on) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread());
system_volume_control_->SetPowerSave(power_save_on);
}
// SystemVolumeControl::Delegate implementation: // SystemVolumeControl::Delegate implementation:
void OnSystemVolumeOrMuteChange(float new_volume, bool new_mute) override { void OnSystemVolumeOrMuteChange(float new_volume, bool new_mute) override {
LOG(INFO) << "System volume/mute change, new volume = " << new_volume
<< ", new mute = " << new_mute;
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
SetVolumeOnThread(AudioContentType::kMedia, new_volume, SetVolumeOnThread(AudioContentType::kMedia, new_volume,
true /* from_system */); true /* from_system */);
...@@ -364,5 +378,10 @@ float VolumeControl::DbFSToVolume(float db) { ...@@ -364,5 +378,10 @@ float VolumeControl::DbFSToVolume(float db) {
return g_volume_map.Get().DbFSToVolume(db); return g_volume_map.Get().DbFSToVolume(db);
} }
// static
void VolumeControl::SetPowerSaveMode(bool power_save_on) {
g_volume_control.Get().SetPowerSaveMode(power_save_on);
}
} // namespace media } // namespace media
} // namespace chromecast } // namespace chromecast
...@@ -87,6 +87,11 @@ class CHROMECAST_EXPORT VolumeControl { ...@@ -87,6 +87,11 @@ class CHROMECAST_EXPORT VolumeControl {
// May be called from multiple processes. // May be called from multiple processes.
static float VolumeToDbFS(float volume) __attribute__((__weak__)); static float VolumeToDbFS(float volume) __attribute__((__weak__));
static float DbFSToVolume(float dbfs) __attribute__((__weak__)); static float DbFSToVolume(float dbfs) __attribute__((__weak__));
// Called to enable power save mode when no audio is being played
// (|power_save_on| will be true in this case), and to disable power save mode
// when audio playback resumes (|power_save_on| will be false).
static void SetPowerSaveMode(bool power_save_on) __attribute__((__weak__));
}; };
} // namespace media } // namespace media
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment