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

[Chromecast] Move global volume multiplier into VolumeControl

This simplifies the implementation.

Merge-With: eureka-internal/318940
Change-Id: I9fda9de4432e67ad4d4ad82823ed57654aca8328
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1829764
Commit-Queue: Kenneth MacKay <kmackay@chromium.org>
Reviewed-by: default avatarYuchen Liu <yucliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700899}
parent 2584db31
......@@ -24,7 +24,6 @@ cast_source_set("backend") {
"cma_backend_factory.h",
"cma_backend_factory_impl.cc",
"cma_backend_factory_impl.h",
"extra_audio_stream.h",
"media_pipeline_backend_manager.cc",
"media_pipeline_backend_manager.h",
"media_pipeline_backend_wrapper.cc",
......
......@@ -54,21 +54,15 @@ class RevokedAudioDecoderWrapper : public DestructableAudioDecoder {
} // namespace
ActiveAudioDecoderWrapper::ActiveAudioDecoderWrapper(
MediaPipelineBackendManager* backend_manager,
MediaPipelineBackend::AudioDecoder* backend_decoder,
AudioContentType type,
MediaPipelineBackendManager::BufferDelegate* buffer_delegate)
: backend_manager_(backend_manager),
decoder_(backend_decoder),
: decoder_(backend_decoder),
content_type_(type),
buffer_delegate_(buffer_delegate),
initialized_(false),
delegate_active_(false),
global_volume_multiplier_(1.0f),
stream_volume_multiplier_(1.0f) {
DCHECK(backend_manager_);
backend_manager_->AddAudioDecoder(this);
if (buffer_delegate_) {
buffer_delegate_->OnStreamStarted();
}
......@@ -78,27 +72,12 @@ ActiveAudioDecoderWrapper::~ActiveAudioDecoderWrapper() {
if (buffer_delegate_) {
buffer_delegate_->OnStreamStopped();
}
backend_manager_->RemoveAudioDecoder(this);
}
void ActiveAudioDecoderWrapper::OnInitialized() {
initialized_ = true;
if (!delegate_active_) {
float volume = stream_volume_multiplier_ * global_volume_multiplier_;
decoder_.SetVolume(volume);
}
}
void ActiveAudioDecoderWrapper::SetGlobalVolumeMultiplier(float multiplier) {
global_volume_multiplier_ = multiplier;
if (!delegate_active_) {
float volume = stream_volume_multiplier_ * global_volume_multiplier_;
if (initialized_) {
decoder_.SetVolume(volume);
}
if (buffer_delegate_) {
buffer_delegate_->OnSetVolume(volume);
}
decoder_.SetVolume(stream_volume_multiplier_);
}
}
......@@ -119,8 +98,7 @@ CmaBackend::BufferStatus ActiveAudioDecoderWrapper::PushBuffer(
// Restore original volume.
if (delegate_active_) {
delegate_active_ = false;
if (!decoder_.SetVolume(stream_volume_multiplier_ *
global_volume_multiplier_)) {
if (!decoder_.SetVolume(stream_volume_multiplier_)) {
LOG(ERROR) << "SetVolume failed";
}
}
......@@ -142,15 +120,14 @@ bool ActiveAudioDecoderWrapper::SetConfig(const AudioConfig& config) {
bool ActiveAudioDecoderWrapper::SetVolume(float multiplier) {
stream_volume_multiplier_ = std::max(0.0f, multiplier);
float volume = stream_volume_multiplier_ * global_volume_multiplier_;
if (buffer_delegate_) {
buffer_delegate_->OnSetVolume(volume);
buffer_delegate_->OnSetVolume(stream_volume_multiplier_);
}
if (delegate_active_ || !initialized_) {
return true;
}
return decoder_.SetVolume(volume);
return decoder_.SetVolume(stream_volume_multiplier_);
}
ActiveAudioDecoderWrapper::RenderingDelay
......@@ -169,13 +146,12 @@ bool ActiveAudioDecoderWrapper::RequiresDecryption() {
}
AudioDecoderWrapper::AudioDecoderWrapper(
MediaPipelineBackendManager* backend_manager,
MediaPipelineBackend::AudioDecoder* backend_decoder,
AudioContentType type,
MediaPipelineBackendManager::BufferDelegate* buffer_delegate)
: decoder_revoked_(false) {
audio_decoder_ = std::make_unique<ActiveAudioDecoderWrapper>(
backend_manager, backend_decoder, type, buffer_delegate);
backend_decoder, type, buffer_delegate);
}
AudioDecoderWrapper::AudioDecoderWrapper(AudioContentType type)
......
......@@ -30,13 +30,11 @@ class DestructableAudioDecoder : public CmaBackend::AudioDecoder {
class ActiveAudioDecoderWrapper : public DestructableAudioDecoder {
public:
ActiveAudioDecoderWrapper(
MediaPipelineBackendManager* backend_manager,
MediaPipelineBackend::AudioDecoder* backend_decoder,
AudioContentType type,
MediaPipelineBackendManager::BufferDelegate* buffer_delegate);
~ActiveAudioDecoderWrapper() override;
void SetGlobalVolumeMultiplier(float multiplier);
AudioContentType content_type() const { return content_type_; }
private:
......@@ -50,7 +48,6 @@ class ActiveAudioDecoderWrapper : public DestructableAudioDecoder {
void GetStatistics(Statistics* statistics) override;
bool RequiresDecryption() override;
MediaPipelineBackendManager* const backend_manager_;
AudioDecoderSoftwareWrapper decoder_;
const AudioContentType content_type_;
......@@ -58,7 +55,6 @@ class ActiveAudioDecoderWrapper : public DestructableAudioDecoder {
bool initialized_;
bool delegate_active_;
float global_volume_multiplier_;
float stream_volume_multiplier_;
scoped_refptr<DecoderBufferBase> pushed_buffer_;
......@@ -70,7 +66,6 @@ class AudioDecoderWrapper : public CmaBackend::AudioDecoder {
public:
// Create a functional "real" AudioDecoder.
AudioDecoderWrapper(
MediaPipelineBackendManager* backend_manager,
MediaPipelineBackend::AudioDecoder* backend_decoder,
AudioContentType type,
MediaPipelineBackendManager::BufferDelegate* buffer_delegate);
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_MEDIA_CMA_BACKEND_EXTRA_AUDIO_STREAM_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_EXTRA_AUDIO_STREAM_H_
namespace chromecast {
namespace media {
class ExtraAudioStream {
public:
virtual void SetGlobalVolumeMultiplier(float multiplier) = 0;
protected:
virtual ~ExtraAudioStream() = default;
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_CMA_BACKEND_EXTRA_AUDIO_STREAM_H_
......@@ -15,7 +15,6 @@
#include "chromecast/chromecast_buildflags.h"
#include "chromecast/media/cma/backend/audio_decoder_wrapper.h"
#include "chromecast/media/cma/backend/cma_backend.h"
#include "chromecast/media/cma/backend/extra_audio_stream.h"
#include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h"
#include "chromecast/public/volume_control.h"
......@@ -55,10 +54,6 @@ MediaPipelineBackendManager::MediaPipelineBackendManager(
{AudioContentType::kOther, 0}}),
allow_volume_feedback_observers_(
new base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>()),
global_volume_multipliers_({{AudioContentType::kMedia, 1.0f},
{AudioContentType::kAlarm, 1.0f},
{AudioContentType::kCommunication, 1.0f},
{AudioContentType::kOther, 1.0f}}),
backend_wrapper_using_video_decoder_(nullptr),
buffer_delegate_(nullptr),
weak_factory_(this) {
......@@ -67,8 +62,6 @@ MediaPipelineBackendManager::MediaPipelineBackendManager(
static_cast<unsigned long>(AudioContentType::kNumTypes));
DCHECK(playing_noneffects_audio_streams_count_.size() ==
static_cast<unsigned long>(AudioContentType::kNumTypes));
DCHECK(global_volume_multipliers_.size() ==
static_cast<unsigned long>(AudioContentType::kNumTypes));
for (int i = 0; i < NUM_DECODER_TYPES; ++i) {
decoder_count_[i] = 0;
}
......@@ -206,39 +199,16 @@ void MediaPipelineBackendManager::RemoveAllowVolumeFeedbackObserver(
void MediaPipelineBackendManager::AddExtraPlayingStream(
bool sfx,
const AudioContentType type,
ExtraAudioStream* extra_audio_stream) {
MAKE_SURE_MEDIA_THREAD(AddExtraPlayingStream, sfx, type, extra_audio_stream);
const AudioContentType type) {
MAKE_SURE_MEDIA_THREAD(AddExtraPlayingStream, sfx, type);
UpdatePlayingAudioCount(sfx, type, 1);
if (extra_audio_stream)
extra_audio_streams_[type].emplace(extra_audio_stream);
}
void MediaPipelineBackendManager::RemoveExtraPlayingStream(
bool sfx,
const AudioContentType type,
ExtraAudioStream* extra_audio_stream) {
MAKE_SURE_MEDIA_THREAD(RemoveExtraPlayingStream, sfx, type,
extra_audio_stream);
const AudioContentType type) {
MAKE_SURE_MEDIA_THREAD(RemoveExtraPlayingStream, sfx, type);
UpdatePlayingAudioCount(sfx, type, -1);
if (extra_audio_stream)
extra_audio_streams_[type].erase(extra_audio_stream);
}
void MediaPipelineBackendManager::SetGlobalVolumeMultiplier(
AudioContentType type,
float multiplier) {
MAKE_SURE_MEDIA_THREAD(SetGlobalVolumeMultiplier, type, multiplier);
DCHECK_GE(multiplier, 0.0f);
global_volume_multipliers_[type] = multiplier;
for (auto* a : audio_decoders_) {
if (a->content_type() == type) {
a->SetGlobalVolumeMultiplier(multiplier);
}
}
for (auto* extra_audio_stream : extra_audio_streams_[type]) {
extra_audio_stream->SetGlobalVolumeMultiplier(multiplier);
}
}
void MediaPipelineBackendManager::SetBufferDelegate(
......@@ -258,19 +228,6 @@ bool MediaPipelineBackendManager::IsPlaying(bool include_sfx,
}
}
void MediaPipelineBackendManager::AddAudioDecoder(
ActiveAudioDecoderWrapper* decoder) {
DCHECK(decoder);
audio_decoders_.insert(decoder);
decoder->SetGlobalVolumeMultiplier(
global_volume_multipliers_[decoder->content_type()]);
}
void MediaPipelineBackendManager::RemoveAudioDecoder(
ActiveAudioDecoderWrapper* decoder) {
audio_decoders_.erase(decoder);
}
void MediaPipelineBackendManager::SetPowerSaveEnabled(bool power_save_enabled) {
MAKE_SURE_MEDIA_THREAD(SetPowerSaveEnabled, power_save_enabled);
power_save_enabled_ = power_save_enabled;
......
......@@ -26,9 +26,7 @@ namespace media {
enum class AudioContentType;
class CastDecoderBuffer;
class CmaBackend;
class ExtraAudioStream;
class MediaPipelineBackendWrapper;
class ActiveAudioDecoderWrapper;
class ActiveMediaPipelineBackendWrapper;
// This class tracks all created media backends, tracking whether or not volume
......@@ -116,18 +114,8 @@ class MediaPipelineBackendManager {
// CmaBackend instance (for example, direct audio output using
// CastMediaShlib::AddDirectAudioSource()). |sfx| indicates whether or not
// the stream is a sound effects stream (has no effect on volume feedback).
void AddExtraPlayingStream(bool sfx,
const AudioContentType type,
ExtraAudioStream* extra_audio_stream = nullptr);
void RemoveExtraPlayingStream(bool sfx,
const AudioContentType type,
ExtraAudioStream* extra_audio_stream = nullptr);
// Sets a global multiplier for output volume for streams of the given |type|.
// The multiplier may be any value >= 0; if the resulting volume for an
// individual stream would be > 1.0, that stream's volume is clamped to 1.0.
// The default multiplier is 1.0. May be called on any thread.
void SetGlobalVolumeMultiplier(AudioContentType type, float multiplier);
void AddExtraPlayingStream(bool sfx, const AudioContentType type);
void RemoveExtraPlayingStream(bool sfx, const AudioContentType type);
// |buffer_delegate| will get notified for all buffers on the media stream.
// |buffer_delegate| must outlive |this|.
......@@ -144,10 +132,6 @@ class MediaPipelineBackendManager {
private:
friend class ActiveMediaPipelineBackendWrapper;
friend class ActiveAudioDecoderWrapper;
void AddAudioDecoder(ActiveAudioDecoderWrapper* decoder);
void RemoveAudioDecoder(ActiveAudioDecoderWrapper* decoder);
// Backend wrapper instances must use these APIs when allocating and releasing
// decoder objects, so we can enforce global limit on #concurrent decoders.
......@@ -177,11 +161,6 @@ class MediaPipelineBackendManager {
scoped_refptr<base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>>
allow_volume_feedback_observers_;
base::flat_set<ActiveAudioDecoderWrapper*> audio_decoders_;
base::flat_map<AudioContentType, base::flat_set<ExtraAudioStream*>>
extra_audio_streams_;
base::flat_map<AudioContentType, float> global_volume_multipliers_;
// Previously issued MediaPipelineBackendWrapper that uses a video decoder.
MediaPipelineBackendWrapper* backend_wrapper_using_video_decoder_;
......
......@@ -195,7 +195,7 @@ ActiveMediaPipelineBackendWrapper::CreateAudioDecoderWrapper() {
}
auto audio_decoder = std::make_unique<AudioDecoderWrapper>(
backend_manager_, real_decoder, content_type_, delegate);
real_decoder, content_type_, delegate);
audio_decoder_ptr_ = audio_decoder.get();
return audio_decoder;
}
......
......@@ -6,7 +6,6 @@
#include <algorithm>
#include <cmath>
#include <map>
#include <memory>
#include <string>
#include <utility>
......@@ -14,6 +13,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
......@@ -168,6 +168,24 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
false /* from_system */));
}
void SetVolumeMultiplier(AudioContentType type, float multiplier) {
if (type == AudioContentType::kOther) {
NOTREACHED() << "Can't set volume multiplier for content type kOther";
return;
}
if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
LOG(INFO) << "Ignore global volume multiplier since volume is externally "
<< "controlled";
return;
}
thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&VolumeControlInternal::SetVolumeMultiplierOnThread,
base::Unretained(this), type, multiplier));
}
bool IsMuted(AudioContentType type) {
base::AutoLock lock(volume_lock_);
return muted_[type];
......@@ -214,6 +232,7 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
AudioContentType::kCommunication}) {
CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &dbfs));
volumes_[type] = VolumeControl::DbFSToVolume(dbfs);
volume_multipliers_[type] = 1.0f;
if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
// If ALSA owns volume, our internal mixer should not apply any scaling
// multiplier.
......@@ -251,6 +270,7 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
DCHECK(thread_.task_runner()->BelongsToCurrentThread());
DCHECK(type != AudioContentType::kOther);
DCHECK(!from_system || type == AudioContentType::kMedia);
DCHECK(volume_multipliers_.find(type) != volume_multipliers_.end());
{
base::AutoLock lock(volume_lock_);
......@@ -266,7 +286,8 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
float dbfs = VolumeControl::VolumeToDbFS(level);
if (!BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
StreamMixer::Get()->SetVolume(type, DbFsToScale(dbfs));
StreamMixer::Get()->SetVolume(
type, DbFsToScale(dbfs) * volume_multipliers_[type]);
}
if (!from_system && type == AudioContentType::kMedia) {
......@@ -284,6 +305,17 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
SerializeJsonToFile(storage_path_, stored_values_);
}
void SetVolumeMultiplierOnThread(AudioContentType type, float multiplier) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread());
DCHECK(type != AudioContentType::kOther);
DCHECK(!BUILDFLAG(SYSTEM_OWNS_VOLUME));
volume_multipliers_[type] = multiplier;
float scale =
DbFsToScale(VolumeControl::VolumeToDbFS(volumes_[type])) * multiplier;
StreamMixer::Get()->SetVolume(type, scale);
}
void SetMutedOnThread(VolumeChangeSource source,
AudioContentType type,
bool muted,
......@@ -353,8 +385,9 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
base::DictionaryValue stored_values_;
base::Lock volume_lock_;
std::map<AudioContentType, float> volumes_;
std::map<AudioContentType, bool> muted_;
base::flat_map<AudioContentType, float> volumes_;
base::flat_map<AudioContentType, float> volume_multipliers_;
base::flat_map<AudioContentType, bool> muted_;
base::Lock observer_lock_;
std::vector<VolumeObserver*> volume_observers_;
......@@ -407,6 +440,12 @@ void VolumeControl::SetVolume(VolumeChangeSource source,
GetVolumeControl().SetVolume(source, type, level);
}
// static
void VolumeControl::SetVolumeMultiplier(AudioContentType type,
float multiplier) {
GetVolumeControl().SetVolumeMultiplier(type, multiplier);
}
// static
bool VolumeControl::IsMuted(AudioContentType type) {
return GetVolumeControl().IsMuted(type);
......
......@@ -85,6 +85,11 @@ class CHROMECAST_EXPORT VolumeControl {
AudioContentType type,
float level);
// Sets a multiplier on the attenuation level for a given audio stream type.
// Used for stereo pair balance.
static void SetVolumeMultiplier(AudioContentType type, float multiplier)
__attribute__((weak));
// Gets/sets the mute state for a given audio stream |type|.
// AudioContentType::kOther is not a valid |type| for these methods.
static bool IsMuted(AudioContentType type);
......
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