diff options
author | tianyuwang <tianyuwang@google.com> | 2016-03-04 13:32:44 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-04 21:33:53 +0000 |
commit | f2c223f01a8ba53630032eb0382e897a86bfe950 (patch) | |
tree | 61bb16e70e93eb1bbaf9cd800f56bfdaa907aa1a /chromecast | |
parent | d4a38f731dd79b849d74f88215488a506f943464 (diff) | |
download | chromium_src-f2c223f01a8ba53630032eb0382e897a86bfe950.zip chromium_src-f2c223f01a8ba53630032eb0382e897a86bfe950.tar.gz chromium_src-f2c223f01a8ba53630032eb0382e897a86bfe950.tar.bz2 |
[Chromecast] Add volume control for different audio stream types.
BUG=internal b/26163065
Review URL: https://codereview.chromium.org/1733203002
Cr-Commit-Position: refs/heads/master@{#379363}
Diffstat (limited to 'chromecast')
-rw-r--r-- | chromecast/browser/media/cma_media_pipeline_client.cc | 4 | ||||
-rw-r--r-- | chromecast/media/audio/BUILD.gn | 1 | ||||
-rw-r--r-- | chromecast/media/audio/cast_audio_manager.cc | 3 | ||||
-rw-r--r-- | chromecast/media/cma/backend/BUILD.gn | 8 | ||||
-rw-r--r-- | chromecast/media/cma/backend/audio_decoder_wrapper.cc | 55 | ||||
-rw-r--r-- | chromecast/media/cma/backend/audio_decoder_wrapper.h | 41 | ||||
-rw-r--r-- | chromecast/media/cma/backend/media_pipeline_backend_manager.cc | 98 | ||||
-rw-r--r-- | chromecast/media/cma/backend/media_pipeline_backend_manager.h | 72 | ||||
-rw-r--r-- | chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc | 89 | ||||
-rw-r--r-- | chromecast/media/cma/backend/media_pipeline_backend_wrapper.h | 59 | ||||
-rw-r--r-- | chromecast/media/media.gyp | 6 |
11 files changed, 434 insertions, 2 deletions
diff --git a/chromecast/browser/media/cma_media_pipeline_client.cc b/chromecast/browser/media/cma_media_pipeline_client.cc index a62e1ec..e91f513 100644 --- a/chromecast/browser/media/cma_media_pipeline_client.cc +++ b/chromecast/browser/media/cma_media_pipeline_client.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chromecast/browser/media/cma_media_pipeline_client.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" #include "chromecast/public/cast_media_shlib.h" namespace chromecast { @@ -17,7 +18,8 @@ CmaMediaPipelineClient::~CmaMediaPipelineClient() {} scoped_ptr<MediaPipelineBackend> CmaMediaPipelineClient::CreateMediaPipelineBackend( const MediaPipelineDeviceParams& params) { - return make_scoped_ptr(CastMediaShlib::CreateMediaPipelineBackend(params)); + return make_scoped_ptr( + MediaPipelineBackendManager::CreateMediaPipelineBackend(params)); } void CmaMediaPipelineClient::OnMediaPipelineBackendCreated() { diff --git a/chromecast/media/audio/BUILD.gn b/chromecast/media/audio/BUILD.gn index 4aeeb38..149a664 100644 --- a/chromecast/media/audio/BUILD.gn +++ b/chromecast/media/audio/BUILD.gn @@ -16,6 +16,7 @@ source_set("audio") { "//base", "//chromecast/base", "//chromecast/media/base", + "//chromecast/media/cma/backend", "//chromecast/media/cma/base", "//chromecast/public/media", "//media", diff --git a/chromecast/media/audio/cast_audio_manager.cc b/chromecast/media/audio/cast_audio_manager.cc index eaed754..3a1e21c 100644 --- a/chromecast/media/audio/cast_audio_manager.cc +++ b/chromecast/media/audio/cast_audio_manager.cc @@ -6,6 +6,7 @@ #include "chromecast/media/audio/cast_audio_output_stream.h" #include "chromecast/media/base/media_message_loop.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" #include "chromecast/public/cast_media_shlib.h" #include "chromecast/public/media/media_pipeline_backend.h" @@ -63,7 +64,7 @@ scoped_ptr<MediaPipelineBackend> CastAudioManager::CreateMediaPipelineBackend( DCHECK(media::MediaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); return scoped_ptr<MediaPipelineBackend>( - CastMediaShlib::CreateMediaPipelineBackend(params)); + MediaPipelineBackendManager::CreateMediaPipelineBackend(params)); } ::media::AudioOutputStream* CastAudioManager::MakeLinearOutputStream( diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn index fc72d02..9e851ff 100644 --- a/chromecast/media/cma/backend/BUILD.gn +++ b/chromecast/media/cma/backend/BUILD.gn @@ -6,8 +6,14 @@ source_set("backend") { sources = [ "audio_decoder_default.cc", "audio_decoder_default.h", + "audio_decoder_wrapper.cc", + "audio_decoder_wrapper.h", "media_pipeline_backend_default.cc", "media_pipeline_backend_default.h", + "media_pipeline_backend_manager.cc", + "media_pipeline_backend_manager.h", + "media_pipeline_backend_wrapper.cc", + "media_pipeline_backend_wrapper.h", "video_decoder_default.cc", "video_decoder_default.h", ] @@ -19,5 +25,7 @@ source_set("backend") { deps = [ "//base", + "//chromecast/base", + "//chromecast/media/base", ] } diff --git a/chromecast/media/cma/backend/audio_decoder_wrapper.cc b/chromecast/media/cma/backend/audio_decoder_wrapper.cc new file mode 100644 index 0000000..eff40d3 --- /dev/null +++ b/chromecast/media/cma/backend/audio_decoder_wrapper.cc @@ -0,0 +1,55 @@ +// Copyright 2016 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. + +#include "chromecast/media/cma/backend/audio_decoder_wrapper.h" + +#include "base/logging.h" + +namespace chromecast { +namespace media { + +AudioDecoderWrapper::AudioDecoderWrapper( + MediaPipelineBackend::AudioDecoder* audio_decoder) + : audio_decoder_(audio_decoder), + stream_type_volume_(1.0), + stream_volume_(1.0) { + DCHECK(audio_decoder_); +} + +AudioDecoderWrapper::~AudioDecoderWrapper() { +} + +void AudioDecoderWrapper::SetDelegate(Delegate* delegate) { + audio_decoder_->SetDelegate(delegate); +} + +MediaPipelineBackend::BufferStatus AudioDecoderWrapper::PushBuffer( + CastDecoderBuffer* buffer) { + return audio_decoder_->PushBuffer(buffer); +} + +void AudioDecoderWrapper::GetStatistics(Statistics* statistics) { + audio_decoder_->GetStatistics(statistics); +} + +bool AudioDecoderWrapper::SetConfig(const AudioConfig& config) { + return audio_decoder_->SetConfig(config); +} + +bool AudioDecoderWrapper::SetVolume(float multiplier) { + stream_volume_ = multiplier; + return audio_decoder_->SetVolume(stream_volume_ * stream_type_volume_); +} + +AudioDecoderWrapper::RenderingDelay AudioDecoderWrapper::GetRenderingDelay() { + return audio_decoder_->GetRenderingDelay(); +} + +bool AudioDecoderWrapper::SetStreamTypeVolume(float stream_type_volume) { + stream_type_volume_ = stream_type_volume; + return audio_decoder_->SetVolume(stream_volume_ * stream_type_volume_); +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/backend/audio_decoder_wrapper.h b/chromecast/media/cma/backend/audio_decoder_wrapper.h new file mode 100644 index 0000000..dc4d3b8 --- /dev/null +++ b/chromecast/media/cma/backend/audio_decoder_wrapper.h @@ -0,0 +1,41 @@ +// Copyright 2016 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_AUDIO_DECODER_WRAPPER_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_AUDIO_DECODER_WRAPPER_H_ + +#include "base/macros.h" +#include "chromecast/public/media/media_pipeline_backend.h" + +namespace chromecast { +namespace media { + +class AudioDecoderWrapper : public MediaPipelineBackend::AudioDecoder { + public: + AudioDecoderWrapper(MediaPipelineBackend::AudioDecoder* audio_decoder); + ~AudioDecoderWrapper() override; + + // MediaPipelineBackend::AudioDecoder implementation: + void SetDelegate(Delegate* delegate) override; + MediaPipelineBackend::BufferStatus PushBuffer( + CastDecoderBuffer* buffer) override; + void GetStatistics(Statistics* statistics) override; + bool SetConfig(const AudioConfig& config) override; + bool SetVolume(float multiplier) override; + RenderingDelay GetRenderingDelay() override; + + bool SetStreamTypeVolume(float stream_type_volume); + + private: + MediaPipelineBackend::AudioDecoder* const audio_decoder_; + float stream_type_volume_; + float stream_volume_; + + DISALLOW_COPY_AND_ASSIGN(AudioDecoderWrapper); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_AUDIO_DECODER_WRAPPER_H_ diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc new file mode 100644 index 0000000..d0db5ad --- /dev/null +++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc @@ -0,0 +1,98 @@ +// Copyright 2016 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. + +#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" + +#include <algorithm> + +#include "base/bind.h" +#include "base/lazy_instance.h" +#include "base/location.h" +#include "chromecast/media/base/media_message_loop.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h" +#include "chromecast/public/cast_media_shlib.h" + +namespace chromecast { +namespace media { + +namespace { + +base::LazyInstance<MediaPipelineBackendManager> g_instance = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// static +MediaPipelineBackend* MediaPipelineBackendManager::CreateMediaPipelineBackend( + const media::MediaPipelineDeviceParams& params) { + DCHECK(MediaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); + return CreateMediaPipelineBackend(params, 0); +} + +// static +MediaPipelineBackend* MediaPipelineBackendManager::CreateMediaPipelineBackend( + const media::MediaPipelineDeviceParams& params, + int stream_type) { + DCHECK(MediaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); + MediaPipelineBackendManager* backend_manager = Get(); + MediaPipelineBackendWrapper* backend_ptr = new MediaPipelineBackendWrapper( + media::CastMediaShlib::CreateMediaPipelineBackend(params), stream_type, + backend_manager->GetVolumeMultiplier(stream_type)); + backend_manager->media_pipeline_backends_.push_back(backend_ptr); + return backend_ptr; +} + +// static +void MediaPipelineBackendManager::OnMediaPipelineBackendDestroyed( + const MediaPipelineBackend* backend) { + DCHECK(MediaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); + MediaPipelineBackendManager* backend_manager = Get(); + backend_manager->media_pipeline_backends_.erase( + std::remove(backend_manager->media_pipeline_backends_.begin(), + backend_manager->media_pipeline_backends_.end(), backend), + backend_manager->media_pipeline_backends_.end()); +} + +// static +void MediaPipelineBackendManager::SetVolumeMultiplier(int stream_type, + float volume) { + DCHECK(MediaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); + MediaPipelineBackendManager* backend_manager = Get(); + volume = std::max(0.0f, std::min(volume, 1.0f)); + backend_manager->volume_by_stream_type_[stream_type] = volume; + + // Set volume for each open media pipeline backends. + for (auto it = backend_manager->media_pipeline_backends_.begin(); + it != backend_manager->media_pipeline_backends_.end(); it++) { + MediaPipelineBackendWrapper* wrapper = + static_cast<MediaPipelineBackendWrapper*>(*it); + if (wrapper->GetStreamType() == stream_type) + wrapper->SetStreamTypeVolume(volume); + } +} + +// static +MediaPipelineBackendManager* MediaPipelineBackendManager::Get() { + return g_instance.Pointer(); +} + +MediaPipelineBackendManager::MediaPipelineBackendManager() { +} + +MediaPipelineBackendManager::~MediaPipelineBackendManager() { +} + +float MediaPipelineBackendManager::GetVolumeMultiplier(int stream_type) { + DCHECK(MediaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); + MediaPipelineBackendManager* backend_manager = Get(); + auto it = backend_manager->volume_by_stream_type_.find(stream_type); + if (it == backend_manager->volume_by_stream_type_.end()) { + return 1.0; + } else { + return it->second; + } +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.h b/chromecast/media/cma/backend/media_pipeline_backend_manager.h new file mode 100644 index 0000000..890dfc8 --- /dev/null +++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.h @@ -0,0 +1,72 @@ +// Copyright 2016 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_MEDIA_PIPELINE_BACKEND_MANAGER_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_BACKEND_MANAGER_H_ + +#include <map> +#include <vector> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "chromecast/public/media/media_pipeline_backend.h" +#include "chromecast/public/media/media_pipeline_device_params.h" + +namespace base { +template <typename T> +struct DefaultLazyInstanceTraits; +} // namespace base + +namespace chromecast { +namespace media { + +// This class manages created media pipelines, and provides volume control by +// stream type. +// All functions in this class should be called on the media thread. +class MediaPipelineBackendManager { + public: + // Create media pipeline backend. + static MediaPipelineBackend* CreateMediaPipelineBackend( + const MediaPipelineDeviceParams& params); + + // Create media pipeline backend with a specific stream_type. + static MediaPipelineBackend* CreateMediaPipelineBackend( + const MediaPipelineDeviceParams& params, + int stream_type); + + // Internal clean up when a new media pipeline backend is destroyed. + static void OnMediaPipelineBackendDestroyed( + const MediaPipelineBackend* backend); + + // Sets the relative volume for a specified stream type, + // with range [0.0, 1.0] inclusive. If |multiplier| is outside the + // range [0.0, 1.0], it is clamped to that range. + // TODO(tianyuwang): change stream_type to use a enum. + static void SetVolumeMultiplier(int stream_type, float volume); + + private: + friend struct base::DefaultLazyInstanceTraits<MediaPipelineBackendManager>; + + // Returns a pointer to a singleton instance of the + // MediaPipelineBackendManager. + static MediaPipelineBackendManager* Get(); + + MediaPipelineBackendManager(); + ~MediaPipelineBackendManager(); + + float GetVolumeMultiplier(int stream_type); + + // A vector that stores all of the existing media_pipeline_backends_. + std::vector<MediaPipelineBackend*> media_pipeline_backends_; + + // Volume multiplier for each type of audio streams. + std::map<int, float> volume_by_stream_type_; + + DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendManager); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_BACKEND_MANAGER_H_ diff --git a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc new file mode 100644 index 0000000..2cda572 --- /dev/null +++ b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc @@ -0,0 +1,89 @@ +// Copyright 2016 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. + +#include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h" + +#include "base/logging.h" +#include "chromecast/base/task_runner_impl.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" + +namespace chromecast { +namespace media { + +MediaPipelineBackendWrapper::MediaPipelineBackendWrapper( + MediaPipelineBackend* backend, + int stream_type, + float stream_type_volume) + : backend_(backend), + stream_type_(stream_type), + audio_decoder_wrapper_(nullptr), + stream_type_volume_(stream_type_volume), + is_initialized_(false) { + DCHECK(backend_); +} + +MediaPipelineBackendWrapper::~MediaPipelineBackendWrapper() { + MediaPipelineBackendManager::OnMediaPipelineBackendDestroyed(this); +} + +MediaPipelineBackend::AudioDecoder* +MediaPipelineBackendWrapper::CreateAudioDecoder() { + if (audio_decoder_wrapper_) + return nullptr; + + audio_decoder_wrapper_.reset( + new AudioDecoderWrapper(backend_->CreateAudioDecoder())); + return audio_decoder_wrapper_.get(); +} + +MediaPipelineBackend::VideoDecoder* +MediaPipelineBackendWrapper::CreateVideoDecoder() { + return backend_->CreateVideoDecoder(); +} + +bool MediaPipelineBackendWrapper::Initialize() { + is_initialized_ = backend_->Initialize(); + if (is_initialized_) + audio_decoder_wrapper_->SetStreamTypeVolume(stream_type_volume_); + + return is_initialized_; +} + +bool MediaPipelineBackendWrapper::Start(int64_t start_pts) { + return backend_->Start(start_pts); +} + +bool MediaPipelineBackendWrapper::Stop() { + return backend_->Stop(); +} + +bool MediaPipelineBackendWrapper::Pause() { + return backend_->Pause(); +} + +bool MediaPipelineBackendWrapper::Resume() { + return backend_->Resume(); +} + +int64_t MediaPipelineBackendWrapper::GetCurrentPts() { + return backend_->GetCurrentPts(); +} + +bool MediaPipelineBackendWrapper::SetPlaybackRate(float rate) { + return backend_->SetPlaybackRate(rate); +} + +int MediaPipelineBackendWrapper::GetStreamType() const { + return stream_type_; +} + +void MediaPipelineBackendWrapper::SetStreamTypeVolume( + float stream_type_volume) { + stream_type_volume_ = stream_type_volume; + if (is_initialized_ && audio_decoder_wrapper_) + audio_decoder_wrapper_->SetStreamTypeVolume(stream_type_volume_); +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h new file mode 100644 index 0000000..f2befb8 --- /dev/null +++ b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h @@ -0,0 +1,59 @@ +// Copyright 2016 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_MEDIA_PIPELINE_BACKEND_WRAPPER_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_BACKEND_WRAPPER_H_ + +#include <stdint.h> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "chromecast/media/cma/backend/audio_decoder_wrapper.h" +#include "chromecast/public/media/media_pipeline_backend.h" +#include "chromecast/public/media/media_pipeline_device_params.h" + +namespace base { +class SingleThreadTaskRunner; +} // namespace base + +namespace chromecast { +namespace media { + +class MediaPipelineBackendWrapper : public MediaPipelineBackend { + public: + MediaPipelineBackendWrapper(MediaPipelineBackend* backend, + int stream_type, + float stream_type_volume); + ~MediaPipelineBackendWrapper() override; + + // MediaPipelineBackend implementation: + AudioDecoder* CreateAudioDecoder() override; + VideoDecoder* CreateVideoDecoder() override; + bool Initialize() override; + bool Start(int64_t start_pts) override; + bool Stop() override; + bool Pause() override; + bool Resume() override; + int64_t GetCurrentPts() override; + bool SetPlaybackRate(float rate) override; + + int GetStreamType() const; + void SetStreamTypeVolume(float stream_type_volume); + + private: + scoped_ptr<MediaPipelineBackend> backend_; + const int stream_type_; + scoped_ptr<AudioDecoderWrapper> audio_decoder_wrapper_; + float stream_type_volume_; + bool is_initialized_; + + DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendWrapper); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_BACKEND_WRAPPER_H_ diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp index 1430fe5..51a772c 100644 --- a/chromecast/media/media.gyp +++ b/chromecast/media/media.gyp @@ -156,8 +156,14 @@ 'sources': [ 'cma/backend/audio_decoder_default.cc', 'cma/backend/audio_decoder_default.h', + 'cma/backend/audio_decoder_wrapper.cc', + 'cma/backend/audio_decoder_wrapper.h', 'cma/backend/media_pipeline_backend_default.cc', 'cma/backend/media_pipeline_backend_default.h', + 'cma/backend/media_pipeline_backend_manager.cc', + 'cma/backend/media_pipeline_backend_manager.h', + 'cma/backend/media_pipeline_backend_wrapper.cc', + 'cma/backend/media_pipeline_backend_wrapper.h', 'cma/backend/video_decoder_default.cc', 'cma/backend/video_decoder_default.h', ], |