| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 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/adapter/backend_adapter.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/location.h" |
| 9 #include "base/single_thread_task_runner.h" |
| 10 #include "chromecast/base/task_runner_impl.h" |
| 11 #include "chromecast/media/cma/adapter/audio_pipeline_device.h" |
| 12 #include "chromecast/media/cma/adapter/media_clock_device.h" |
| 13 #include "chromecast/media/cma/adapter/media_pipeline_backend_v1.h" |
| 14 #include "chromecast/media/cma/adapter/video_pipeline_device.h" |
| 15 #include "chromecast/public/graphics_types.h" |
| 16 #include "chromecast/public/media/cast_decoder_buffer.h" |
| 17 #include "chromecast/public/media/decrypt_context.h" |
| 18 #include "chromecast/public/media/media_pipeline_device_params.h" |
| 19 |
| 20 namespace chromecast { |
| 21 namespace media { |
| 22 |
| 23 #define RUN_ON_MEDIA_THREAD(type, method, ...) \ |
| 24 media_task_runner_->PostTask( \ |
| 25 FROM_HERE, \ |
| 26 base::Bind(&type::method, base::Unretained(this), ##__VA_ARGS__)); |
| 27 |
| 28 #define MAKE_SURE_MEDIA_THREAD(type, method, ...) \ |
| 29 DCHECK(media_task_runner_); \ |
| 30 if (!media_task_runner_->BelongsToCurrentThread()) { \ |
| 31 RUN_ON_MEDIA_THREAD(type, method, ##__VA_ARGS__) \ |
| 32 return; \ |
| 33 } |
| 34 |
| 35 namespace { |
| 36 |
| 37 MediaPipelineBackend::BufferStatus ConvertStatus( |
| 38 MediaComponentDevice::FrameStatus status_in) { |
| 39 switch (status_in) { |
| 40 case MediaComponentDevice::kFrameSuccess: |
| 41 return MediaPipelineBackend::kBufferSuccess; |
| 42 case MediaComponentDevice::kFrameFailed: |
| 43 return MediaPipelineBackend::kBufferFailed; |
| 44 default: |
| 45 NOTREACHED(); |
| 46 case MediaComponentDevice::kFramePending: |
| 47 return MediaPipelineBackend::kBufferPending; |
| 48 } |
| 49 } |
| 50 |
| 51 // Since the ownership model has changed from "callee-owned" to "caller-owned", |
| 52 // we need wrappers to pass to the V1 interface that can safely be deleted |
| 53 // at any time. |
| 54 class DecryptContextWrapper : public DecryptContext { |
| 55 public: |
| 56 DecryptContextWrapper(DecryptContext* wrapped_in) : wrapped_(wrapped_in) {} |
| 57 |
| 58 ~DecryptContextWrapper() override {} |
| 59 |
| 60 // DecryptContext implementation: |
| 61 CastKeySystem GetKeySystem() override { |
| 62 return wrapped_ ? wrapped_->GetKeySystem() : KEY_SYSTEM_NONE; |
| 63 } |
| 64 |
| 65 bool Decrypt(CastDecoderBuffer* buffer, |
| 66 std::vector<uint8_t>* output) override { |
| 67 return wrapped_->Decrypt(buffer, output); |
| 68 } |
| 69 |
| 70 private: |
| 71 DecryptContext* wrapped_; |
| 72 |
| 73 DISALLOW_COPY_AND_ASSIGN(DecryptContextWrapper); |
| 74 }; |
| 75 |
| 76 class CastDecoderBufferWrapper : public CastDecoderBuffer { |
| 77 public: |
| 78 CastDecoderBufferWrapper(CastDecoderBuffer* wrapped_in) |
| 79 : wrapped_(wrapped_in) { |
| 80 DCHECK(wrapped_); |
| 81 } |
| 82 |
| 83 ~CastDecoderBufferWrapper() override {} |
| 84 |
| 85 // CastDecoderBuffer implementation: |
| 86 StreamId stream_id() const override { return wrapped_->stream_id(); } |
| 87 int64_t timestamp() const override { return wrapped_->timestamp(); } |
| 88 const uint8_t* data() const override { return wrapped_->data(); } |
| 89 size_t data_size() const override { return wrapped_->data_size(); } |
| 90 const CastDecryptConfig* decrypt_config() const override { |
| 91 return wrapped_->decrypt_config(); |
| 92 } |
| 93 bool end_of_stream() const override { return wrapped_->end_of_stream(); } |
| 94 |
| 95 private: |
| 96 CastDecoderBuffer* wrapped_; |
| 97 |
| 98 DISALLOW_COPY_AND_ASSIGN(CastDecoderBufferWrapper); |
| 99 }; |
| 100 |
| 101 class FrameStatusCallback : public MediaComponentDevice::FrameStatusCB { |
| 102 public: |
| 103 FrameStatusCallback( |
| 104 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 105 const base::WeakPtr<MediaPipelineBackendAdapter>& adapter, |
| 106 bool video) |
| 107 : media_task_runner_(media_task_runner), |
| 108 adapter_(adapter), |
| 109 video_(video) { |
| 110 DCHECK(adapter_); |
| 111 } |
| 112 |
| 113 ~FrameStatusCallback() override {} |
| 114 |
| 115 // MediaComponentDevice::FrameStatusCB implementation: |
| 116 void Run(MediaComponentDevice::FrameStatus status) override { |
| 117 MAKE_SURE_MEDIA_THREAD(FrameStatusCallback, Run, status); |
| 118 if (adapter_) { |
| 119 MediaPipelineBackend::BufferStatus status_out; |
| 120 switch (status) { |
| 121 case MediaComponentDevice::kFrameSuccess: |
| 122 status_out = MediaPipelineBackend::kBufferSuccess; |
| 123 break; |
| 124 default: |
| 125 NOTREACHED(); |
| 126 case MediaComponentDevice::kFrameFailed: |
| 127 status_out = MediaPipelineBackend::kBufferFailed; |
| 128 break; |
| 129 } |
| 130 adapter_->OnPushBufferComplete(video_, status_out); |
| 131 } |
| 132 } |
| 133 |
| 134 private: |
| 135 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| 136 base::WeakPtr<MediaPipelineBackendAdapter> adapter_; |
| 137 bool video_; |
| 138 |
| 139 DISALLOW_COPY_AND_ASSIGN(FrameStatusCallback); |
| 140 }; |
| 141 |
| 142 class V2AudioDecoder : public MediaPipelineBackend::AudioDecoder { |
| 143 public: |
| 144 V2AudioDecoder( |
| 145 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 146 const base::WeakPtr<MediaPipelineBackendAdapter>& adapter, |
| 147 media::AudioPipelineDevice* device) |
| 148 : media_task_runner_(media_task_runner), |
| 149 device_(device), |
| 150 adapter_(adapter) {} |
| 151 |
| 152 BufferStatus PushBuffer(DecryptContext* decrypt_context, |
| 153 CastDecoderBuffer* buffer) override { |
| 154 return ConvertStatus(device_->PushFrame( |
| 155 new DecryptContextWrapper(decrypt_context), |
| 156 new CastDecoderBufferWrapper(buffer), |
| 157 new FrameStatusCallback( |
| 158 media_task_runner_, adapter_, false /* video */))); |
| 159 } |
| 160 |
| 161 void GetStatistics(Statistics* statistics) override { |
| 162 device_->GetStatistics(statistics); |
| 163 } |
| 164 |
| 165 bool SetConfig(const AudioConfig& config) override { |
| 166 return device_->SetConfig(config); |
| 167 } |
| 168 |
| 169 bool SetVolume(float multiplier) override { |
| 170 device_->SetStreamVolumeMultiplier(multiplier); |
| 171 return true; |
| 172 } |
| 173 |
| 174 RenderingDelay GetRenderingDelay() override { |
| 175 return device_->GetRenderingDelay(); |
| 176 } |
| 177 |
| 178 private: |
| 179 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| 180 media::AudioPipelineDevice* device_; |
| 181 base::WeakPtr<MediaPipelineBackendAdapter> adapter_; |
| 182 }; |
| 183 |
| 184 class V2VideoDecoder : public MediaPipelineBackend::VideoDecoder { |
| 185 public: |
| 186 V2VideoDecoder( |
| 187 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 188 base::WeakPtr<MediaPipelineBackendAdapter> adapter, |
| 189 media::VideoPipelineDevice* device) |
| 190 : media_task_runner_(media_task_runner), |
| 191 device_(device), |
| 192 adapter_(adapter) {} |
| 193 |
| 194 BufferStatus PushBuffer(DecryptContext* decrypt_context, |
| 195 CastDecoderBuffer* buffer) override { |
| 196 return ConvertStatus(device_->PushFrame( |
| 197 new DecryptContextWrapper(decrypt_context), |
| 198 new CastDecoderBufferWrapper(buffer), |
| 199 new FrameStatusCallback( |
| 200 media_task_runner_, adapter_, true /* video */))); |
| 201 } |
| 202 |
| 203 void GetStatistics(MediaComponentDevice::Statistics* statistics) override { |
| 204 device_->GetStatistics(statistics); |
| 205 } |
| 206 |
| 207 bool SetConfig(const VideoConfig& config) override { |
| 208 return device_->SetConfig(config); |
| 209 } |
| 210 |
| 211 private: |
| 212 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| 213 media::VideoPipelineDevice* device_; |
| 214 base::WeakPtr<MediaPipelineBackendAdapter> adapter_; |
| 215 }; |
| 216 |
| 217 class AudioClientAdapter : public MediaComponentDevice::Client { |
| 218 public: |
| 219 AudioClientAdapter( |
| 220 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 221 const base::WeakPtr<MediaPipelineBackendAdapter>& adapter) |
| 222 : media_task_runner_(media_task_runner), adapter_(adapter) {} |
| 223 void OnEndOfStream() override { |
| 224 MAKE_SURE_MEDIA_THREAD(AudioClientAdapter, OnEndOfStream); |
| 225 if (adapter_) |
| 226 adapter_->OnEndOfAudioStream(); |
| 227 } |
| 228 |
| 229 private: |
| 230 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| 231 base::WeakPtr<MediaPipelineBackendAdapter> adapter_; |
| 232 }; |
| 233 |
| 234 class VideoClientAdapter : public MediaComponentDevice::Client, |
| 235 public VideoPipelineDevice::VideoClient { |
| 236 public: |
| 237 VideoClientAdapter( |
| 238 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 239 const base::WeakPtr<MediaPipelineBackendAdapter>& adapter) |
| 240 : media_task_runner_(media_task_runner), adapter_(adapter) {} |
| 241 void OnEndOfStream() override { |
| 242 MAKE_SURE_MEDIA_THREAD(VideoClientAdapter, OnEndOfStream); |
| 243 if (adapter_) |
| 244 adapter_->OnEndOfVideoStream(); |
| 245 } |
| 246 void OnNaturalSizeChanged(const Size& size) override { |
| 247 MAKE_SURE_MEDIA_THREAD(VideoClientAdapter, OnNaturalSizeChanged, size); |
| 248 if (adapter_) |
| 249 adapter_->OnNaturalSizeChanged(size); |
| 250 } |
| 251 |
| 252 private: |
| 253 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| 254 base::WeakPtr<MediaPipelineBackendAdapter> adapter_; |
| 255 }; |
| 256 |
| 257 } // namespace |
| 258 |
| 259 MediaPipelineBackendAdapter::MediaPipelineBackendAdapter( |
| 260 const MediaPipelineDeviceParams& params, |
| 261 scoped_ptr<media::MediaPipelineBackendV1> backend_v1) |
| 262 : backend_v1_(backend_v1.Pass()), |
| 263 clock_(backend_v1_->GetClock()), |
| 264 audio_(nullptr), |
| 265 video_(nullptr), |
| 266 playing_(false), |
| 267 rate_(1.0f), |
| 268 weak_factory_(this) { |
| 269 DCHECK(clock_); |
| 270 |
| 271 media_task_runner_ = |
| 272 static_cast<TaskRunnerImpl*>(params.task_runner)->runner(); |
| 273 } |
| 274 |
| 275 MediaPipelineBackendAdapter::~MediaPipelineBackendAdapter() { |
| 276 } |
| 277 |
| 278 MediaPipelineBackend::AudioDecoder* |
| 279 MediaPipelineBackendAdapter::CreateAudioDecoder() { |
| 280 DCHECK(!audio_); |
| 281 audio_ = backend_v1_->GetAudio(); |
| 282 audio_->SetClient( |
| 283 new AudioClientAdapter(media_task_runner_, weak_factory_.GetWeakPtr())); |
| 284 audio_decoder_ = new V2AudioDecoder( |
| 285 media_task_runner_, weak_factory_.GetWeakPtr(), audio_); |
| 286 return audio_decoder_; |
| 287 } |
| 288 |
| 289 MediaPipelineBackend::VideoDecoder* |
| 290 MediaPipelineBackendAdapter::CreateVideoDecoder() { |
| 291 DCHECK(!video_); |
| 292 video_ = backend_v1_->GetVideo(); |
| 293 video_->SetClient( |
| 294 new VideoClientAdapter(media_task_runner_, weak_factory_.GetWeakPtr())); |
| 295 video_->SetVideoClient( |
| 296 new VideoClientAdapter(media_task_runner_, weak_factory_.GetWeakPtr())); |
| 297 video_decoder_ = new V2VideoDecoder( |
| 298 media_task_runner_, weak_factory_.GetWeakPtr(), video_); |
| 299 return video_decoder_; |
| 300 } |
| 301 |
| 302 bool MediaPipelineBackendAdapter::Initialize(Delegate* delegate) { |
| 303 DCHECK(delegate); |
| 304 delegate_ = delegate; |
| 305 |
| 306 if (!clock_->SetState(MediaClockDevice::kStateIdle)) |
| 307 return false; |
| 308 |
| 309 if (audio_ && !audio_->SetState(MediaComponentDevice::kStateIdle)) |
| 310 return false; |
| 311 |
| 312 if (video_ && !video_->SetState(MediaComponentDevice::kStateIdle)) |
| 313 return false; |
| 314 |
| 315 return true; |
| 316 } |
| 317 |
| 318 bool MediaPipelineBackendAdapter::Start(int64_t start_pts) { |
| 319 DCHECK(!playing_); |
| 320 if (!clock_->ResetTimeline(start_pts)) |
| 321 return false; |
| 322 if (audio_ && !audio_->SetStartPts(start_pts)) |
| 323 return false; |
| 324 if (video_ && !video_->SetStartPts(start_pts)) |
| 325 return false; |
| 326 |
| 327 if (!clock_->SetRate(rate_)) |
| 328 return false; |
| 329 if (!clock_->SetState(MediaClockDevice::kStateRunning)) |
| 330 return false; |
| 331 if (audio_ && !audio_->SetState(MediaComponentDevice::kStateRunning)) |
| 332 return false; |
| 333 if (video_ && !video_->SetState(MediaComponentDevice::kStateRunning)) |
| 334 return false; |
| 335 |
| 336 playing_ = true; |
| 337 return true; |
| 338 } |
| 339 |
| 340 bool MediaPipelineBackendAdapter::Stop() { |
| 341 DCHECK(playing_); |
| 342 playing_ = false; |
| 343 if (!clock_->SetState(MediaClockDevice::kStateIdle)) |
| 344 return false; |
| 345 if (audio_ && !audio_->SetState(MediaComponentDevice::kStateIdle)) |
| 346 return false; |
| 347 if (video_ && !video_->SetState(MediaComponentDevice::kStateIdle)) |
| 348 return false; |
| 349 return true; |
| 350 } |
| 351 |
| 352 bool MediaPipelineBackendAdapter::Pause() { |
| 353 DCHECK(playing_); |
| 354 return clock_->SetRate(0.0f); |
| 355 } |
| 356 |
| 357 bool MediaPipelineBackendAdapter::Resume() { |
| 358 DCHECK(playing_); |
| 359 return clock_->SetRate(rate_); |
| 360 } |
| 361 |
| 362 int64_t MediaPipelineBackendAdapter::GetCurrentPts() { |
| 363 return clock_->GetTimeMicroseconds(); |
| 364 } |
| 365 |
| 366 bool MediaPipelineBackendAdapter::SetPlaybackRate(float rate) { |
| 367 DCHECK_GE(rate, 0.0f); |
| 368 DCHECK_LE(rate, 1.0f); |
| 369 rate_ = rate; |
| 370 if (playing_) |
| 371 return clock_->SetRate(rate); |
| 372 return true; |
| 373 } |
| 374 |
| 375 void MediaPipelineBackendAdapter::OnEndOfAudioStream() { |
| 376 delegate_->OnEndOfStream(audio_decoder_); |
| 377 } |
| 378 |
| 379 void MediaPipelineBackendAdapter::OnEndOfVideoStream() { |
| 380 delegate_->OnEndOfStream(video_decoder_); |
| 381 } |
| 382 |
| 383 void MediaPipelineBackendAdapter::OnPushBufferComplete(bool video, |
| 384 BufferStatus status) { |
| 385 MAKE_SURE_MEDIA_THREAD( |
| 386 MediaPipelineBackendAdapter, OnPushBufferComplete, video, status); |
| 387 if (video) |
| 388 delegate_->OnPushBufferComplete(video_decoder_, status); |
| 389 else |
| 390 delegate_->OnPushBufferComplete(audio_decoder_, status); |
| 391 } |
| 392 |
| 393 void MediaPipelineBackendAdapter::OnNaturalSizeChanged(const Size& size) { |
| 394 delegate_->OnVideoResolutionChanged(video_decoder_, size); |
| 395 } |
| 396 |
| 397 } // namespace media |
| 398 } // namespace chromecast |
| OLD | NEW |