OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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/media_pipeline_device_fake.h" |
| 6 |
| 7 #include <list> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" |
| 11 #include "base/location.h" |
| 12 #include "base/logging.h" |
| 13 #include "base/macros.h" |
| 14 #include "base/message_loop/message_loop_proxy.h" |
| 15 #include "chromecast/media/cma/backend/audio_pipeline_device.h" |
| 16 #include "chromecast/media/cma/backend/media_clock_device.h" |
| 17 #include "chromecast/media/cma/backend/media_component_device.h" |
| 18 #include "chromecast/media/cma/backend/video_pipeline_device.h" |
| 19 #include "chromecast/media/cma/base/decoder_buffer_base.h" |
| 20 #include "media/base/audio_decoder_config.h" |
| 21 #include "media/base/buffers.h" |
| 22 #include "media/base/video_decoder_config.h" |
| 23 |
| 24 namespace chromecast { |
| 25 namespace media { |
| 26 |
| 27 class MediaClockDeviceFake : public MediaClockDevice { |
| 28 public: |
| 29 MediaClockDeviceFake(); |
| 30 virtual ~MediaClockDeviceFake(); |
| 31 |
| 32 // MediaClockDevice implementation. |
| 33 virtual State GetState() const override; |
| 34 virtual bool SetState(State new_state) override; |
| 35 virtual bool ResetTimeline(base::TimeDelta time) override; |
| 36 virtual bool SetRate(float rate) override; |
| 37 virtual base::TimeDelta GetTime() override; |
| 38 |
| 39 private: |
| 40 State state_; |
| 41 |
| 42 // Media time sampled at STC time |stc_|. |
| 43 base::TimeDelta media_time_; |
| 44 base::TimeTicks stc_; |
| 45 |
| 46 float rate_; |
| 47 |
| 48 DISALLOW_COPY_AND_ASSIGN(MediaClockDeviceFake); |
| 49 }; |
| 50 |
| 51 MediaClockDeviceFake::MediaClockDeviceFake() |
| 52 : state_(kStateUninitialized), |
| 53 media_time_(::media::kNoTimestamp()) { |
| 54 DetachFromThread(); |
| 55 } |
| 56 |
| 57 MediaClockDeviceFake::~MediaClockDeviceFake() { |
| 58 } |
| 59 |
| 60 MediaClockDevice::State MediaClockDeviceFake::GetState() const { |
| 61 DCHECK(CalledOnValidThread()); |
| 62 return state_; |
| 63 } |
| 64 |
| 65 bool MediaClockDeviceFake::SetState(State new_state) { |
| 66 DCHECK(CalledOnValidThread()); |
| 67 if (!MediaClockDevice::IsValidStateTransition(state_, new_state)) |
| 68 return false; |
| 69 |
| 70 if (new_state == state_) |
| 71 return true; |
| 72 |
| 73 state_ = new_state; |
| 74 |
| 75 if (state_ == kStateRunning) { |
| 76 stc_ = base::TimeTicks::Now(); |
| 77 DCHECK(media_time_ != ::media::kNoTimestamp()); |
| 78 return true; |
| 79 } |
| 80 |
| 81 if (state_ == kStateIdle) { |
| 82 media_time_ = ::media::kNoTimestamp(); |
| 83 return true; |
| 84 } |
| 85 |
| 86 return true; |
| 87 } |
| 88 |
| 89 bool MediaClockDeviceFake::ResetTimeline(base::TimeDelta time) { |
| 90 DCHECK(CalledOnValidThread()); |
| 91 DCHECK_EQ(state_, kStateIdle); |
| 92 media_time_ = time; |
| 93 return true; |
| 94 } |
| 95 |
| 96 bool MediaClockDeviceFake::SetRate(float rate) { |
| 97 DCHECK(CalledOnValidThread()); |
| 98 if (state_ == kStateRunning) { |
| 99 base::TimeTicks now = base::TimeTicks::Now(); |
| 100 media_time_ = media_time_ + (now - stc_) * rate_; |
| 101 stc_ = now; |
| 102 } |
| 103 |
| 104 rate_ = rate; |
| 105 return true; |
| 106 } |
| 107 |
| 108 base::TimeDelta MediaClockDeviceFake::GetTime() { |
| 109 DCHECK(CalledOnValidThread()); |
| 110 if (state_ != kStateRunning) |
| 111 return media_time_; |
| 112 |
| 113 if (media_time_ == ::media::kNoTimestamp()) |
| 114 return ::media::kNoTimestamp(); |
| 115 |
| 116 base::TimeTicks now = base::TimeTicks::Now(); |
| 117 base::TimeDelta interpolated_media_time = |
| 118 media_time_ + (now - stc_) * rate_; |
| 119 return interpolated_media_time; |
| 120 } |
| 121 |
| 122 |
| 123 namespace { |
| 124 |
| 125 // Maximum number of frames that can be buffered. |
| 126 const size_t kMaxFrameCount = 20; |
| 127 |
| 128 } // namespace |
| 129 |
| 130 class MediaComponentDeviceFake : public MediaComponentDevice { |
| 131 public: |
| 132 explicit MediaComponentDeviceFake(MediaClockDeviceFake* media_clock_device); |
| 133 virtual ~MediaComponentDeviceFake(); |
| 134 |
| 135 // MediaComponentDevice implementation. |
| 136 virtual void SetClient(const Client& client) override; |
| 137 virtual State GetState() const override; |
| 138 virtual bool SetState(State new_state) override; |
| 139 virtual bool SetStartPts(base::TimeDelta time) override; |
| 140 virtual FrameStatus PushFrame( |
| 141 const scoped_refptr<DecryptContext>& decrypt_context, |
| 142 const scoped_refptr<DecoderBufferBase>& buffer, |
| 143 const FrameStatusCB& completion_cb) override; |
| 144 virtual base::TimeDelta GetRenderingTime() const override; |
| 145 virtual base::TimeDelta GetRenderingDelay() const override; |
| 146 virtual bool GetStatistics(Statistics* stats) const override; |
| 147 |
| 148 private: |
| 149 struct FakeDecoderBuffer { |
| 150 FakeDecoderBuffer(); |
| 151 ~FakeDecoderBuffer(); |
| 152 |
| 153 // Buffer size. |
| 154 size_t size; |
| 155 |
| 156 // Presentation timestamp. |
| 157 base::TimeDelta pts; |
| 158 }; |
| 159 |
| 160 void RenderTask(); |
| 161 |
| 162 MediaClockDeviceFake* const media_clock_device_; |
| 163 Client client_; |
| 164 |
| 165 State state_; |
| 166 |
| 167 // Indicate whether the end of stream has been received. |
| 168 bool is_eos_; |
| 169 |
| 170 // Media time of the last rendered audio sample. |
| 171 base::TimeDelta rendering_time_; |
| 172 |
| 173 // Frame decoded/rendered since the pipeline left the idle state. |
| 174 uint64 decoded_frame_count_; |
| 175 uint64 decoded_byte_count_; |
| 176 |
| 177 // List of frames not rendered yet. |
| 178 std::list<FakeDecoderBuffer> frames_; |
| 179 |
| 180 // Indicate whether there is a scheduled rendering task. |
| 181 bool scheduled_rendering_task_; |
| 182 |
| 183 // Pending frame. |
| 184 scoped_refptr<DecoderBufferBase> pending_buffer_; |
| 185 FrameStatusCB frame_pushed_cb_; |
| 186 |
| 187 base::WeakPtr<MediaComponentDeviceFake> weak_this_; |
| 188 base::WeakPtrFactory<MediaComponentDeviceFake> weak_factory_; |
| 189 |
| 190 DISALLOW_COPY_AND_ASSIGN(MediaComponentDeviceFake); |
| 191 }; |
| 192 |
| 193 MediaComponentDeviceFake::FakeDecoderBuffer::FakeDecoderBuffer() |
| 194 : size(0) { |
| 195 } |
| 196 |
| 197 MediaComponentDeviceFake::FakeDecoderBuffer::~FakeDecoderBuffer() { |
| 198 } |
| 199 |
| 200 MediaComponentDeviceFake::MediaComponentDeviceFake( |
| 201 MediaClockDeviceFake* media_clock_device) |
| 202 : media_clock_device_(media_clock_device), |
| 203 state_(kStateUninitialized), |
| 204 rendering_time_(::media::kNoTimestamp()), |
| 205 decoded_frame_count_(0), |
| 206 decoded_byte_count_(0), |
| 207 scheduled_rendering_task_(false), |
| 208 weak_factory_(this) { |
| 209 weak_this_ = weak_factory_.GetWeakPtr(); |
| 210 DetachFromThread(); |
| 211 } |
| 212 |
| 213 MediaComponentDeviceFake::~MediaComponentDeviceFake() { |
| 214 } |
| 215 |
| 216 void MediaComponentDeviceFake::SetClient(const Client& client) { |
| 217 DCHECK(CalledOnValidThread()); |
| 218 client_ = client; |
| 219 } |
| 220 |
| 221 MediaComponentDevice::State MediaComponentDeviceFake::GetState() const { |
| 222 DCHECK(CalledOnValidThread()); |
| 223 return state_; |
| 224 } |
| 225 |
| 226 bool MediaComponentDeviceFake::SetState(State new_state) { |
| 227 DCHECK(CalledOnValidThread()); |
| 228 if (!MediaComponentDevice::IsValidStateTransition(state_, new_state)) |
| 229 return false; |
| 230 state_ = new_state; |
| 231 |
| 232 if (state_ == kStateIdle) { |
| 233 // Back to the idle state: reset a bunch of parameters. |
| 234 is_eos_ = false; |
| 235 rendering_time_ = ::media::kNoTimestamp(); |
| 236 decoded_frame_count_ = 0; |
| 237 decoded_byte_count_ = 0; |
| 238 frames_.clear(); |
| 239 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 240 frame_pushed_cb_.Reset(); |
| 241 return true; |
| 242 } |
| 243 |
| 244 if (state_ == kStateRunning) { |
| 245 if (!scheduled_rendering_task_) { |
| 246 scheduled_rendering_task_ = true; |
| 247 base::MessageLoopProxy::current()->PostTask( |
| 248 FROM_HERE, |
| 249 base::Bind(&MediaComponentDeviceFake::RenderTask, weak_this_)); |
| 250 } |
| 251 return true; |
| 252 } |
| 253 |
| 254 return true; |
| 255 } |
| 256 |
| 257 bool MediaComponentDeviceFake::SetStartPts(base::TimeDelta time) { |
| 258 DCHECK(CalledOnValidThread()); |
| 259 DCHECK_EQ(state_, kStateIdle); |
| 260 rendering_time_ = time; |
| 261 return true; |
| 262 } |
| 263 |
| 264 MediaComponentDevice::FrameStatus MediaComponentDeviceFake::PushFrame( |
| 265 const scoped_refptr<DecryptContext>& decrypt_context, |
| 266 const scoped_refptr<DecoderBufferBase>& buffer, |
| 267 const FrameStatusCB& completion_cb) { |
| 268 DCHECK(CalledOnValidThread()); |
| 269 DCHECK(state_ == kStatePaused || state_ == kStateRunning); |
| 270 DCHECK(!is_eos_); |
| 271 DCHECK(!pending_buffer_.get()); |
| 272 DCHECK(buffer.get()); |
| 273 |
| 274 if (buffer->end_of_stream()) { |
| 275 is_eos_ = true; |
| 276 return kFrameSuccess; |
| 277 } |
| 278 |
| 279 if (frames_.size() > kMaxFrameCount) { |
| 280 pending_buffer_ = buffer; |
| 281 frame_pushed_cb_ = completion_cb; |
| 282 return kFramePending; |
| 283 } |
| 284 |
| 285 FakeDecoderBuffer fake_buffer; |
| 286 fake_buffer.size = buffer->data_size(); |
| 287 fake_buffer.pts = buffer->timestamp(); |
| 288 frames_.push_back(fake_buffer); |
| 289 return kFrameSuccess; |
| 290 } |
| 291 |
| 292 base::TimeDelta MediaComponentDeviceFake::GetRenderingTime() const { |
| 293 return rendering_time_; |
| 294 } |
| 295 |
| 296 base::TimeDelta MediaComponentDeviceFake::GetRenderingDelay() const { |
| 297 NOTIMPLEMENTED(); |
| 298 return ::media::kNoTimestamp(); |
| 299 } |
| 300 |
| 301 void MediaComponentDeviceFake::RenderTask() { |
| 302 scheduled_rendering_task_ = false; |
| 303 |
| 304 if (state_ != kStateRunning) |
| 305 return; |
| 306 |
| 307 base::TimeDelta media_time = media_clock_device_->GetTime(); |
| 308 if (media_time == ::media::kNoTimestamp()) { |
| 309 scheduled_rendering_task_ = true; |
| 310 base::MessageLoopProxy::current()->PostDelayedTask( |
| 311 FROM_HERE, |
| 312 base::Bind(&MediaComponentDeviceFake::RenderTask, weak_this_), |
| 313 base::TimeDelta::FromMilliseconds(50)); |
| 314 return; |
| 315 } |
| 316 |
| 317 while (!frames_.empty() && frames_.front().pts <= media_time) { |
| 318 rendering_time_ = frames_.front().pts; |
| 319 decoded_frame_count_++; |
| 320 decoded_byte_count_ += frames_.front().size; |
| 321 frames_.pop_front(); |
| 322 if (pending_buffer_.get()) { |
| 323 FakeDecoderBuffer fake_buffer; |
| 324 fake_buffer.size = pending_buffer_->data_size(); |
| 325 fake_buffer.pts = pending_buffer_->timestamp(); |
| 326 frames_.push_back(fake_buffer); |
| 327 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 328 base::ResetAndReturn(&frame_pushed_cb_).Run(kFrameSuccess); |
| 329 } |
| 330 } |
| 331 |
| 332 if (frames_.empty() && is_eos_) { |
| 333 if (!client_.eos_cb.is_null()) |
| 334 client_.eos_cb.Run(); |
| 335 return; |
| 336 } |
| 337 |
| 338 scheduled_rendering_task_ = true; |
| 339 base::MessageLoopProxy::current()->PostDelayedTask( |
| 340 FROM_HERE, |
| 341 base::Bind(&MediaComponentDeviceFake::RenderTask, weak_this_), |
| 342 base::TimeDelta::FromMilliseconds(50)); |
| 343 } |
| 344 |
| 345 bool MediaComponentDeviceFake::GetStatistics(Statistics* stats) const { |
| 346 if (state_ != kStateRunning) |
| 347 return false; |
| 348 |
| 349 // Note: what is returned here is not the number of samples but the number of |
| 350 // frames. The value is different for audio. |
| 351 stats->decoded_bytes = decoded_byte_count_; |
| 352 stats->decoded_samples = decoded_frame_count_; |
| 353 stats->dropped_samples = 0; |
| 354 return true; |
| 355 } |
| 356 |
| 357 |
| 358 class AudioPipelineDeviceFake : public AudioPipelineDevice { |
| 359 public: |
| 360 explicit AudioPipelineDeviceFake(MediaClockDeviceFake* media_clock_device); |
| 361 virtual ~AudioPipelineDeviceFake(); |
| 362 |
| 363 // AudioPipelineDevice implementation. |
| 364 virtual void SetClient(const Client& client) override; |
| 365 virtual State GetState() const override; |
| 366 virtual bool SetState(State new_state) override; |
| 367 virtual bool SetStartPts(base::TimeDelta time) override; |
| 368 virtual FrameStatus PushFrame( |
| 369 const scoped_refptr<DecryptContext>& decrypt_context, |
| 370 const scoped_refptr<DecoderBufferBase>& buffer, |
| 371 const FrameStatusCB& completion_cb) override; |
| 372 virtual base::TimeDelta GetRenderingTime() const override; |
| 373 virtual base::TimeDelta GetRenderingDelay() const override; |
| 374 virtual bool SetConfig(const ::media::AudioDecoderConfig& config) override; |
| 375 virtual void SetStreamVolumeMultiplier(float multiplier) override; |
| 376 virtual bool GetStatistics(Statistics* stats) const override; |
| 377 |
| 378 private: |
| 379 scoped_ptr<MediaComponentDeviceFake> fake_pipeline_; |
| 380 |
| 381 ::media::AudioDecoderConfig config_; |
| 382 |
| 383 DISALLOW_COPY_AND_ASSIGN(AudioPipelineDeviceFake); |
| 384 }; |
| 385 |
| 386 AudioPipelineDeviceFake::AudioPipelineDeviceFake( |
| 387 MediaClockDeviceFake* media_clock_device) |
| 388 : fake_pipeline_(new MediaComponentDeviceFake(media_clock_device)) { |
| 389 DetachFromThread(); |
| 390 } |
| 391 |
| 392 AudioPipelineDeviceFake::~AudioPipelineDeviceFake() { |
| 393 } |
| 394 |
| 395 void AudioPipelineDeviceFake::SetClient(const Client& client) { |
| 396 fake_pipeline_->SetClient(client); |
| 397 } |
| 398 |
| 399 MediaComponentDevice::State AudioPipelineDeviceFake::GetState() const { |
| 400 return fake_pipeline_->GetState(); |
| 401 } |
| 402 |
| 403 bool AudioPipelineDeviceFake::SetState(State new_state) { |
| 404 bool success = fake_pipeline_->SetState(new_state); |
| 405 if (!success) |
| 406 return false; |
| 407 |
| 408 if (new_state == kStateIdle) { |
| 409 DCHECK(config_.IsValidConfig()); |
| 410 } |
| 411 if (new_state == kStateUninitialized) { |
| 412 config_ = ::media::AudioDecoderConfig(); |
| 413 } |
| 414 return true; |
| 415 } |
| 416 |
| 417 bool AudioPipelineDeviceFake::SetStartPts(base::TimeDelta time) { |
| 418 return fake_pipeline_->SetStartPts(time); |
| 419 } |
| 420 |
| 421 MediaComponentDevice::FrameStatus AudioPipelineDeviceFake::PushFrame( |
| 422 const scoped_refptr<DecryptContext>& decrypt_context, |
| 423 const scoped_refptr<DecoderBufferBase>& buffer, |
| 424 const FrameStatusCB& completion_cb) { |
| 425 return fake_pipeline_->PushFrame(decrypt_context, buffer, completion_cb); |
| 426 } |
| 427 |
| 428 base::TimeDelta AudioPipelineDeviceFake::GetRenderingTime() const { |
| 429 return fake_pipeline_->GetRenderingTime(); |
| 430 } |
| 431 |
| 432 base::TimeDelta AudioPipelineDeviceFake::GetRenderingDelay() const { |
| 433 return fake_pipeline_->GetRenderingDelay(); |
| 434 } |
| 435 |
| 436 bool AudioPipelineDeviceFake::SetConfig( |
| 437 const ::media::AudioDecoderConfig& config) { |
| 438 DCHECK(CalledOnValidThread()); |
| 439 if (!config.IsValidConfig()) |
| 440 return false; |
| 441 config_ = config; |
| 442 return true; |
| 443 } |
| 444 |
| 445 void AudioPipelineDeviceFake::SetStreamVolumeMultiplier(float multiplier) { |
| 446 DCHECK(CalledOnValidThread()); |
| 447 } |
| 448 |
| 449 bool AudioPipelineDeviceFake::GetStatistics(Statistics* stats) const { |
| 450 return fake_pipeline_->GetStatistics(stats); |
| 451 } |
| 452 |
| 453 |
| 454 class VideoPipelineDeviceFake : public VideoPipelineDevice { |
| 455 public: |
| 456 explicit VideoPipelineDeviceFake(MediaClockDeviceFake* media_clock_device); |
| 457 virtual ~VideoPipelineDeviceFake(); |
| 458 |
| 459 // VideoPipelineDevice implementation. |
| 460 virtual void SetClient(const Client& client) override; |
| 461 virtual State GetState() const override; |
| 462 virtual bool SetState(State new_state) override; |
| 463 virtual bool SetStartPts(base::TimeDelta time) override; |
| 464 virtual FrameStatus PushFrame( |
| 465 const scoped_refptr<DecryptContext>& decrypt_context, |
| 466 const scoped_refptr<DecoderBufferBase>& buffer, |
| 467 const FrameStatusCB& completion_cb) override; |
| 468 virtual base::TimeDelta GetRenderingTime() const override; |
| 469 virtual base::TimeDelta GetRenderingDelay() const override; |
| 470 virtual void SetVideoClient(const VideoClient& client) override; |
| 471 virtual bool SetConfig(const ::media::VideoDecoderConfig& config) override; |
| 472 virtual bool GetStatistics(Statistics* stats) const override; |
| 473 |
| 474 private: |
| 475 scoped_ptr<MediaComponentDeviceFake> fake_pipeline_; |
| 476 |
| 477 ::media::VideoDecoderConfig config_; |
| 478 |
| 479 DISALLOW_COPY_AND_ASSIGN(VideoPipelineDeviceFake); |
| 480 }; |
| 481 |
| 482 VideoPipelineDeviceFake::VideoPipelineDeviceFake( |
| 483 MediaClockDeviceFake* media_clock_device) |
| 484 : fake_pipeline_(new MediaComponentDeviceFake(media_clock_device)) { |
| 485 DetachFromThread(); |
| 486 } |
| 487 |
| 488 VideoPipelineDeviceFake::~VideoPipelineDeviceFake() { |
| 489 } |
| 490 |
| 491 void VideoPipelineDeviceFake::SetClient(const Client& client) { |
| 492 fake_pipeline_->SetClient(client); |
| 493 } |
| 494 |
| 495 MediaComponentDevice::State VideoPipelineDeviceFake::GetState() const { |
| 496 return fake_pipeline_->GetState(); |
| 497 } |
| 498 |
| 499 bool VideoPipelineDeviceFake::SetState(State new_state) { |
| 500 bool success = fake_pipeline_->SetState(new_state); |
| 501 if (!success) |
| 502 return false; |
| 503 |
| 504 if (new_state == kStateIdle) { |
| 505 DCHECK(config_.IsValidConfig()); |
| 506 } |
| 507 if (new_state == kStateUninitialized) { |
| 508 config_ = ::media::VideoDecoderConfig(); |
| 509 } |
| 510 return true; |
| 511 } |
| 512 |
| 513 bool VideoPipelineDeviceFake::SetStartPts(base::TimeDelta time) { |
| 514 return fake_pipeline_->SetStartPts(time); |
| 515 } |
| 516 |
| 517 MediaComponentDevice::FrameStatus VideoPipelineDeviceFake::PushFrame( |
| 518 const scoped_refptr<DecryptContext>& decrypt_context, |
| 519 const scoped_refptr<DecoderBufferBase>& buffer, |
| 520 const FrameStatusCB& completion_cb) { |
| 521 return fake_pipeline_->PushFrame(decrypt_context, buffer, completion_cb); |
| 522 } |
| 523 |
| 524 base::TimeDelta VideoPipelineDeviceFake::GetRenderingTime() const { |
| 525 return fake_pipeline_->GetRenderingTime(); |
| 526 } |
| 527 |
| 528 base::TimeDelta VideoPipelineDeviceFake::GetRenderingDelay() const { |
| 529 return fake_pipeline_->GetRenderingDelay(); |
| 530 } |
| 531 |
| 532 void VideoPipelineDeviceFake::SetVideoClient(const VideoClient& client) { |
| 533 } |
| 534 |
| 535 bool VideoPipelineDeviceFake::SetConfig( |
| 536 const ::media::VideoDecoderConfig& config) { |
| 537 DCHECK(CalledOnValidThread()); |
| 538 if (!config.IsValidConfig()) |
| 539 return false; |
| 540 config_ = config; |
| 541 return true; |
| 542 } |
| 543 |
| 544 bool VideoPipelineDeviceFake::GetStatistics(Statistics* stats) const { |
| 545 return fake_pipeline_->GetStatistics(stats); |
| 546 } |
| 547 |
| 548 |
| 549 MediaPipelineDeviceFake::MediaPipelineDeviceFake() |
| 550 : media_clock_device_(new MediaClockDeviceFake()), |
| 551 audio_pipeline_device_( |
| 552 new AudioPipelineDeviceFake(media_clock_device_.get())), |
| 553 video_pipeline_device_( |
| 554 new VideoPipelineDeviceFake(media_clock_device_.get())) { |
| 555 } |
| 556 |
| 557 MediaPipelineDeviceFake::~MediaPipelineDeviceFake() { |
| 558 } |
| 559 |
| 560 AudioPipelineDevice* MediaPipelineDeviceFake::GetAudioPipelineDevice() const { |
| 561 return audio_pipeline_device_.get(); |
| 562 } |
| 563 |
| 564 VideoPipelineDevice* MediaPipelineDeviceFake::GetVideoPipelineDevice() const { |
| 565 return video_pipeline_device_.get(); |
| 566 } |
| 567 |
| 568 MediaClockDevice* MediaPipelineDeviceFake::GetMediaClockDevice() const { |
| 569 return media_clock_device_.get(); |
| 570 } |
| 571 |
| 572 } // namespace media |
| 573 } // namespace chromecast |
OLD | NEW |