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.
5 #include "media/base/null_video_sink.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
14 NullVideoSink::NullVideoSink(
16 base::TimeDelta interval
,
17 const NewFrameCB
& new_frame_cb
,
18 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
)
19 : clockless_(clockless
),
21 new_frame_cb_(new_frame_cb
),
22 task_runner_(task_runner
),
25 tick_clock_(&default_tick_clock_
),
26 background_render_(false) {
29 NullVideoSink::~NullVideoSink() {
33 void NullVideoSink::Start(RenderCallback
* callback
) {
34 DCHECK(task_runner_
->BelongsToCurrentThread());
38 last_now_
= current_render_time_
= tick_clock_
->NowTicks();
39 cancelable_worker_
.Reset(
40 base::Bind(&NullVideoSink::CallRender
, base::Unretained(this)));
41 task_runner_
->PostTask(FROM_HERE
, cancelable_worker_
.callback());
44 void NullVideoSink::Stop() {
45 DCHECK(task_runner_
->BelongsToCurrentThread());
46 cancelable_worker_
.Cancel();
48 if (!stop_cb_
.is_null())
49 base::ResetAndReturn(&stop_cb_
).Run();
52 void NullVideoSink::CallRender() {
53 DCHECK(task_runner_
->BelongsToCurrentThread());
56 const base::TimeTicks end_of_interval
= current_render_time_
+ interval_
;
57 scoped_refptr
<VideoFrame
> new_frame
= callback_
->Render(
58 current_render_time_
, end_of_interval
, background_render_
);
59 const bool is_new_frame
= new_frame
!= last_frame_
;
60 last_frame_
= new_frame
;
61 if (is_new_frame
&& !new_frame_cb_
.is_null())
62 new_frame_cb_
.Run(new_frame
);
64 current_render_time_
+= interval_
;
67 task_runner_
->PostTask(FROM_HERE
, cancelable_worker_
.callback());
71 const base::TimeTicks now
= tick_clock_
->NowTicks();
72 base::TimeDelta delay
;
73 if (last_now_
== now
) {
74 // The tick clock is frozen in this case, so don't advance deadline.
76 current_render_time_
= now
;
78 // If we're behind, find the next nearest on time interval.
79 delay
= current_render_time_
- now
;
80 if (delay
< base::TimeDelta())
81 delay
+= interval_
* (-delay
/ interval_
+ 1);
82 current_render_time_
= now
+ delay
;
86 task_runner_
->PostDelayedTask(FROM_HERE
, cancelable_worker_
.callback(),
90 void NullVideoSink::PaintFrameUsingOldRenderingPath(
91 const scoped_refptr
<VideoFrame
>& frame
) {
92 new_frame_cb_
.Run(frame
);