Commit 18d20394 authored by Ryan Keane's avatar Ryan Keane Committed by Chromium LUCI CQ

[Cast] Use gRPC Pipeline in CmaBackendProxy

This CL Updates CmaBackendProxy to make the following changes:
- Calls to CmaBackendProxy now call into the CmaProxyHandler.
- Calls to MultizoneAudioDecoderProxyImpl now also are duplicated to the
  underlying CmaBackend::AudioDecoder (when appropriate).

Bug: b/167426091
Change-Id: Ib07dd53d0efc5a4a080a6b4762502a9447ec0002
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2561783
Commit-Queue: Ryan Keane <rwkeane@google.com>
Reviewed-by: default avatarYuchen Liu <yucliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835970}
parent be3ff3f3
...@@ -29,7 +29,7 @@ std::unique_ptr<CmaBackend> CmaBackendFactoryImpl::CreateBackend( ...@@ -29,7 +29,7 @@ std::unique_ptr<CmaBackend> CmaBackendFactoryImpl::CreateBackend(
media_pipeline_backend_manager_->CreateBackend(params); media_pipeline_backend_manager_->CreateBackend(params);
#if BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER) #if BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER)
backend = std::make_unique<CmaBackendProxy>(std::move(backend)); backend = std::make_unique<CmaBackendProxy>(params, std::move(backend));
#endif // BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER) #endif // BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER)
return backend; return backend;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/notreached.h" #include "base/notreached.h"
#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h" #include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h"
#include "chromecast/public/media/decoder_config.h" #include "chromecast/public/media/decoder_config.h"
#include "chromecast/public/media/media_pipeline_device_params.h"
namespace chromecast { namespace chromecast {
namespace media { namespace media {
...@@ -25,20 +26,19 @@ int64_t kMaxAllowedPtsDrift = 500; ...@@ -25,20 +26,19 @@ int64_t kMaxAllowedPtsDrift = 500;
} // namespace } // namespace
CmaBackendProxy::CmaBackendProxy( CmaBackendProxy::CmaBackendProxy(const MediaPipelineDeviceParams& params,
std::unique_ptr<CmaBackend> delegated_video_pipeline) std::unique_ptr<CmaBackend> delegated_pipeline)
: CmaBackendProxy( : CmaBackendProxy(base::BindOnce(&CmaBackendProxy::CreateAudioDecoderProxy,
std::move(delegated_video_pipeline), base::Unretained(this),
base::BindOnce([]() -> std::unique_ptr<MultizoneAudioDecoderProxy> { params),
return std::make_unique<MultizoneAudioDecoderProxyImpl>(); std::move(delegated_pipeline)) {}
})) {}
CmaBackendProxy::CmaBackendProxy( CmaBackendProxy::CmaBackendProxy(
std::unique_ptr<CmaBackend> delegated_video_pipeline, CmaBackendProxy::AudioDecoderFactoryCB audio_decoder_factory,
CmaBackendProxy::AudioDecoderFactoryCB audio_decoder_factory) std::unique_ptr<CmaBackend> delegated_pipeline)
: delegated_video_pipeline_(std::move(delegated_video_pipeline)), : delegated_pipeline_(std::move(delegated_pipeline)),
audio_decoder_factory_(std::move(audio_decoder_factory)) { audio_decoder_factory_(std::move(audio_decoder_factory)) {
DCHECK(delegated_video_pipeline_); DCHECK(delegated_pipeline_);
DCHECK(audio_decoder_factory_); DCHECK(audio_decoder_factory_);
} }
...@@ -53,28 +53,36 @@ CmaBackend::AudioDecoder* CmaBackendProxy::CreateAudioDecoder() { ...@@ -53,28 +53,36 @@ CmaBackend::AudioDecoder* CmaBackendProxy::CreateAudioDecoder() {
CmaBackend::VideoDecoder* CmaBackendProxy::CreateVideoDecoder() { CmaBackend::VideoDecoder* CmaBackendProxy::CreateVideoDecoder() {
has_video_decoder_ = true; has_video_decoder_ = true;
return delegated_video_pipeline_->CreateVideoDecoder(); return delegated_pipeline_->CreateVideoDecoder();
} }
bool CmaBackendProxy::Initialize() { bool CmaBackendProxy::Initialize() {
if (has_video_decoder_ && !delegated_video_pipeline_->Initialize()) { if (audio_decoder_) {
return false; audio_decoder_->Initialize();
} }
return !audio_decoder_ || audio_decoder_->Initialize(); if (audio_decoder_ || has_video_decoder_) {
return delegated_pipeline_->Initialize();
} else {
return true;
}
} }
bool CmaBackendProxy::Start(int64_t start_pts) { bool CmaBackendProxy::Start(int64_t start_pts) {
if (has_video_decoder_ && !delegated_video_pipeline_->Start(start_pts)) { if (audio_decoder_) {
return false; audio_decoder_->Start(start_pts);
} }
return !audio_decoder_ || audio_decoder_->Start(start_pts); if (audio_decoder_ || has_video_decoder_) {
return delegated_pipeline_->Start(start_pts);
} else {
return true;
}
} }
void CmaBackendProxy::Stop() { void CmaBackendProxy::Stop() {
if (has_video_decoder_) { if (has_video_decoder_ || audio_decoder_) {
delegated_video_pipeline_->Stop(); delegated_pipeline_->Stop();
} }
if (audio_decoder_) { if (audio_decoder_) {
...@@ -83,60 +91,58 @@ void CmaBackendProxy::Stop() { ...@@ -83,60 +91,58 @@ void CmaBackendProxy::Stop() {
} }
bool CmaBackendProxy::Pause() { bool CmaBackendProxy::Pause() {
bool result = true;
if (has_video_decoder_) {
result &= delegated_video_pipeline_->Pause();
}
if (audio_decoder_) { if (audio_decoder_) {
result &= audio_decoder_->Pause(); audio_decoder_->Pause();
} }
return result; if (audio_decoder_ || has_video_decoder_) {
return delegated_pipeline_->Pause();
} else {
return true;
}
} }
bool CmaBackendProxy::Resume() { bool CmaBackendProxy::Resume() {
if (has_video_decoder_ && !delegated_video_pipeline_->Resume()) { if (audio_decoder_) {
return false; audio_decoder_->Resume();
} }
return !audio_decoder_ || audio_decoder_->Resume(); if (audio_decoder_ || has_video_decoder_) {
return delegated_pipeline_->Resume();
} else {
return true;
}
} }
int64_t CmaBackendProxy::GetCurrentPts() { int64_t CmaBackendProxy::GetCurrentPts() {
if (audio_decoder_ && has_video_decoder_) { if (audio_decoder_) {
const int64_t audio_pts = audio_decoder_->GetCurrentPts(); const int64_t audio_pts = audio_decoder_->GetCurrentPts();
const int64_t video_pts = delegated_video_pipeline_->GetCurrentPts(); const int64_t video_pts = delegated_pipeline_->GetCurrentPts();
const int64_t min = std::min(audio_pts, video_pts); const int64_t min = std::min(audio_pts, video_pts);
LOG_IF(WARNING, std::max(audio_pts, video_pts) - min > kMaxAllowedPtsDrift); LOG_IF(WARNING, std::max(audio_pts, video_pts) - min > kMaxAllowedPtsDrift);
return min; return min;
} else if (audio_decoder_) {
return audio_decoder_->GetCurrentPts();
} else if (has_video_decoder_) { } else if (has_video_decoder_) {
return delegated_video_pipeline_->GetCurrentPts(); return delegated_pipeline_->GetCurrentPts();
} else { } else {
return std::numeric_limits<int64_t>::min(); return std::numeric_limits<int64_t>::min();
} }
} }
bool CmaBackendProxy::SetPlaybackRate(float rate) { bool CmaBackendProxy::SetPlaybackRate(float rate) {
bool result = true;
if (has_video_decoder_) {
result &= delegated_video_pipeline_->SetPlaybackRate(rate);
}
if (audio_decoder_) { if (audio_decoder_) {
result &= audio_decoder_->SetPlaybackRate(rate); audio_decoder_->SetPlaybackRate(rate);
} }
return result; if (audio_decoder_ || has_video_decoder_) {
return delegated_pipeline_->SetPlaybackRate(rate);
} else {
return true;
}
} }
void CmaBackendProxy::LogicalPause() { void CmaBackendProxy::LogicalPause() {
if (has_video_decoder_) { if (has_video_decoder_ || audio_decoder_) {
delegated_video_pipeline_->LogicalPause(); delegated_pipeline_->LogicalPause();
} }
if (audio_decoder_) { if (audio_decoder_) {
...@@ -145,8 +151,8 @@ void CmaBackendProxy::LogicalPause() { ...@@ -145,8 +151,8 @@ void CmaBackendProxy::LogicalPause() {
} }
void CmaBackendProxy::LogicalResume() { void CmaBackendProxy::LogicalResume() {
if (has_video_decoder_) { if (has_video_decoder_ || audio_decoder_) {
delegated_video_pipeline_->LogicalResume(); delegated_pipeline_->LogicalResume();
} }
if (audio_decoder_) { if (audio_decoder_) {
...@@ -154,5 +160,14 @@ void CmaBackendProxy::LogicalResume() { ...@@ -154,5 +160,14 @@ void CmaBackendProxy::LogicalResume() {
} }
} }
std::unique_ptr<MultizoneAudioDecoderProxy>
CmaBackendProxy::CreateAudioDecoderProxy(
const MediaPipelineDeviceParams& params) {
CmaBackend::AudioDecoder* downstream_decoder =
delegated_pipeline_->CreateAudioDecoder();
return std::make_unique<MultizoneAudioDecoderProxyImpl>(params,
downstream_decoder);
}
} // namespace media } // namespace media
} // namespace chromecast } // namespace chromecast
...@@ -17,11 +17,14 @@ ...@@ -17,11 +17,14 @@
namespace chromecast { namespace chromecast {
namespace media { namespace media {
// This class is used to proxy audio data to an external struct MediaPipelineDeviceParams;
// CmaBackend::AudioDecoder over gRPC, while delegating video decoding to an
// alternate CMA Backend. // This class is used to intercept audio data and control messages being sent to
// the local CmaBackend and forward it to a remote instance prior to local
// processing in the underlying CmaBackend.
//
// NOTE: By design, this class does NOT handle a/v sync drift between // NOTE: By design, this class does NOT handle a/v sync drift between
// |audio_decoder_| and |delegated_video_pipeline_|. // |audio_decoder_| and |delegated_pipeline_|.
class CmaBackendProxy : public CmaBackend { class CmaBackendProxy : public CmaBackend {
public: public:
using AudioDecoderFactoryCB = using AudioDecoderFactoryCB =
...@@ -29,11 +32,15 @@ class CmaBackendProxy : public CmaBackend { ...@@ -29,11 +32,15 @@ class CmaBackendProxy : public CmaBackend {
// Creates a new CmaBackendProxy such that all video processing is delegated // Creates a new CmaBackendProxy such that all video processing is delegated
// to |delegated_video_pipeline|. // to |delegated_video_pipeline|.
explicit CmaBackendProxy( CmaBackendProxy(const MediaPipelineDeviceParams& params,
std::unique_ptr<CmaBackend> delegated_video_pipeline); std::unique_ptr<CmaBackend> delegated_video_pipeline);
~CmaBackendProxy() override; ~CmaBackendProxy() override;
// MediaPipelineBackend implementation: // MediaPipelineBackend implementation:
//
// NOTE: Each of these calls must forward the call both to the gRPC Pipe (if
// the audio decoder exists) and to the local audio decoder (if either audio
// or video decoding is occuring).
CmaBackend::AudioDecoder* CreateAudioDecoder() override; CmaBackend::AudioDecoder* CreateAudioDecoder() override;
CmaBackend::VideoDecoder* CreateVideoDecoder() override; CmaBackend::VideoDecoder* CreateVideoDecoder() override;
bool Initialize() override; bool Initialize() override;
...@@ -50,19 +57,23 @@ class CmaBackendProxy : public CmaBackend { ...@@ -50,19 +57,23 @@ class CmaBackendProxy : public CmaBackend {
friend class CmaBackendProxyTest; friend class CmaBackendProxyTest;
// Creates a new CmaBackendProxy such that all video processing is delegated // Creates a new CmaBackendProxy such that all video processing is delegated
// to |delegated_video_pipeline| and all audio processing is delegated to a // to |delegated_pipeline| and all audio processing is delegated to a
// new MultizoneAudioDecoderProxy created by |audio_decoder_factory|. // new MultizoneAudioDecoderProxy created by |audio_decoder_factory|.
CmaBackendProxy(std::unique_ptr<CmaBackend> delegated_video_pipeline, CmaBackendProxy(AudioDecoderFactoryCB audio_decoder_factory,
AudioDecoderFactoryCB audio_decoder_factory); std::unique_ptr<CmaBackend> delegated_pipeline);
// Helper to create the AudioDecoder instance, used with base::bind.
std::unique_ptr<MultizoneAudioDecoderProxy> CreateAudioDecoderProxy(
const MediaPipelineDeviceParams& params);
// The audio decoder to which audio operations should be delegated. // The audio decoder to which audio operations should be delegated.
std::unique_ptr<MultizoneAudioDecoderProxy> audio_decoder_; std::unique_ptr<MultizoneAudioDecoderProxy> audio_decoder_;
// The CMA Backend to which all video decoding is delegated. // The CMA Backend to which all video decoding is delegated.
std::unique_ptr<CmaBackend> delegated_video_pipeline_; std::unique_ptr<CmaBackend> delegated_pipeline_;
// Determines whether a video decoder is being used. If not, calls should not // 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 // be delegated to the |delegated_pipeline_|, as it may not behave as
// expected when neither the audio or video decoders are initialized. // expected when neither the audio or video decoders are initialized.
bool has_video_decoder_ = false; bool has_video_decoder_ = false;
......
...@@ -27,12 +27,12 @@ class MultizoneAudioDecoderProxy : public CmaBackend::AudioDecoder { ...@@ -27,12 +27,12 @@ class MultizoneAudioDecoderProxy : public CmaBackend::AudioDecoder {
~MultizoneAudioDecoderProxy() override = default; ~MultizoneAudioDecoderProxy() override = default;
virtual bool Initialize() = 0; virtual void Initialize() = 0;
virtual bool Start(int64_t start_pts) = 0; virtual void Start(int64_t start_pts) = 0;
virtual void Stop() = 0; virtual void Stop() = 0;
virtual bool Pause() = 0; virtual void Pause() = 0;
virtual bool Resume() = 0; virtual void Resume() = 0;
virtual bool SetPlaybackRate(float rate) = 0; virtual void SetPlaybackRate(float rate) = 0;
virtual void LogicalPause() = 0; virtual void LogicalPause() = 0;
virtual void LogicalResume() = 0; virtual void LogicalResume() = 0;
virtual int64_t GetCurrentPts() const = 0; virtual int64_t GetCurrentPts() const = 0;
......
...@@ -6,93 +6,143 @@ ...@@ -6,93 +6,143 @@
#include "base/notreached.h" #include "base/notreached.h"
#include "chromecast/public/media/decoder_config.h" #include "chromecast/public/media/decoder_config.h"
#include "chromecast/public/media/media_pipeline_device_params.h"
namespace chromecast { namespace chromecast {
namespace media { namespace media {
MultizoneAudioDecoderProxyImpl::MultizoneAudioDecoderProxyImpl() = default; MultizoneAudioDecoderProxyImpl::MultizoneAudioDecoderProxyImpl(
const MediaPipelineDeviceParams& params,
CmaBackend::AudioDecoder* downstream_decoder)
: cast_session_id_(params.session_id),
decoder_mode_(CmaProxyHandler::AudioDecoderOperationMode::kMultiroomOnly),
downstream_decoder_(downstream_decoder),
proxy_handler_(CmaProxyHandler::Create(params.task_runner, this)) {
DCHECK(downstream_decoder_);
DCHECK(proxy_handler_);
DETACH_FROM_SEQUENCE(sequence_checker_);
}
MultizoneAudioDecoderProxyImpl::~MultizoneAudioDecoderProxyImpl() = default; MultizoneAudioDecoderProxyImpl::~MultizoneAudioDecoderProxyImpl() = default;
bool MultizoneAudioDecoderProxyImpl::Initialize() { void MultizoneAudioDecoderProxyImpl::Initialize() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return true; proxy_handler_->Initialize(cast_session_id_, decoder_mode_);
} }
bool MultizoneAudioDecoderProxyImpl::Start(int64_t start_pts) { void MultizoneAudioDecoderProxyImpl::Start(int64_t start_pts) {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return true; proxy_handler_->Start(start_pts);
} }
void MultizoneAudioDecoderProxyImpl::Stop() { void MultizoneAudioDecoderProxyImpl::Stop() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
proxy_handler_->Stop();
} }
bool MultizoneAudioDecoderProxyImpl::Pause() { void MultizoneAudioDecoderProxyImpl::Pause() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return true; proxy_handler_->Pause();
} }
bool MultizoneAudioDecoderProxyImpl::Resume() { void MultizoneAudioDecoderProxyImpl::Resume() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return true; proxy_handler_->Resume();
} }
bool MultizoneAudioDecoderProxyImpl::SetPlaybackRate(float rate) { void MultizoneAudioDecoderProxyImpl::SetPlaybackRate(float rate) {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return true; proxy_handler_->SetPlaybackRate(rate);
} }
void MultizoneAudioDecoderProxyImpl::LogicalPause() { void MultizoneAudioDecoderProxyImpl::LogicalPause() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// There is intentionally no proxy implementation of this method.
} }
void MultizoneAudioDecoderProxyImpl::LogicalResume() { void MultizoneAudioDecoderProxyImpl::LogicalResume() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// There is intentionally no proxy implementation of this method.
} }
int64_t MultizoneAudioDecoderProxyImpl::GetCurrentPts() const { int64_t MultizoneAudioDecoderProxyImpl::GetCurrentPts() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// This will be implemented as part of audio-audio sync.
NOTIMPLEMENTED();
return pts_offset_; return pts_offset_;
} }
void MultizoneAudioDecoderProxyImpl::SetDelegate(Delegate* delegate) { void MultizoneAudioDecoderProxyImpl::SetDelegate(Delegate* delegate) {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
downstream_decoder_->SetDelegate(delegate);
} }
MultizoneAudioDecoderProxy::BufferStatus MultizoneAudioDecoderProxy::BufferStatus
MultizoneAudioDecoderProxyImpl::PushBuffer( MultizoneAudioDecoderProxyImpl::PushBuffer(
scoped_refptr<DecoderBufferBase> buffer) { scoped_refptr<DecoderBufferBase> buffer) {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return BufferStatus::kBufferSuccess;
if (!proxy_handler_->PushBuffer(buffer)) {
return BufferStatus::kBufferFailed;
}
return downstream_decoder_->PushBuffer(std::move(buffer));
} }
bool MultizoneAudioDecoderProxyImpl::SetConfig(const AudioConfig& config) { bool MultizoneAudioDecoderProxyImpl::SetConfig(const AudioConfig& config) {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return true; return proxy_handler_->SetConfig(config) &&
downstream_decoder_->SetConfig(config);
} }
bool MultizoneAudioDecoderProxyImpl::SetVolume(float multiplier) { bool MultizoneAudioDecoderProxyImpl::SetVolume(float multiplier) {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// The proxy implementation of this method is INTENTIONALLY not called here.
return true; return true;
} }
MultizoneAudioDecoderProxyImpl::RenderingDelay MultizoneAudioDecoderProxyImpl::RenderingDelay
MultizoneAudioDecoderProxyImpl::GetRenderingDelay() { MultizoneAudioDecoderProxyImpl::GetRenderingDelay() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// This will be implemented as part of audio-audio sync.
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return RenderingDelay{}; return RenderingDelay{};
} }
void MultizoneAudioDecoderProxyImpl::GetStatistics(Statistics* statistics) { void MultizoneAudioDecoderProxyImpl::GetStatistics(Statistics* statistics) {
NOTIMPLEMENTED(); DCHECK(statistics);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
statistics->decoded_bytes = bytes_decoded_;
} }
bool MultizoneAudioDecoderProxyImpl::RequiresDecryption() { bool MultizoneAudioDecoderProxyImpl::RequiresDecryption() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return true; return downstream_decoder_->RequiresDecryption();
} }
void MultizoneAudioDecoderProxyImpl::SetObserver(Observer* observer) { void MultizoneAudioDecoderProxyImpl::SetObserver(Observer* observer) {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
downstream_decoder_->SetObserver(observer);
}
void MultizoneAudioDecoderProxyImpl::OnError() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NOTREACHED();
}
void MultizoneAudioDecoderProxyImpl::OnPipelineStateChange(
CmaProxyHandler::PipelineState state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void MultizoneAudioDecoderProxyImpl::OnBytesDecoded(
int64_t decoded_byte_count) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bytes_decoded_ = decoded_byte_count;
} }
} // namespace media } // namespace media
......
...@@ -8,33 +8,44 @@ ...@@ -8,33 +8,44 @@
#include <limits> #include <limits>
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "chromecast/media/api/cma_backend.h" #include "chromecast/media/api/cma_backend.h"
#include "chromecast/media/api/decoder_buffer_base.h" #include "chromecast/media/api/decoder_buffer_base.h"
#include "chromecast/media/cma/backend/proxy/cma_proxy_handler.h"
#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h" #include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h"
namespace chromecast { namespace chromecast {
namespace media { namespace media {
struct AudioConfig; struct AudioConfig;
struct MediaPipelineDeviceParams;
// This class is used to proxy audio data to an external // This class is used to proxy audio data to an external
// CmaBackend::AudioDecoder over gRPC. // CmaBackend::AudioDecoder over gRPC.
class MultizoneAudioDecoderProxyImpl : public MultizoneAudioDecoderProxy { class MultizoneAudioDecoderProxyImpl : public MultizoneAudioDecoderProxy,
public CmaProxyHandler::Client {
public: public:
// Creates a new MultizoneAudioDecoderProxy, such that in the event of an // Creates a new MultizoneAudioDecoderProxy, such that in the event of an
// unrecoverable error, |fatal_error_callback| will be called. Fallowing this // unrecoverable error, |fatal_error_callback| will be called. Fallowing this
// call, this instance will be in an undefined state. // call, this instance will be in an undefined state.
MultizoneAudioDecoderProxyImpl(); MultizoneAudioDecoderProxyImpl(const MediaPipelineDeviceParams& params,
CmaBackend::AudioDecoder* downstream_decoder);
~MultizoneAudioDecoderProxyImpl() override; ~MultizoneAudioDecoderProxyImpl() override;
// MultizoneAudioDecoderProxy implementation: // MultizoneAudioDecoderProxy implementation:
bool Initialize() override; //
bool Start(int64_t start_pts) override; // Note that the methods implementing of CmaBackend::AudioDecoder (which
// MultizoneAudioDecoderProxy extends) must call both into the downstream
// decoder and into the |proxy_handler_|, so that audio can be processed both
// locally and remotely. The remaining methods should NOT call into the
// downstream CmaBackend, as this is the responsibility of the caller.
void Initialize() override;
void Start(int64_t start_pts) override;
void Stop() override; void Stop() override;
bool Pause() override; void Pause() override;
bool Resume() override; void Resume() override;
int64_t GetCurrentPts() const override; int64_t GetCurrentPts() const override;
bool SetPlaybackRate(float rate) override; void SetPlaybackRate(float rate) override;
void LogicalPause() override; void LogicalPause() override;
void LogicalResume() override; void LogicalResume() override;
void SetDelegate(Delegate* delegate) override; void SetDelegate(Delegate* delegate) override;
...@@ -47,10 +58,35 @@ class MultizoneAudioDecoderProxyImpl : public MultizoneAudioDecoderProxy { ...@@ -47,10 +58,35 @@ class MultizoneAudioDecoderProxyImpl : public MultizoneAudioDecoderProxy {
void SetObserver(Observer* observer) override; void SetObserver(Observer* observer) override;
private: private:
// CmaProxyHandler::Client overrides:
void OnError() override;
void OnPipelineStateChange(CmaProxyHandler::PipelineState state) override;
void OnBytesDecoded(int64_t decoded_byte_count) override;
// The PTS offset as determined by the receiver of the gRPC endpoint wrapped // 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 // by this class. This value is updated as new PTS values are received over
// the IPC. // the IPC.
int64_t pts_offset_ = std::numeric_limits<int64_t>::min(); int64_t pts_offset_ = std::numeric_limits<int64_t>::min();
// Number of bytes decoded so far.
int64_t bytes_decoded_ = 0;
// Parameters for the Initialize() call captured in the ctor.
const std::string cast_session_id_;
const CmaProxyHandler::AudioDecoderOperationMode decoder_mode_;
// Decoder to which the CmaBackend::AudioDecoder calls should be duplicated
// (when appropriate). It is expected to be the AudioDecoder associated with
// the "real" CmaBackend, which plays out audio data using the physical
// device's hardware. By design, this decoder is always assumed to exist.
CmaBackend::AudioDecoder* const downstream_decoder_;
// This is the local instance representing the "remote" backend. All above
// public method calls should call into this instance to proxy the call to
// the remote backend.
std::unique_ptr<CmaProxyHandler> proxy_handler_;
SEQUENCE_CHECKER(sequence_checker_);
}; };
} // 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