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.
5 #include "media/blink/video_frame_compositor.h"
8 #include "base/message_loop/message_loop.h"
9 #include "media/base/video_frame.h"
13 static bool IsOpaque(const scoped_refptr
<VideoFrame
>& frame
) {
14 switch (frame
->format()) {
15 case VideoFrame::UNKNOWN
:
16 case VideoFrame::YV12
:
17 case VideoFrame::YV12J
:
18 case VideoFrame::YV12HD
:
19 case VideoFrame::YV16
:
20 case VideoFrame::I420
:
21 case VideoFrame::YV24
:
22 case VideoFrame::NV12
:
25 case VideoFrame::YV12A
:
26 #if defined(VIDEO_HOLE)
27 case VideoFrame::HOLE
:
28 #endif // defined(VIDEO_HOLE)
29 case VideoFrame::NATIVE_TEXTURE
:
30 case VideoFrame::ARGB
:
36 VideoFrameCompositor::VideoFrameCompositor(
37 const scoped_refptr
<base::SingleThreadTaskRunner
>& compositor_task_runner
,
38 const base::Callback
<void(gfx::Size
)>& natural_size_changed_cb
,
39 const base::Callback
<void(bool)>& opacity_changed_cb
)
40 : compositor_task_runner_(compositor_task_runner
),
41 natural_size_changed_cb_(natural_size_changed_cb
),
42 opacity_changed_cb_(opacity_changed_cb
),
48 VideoFrameCompositor::~VideoFrameCompositor() {
49 DCHECK(compositor_task_runner_
->BelongsToCurrentThread());
53 client_
->StopUsingProvider();
56 void VideoFrameCompositor::OnRendererStateUpdate() {
57 DCHECK(compositor_task_runner_
->BelongsToCurrentThread());
61 base::AutoLock
lock(lock_
);
64 client_
->StartRendering();
66 // TODO(dalecurtis): This will need to request the first frame so we have
67 // something to show, even if playback hasn't started yet.
68 } else if (rendering_
) {
69 client_
->StopRendering();
73 scoped_refptr
<VideoFrame
>
74 VideoFrameCompositor::GetCurrentFrameAndUpdateIfStale() {
75 // TODO(dalecurtis): Implement frame refresh when stale.
76 DCHECK(compositor_task_runner_
->BelongsToCurrentThread());
77 return GetCurrentFrame();
80 void VideoFrameCompositor::SetVideoFrameProviderClient(
81 cc::VideoFrameProvider::Client
* client
) {
82 DCHECK(compositor_task_runner_
->BelongsToCurrentThread());
84 client_
->StopUsingProvider();
86 OnRendererStateUpdate();
89 scoped_refptr
<VideoFrame
> VideoFrameCompositor::GetCurrentFrame() {
90 DCHECK(compositor_task_runner_
->BelongsToCurrentThread());
91 return current_frame_
;
94 void VideoFrameCompositor::PutCurrentFrame() {
95 DCHECK(compositor_task_runner_
->BelongsToCurrentThread());
96 // TODO(dalecurtis): Wire up a flag for RenderCallback::OnFrameDropped().
99 bool VideoFrameCompositor::UpdateCurrentFrame(base::TimeTicks deadline_min
,
100 base::TimeTicks deadline_max
) {
101 // TODO(dalecurtis): Wire this up to RenderCallback::Render().
102 base::AutoLock
lock(lock_
);
106 void VideoFrameCompositor::Start(RenderCallback
* callback
) {
109 // Called from the media thread, so acquire the callback under lock before
110 // returning in case a Stop() call comes in before the PostTask is processed.
111 base::AutoLock
lock(lock_
);
112 callback_
= callback
;
114 compositor_task_runner_
->PostTask(
115 FROM_HERE
, base::Bind(&VideoFrameCompositor::OnRendererStateUpdate
,
116 base::Unretained(this)));
119 void VideoFrameCompositor::Stop() {
122 // Called from the media thread, so release the callback under lock before
123 // returning to avoid a pending UpdateCurrentFrame() call occurring before
124 // the PostTask is processed.
125 base::AutoLock
lock(lock_
);
128 compositor_task_runner_
->PostTask(
129 FROM_HERE
, base::Bind(&VideoFrameCompositor::OnRendererStateUpdate
,
130 base::Unretained(this)));
133 void VideoFrameCompositor::PaintFrameUsingOldRenderingPath(
134 const scoped_refptr
<VideoFrame
>& frame
) {
135 if (!compositor_task_runner_
->BelongsToCurrentThread()) {
136 compositor_task_runner_
->PostTask(
138 base::Bind(&VideoFrameCompositor::PaintFrameUsingOldRenderingPath
,
139 base::Unretained(this), frame
));
143 if (current_frame_
.get() &&
144 current_frame_
->natural_size() != frame
->natural_size()) {
145 natural_size_changed_cb_
.Run(frame
->natural_size());
148 if (!current_frame_
.get() || IsOpaque(current_frame_
) != IsOpaque(frame
)) {
149 opacity_changed_cb_
.Run(IsOpaque(frame
));
152 current_frame_
= frame
;
155 client_
->DidReceiveFrame();