[Chromoting] Only raise the CONNECTED event when capabilities are negotiated.
[chromium-blink-merge.git] / media / blink / video_frame_compositor.cc
blob90af145c7ed71fb269f1f35731f372d5756d9512
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"
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "media/base/video_frame.h"
11 namespace media {
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:
23 return true;
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:
31 break;
33 return false;
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),
43 client_(nullptr),
44 rendering_(false),
45 callback_(nullptr) {
48 VideoFrameCompositor::~VideoFrameCompositor() {
49 DCHECK(compositor_task_runner_->BelongsToCurrentThread());
50 DCHECK(!callback_);
51 DCHECK(!rendering_);
52 if (client_)
53 client_->StopUsingProvider();
56 void VideoFrameCompositor::OnRendererStateUpdate() {
57 DCHECK(compositor_task_runner_->BelongsToCurrentThread());
58 if (!client_)
59 return;
61 base::AutoLock lock(lock_);
62 if (callback_) {
63 if (rendering_)
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());
83 if (client_)
84 client_->StopUsingProvider();
85 client_ = client;
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_);
103 return false;
106 void VideoFrameCompositor::Start(RenderCallback* callback) {
107 NOTREACHED();
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;
113 rendering_ = true;
114 compositor_task_runner_->PostTask(
115 FROM_HERE, base::Bind(&VideoFrameCompositor::OnRendererStateUpdate,
116 base::Unretained(this)));
119 void VideoFrameCompositor::Stop() {
120 NOTREACHED();
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_);
126 callback_ = nullptr;
127 rendering_ = false;
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(
137 FROM_HERE,
138 base::Bind(&VideoFrameCompositor::PaintFrameUsingOldRenderingPath,
139 base::Unretained(this), frame));
140 return;
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;
154 if (client_)
155 client_->DidReceiveFrame();
158 } // namespace media