null_video_sink.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. #include "media/base/null_video_sink.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "base/location.h"
  8. #include "base/task/single_thread_task_runner.h"
  9. namespace media {
  10. NullVideoSink::NullVideoSink(
  11. bool clockless,
  12. base::TimeDelta interval,
  13. const NewFrameCB& new_frame_cb,
  14. const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
  15. : clockless_(clockless),
  16. interval_(interval),
  17. new_frame_cb_(new_frame_cb),
  18. task_runner_(task_runner),
  19. started_(false),
  20. callback_(nullptr),
  21. tick_clock_(base::DefaultTickClock::GetInstance()),
  22. background_render_(false) {}
  23. NullVideoSink::~NullVideoSink() {
  24. DCHECK(!started_);
  25. }
  26. void NullVideoSink::Start(RenderCallback* callback) {
  27. DCHECK(task_runner_->BelongsToCurrentThread());
  28. DCHECK(!started_);
  29. callback_ = callback;
  30. started_ = true;
  31. last_now_ = current_render_time_ = tick_clock_->NowTicks();
  32. cancelable_worker_.Reset(
  33. base::BindRepeating(&NullVideoSink::CallRender, base::Unretained(this)));
  34. task_runner_->PostTask(FROM_HERE, cancelable_worker_.callback());
  35. }
  36. void NullVideoSink::Stop() {
  37. DCHECK(task_runner_->BelongsToCurrentThread());
  38. cancelable_worker_.Cancel();
  39. started_ = false;
  40. if (stop_cb_)
  41. std::move(stop_cb_).Run();
  42. }
  43. void NullVideoSink::CallRender() {
  44. DCHECK(task_runner_->BelongsToCurrentThread());
  45. DCHECK(started_);
  46. const base::TimeTicks end_of_interval = current_render_time_ + interval_;
  47. scoped_refptr<VideoFrame> new_frame = callback_->Render(
  48. current_render_time_, end_of_interval,
  49. background_render_
  50. ? VideoRendererSink::RenderCallback::RenderingMode::kBackground
  51. : VideoRendererSink::RenderCallback::RenderingMode::kNormal);
  52. DCHECK(new_frame);
  53. const bool is_new_frame = new_frame != last_frame_;
  54. last_frame_ = new_frame;
  55. if (is_new_frame && new_frame_cb_)
  56. new_frame_cb_.Run(new_frame);
  57. current_render_time_ += interval_;
  58. if (clockless_) {
  59. task_runner_->PostTask(FROM_HERE, cancelable_worker_.callback());
  60. return;
  61. }
  62. const base::TimeTicks now = tick_clock_->NowTicks();
  63. base::TimeDelta delay;
  64. if (last_now_ == now) {
  65. // The tick clock is frozen in this case, so don't advance deadline.
  66. delay = interval_;
  67. current_render_time_ = now;
  68. } else {
  69. // If we're behind, find the next nearest on time interval.
  70. delay = current_render_time_ - now;
  71. if (delay.is_negative())
  72. delay = interval_ + (delay % interval_);
  73. current_render_time_ = now + delay;
  74. last_now_ = now;
  75. }
  76. task_runner_->PostDelayedTask(FROM_HERE, cancelable_worker_.callback(),
  77. delay);
  78. }
  79. void NullVideoSink::PaintSingleFrame(scoped_refptr<VideoFrame> frame,
  80. bool repaint_duplicate_frame) {
  81. if (!repaint_duplicate_frame && frame == last_frame_)
  82. return;
  83. last_frame_ = frame;
  84. if (new_frame_cb_)
  85. new_frame_cb_.Run(std::move(frame));
  86. }
  87. } // namespace media