OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/blink/video_frame_compositor.h" | 5 #include "media/blink/video_frame_compositor.h" |
6 | 6 |
7 #include "base/bind.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "media/base/video_frame.h" | 7 #include "media/base/video_frame.h" |
10 | 8 |
11 namespace media { | 9 namespace media { |
12 | 10 |
13 static bool IsOpaque(const scoped_refptr<VideoFrame>& frame) { | 11 static bool IsOpaque(const scoped_refptr<VideoFrame>& frame) { |
14 switch (frame->format()) { | 12 switch (frame->format()) { |
15 case VideoFrame::UNKNOWN: | 13 case VideoFrame::UNKNOWN: |
16 case VideoFrame::YV12: | 14 case VideoFrame::YV12: |
17 case VideoFrame::YV12J: | 15 case VideoFrame::YV12J: |
18 case VideoFrame::YV12HD: | 16 case VideoFrame::YV12HD: |
19 case VideoFrame::YV16: | 17 case VideoFrame::YV16: |
20 case VideoFrame::I420: | 18 case VideoFrame::I420: |
21 case VideoFrame::YV24: | 19 case VideoFrame::YV24: |
22 case VideoFrame::NV12: | 20 case VideoFrame::NV12: |
23 return true; | 21 return true; |
24 | 22 |
25 case VideoFrame::YV12A: | 23 case VideoFrame::YV12A: |
26 #if defined(VIDEO_HOLE) | 24 #if defined(VIDEO_HOLE) |
27 case VideoFrame::HOLE: | 25 case VideoFrame::HOLE: |
28 #endif // defined(VIDEO_HOLE) | 26 #endif // defined(VIDEO_HOLE) |
29 case VideoFrame::NATIVE_TEXTURE: | 27 case VideoFrame::NATIVE_TEXTURE: |
30 case VideoFrame::ARGB: | 28 case VideoFrame::ARGB: |
31 break; | 29 break; |
32 } | 30 } |
33 return false; | 31 return false; |
34 } | 32 } |
35 | 33 |
36 VideoFrameCompositor::VideoFrameCompositor( | 34 VideoFrameCompositor::VideoFrameCompositor( |
37 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, | |
38 const base::Callback<void(gfx::Size)>& natural_size_changed_cb, | 35 const base::Callback<void(gfx::Size)>& natural_size_changed_cb, |
39 const base::Callback<void(bool)>& opacity_changed_cb) | 36 const base::Callback<void(bool)>& opacity_changed_cb) |
40 : compositor_task_runner_(compositor_task_runner), | 37 : natural_size_changed_cb_(natural_size_changed_cb), |
41 natural_size_changed_cb_(natural_size_changed_cb), | |
42 opacity_changed_cb_(opacity_changed_cb), | 38 opacity_changed_cb_(opacity_changed_cb), |
43 client_(nullptr), | 39 client_(NULL) { |
44 rendering_(false), | |
45 callback_(nullptr) { | |
46 } | 40 } |
47 | 41 |
48 VideoFrameCompositor::~VideoFrameCompositor() { | 42 VideoFrameCompositor::~VideoFrameCompositor() { |
49 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
50 DCHECK(!callback_); | |
51 DCHECK(!rendering_); | |
52 if (client_) | 43 if (client_) |
53 client_->StopUsingProvider(); | 44 client_->StopUsingProvider(); |
54 } | 45 } |
55 | 46 |
56 void VideoFrameCompositor::OnRendererStateUpdate() { | |
57 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
58 if (!client_) | |
59 return; | |
60 | |
61 base::AutoLock lock(lock_); | |
62 if (callback_) { | |
63 if (rendering_) | |
64 client_->StartRendering(); | |
65 | |
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(); | |
70 } | |
71 } | |
72 | |
73 scoped_refptr<VideoFrame> | |
74 VideoFrameCompositor::GetCurrentFrameAndUpdateIfStale() { | |
75 // TODO(dalecurtis): Implement frame refresh when stale. | |
76 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
77 return GetCurrentFrame(); | |
78 } | |
79 | |
80 void VideoFrameCompositor::SetVideoFrameProviderClient( | 47 void VideoFrameCompositor::SetVideoFrameProviderClient( |
81 cc::VideoFrameProvider::Client* client) { | 48 cc::VideoFrameProvider::Client* client) { |
82 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
83 if (client_) | 49 if (client_) |
84 client_->StopUsingProvider(); | 50 client_->StopUsingProvider(); |
85 client_ = client; | 51 client_ = client; |
86 OnRendererStateUpdate(); | |
87 } | 52 } |
88 | 53 |
89 scoped_refptr<VideoFrame> VideoFrameCompositor::GetCurrentFrame() { | 54 scoped_refptr<VideoFrame> VideoFrameCompositor::GetCurrentFrame() { |
90 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
91 return current_frame_; | 55 return current_frame_; |
92 } | 56 } |
93 | 57 |
94 void VideoFrameCompositor::PutCurrentFrame() { | 58 void VideoFrameCompositor::PutCurrentFrame( |
95 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 59 const scoped_refptr<VideoFrame>& frame) { |
96 // TODO(dalecurtis): Wire up a flag for RenderCallback::OnFrameDropped(). | |
97 } | 60 } |
98 | 61 |
99 bool VideoFrameCompositor::UpdateCurrentFrame(base::TimeTicks deadline_min, | 62 void VideoFrameCompositor::UpdateCurrentFrame( |
100 base::TimeTicks deadline_max) { | |
101 // TODO(dalecurtis): Wire this up to RenderCallback::Render(). | |
102 base::AutoLock lock(lock_); | |
103 return false; | |
104 } | |
105 | |
106 void VideoFrameCompositor::Start(RenderCallback* callback) { | |
107 NOTREACHED(); | |
108 | |
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))); | |
117 } | |
118 | |
119 void VideoFrameCompositor::Stop() { | |
120 NOTREACHED(); | |
121 | |
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))); | |
131 } | |
132 | |
133 void VideoFrameCompositor::PaintFrameUsingOldRenderingPath( | |
134 const scoped_refptr<VideoFrame>& frame) { | 63 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; | |
141 } | |
142 | |
143 if (current_frame_.get() && | 64 if (current_frame_.get() && |
144 current_frame_->natural_size() != frame->natural_size()) { | 65 current_frame_->natural_size() != frame->natural_size()) { |
145 natural_size_changed_cb_.Run(frame->natural_size()); | 66 natural_size_changed_cb_.Run(frame->natural_size()); |
146 } | 67 } |
147 | 68 |
148 if (!current_frame_.get() || IsOpaque(current_frame_) != IsOpaque(frame)) { | 69 if (!current_frame_.get() || IsOpaque(current_frame_) != IsOpaque(frame)) { |
149 opacity_changed_cb_.Run(IsOpaque(frame)); | 70 opacity_changed_cb_.Run(IsOpaque(frame)); |
150 } | 71 } |
151 | 72 |
152 current_frame_ = frame; | 73 current_frame_ = frame; |
153 | 74 |
154 if (client_) | 75 if (client_) |
155 client_->DidReceiveFrame(); | 76 client_->DidReceiveFrame(); |
156 } | 77 } |
157 | 78 |
158 } // namespace media | 79 } // namespace media |
OLD | NEW |