Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: cc/resources/video_resource_updater.cc

Issue 13445009: cc: Move video upload to VideoResourceUpdater. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix software compositing Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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
5 #include "cc/resources/video_resource_updater.h"
6
7 #include "base/bind.h"
8 #include "cc/output/gl_renderer.h"
9 #include "cc/resources/resource_provider.h"
10 #include "gpu/GLES2/gl2extchromium.h"
11 #include "media/base/video_frame.h"
12 #include "media/filters/skcanvas_video_renderer.h"
13 #include "third_party/khronos/GLES2/gl2.h"
14 #include "third_party/khronos/GLES2/gl2ext.h"
15 #include "ui/gfx/size_conversions.h"
16
17 const unsigned kYUVResourceFormat = GL_LUMINANCE;
18 const unsigned kRGBResourceFormat = GL_RGBA;
19
20 namespace cc {
21
22 VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {}
23
24 VideoFrameExternalResources::~VideoFrameExternalResources() {}
25
26 VideoResourceUpdater::VideoResourceUpdater(ResourceProvider* resource_provider)
27 : resource_provider_(resource_provider) {
28 }
29
30 VideoResourceUpdater::~VideoResourceUpdater() {}
31
32 bool VideoResourceUpdater::VerifyFrame(
33 const scoped_refptr<media::VideoFrame>& video_frame) {
34 // If these fail, we'll have to add logic that handles offset bitmap/texture
35 // UVs. For now, just expect (0, 0) offset, since all our decoders so far
36 // don't offset.
37 DCHECK_EQ(video_frame->visible_rect().x(), 0);
38 DCHECK_EQ(video_frame->visible_rect().y(), 0);
39
40 switch (video_frame->format()) {
41 // Acceptable inputs.
42 case media::VideoFrame::YV12:
43 case media::VideoFrame::YV16:
44 case media::VideoFrame::NATIVE_TEXTURE:
45 #if defined(GOOGLE_TV)
46 case media::VideoFrame::HOLE:
47 #endif
48 return true;
49
50 // Unacceptable inputs. ¯\(°_o)/¯
51 case media::VideoFrame::INVALID:
52 case media::VideoFrame::RGB32:
53 case media::VideoFrame::EMPTY:
54 case media::VideoFrame::I420:
55 break;
56 }
57 return false;
58 }
59
60 // For frames that we receive in software format, determine the dimensions of
61 // each plane in the frame.
62 static gfx::Size SoftwarePlaneDimension(
63 media::VideoFrame::Format input_frame_format,
64 gfx::Size coded_size,
65 GLenum output_resource_format,
66 int plane_index) {
67 if (output_resource_format == kYUVResourceFormat) {
68 if (plane_index == media::VideoFrame::kYPlane)
69 return coded_size;
70
71 switch (input_frame_format) {
72 case media::VideoFrame::YV12:
73 return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 0.5f));
74 case media::VideoFrame::YV16:
75 return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 1.f));
76
77 case media::VideoFrame::INVALID:
78 case media::VideoFrame::RGB32:
79 case media::VideoFrame::EMPTY:
80 case media::VideoFrame::I420:
81 case media::VideoFrame::NATIVE_TEXTURE:
82 #if defined(GOOGLE_TV)
83 case media::VideoFrame::HOLE:
84 #endif
85 NOTREACHED();
86 }
87 }
88
89 DCHECK_EQ(output_resource_format, static_cast<unsigned>(kRGBResourceFormat));
90 return coded_size;
91 }
92
93 static void ReleaseResource(base::WeakPtr<ResourceProvider> resource_provider,
94 ResourceProvider::ResourceId resource_id,
95 unsigned sync_point) {
96 if (resource_provider)
97 resource_provider->DeleteResource(resource_id);
98 }
99
100 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
101 const scoped_refptr<media::VideoFrame>& video_frame) {
102 if (!VerifyFrame(video_frame))
103 return VideoFrameExternalResources();
104
105 media::VideoFrame::Format input_frame_format = video_frame->format();
106
107 #if defined(GOOGLE_TV)
108 if (input_frame_format == media::VideoFrame::HOLE) {
109 VideoFrameExternalResources external_resources;
110 external_resources.type = VideoFrameExternalResources::HOLE;
111 return external_resources;
112 }
113 #endif
114
115 // Only YUV software video frames are supported.
116 DCHECK(input_frame_format == media::VideoFrame::YV12 ||
117 input_frame_format == media::VideoFrame::YV16);
118 if (input_frame_format != media::VideoFrame::YV12 &&
119 input_frame_format != media::VideoFrame::YV16)
120 return VideoFrameExternalResources();
121
122 bool software_compositor = !resource_provider_->GraphicsContext3D();
123
124 GLenum output_resource_format = kYUVResourceFormat;
125 size_t output_plane_count = 3;
126
127 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB
128 // conversion here. That involves an extra copy of each frame to a bitmap.
129 // Obviously, this is suboptimal and should be addressed once ubercompositor
130 // starts shaping up.
piman 2013/04/08 21:03:47 (not for this CL) would it make sense to move the
danakj 2013/04/08 21:44:56 I think we should only be generating 1 mailbox vid
131 if (software_compositor) {
132 output_resource_format = kRGBResourceFormat;
133 output_plane_count = 1;
134 }
135
136 int max_resource_size = resource_provider_->max_texture_size();
137 gfx::Size coded_frame_size = video_frame->coded_size();
138
139 ResourceProvider::ResourceIdArray plane_resources;
140 bool allocation_success = true;
141
142 for (size_t i = 0; i < output_plane_count; ++i) {
143 gfx::Size plane_size =
144 SoftwarePlaneDimension(input_frame_format,
145 coded_frame_size,
146 output_resource_format,
147 i);
148 if (plane_size.IsEmpty() ||
149 plane_size.width() > max_resource_size ||
150 plane_size.height() > max_resource_size) {
151 allocation_success = false;
152 break;
153 }
154
155 // TODO(danakj): Could recycle resources that we previously allocated and
156 // were returned to us.
piman 2013/04/08 21:03:47 I think this is important. genMailboxCHROMIUM is a
danakj 2013/04/08 21:44:56 OK, I will do this in my next CL, is that sufficie
157 ResourceProvider::ResourceId resource_id =
158 resource_provider_->CreateResource(plane_size,
159 output_resource_format,
160 ResourceProvider::TextureUsageAny);
161 if (resource_id == 0) {
162 allocation_success = false;
163 break;
164 }
165
166 plane_resources.push_back(resource_id);
167 }
168
169 if (!allocation_success) {
170 for (size_t i = 0; i < plane_resources.size(); ++i)
171 resource_provider_->DeleteResource(plane_resources[i]);
172 return VideoFrameExternalResources();
173 }
174
175 VideoFrameExternalResources external_resources;
176
177 if (software_compositor) {
178 DCHECK_EQ(output_resource_format, kRGBResourceFormat);
179 DCHECK_EQ(plane_resources.size(), 1u);
180
181 if (!video_renderer_)
182 video_renderer_.reset(new media::SkCanvasVideoRenderer);
183
184 {
185 ResourceProvider::ScopedWriteLockSoftware lock(
186 resource_provider_, plane_resources[0]);
187 video_renderer_->Paint(video_frame,
188 lock.sk_canvas(),
189 video_frame->visible_rect(),
190 0xff);
191 }
192
193 TextureMailbox::ReleaseCallback callback_to_free_resource =
194 base::Bind(&ReleaseResource,
195 resource_provider_->AsWeakPtr(),
196 plane_resources[0]);
197 external_resources.software_resources.push_back(plane_resources[0]);
198 external_resources.software_release_callback = callback_to_free_resource;
199
200 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
201 return external_resources;
202 }
203
204 DCHECK_EQ(output_resource_format,
205 static_cast<unsigned>(kYUVResourceFormat));
206
207 WebKit::WebGraphicsContext3D* context =
208 resource_provider_->GraphicsContext3D();
209 DCHECK(context);
210
211 for (size_t plane = 0; plane < plane_resources.size(); ++plane) {
212 // Update each plane's resource id with its content.
213 ResourceProvider::ResourceId output_plane_resource_id =
214 plane_resources[plane];
215 gfx::Size plane_size =
216 SoftwarePlaneDimension(input_frame_format,
217 coded_frame_size,
218 output_resource_format,
219 plane);
220 const uint8_t* input_plane_pixels = video_frame->data(plane);
221
222 gfx::Rect image_rect(
223 0, 0, video_frame->stride(plane), plane_size.height());
224 gfx::Rect source_rect(plane_size);
225 resource_provider_->SetPixels(output_plane_resource_id,
226 input_plane_pixels,
227 image_rect,
228 source_rect,
229 gfx::Vector2d());
230
231 gpu::Mailbox mailbox;
232 {
233 ResourceProvider::ScopedWriteLockGL lock(
234 resource_provider_, output_plane_resource_id);
235
236 GLC(context, context->genMailboxCHROMIUM(mailbox.name));
237 GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id()));
238 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D,
239 mailbox.name));
240 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
241 }
242
243 TextureMailbox::ReleaseCallback callback_to_free_resource =
244 base::Bind(&ReleaseResource,
245 resource_provider_->AsWeakPtr(),
246 output_plane_resource_id);
247 external_resources.mailboxes.push_back(
248 TextureMailbox(mailbox, callback_to_free_resource));
249 }
250
251 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
252 return external_resources;
253 }
254
255 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
256 const scoped_refptr<media::VideoFrame>& video_frame,
257 const TextureMailbox::ReleaseCallback& release_callback) {
258 if (!VerifyFrame(video_frame))
259 return VideoFrameExternalResources();
260
261 media::VideoFrame::Format frame_format = video_frame->format();
262
263 DCHECK_EQ(frame_format, media::VideoFrame::NATIVE_TEXTURE);
264 if (frame_format != media::VideoFrame::NATIVE_TEXTURE)
265 return VideoFrameExternalResources();
266
267 WebKit::WebGraphicsContext3D* context =
268 resource_provider_->GraphicsContext3D();
269 if (!context)
270 return VideoFrameExternalResources();
271
272 VideoFrameExternalResources external_resources;
273 switch (video_frame->texture_target()) {
274 case GL_TEXTURE_2D:
275 external_resources.type = VideoFrameExternalResources::RGB_RESOURCE;
276 break;
277 case GL_TEXTURE_EXTERNAL_OES:
278 external_resources.type =
279 VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE;
280 break;
281 case GL_TEXTURE_RECTANGLE_ARB:
282 external_resources.type = VideoFrameExternalResources::IO_SURFACE;
283 break;
284 default:
285 NOTREACHED();
286 return VideoFrameExternalResources();
287 }
288
289 gpu::Mailbox mailbox;
290 GLC(context, context->genMailboxCHROMIUM(mailbox.name));
291 GLC(context, context->bindTexture(GL_TEXTURE_2D, video_frame->texture_id()));
292 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
293 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
294
295 external_resources.mailboxes.push_back(
296 TextureMailbox(mailbox, release_callback));
297 return external_resources;
298 }
299
300 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698