1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chromecast/media/cma/backend/proxy/cma_backend_proxy.h" 6 7 #include <algorithm> 8 9 #include "base/bind.h" 10 #include "base/logging.h" 11 #include "base/macros.h" 12 #include "base/notreached.h" 13 #include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h" 14 #include "chromecast/public/media/decoder_config.h" 15 16 namespace chromecast { 17 namespace media { 18 namespace { 19 20 // The maximum allowed difference between the audio and video decoders used for 21 // the CmaBackendProxy. 22 // TODO(b/168748626): Determine the correct value for this variable 23 // experimentally. 24 int64_t kMaxAllowedPtsDrift = 500; 25 26 } // namespace 27 CmaBackendProxy(std::unique_ptr<CmaBackend> delegated_video_pipeline)28CmaBackendProxy::CmaBackendProxy( 29 std::unique_ptr<CmaBackend> delegated_video_pipeline) 30 : CmaBackendProxy( 31 std::move(delegated_video_pipeline), 32 base::BindOnce([]() -> std::unique_ptr<MultizoneAudioDecoderProxy> { 33 return std::make_unique<MultizoneAudioDecoderProxyImpl>(); 34 })) {} 35 CmaBackendProxy(std::unique_ptr<CmaBackend> delegated_video_pipeline,CmaBackendProxy::AudioDecoderFactoryCB audio_decoder_factory)36CmaBackendProxy::CmaBackendProxy( 37 std::unique_ptr<CmaBackend> delegated_video_pipeline, 38 CmaBackendProxy::AudioDecoderFactoryCB audio_decoder_factory) 39 : delegated_video_pipeline_(std::move(delegated_video_pipeline)), 40 audio_decoder_factory_(std::move(audio_decoder_factory)) { 41 DCHECK(delegated_video_pipeline_); 42 DCHECK(audio_decoder_factory_); 43 } 44 45 CmaBackendProxy::~CmaBackendProxy() = default; 46 CreateAudioDecoder()47CmaBackend::AudioDecoder* CmaBackendProxy::CreateAudioDecoder() { 48 DCHECK(!audio_decoder_); 49 DCHECK(audio_decoder_factory_); 50 audio_decoder_ = std::move(audio_decoder_factory_).Run(); 51 return audio_decoder_.get(); 52 } 53 CreateVideoDecoder()54CmaBackend::VideoDecoder* CmaBackendProxy::CreateVideoDecoder() { 55 has_video_decoder_ = true; 56 return delegated_video_pipeline_->CreateVideoDecoder(); 57 } 58 Initialize()59bool CmaBackendProxy::Initialize() { 60 if (has_video_decoder_ && !delegated_video_pipeline_->Initialize()) { 61 return false; 62 } 63 64 return !audio_decoder_ || audio_decoder_->Initialize(); 65 } 66 Start(int64_t start_pts)67bool CmaBackendProxy::Start(int64_t start_pts) { 68 if (has_video_decoder_ && !delegated_video_pipeline_->Start(start_pts)) { 69 return false; 70 } 71 72 return !audio_decoder_ || audio_decoder_->Start(start_pts); 73 } 74 Stop()75void CmaBackendProxy::Stop() { 76 if (has_video_decoder_) { 77 delegated_video_pipeline_->Stop(); 78 } 79 80 if (audio_decoder_) { 81 audio_decoder_->Stop(); 82 } 83 } 84 Pause()85bool CmaBackendProxy::Pause() { 86 bool result = true; 87 88 if (has_video_decoder_) { 89 result &= delegated_video_pipeline_->Pause(); 90 } 91 92 if (audio_decoder_) { 93 result &= audio_decoder_->Pause(); 94 } 95 96 return result; 97 } 98 Resume()99bool CmaBackendProxy::Resume() { 100 if (has_video_decoder_ && !delegated_video_pipeline_->Resume()) { 101 return false; 102 } 103 104 return !audio_decoder_ || audio_decoder_->Resume(); 105 } 106 GetCurrentPts()107int64_t CmaBackendProxy::GetCurrentPts() { 108 if (audio_decoder_ && has_video_decoder_) { 109 const int64_t audio_pts = audio_decoder_->GetCurrentPts(); 110 const int64_t video_pts = delegated_video_pipeline_->GetCurrentPts(); 111 const int64_t min = std::min(audio_pts, video_pts); 112 LOG_IF(WARNING, std::max(audio_pts, video_pts) - min > kMaxAllowedPtsDrift); 113 return min; 114 } else if (audio_decoder_) { 115 return audio_decoder_->GetCurrentPts(); 116 } else if (has_video_decoder_) { 117 return delegated_video_pipeline_->GetCurrentPts(); 118 } else { 119 return std::numeric_limits<int64_t>::min(); 120 } 121 } 122 SetPlaybackRate(float rate)123bool CmaBackendProxy::SetPlaybackRate(float rate) { 124 bool result = true; 125 126 if (has_video_decoder_) { 127 result &= delegated_video_pipeline_->SetPlaybackRate(rate); 128 } 129 130 if (audio_decoder_) { 131 result &= audio_decoder_->SetPlaybackRate(rate); 132 } 133 134 return result; 135 } 136 LogicalPause()137void CmaBackendProxy::LogicalPause() { 138 if (has_video_decoder_) { 139 delegated_video_pipeline_->LogicalPause(); 140 } 141 142 if (audio_decoder_) { 143 audio_decoder_->LogicalPause(); 144 } 145 } 146 LogicalResume()147void CmaBackendProxy::LogicalResume() { 148 if (has_video_decoder_) { 149 delegated_video_pipeline_->LogicalResume(); 150 } 151 152 if (audio_decoder_) { 153 audio_decoder_->LogicalResume(); 154 } 155 } 156 157 } // namespace media 158 } // namespace chromecast 159