Commit 67064cf3 authored by Ryan Keane's avatar Ryan Keane Committed by Commit Bot

[Cast] Add CmaBackend for Proxying Audio Data

This CL adds a new MediaPipelineBackend to allow audio data to be
proxied across an IPC through the MultizoneAudioDecoderProxy. Video data
decoding will not be changed, and should be passed through to the
environment-specific CmaBackend. This change is accomplished through the
use of an environment variable orthogonal to that used for platform type.

After this change, all audio data processed by the AudioPipelineImpl
should be diverted across the IPC, as described in
go/cast-media-chromium-runtime

Bug: b/167425332
Change-Id: Iaefd150bac0b6edf9708c79d4c6d50f2a5eb27ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412558Reviewed-by: default avatarYuchen Liu <yucliu@chromium.org>
Commit-Queue: Ryan Keane <rwkeane@google.com>
Cr-Commit-Position: refs/heads/master@{#809635}
parent 22a5368c
......@@ -613,6 +613,7 @@ buildflag_header("chromecast_buildflags") {
"SUPPORTS_MULTIZONE=$supports_multizone",
"USE_ANDROID_USER_AGENT=$use_android_user_agent",
"USE_CHROMECAST_CDMS=$use_chromecast_cdms",
"ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER=$enable_chromium_runtime_cast_renderer",
]
}
......
......@@ -141,6 +141,9 @@ declare_args() {
# Set to true to forward crashes to the system's crash handler instead of
# handling them internally. This disables the built-in crash handler.
use_system_crash_handler = false
# True to use the Chromium runtime for cast rendering.
enable_chromium_runtime_cast_renderer = false
}
declare_args() {
......
......@@ -51,6 +51,7 @@ cast_source_set("unittests") {
testonly = true
sources = [
"backend/audio_video_pipeline_device_unittest.cc",
"backend/proxy/cma_backend_proxy_unittest.cc",
"base/balanced_media_task_runner_unittest.cc",
"base/buffering_controller_unittest.cc",
"base/buffering_frame_provider_unittest.cc",
......@@ -71,6 +72,7 @@ cast_source_set("unittests") {
"//chromecast/media:libcast_media",
"//chromecast/media/api",
"//chromecast/media/api:test_support",
"//chromecast/media/cma/backend/proxy",
"//media",
"//testing/gmock",
"//testing/gtest",
......
......@@ -44,6 +44,10 @@ cast_source_set("backend") {
"//chromecast/media/cma/decoder",
]
if (enable_chromium_runtime_cast_renderer) {
deps += [ "//chromecast/media/cma/backend/proxy" ]
}
if (have_full_mixer) {
sources += [ "media_pipeline_backend_manager_mixer.cc" ]
deps += [ "//chromecast/media/audio/mixer_service:control_connection" ]
......
......@@ -4,8 +4,12 @@
#include "chromecast/media/cma/backend/cma_backend_factory_impl.h"
#include "chromecast/chromecast_buildflags.h"
#include "chromecast/media/api/cma_backend.h"
#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
#if BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER)
#include "chromecast/media/cma/backend/proxy/cma_backend_proxy.h" // nogncheck
#endif // BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER)
#include "chromecast/public/media/media_pipeline_device_params.h"
namespace chromecast {
......@@ -21,7 +25,14 @@ CmaBackendFactoryImpl::~CmaBackendFactoryImpl() = default;
std::unique_ptr<CmaBackend> CmaBackendFactoryImpl::CreateBackend(
const MediaPipelineDeviceParams& params) {
return media_pipeline_backend_manager_->CreateBackend(params);
std::unique_ptr<CmaBackend> backend =
media_pipeline_backend_manager_->CreateBackend(params);
#if BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER)
backend = std::make_unique<CmaBackendProxy>(std::move(backend));
#endif // BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER)
return backend;
}
} // namespace media
......
......@@ -6,8 +6,11 @@ import("//chromecast/chromecast.gni")
cast_source_set("proxy") {
sources = [
"multizone_audio_decoder_proxy.cc",
"cma_backend_proxy.cc",
"cma_backend_proxy.h",
"multizone_audio_decoder_proxy.h",
"multizone_audio_decoder_proxy_impl.cc",
"multizone_audio_decoder_proxy_impl.h",
]
deps = [
......
// Copyright 2020 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/proxy/cma_backend_proxy.h"
#include <algorithm>
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/notreached.h"
#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h"
#include "chromecast/public/media/decoder_config.h"
namespace chromecast {
namespace media {
namespace {
// The maximum allowed difference between the audio and video decoders used for
// the CmaBackendProxy.
// TODO(b/168748626): Determine the correct value for this variable
// experimentally.
int64_t kMaxAllowedPtsDrift = 500;
} // namespace
CmaBackendProxy::CmaBackendProxy(
std::unique_ptr<CmaBackend> delegated_video_pipeline)
: CmaBackendProxy(
std::move(delegated_video_pipeline),
base::BindOnce([]() -> std::unique_ptr<MultizoneAudioDecoderProxy> {
return std::make_unique<MultizoneAudioDecoderProxyImpl>();
})) {}
CmaBackendProxy::CmaBackendProxy(
std::unique_ptr<CmaBackend> delegated_video_pipeline,
CmaBackendProxy::AudioDecoderFactoryCB audio_decoder_factory)
: delegated_video_pipeline_(std::move(delegated_video_pipeline)),
audio_decoder_factory_(std::move(audio_decoder_factory)) {
DCHECK(delegated_video_pipeline_);
DCHECK(audio_decoder_factory_);
}
CmaBackendProxy::~CmaBackendProxy() = default;
CmaBackend::AudioDecoder* CmaBackendProxy::CreateAudioDecoder() {
DCHECK(!audio_decoder_);
DCHECK(audio_decoder_factory_);
audio_decoder_ = std::move(audio_decoder_factory_).Run();
return audio_decoder_.get();
}
CmaBackend::VideoDecoder* CmaBackendProxy::CreateVideoDecoder() {
has_video_decoder_ = true;
return delegated_video_pipeline_->CreateVideoDecoder();
}
bool CmaBackendProxy::Initialize() {
if (has_video_decoder_ && !delegated_video_pipeline_->Initialize()) {
return false;
}
return !audio_decoder_ || audio_decoder_->Initialize();
}
bool CmaBackendProxy::Start(int64_t start_pts) {
if (has_video_decoder_ && !delegated_video_pipeline_->Start(start_pts)) {
return false;
}
return !audio_decoder_ || audio_decoder_->Start(start_pts);
}
void CmaBackendProxy::Stop() {
if (has_video_decoder_) {
delegated_video_pipeline_->Stop();
}
if (audio_decoder_) {
audio_decoder_->Stop();
}
}
bool CmaBackendProxy::Pause() {
bool result = true;
if (has_video_decoder_) {
result &= delegated_video_pipeline_->Pause();
}
if (audio_decoder_) {
result &= audio_decoder_->Pause();
}
return result;
}
bool CmaBackendProxy::Resume() {
if (has_video_decoder_ && !delegated_video_pipeline_->Resume()) {
return false;
}
return !audio_decoder_ || audio_decoder_->Resume();
}
int64_t CmaBackendProxy::GetCurrentPts() {
if (audio_decoder_ && has_video_decoder_) {
const int64_t audio_pts = audio_decoder_->GetCurrentPts();
const int64_t video_pts = delegated_video_pipeline_->GetCurrentPts();
const int64_t min = std::min(audio_pts, video_pts);
LOG_IF(WARNING, std::max(audio_pts, video_pts) - min > kMaxAllowedPtsDrift);
return min;
} else if (audio_decoder_) {
return audio_decoder_->GetCurrentPts();
} else if (has_video_decoder_) {
return delegated_video_pipeline_->GetCurrentPts();
} else {
return std::numeric_limits<int64_t>::min();
}
}
bool CmaBackendProxy::SetPlaybackRate(float rate) {
bool result = true;
if (has_video_decoder_) {
result &= delegated_video_pipeline_->SetPlaybackRate(rate);
}
if (audio_decoder_) {
result &= audio_decoder_->SetPlaybackRate(rate);
}
return result;
}
void CmaBackendProxy::LogicalPause() {
if (has_video_decoder_) {
delegated_video_pipeline_->LogicalPause();
}
if (audio_decoder_) {
audio_decoder_->LogicalPause();
}
}
void CmaBackendProxy::LogicalResume() {
if (has_video_decoder_) {
delegated_video_pipeline_->LogicalResume();
}
if (audio_decoder_) {
audio_decoder_->LogicalResume();
}
}
} // namespace media
} // namespace chromecast
// Copyright 2020 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_PROXY_CMA_BACKEND_PROXY_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_CMA_BACKEND_PROXY_H_
#include <stdint.h>
#include <memory>
#include "base/callback.h"
#include "base/optional.h"
#include "chromecast/media/api/cma_backend.h"
#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h"
namespace chromecast {
namespace media {
// This class is used to proxy audio data to an external
// CmaBackend::AudioDecoder over gRPC, while delegating video decoding to an
// alternate CMA Backend.
// NOTE: By design, this class does NOT handle a/v sync drift between
// |audio_decoder_| and |delegated_video_pipeline_|.
class CmaBackendProxy : public CmaBackend {
public:
using AudioDecoderFactoryCB =
base::OnceCallback<std::unique_ptr<MultizoneAudioDecoderProxy>()>;
// Creates a new CmaBackendProxy such that all video processing is delegated
// to |delegated_video_pipeline|.
explicit CmaBackendProxy(
std::unique_ptr<CmaBackend> delegated_video_pipeline);
~CmaBackendProxy() override;
// MediaPipelineBackend implementation:
CmaBackend::AudioDecoder* CreateAudioDecoder() override;
CmaBackend::VideoDecoder* CreateVideoDecoder() override;
bool Initialize() override;
bool Start(int64_t start_pts) override;
void Stop() override;
bool Pause() override;
bool Resume() override;
int64_t GetCurrentPts() override;
bool SetPlaybackRate(float rate) override;
void LogicalPause() override;
void LogicalResume() override;
private:
friend class CmaBackendProxyTest;
// Creates a new CmaBackendProxy such that all video processing is delegated
// to |delegated_video_pipeline| and all audio processing is delegated to a
// new MultizoneAudioDecoderProxy created by |audio_decoder_factory|.
CmaBackendProxy(std::unique_ptr<CmaBackend> delegated_video_pipeline,
AudioDecoderFactoryCB audio_decoder_factory);
// The audio decoder to which audio operations should be delegated.
std::unique_ptr<MultizoneAudioDecoderProxy> audio_decoder_;
// The CMA Backend to which all video decoding is delegated.
std::unique_ptr<CmaBackend> delegated_video_pipeline_;
// Determines whether a video decoder is being used. If not, calls should not
// be delegated to the |delegated_video_pipeline_|, as it may not behave as
// expected when neither the audio or video decoders are initialized.
bool has_video_decoder_ = false;
// The factory to use to populate the |audio_decoder_| object when needed.
AudioDecoderFactoryCB audio_decoder_factory_;
DISALLOW_COPY_AND_ASSIGN(CmaBackendProxy);
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_CMA_BACKEND_PROXY_CMA_BACKEND_PROXY_H_
// Copyright 2020 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/proxy/cma_backend_proxy.h"
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "chromecast/media/api/cma_backend.h"
#include "chromecast/media/api/decoder_buffer_base.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Return;
using testing::StrictMock;
namespace chromecast {
namespace media {
namespace {
class MockCmaBackend : public CmaBackend {
public:
MOCK_METHOD0(CreateAudioDecoder, CmaBackend::AudioDecoder*());
MOCK_METHOD0(CreateVideoDecoder, CmaBackend::VideoDecoder*());
MOCK_METHOD0(Initialize, bool());
MOCK_METHOD1(Start, bool(int64_t));
MOCK_METHOD0(Stop, void());
MOCK_METHOD0(Pause, bool());
MOCK_METHOD0(Resume, bool());
MOCK_METHOD0(GetCurrentPts, int64_t());
MOCK_METHOD1(SetPlaybackRate, bool(float rate));
MOCK_METHOD0(LogicalPause, void());
MOCK_METHOD0(LogicalResume, void());
};
class MockMultizoneAudioDecoderProxy : public MultizoneAudioDecoderProxy {
public:
MOCK_METHOD0(Initialize, bool());
MOCK_METHOD1(Start, bool(int64_t));
MOCK_METHOD0(Stop, void());
MOCK_METHOD0(Pause, bool());
MOCK_METHOD0(Resume, bool());
MOCK_CONST_METHOD0(GetCurrentPts, int64_t());
MOCK_METHOD1(SetPlaybackRate, bool(float rate));
MOCK_METHOD0(LogicalPause, void());
MOCK_METHOD0(LogicalResume, void());
MOCK_METHOD1(SetDelegate, void(Delegate*));
MOCK_METHOD1(PushBuffer, BufferStatus(scoped_refptr<DecoderBufferBase>));
MOCK_METHOD1(SetConfig, bool(const AudioConfig&));
MOCK_METHOD1(SetVolume, bool(float));
MOCK_METHOD0(GetRenderingDelay, RenderingDelay());
MOCK_METHOD1(GetStatistics, void(Statistics*));
MOCK_METHOD0(RequiresDecryption, bool());
MOCK_METHOD1(SetObserver, void(Observer*));
};
} // namespace
class CmaBackendProxyTest : public testing::Test {
public:
CmaBackendProxyTest() {
auto delegated_video_backend =
std::make_unique<StrictMock<MockCmaBackend>>();
auto audio_decoder =
std::make_unique<StrictMock<MockMultizoneAudioDecoderProxy>>();
delegated_video_backend_ = delegated_video_backend.get();
audio_decoder_ = audio_decoder.get();
CmaBackendProxy::AudioDecoderFactoryCB factory = base::BindOnce(
[](std::unique_ptr<MultizoneAudioDecoderProxy> ptr) { return ptr; },
std::move(audio_decoder));
CmaBackendProxy* proxy = new CmaBackendProxy(
std::move(delegated_video_backend), std::move(factory));
backend_.reset(proxy);
}
protected:
void CreateVideoDecoder() {
EXPECT_CALL(*delegated_video_backend_, CreateVideoDecoder()).Times(1);
backend_->CreateVideoDecoder();
testing::Mock::VerifyAndClearExpectations(delegated_video_backend_);
}
std::unique_ptr<CmaBackendProxy> backend_;
MockCmaBackend* delegated_video_backend_;
MockMultizoneAudioDecoderProxy* audio_decoder_;
};
TEST_F(CmaBackendProxyTest, Initialize) {
EXPECT_TRUE(backend_->Initialize());
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, Initialize())
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Initialize());
EXPECT_FALSE(backend_->Initialize());
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, Initialize())
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*delegated_video_backend_, Initialize())
.WillOnce(Return(true))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Initialize());
EXPECT_FALSE(backend_->Initialize());
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
EXPECT_FALSE(backend_->Initialize());
EXPECT_FALSE(backend_->Initialize());
}
TEST_F(CmaBackendProxyTest, Start) {
constexpr float kStartPts = 42;
EXPECT_TRUE(backend_->Start(kStartPts));
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, Start(kStartPts))
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Start(kStartPts));
EXPECT_FALSE(backend_->Start(kStartPts));
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, Start(kStartPts))
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*delegated_video_backend_, Start(kStartPts))
.WillOnce(Return(true))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Start(kStartPts));
EXPECT_FALSE(backend_->Start(kStartPts));
EXPECT_FALSE(backend_->Start(kStartPts));
EXPECT_FALSE(backend_->Start(kStartPts));
}
TEST_F(CmaBackendProxyTest, Stop) {
backend_->Stop();
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, Stop());
backend_->Stop();
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, Stop());
EXPECT_CALL(*delegated_video_backend_, Stop());
backend_->Stop();
}
TEST_F(CmaBackendProxyTest, Pause) {
EXPECT_TRUE(backend_->Pause());
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, Pause())
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Pause());
EXPECT_FALSE(backend_->Pause());
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, Pause())
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*delegated_video_backend_, Pause())
.WillOnce(Return(true))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Pause());
EXPECT_FALSE(backend_->Pause());
EXPECT_FALSE(backend_->Pause());
EXPECT_FALSE(backend_->Pause());
}
TEST_F(CmaBackendProxyTest, Resume) {
EXPECT_TRUE(backend_->Resume());
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, Resume())
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Resume());
EXPECT_FALSE(backend_->Resume());
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, Resume())
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*delegated_video_backend_, Resume())
.WillOnce(Return(true))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->Resume());
EXPECT_FALSE(backend_->Resume());
EXPECT_FALSE(backend_->Resume());
EXPECT_FALSE(backend_->Resume());
}
TEST_F(CmaBackendProxyTest, GetCurrentPts) {
EXPECT_EQ(backend_->GetCurrentPts(), std::numeric_limits<int64_t>::min());
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, GetCurrentPts()).WillOnce(Return(42));
EXPECT_EQ(backend_->GetCurrentPts(), 42);
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, GetCurrentPts())
.WillOnce(Return(42))
.WillOnce(Return(42));
EXPECT_CALL(*delegated_video_backend_, GetCurrentPts())
.WillOnce(Return(16))
.WillOnce(Return(360));
EXPECT_EQ(backend_->GetCurrentPts(), 16);
EXPECT_EQ(backend_->GetCurrentPts(), 42);
}
TEST_F(CmaBackendProxyTest, SetPlaybackRate) {
constexpr float kSetPlaybackRatePts = 0.5;
EXPECT_TRUE(backend_->SetPlaybackRate(kSetPlaybackRatePts));
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, SetPlaybackRate(kSetPlaybackRatePts))
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->SetPlaybackRate(kSetPlaybackRatePts));
EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts));
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, SetPlaybackRate(kSetPlaybackRatePts))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*delegated_video_backend_, SetPlaybackRate(kSetPlaybackRatePts))
.WillOnce(Return(true))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(false));
EXPECT_TRUE(backend_->SetPlaybackRate(kSetPlaybackRatePts));
EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts));
EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts));
EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts));
}
TEST_F(CmaBackendProxyTest, LogicalPause) {
backend_->LogicalPause();
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, LogicalPause());
backend_->LogicalPause();
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, LogicalPause());
EXPECT_CALL(*delegated_video_backend_, LogicalPause());
backend_->LogicalPause();
}
TEST_F(CmaBackendProxyTest, LogicalResume) {
backend_->LogicalResume();
ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_);
EXPECT_CALL(*audio_decoder_, LogicalResume());
backend_->LogicalResume();
testing::Mock::VerifyAndClearExpectations(audio_decoder_);
CreateVideoDecoder();
EXPECT_CALL(*audio_decoder_, LogicalResume());
EXPECT_CALL(*delegated_video_backend_, LogicalResume());
backend_->LogicalResume();
}
} // namespace media
} // namespace chromecast
// Copyright 2020 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/proxy/multizone_audio_decoder_proxy.h"
#include "base/notreached.h"
#include "chromecast/public/media/decoder_config.h"
namespace chromecast {
namespace media {
void MultizoneAudioDecoderProxy::SetDelegate(Delegate* delegate) {
NOTREACHED();
}
MultizoneAudioDecoderProxy::BufferStatus MultizoneAudioDecoderProxy::PushBuffer(
scoped_refptr<DecoderBufferBase> buffer) {
NOTREACHED();
return BufferStatus::kBufferSuccess;
}
bool MultizoneAudioDecoderProxy::SetConfig(const AudioConfig& config) {
NOTREACHED();
return true;
}
bool MultizoneAudioDecoderProxy::SetVolume(float multiplier) {
NOTREACHED();
return true;
}
MultizoneAudioDecoderProxy::RenderingDelay
MultizoneAudioDecoderProxy::GetRenderingDelay() {
NOTREACHED();
return RenderingDelay{};
}
void MultizoneAudioDecoderProxy::GetStatistics(Statistics* statistics) {
NOTREACHED();
}
bool MultizoneAudioDecoderProxy::RequiresDecryption() {
NOTREACHED();
return true;
}
void MultizoneAudioDecoderProxy::SetObserver(Observer* observer) {
NOTREACHED();
}
} // namespace media
} // namespace chromecast
......@@ -5,6 +5,9 @@
#ifndef CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_H_
#include <limits>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "chromecast/media/api/cma_backend.h"
#include "chromecast/media/api/decoder_buffer_base.h"
......@@ -12,8 +15,6 @@
namespace chromecast {
namespace media {
struct AudioConfig;
// This class is used to decrypt then proxy audio data to an external
// CmaBackend::AudioDecoder over gRPC.
class MultizoneAudioDecoderProxy : public CmaBackend::AudioDecoder {
......@@ -24,17 +25,17 @@ class MultizoneAudioDecoderProxy : public CmaBackend::AudioDecoder {
using RenderingDelay = CmaBackend::AudioDecoder::RenderingDelay;
using Statistics = CmaBackend::AudioDecoder::Statistics;
~MultizoneAudioDecoderProxy() override;
// CmaBackend::AudioDecoder implementation:
void SetDelegate(Delegate* delegate) override;
BufferStatus PushBuffer(scoped_refptr<DecoderBufferBase> buffer) override;
bool SetConfig(const AudioConfig& config) override;
bool SetVolume(float multiplier) override;
RenderingDelay GetRenderingDelay() override;
void GetStatistics(Statistics* statistics) override;
bool RequiresDecryption() override;
void SetObserver(Observer* observer) override;
~MultizoneAudioDecoderProxy() override = default;
virtual bool Initialize() = 0;
virtual bool Start(int64_t start_pts) = 0;
virtual void Stop() = 0;
virtual bool Pause() = 0;
virtual bool Resume() = 0;
virtual bool SetPlaybackRate(float rate) = 0;
virtual void LogicalPause() = 0;
virtual void LogicalResume() = 0;
virtual int64_t GetCurrentPts() const = 0;
};
} // namespace media
......
// Copyright 2020 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/proxy/multizone_audio_decoder_proxy_impl.h"
#include "base/notreached.h"
#include "chromecast/public/media/decoder_config.h"
namespace chromecast {
namespace media {
MultizoneAudioDecoderProxyImpl::MultizoneAudioDecoderProxyImpl() = default;
MultizoneAudioDecoderProxyImpl::~MultizoneAudioDecoderProxyImpl() = default;
bool MultizoneAudioDecoderProxyImpl::Initialize() {
NOTIMPLEMENTED();
return true;
}
bool MultizoneAudioDecoderProxyImpl::Start(int64_t start_pts) {
NOTIMPLEMENTED();
return true;
}
void MultizoneAudioDecoderProxyImpl::Stop() {
NOTIMPLEMENTED();
}
bool MultizoneAudioDecoderProxyImpl::Pause() {
NOTIMPLEMENTED();
return true;
}
bool MultizoneAudioDecoderProxyImpl::Resume() {
NOTIMPLEMENTED();
return true;
}
bool MultizoneAudioDecoderProxyImpl::SetPlaybackRate(float rate) {
NOTIMPLEMENTED();
return true;
}
void MultizoneAudioDecoderProxyImpl::LogicalPause() {
NOTIMPLEMENTED();
}
void MultizoneAudioDecoderProxyImpl::LogicalResume() {
NOTIMPLEMENTED();
}
int64_t MultizoneAudioDecoderProxyImpl::GetCurrentPts() const {
return pts_offset_;
}
void MultizoneAudioDecoderProxyImpl::SetDelegate(Delegate* delegate) {
NOTIMPLEMENTED();
}
MultizoneAudioDecoderProxy::BufferStatus
MultizoneAudioDecoderProxyImpl::PushBuffer(
scoped_refptr<DecoderBufferBase> buffer) {
NOTIMPLEMENTED();
return BufferStatus::kBufferSuccess;
}
bool MultizoneAudioDecoderProxyImpl::SetConfig(const AudioConfig& config) {
NOTIMPLEMENTED();
return true;
}
bool MultizoneAudioDecoderProxyImpl::SetVolume(float multiplier) {
NOTIMPLEMENTED();
return true;
}
MultizoneAudioDecoderProxyImpl::RenderingDelay
MultizoneAudioDecoderProxyImpl::GetRenderingDelay() {
NOTIMPLEMENTED();
return RenderingDelay{};
}
void MultizoneAudioDecoderProxyImpl::GetStatistics(Statistics* statistics) {
NOTIMPLEMENTED();
}
bool MultizoneAudioDecoderProxyImpl::RequiresDecryption() {
NOTIMPLEMENTED();
return true;
}
void MultizoneAudioDecoderProxyImpl::SetObserver(Observer* observer) {
NOTIMPLEMENTED();
}
} // namespace media
} // namespace chromecast
// Copyright 2020 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_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_IMPL_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_IMPL_H_
#include <limits>
#include "base/memory/ref_counted.h"
#include "chromecast/media/api/cma_backend.h"
#include "chromecast/media/api/decoder_buffer_base.h"
#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h"
namespace chromecast {
namespace media {
struct AudioConfig;
// This class is used to proxy audio data to an external
// CmaBackend::AudioDecoder over gRPC.
class MultizoneAudioDecoderProxyImpl : public MultizoneAudioDecoderProxy {
public:
// Creates a new MultizoneAudioDecoderProxy, such that in the event of an
// unrecoverable error, |fatal_error_callback| will be called. Fallowing this
// call, this instance will be in an undefined state.
MultizoneAudioDecoderProxyImpl();
~MultizoneAudioDecoderProxyImpl() override;
// MultizoneAudioDecoderProxy implementation:
bool Initialize() override;
bool Start(int64_t start_pts) override;
void Stop() override;
bool Pause() override;
bool Resume() override;
int64_t GetCurrentPts() const override;
bool SetPlaybackRate(float rate) override;
void LogicalPause() override;
void LogicalResume() override;
void SetDelegate(Delegate* delegate) override;
BufferStatus PushBuffer(scoped_refptr<DecoderBufferBase> buffer) override;
bool SetConfig(const AudioConfig& config) override;
bool SetVolume(float multiplier) override;
RenderingDelay GetRenderingDelay() override;
void GetStatistics(Statistics* statistics) override;
bool RequiresDecryption() override;
void SetObserver(Observer* observer) override;
private:
// The PTS offset as determined by the receiver of the gRPC endpoint wrapped
// by this class. This value is updated as new PTS values are received over
// the IPC.
int64_t pts_offset_ = std::numeric_limits<int64_t>::min();
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_IMPL_H_
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