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

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

Issue 13959005: cc: Recycle resources for software video decode. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Destroy recycled textures when VRU shuts down 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
« no previous file with comments | « cc/resources/video_resource_updater.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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 "cc/resources/video_resource_updater.h" 5 #include "cc/resources/video_resource_updater.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "cc/output/gl_renderer.h" 8 #include "cc/output/gl_renderer.h"
9 #include "cc/resources/resource_provider.h" 9 #include "cc/resources/resource_provider.h"
10 #include "gpu/GLES2/gl2extchromium.h" 10 #include "gpu/GLES2/gl2extchromium.h"
11 #include "media/base/video_frame.h" 11 #include "media/base/video_frame.h"
12 #include "media/filters/skcanvas_video_renderer.h" 12 #include "media/filters/skcanvas_video_renderer.h"
13 #include "third_party/khronos/GLES2/gl2.h" 13 #include "third_party/khronos/GLES2/gl2.h"
14 #include "third_party/khronos/GLES2/gl2ext.h" 14 #include "third_party/khronos/GLES2/gl2ext.h"
15 #include "ui/gfx/size_conversions.h" 15 #include "ui/gfx/size_conversions.h"
16 16
17 const unsigned kYUVResourceFormat = GL_LUMINANCE; 17 const unsigned kYUVResourceFormat = GL_LUMINANCE;
18 const unsigned kRGBResourceFormat = GL_RGBA; 18 const unsigned kRGBResourceFormat = GL_RGBA;
19 19
20 namespace cc { 20 namespace cc {
21 21
22 VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {} 22 VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {}
23 23
24 VideoFrameExternalResources::~VideoFrameExternalResources() {} 24 VideoFrameExternalResources::~VideoFrameExternalResources() {}
25 25
26 VideoResourceUpdater::VideoResourceUpdater(ResourceProvider* resource_provider) 26 VideoResourceUpdater::VideoResourceUpdater(ResourceProvider* resource_provider)
27 : resource_provider_(resource_provider) { 27 : resource_provider_(resource_provider) {
28 } 28 }
29 29
30 VideoResourceUpdater::~VideoResourceUpdater() {} 30 VideoResourceUpdater::~VideoResourceUpdater() {
31 while (!recycled_resources_.empty()) {
32 resource_provider_->DeleteResource(recycled_resources_.back().resource_id);
33 recycled_resources_.pop_back();
34 }
35 }
31 36
32 bool VideoResourceUpdater::VerifyFrame( 37 bool VideoResourceUpdater::VerifyFrame(
33 const scoped_refptr<media::VideoFrame>& video_frame) { 38 const scoped_refptr<media::VideoFrame>& video_frame) {
34 // If these fail, we'll have to add logic that handles offset bitmap/texture 39 // 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 40 // UVs. For now, just expect (0, 0) offset, since all our decoders so far
36 // don't offset. 41 // don't offset.
37 DCHECK_EQ(video_frame->visible_rect().x(), 0); 42 DCHECK_EQ(video_frame->visible_rect().x(), 0);
38 DCHECK_EQ(video_frame->visible_rect().y(), 0); 43 DCHECK_EQ(video_frame->visible_rect().y(), 0);
39 44
40 switch (video_frame->format()) { 45 switch (video_frame->format()) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 case media::VideoFrame::HOLE: 88 case media::VideoFrame::HOLE:
84 #endif 89 #endif
85 NOTREACHED(); 90 NOTREACHED();
86 } 91 }
87 } 92 }
88 93
89 DCHECK_EQ(output_resource_format, static_cast<unsigned>(kRGBResourceFormat)); 94 DCHECK_EQ(output_resource_format, static_cast<unsigned>(kRGBResourceFormat));
90 return coded_size; 95 return coded_size;
91 } 96 }
92 97
93 static void ReleaseResource(ResourceProvider* resource_provider,
94 ResourceProvider::ResourceId resource_id,
95 unsigned sync_point) {
96 resource_provider->DeleteResource(resource_id);
97 }
98
99 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( 98 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
100 const scoped_refptr<media::VideoFrame>& video_frame) { 99 const scoped_refptr<media::VideoFrame>& video_frame) {
101 if (!VerifyFrame(video_frame)) 100 if (!VerifyFrame(video_frame))
102 return VideoFrameExternalResources(); 101 return VideoFrameExternalResources();
103 102
104 media::VideoFrame::Format input_frame_format = video_frame->format(); 103 media::VideoFrame::Format input_frame_format = video_frame->format();
105 104
106 #if defined(GOOGLE_TV) 105 #if defined(GOOGLE_TV)
107 if (input_frame_format == media::VideoFrame::HOLE) { 106 if (input_frame_format == media::VideoFrame::HOLE) {
108 VideoFrameExternalResources external_resources; 107 VideoFrameExternalResources external_resources;
(...skipping 19 matching lines...) Expand all
128 // Obviously, this is suboptimal and should be addressed once ubercompositor 127 // Obviously, this is suboptimal and should be addressed once ubercompositor
129 // starts shaping up. 128 // starts shaping up.
130 if (software_compositor) { 129 if (software_compositor) {
131 output_resource_format = kRGBResourceFormat; 130 output_resource_format = kRGBResourceFormat;
132 output_plane_count = 1; 131 output_plane_count = 1;
133 } 132 }
134 133
135 int max_resource_size = resource_provider_->max_texture_size(); 134 int max_resource_size = resource_provider_->max_texture_size();
136 gfx::Size coded_frame_size = video_frame->coded_size(); 135 gfx::Size coded_frame_size = video_frame->coded_size();
137 136
138 ResourceProvider::ResourceIdArray plane_resources; 137 std::vector<PlaneResource> plane_resources;
139 bool allocation_success = true; 138 bool allocation_success = true;
140 139
141 for (size_t i = 0; i < output_plane_count; ++i) { 140 for (size_t i = 0; i < output_plane_count; ++i) {
142 gfx::Size plane_size = 141 gfx::Size output_plane_resource_size =
143 SoftwarePlaneDimension(input_frame_format, 142 SoftwarePlaneDimension(input_frame_format,
144 coded_frame_size, 143 coded_frame_size,
145 output_resource_format, 144 output_resource_format,
146 i); 145 i);
147 if (plane_size.IsEmpty() || 146 if (output_plane_resource_size.IsEmpty() ||
148 plane_size.width() > max_resource_size || 147 output_plane_resource_size.width() > max_resource_size ||
149 plane_size.height() > max_resource_size) { 148 output_plane_resource_size.height() > max_resource_size) {
150 allocation_success = false; 149 allocation_success = false;
151 break; 150 break;
152 } 151 }
153 152
154 // TODO(danakj): Could recycle resources that we previously allocated and 153 ResourceProvider::ResourceId resource_id = 0;
155 // were returned to us. 154 unsigned sync_point = 0;
156 ResourceProvider::ResourceId resource_id = 155
157 resource_provider_->CreateResource(plane_size, 156 // Try recycle a previously-allocated resource.
158 output_resource_format, 157 for (size_t i = 0; i < recycled_resources_.size(); ++i) {
159 ResourceProvider::TextureUsageAny); 158 if (recycled_resources_[i].resource_format == output_resource_format &&
159 recycled_resources_[i].resource_size == output_plane_resource_size) {
160 resource_id = recycled_resources_[i].resource_id;
161 sync_point = recycled_resources_[i].sync_point;
162 recycled_resources_.erase(recycled_resources_.begin() + i);
163 break;
164 }
165 }
166
167 if (resource_id == 0) {
168 // TODO(danakj): Abstract out hw/sw resource create/delete from
169 // ResourceProvider and stop using ResourceProvider in this class.
170 resource_id =
171 resource_provider_->CreateResource(output_plane_resource_size,
172 output_resource_format,
173 ResourceProvider::TextureUsageAny);
174 }
175
160 if (resource_id == 0) { 176 if (resource_id == 0) {
161 allocation_success = false; 177 allocation_success = false;
162 break; 178 break;
163 } 179 }
164 180
165 plane_resources.push_back(resource_id); 181 plane_resources.push_back(PlaneResource(resource_id,
182 output_plane_resource_size,
183 output_resource_format,
184 sync_point));
166 } 185 }
167 186
168 if (!allocation_success) { 187 if (!allocation_success) {
169 for (size_t i = 0; i < plane_resources.size(); ++i) 188 for (size_t i = 0; i < plane_resources.size(); ++i)
170 resource_provider_->DeleteResource(plane_resources[i]); 189 resource_provider_->DeleteResource(plane_resources[i].resource_id);
171 return VideoFrameExternalResources(); 190 return VideoFrameExternalResources();
172 } 191 }
173 192
174 VideoFrameExternalResources external_resources; 193 VideoFrameExternalResources external_resources;
175 194
176 if (software_compositor) { 195 if (software_compositor) {
177 DCHECK_EQ(output_resource_format, kRGBResourceFormat);
178 DCHECK_EQ(plane_resources.size(), 1u); 196 DCHECK_EQ(plane_resources.size(), 1u);
197 DCHECK_EQ(plane_resources[0].resource_format, kRGBResourceFormat);
198 DCHECK_EQ(plane_resources[0].sync_point, 0u);
179 199
180 if (!video_renderer_) 200 if (!video_renderer_)
181 video_renderer_.reset(new media::SkCanvasVideoRenderer); 201 video_renderer_.reset(new media::SkCanvasVideoRenderer);
182 202
183 { 203 {
184 ResourceProvider::ScopedWriteLockSoftware lock( 204 ResourceProvider::ScopedWriteLockSoftware lock(
185 resource_provider_, plane_resources[0]); 205 resource_provider_, plane_resources[0].resource_id);
186 video_renderer_->Paint(video_frame, 206 video_renderer_->Paint(video_frame,
187 lock.sk_canvas(), 207 lock.sk_canvas(),
188 video_frame->visible_rect(), 208 video_frame->visible_rect(),
189 0xff); 209 0xff);
190 } 210 }
191 211
192 // In software mode, the resource provider won't be lost. Soon this callback 212 // In software mode, the resource provider won't be lost. Soon this callback
193 // will be called directly from the resource provider, same as 3d 213 // will be called directly from the resource provider, same as 3d
194 // compositing mode, so this raw unretained resource_provider will always 214 // compositing mode, so this raw unretained resource_provider will always
195 // be valid when the callback is fired. 215 // be valid when the callback is fired.
196 TextureMailbox::ReleaseCallback callback_to_free_resource = 216 TextureMailbox::ReleaseCallback callback_to_free_resource =
197 base::Bind(&ReleaseResource, 217 base::Bind(&RecycleResource,
218 AsWeakPtr(),
198 base::Unretained(resource_provider_), 219 base::Unretained(resource_provider_),
199 plane_resources[0]); 220 plane_resources[0].resource_id,
200 external_resources.software_resources.push_back(plane_resources[0]); 221 plane_resources[0].resource_size,
222 plane_resources[0].resource_format,
223 gpu::Mailbox());
224 external_resources.software_resources.push_back(
225 plane_resources[0].resource_id);
201 external_resources.software_release_callback = callback_to_free_resource; 226 external_resources.software_release_callback = callback_to_free_resource;
202 227
203 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; 228 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
204 return external_resources; 229 return external_resources;
205 } 230 }
206 231
207 DCHECK_EQ(output_resource_format,
208 static_cast<unsigned>(kYUVResourceFormat));
209
210 WebKit::WebGraphicsContext3D* context = 232 WebKit::WebGraphicsContext3D* context =
211 resource_provider_->GraphicsContext3D(); 233 resource_provider_->GraphicsContext3D();
212 DCHECK(context); 234 DCHECK(context);
213 235
214 for (size_t plane = 0; plane < plane_resources.size(); ++plane) { 236 for (size_t i = 0; i < plane_resources.size(); ++i) {
215 // Update each plane's resource id with its content. 237 // Update each plane's resource id with its content.
216 ResourceProvider::ResourceId output_plane_resource_id = 238 DCHECK_EQ(plane_resources[i].resource_format,
217 plane_resources[plane]; 239 static_cast<unsigned>(kYUVResourceFormat));
218 gfx::Size plane_size =
219 SoftwarePlaneDimension(input_frame_format,
220 coded_frame_size,
221 output_resource_format,
222 plane);
223 const uint8_t* input_plane_pixels = video_frame->data(plane);
224 240
225 gfx::Rect image_rect( 241 const uint8_t* input_plane_pixels = video_frame->data(i);
226 0, 0, video_frame->stride(plane), plane_size.height()); 242
227 gfx::Rect source_rect(plane_size); 243 gfx::Rect image_rect(0,
228 resource_provider_->SetPixels(output_plane_resource_id, 244 0,
245 video_frame->stride(i),
246 plane_resources[i].resource_size.height());
247 gfx::Rect source_rect(plane_resources[i].resource_size);
248 resource_provider_->SetPixels(plane_resources[i].resource_id,
229 input_plane_pixels, 249 input_plane_pixels,
230 image_rect, 250 image_rect,
231 source_rect, 251 source_rect,
232 gfx::Vector2d()); 252 gfx::Vector2d());
233 253
234 gpu::Mailbox mailbox; 254 gpu::Mailbox mailbox;
235 { 255 {
236 ResourceProvider::ScopedWriteLockGL lock( 256 ResourceProvider::ScopedWriteLockGL lock(
237 resource_provider_, output_plane_resource_id); 257 resource_provider_, plane_resources[i].resource_id);
238 258
239 GLC(context, context->genMailboxCHROMIUM(mailbox.name)); 259 GLC(context, context->genMailboxCHROMIUM(mailbox.name));
240 GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id())); 260 GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id()));
241 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, 261 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D,
242 mailbox.name)); 262 mailbox.name));
243 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0)); 263 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
244 } 264 }
245 265
246 // This callback is called by the resource provider itself, so it's okay to 266 // This callback is called by the resource provider itself, so it's okay to
247 // use an unretained raw pointer here. 267 // use an unretained raw pointer here.
248 TextureMailbox::ReleaseCallback callback_to_free_resource = 268 TextureMailbox::ReleaseCallback callback_to_free_resource =
249 base::Bind(&ReleaseResource, 269 base::Bind(&RecycleResource,
270 AsWeakPtr(),
250 base::Unretained(resource_provider_), 271 base::Unretained(resource_provider_),
251 output_plane_resource_id); 272 plane_resources[i].resource_id,
273 plane_resources[i].resource_size,
274 plane_resources[i].resource_format,
275 mailbox);
252 external_resources.mailboxes.push_back( 276 external_resources.mailboxes.push_back(
253 TextureMailbox(mailbox, callback_to_free_resource)); 277 TextureMailbox(mailbox,
278 callback_to_free_resource,
279 plane_resources[i].sync_point));
254 } 280 }
255 281
256 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; 282 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
257 return external_resources; 283 return external_resources;
258 } 284 }
259 285
260 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( 286 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
261 const scoped_refptr<media::VideoFrame>& video_frame, 287 const scoped_refptr<media::VideoFrame>& video_frame,
262 const TextureMailbox::ReleaseCallback& release_callback) { 288 const TextureMailbox::ReleaseCallback& release_callback) {
263 if (!VerifyFrame(video_frame)) 289 if (!VerifyFrame(video_frame))
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 gpu::Mailbox mailbox, 342 gpu::Mailbox mailbox,
317 unsigned sync_point) { 343 unsigned sync_point) {
318 WebKit::WebGraphicsContext3D* context = 344 WebKit::WebGraphicsContext3D* context =
319 resource_provider->GraphicsContext3D(); 345 resource_provider->GraphicsContext3D();
320 GLC(context, context->bindTexture(GL_TEXTURE_2D, texture_id)); 346 GLC(context, context->bindTexture(GL_TEXTURE_2D, texture_id));
321 GLC(context, context->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name)); 347 GLC(context, context->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
322 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0)); 348 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
323 callback.Run(sync_point); 349 callback.Run(sync_point);
324 } 350 }
325 351
352 // static
353 void VideoResourceUpdater::RecycleResource(
354 base::WeakPtr<VideoResourceUpdater> updater,
355 ResourceProvider* resource_provider,
356 unsigned resource_id,
357 gfx::Size resource_size,
358 unsigned resource_format,
359 gpu::Mailbox mailbox,
360 unsigned sync_point) {
361 WebKit::WebGraphicsContext3D* context =
362 resource_provider->GraphicsContext3D();
363 if (context) {
364 ResourceProvider::ScopedWriteLockGL lock(resource_provider, resource_id);
365 GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id()));
366 GLC(context, context->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
367 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
368 }
369
370 if (!updater) {
371 resource_provider->DeleteResource(resource_id);
372 return;
373 }
374
375 // Drop recycled resources that are the wrong format.
376 while (!updater->recycled_resources_.empty() &&
377 updater->recycled_resources_.back().resource_format !=
378 resource_format) {
379 resource_provider->DeleteResource(
380 updater->recycled_resources_.back().resource_id);
381 updater->recycled_resources_.pop_back();
382 }
383
384 PlaneResource recycled_resource(resource_id,
385 resource_size,
386 resource_format,
387 sync_point);
388 updater->recycled_resources_.push_back(recycled_resource);
389 }
390
326 } // namespace cc 391 } // namespace cc
OLDNEW
« no previous file with comments | « cc/resources/video_resource_updater.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698