summaryrefslogtreecommitdiffstats
path: root/chromecast
diff options
context:
space:
mode:
authortianyuwang <tianyuwang@google.com>2016-03-04 13:32:44 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-04 21:33:53 +0000
commitf2c223f01a8ba53630032eb0382e897a86bfe950 (patch)
tree61bb16e70e93eb1bbaf9cd800f56bfdaa907aa1a /chromecast
parentd4a38f731dd79b849d74f88215488a506f943464 (diff)
downloadchromium_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.cc4
-rw-r--r--chromecast/media/audio/BUILD.gn1
-rw-r--r--chromecast/media/audio/cast_audio_manager.cc3
-rw-r--r--chromecast/media/cma/backend/BUILD.gn8
-rw-r--r--chromecast/media/cma/backend/audio_decoder_wrapper.cc55
-rw-r--r--chromecast/media/cma/backend/audio_decoder_wrapper.h41
-rw-r--r--chromecast/media/cma/backend/media_pipeline_backend_manager.cc98
-rw-r--r--chromecast/media/cma/backend/media_pipeline_backend_manager.h72
-rw-r--r--chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc89
-rw-r--r--chromecast/media/cma/backend/media_pipeline_backend_wrapper.h59
-rw-r--r--chromecast/media/media.gyp6
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',
],