OLD | NEW |
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() |
| 23 #ifdef VIDEO_FRAME_MAILBOX |
| 24 : type(NONE) {} |
| 25 #else |
| 26 : type(NONE), |
| 27 hardware_resource(0) {} |
| 28 #endif |
23 | 29 |
24 VideoFrameExternalResources::~VideoFrameExternalResources() {} | 30 VideoFrameExternalResources::~VideoFrameExternalResources() {} |
25 | 31 |
26 VideoResourceUpdater::VideoResourceUpdater(ResourceProvider* resource_provider) | 32 VideoResourceUpdater::VideoResourceUpdater(ResourceProvider* resource_provider) |
27 : resource_provider_(resource_provider) { | 33 : resource_provider_(resource_provider) { |
28 } | 34 } |
29 | 35 |
30 VideoResourceUpdater::~VideoResourceUpdater() { | 36 VideoResourceUpdater::~VideoResourceUpdater() { |
31 while (!recycled_resources_.empty()) { | 37 while (!recycled_resources_.empty()) { |
32 resource_provider_->DeleteResource(recycled_resources_.back().resource_id); | 38 resource_provider_->DeleteResource(recycled_resources_.back().resource_id); |
33 recycled_resources_.pop_back(); | 39 recycled_resources_.pop_back(); |
34 } | 40 } |
35 } | 41 } |
36 | 42 |
| 43 VideoFrameExternalResources VideoResourceUpdater:: |
| 44 CreateExternalResourcesFromVideoFrame( |
| 45 const scoped_refptr<media::VideoFrame>& video_frame) { |
| 46 if (!VerifyFrame(video_frame)) |
| 47 return VideoFrameExternalResources(); |
| 48 |
| 49 if (video_frame->format() == media::VideoFrame::NATIVE_TEXTURE) |
| 50 return CreateForHardwarePlanes(video_frame); |
| 51 else |
| 52 return CreateForSoftwarePlanes(video_frame); |
| 53 } |
| 54 |
37 bool VideoResourceUpdater::VerifyFrame( | 55 bool VideoResourceUpdater::VerifyFrame( |
38 const scoped_refptr<media::VideoFrame>& video_frame) { | 56 const scoped_refptr<media::VideoFrame>& video_frame) { |
39 // If these fail, we'll have to add logic that handles offset bitmap/texture | 57 // If these fail, we'll have to add logic that handles offset bitmap/texture |
40 // UVs. For now, just expect (0, 0) offset, since all our decoders so far | 58 // UVs. For now, just expect (0, 0) offset, since all our decoders so far |
41 // don't offset. | 59 // don't offset. |
42 DCHECK_EQ(video_frame->visible_rect().x(), 0); | 60 DCHECK_EQ(video_frame->visible_rect().x(), 0); |
43 DCHECK_EQ(video_frame->visible_rect().y(), 0); | 61 DCHECK_EQ(video_frame->visible_rect().y(), 0); |
44 | 62 |
45 switch (video_frame->format()) { | 63 switch (video_frame->format()) { |
46 // Acceptable inputs. | 64 // Acceptable inputs. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 NOTREACHED(); | 108 NOTREACHED(); |
91 } | 109 } |
92 } | 110 } |
93 | 111 |
94 DCHECK_EQ(output_resource_format, static_cast<unsigned>(kRGBResourceFormat)); | 112 DCHECK_EQ(output_resource_format, static_cast<unsigned>(kRGBResourceFormat)); |
95 return coded_size; | 113 return coded_size; |
96 } | 114 } |
97 | 115 |
98 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( | 116 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
99 const scoped_refptr<media::VideoFrame>& video_frame) { | 117 const scoped_refptr<media::VideoFrame>& video_frame) { |
100 if (!VerifyFrame(video_frame)) | |
101 return VideoFrameExternalResources(); | |
102 | |
103 media::VideoFrame::Format input_frame_format = video_frame->format(); | 118 media::VideoFrame::Format input_frame_format = video_frame->format(); |
104 | 119 |
105 #if defined(GOOGLE_TV) | 120 #if defined(GOOGLE_TV) |
106 if (input_frame_format == media::VideoFrame::HOLE) { | 121 if (input_frame_format == media::VideoFrame::HOLE) { |
107 VideoFrameExternalResources external_resources; | 122 VideoFrameExternalResources external_resources; |
108 external_resources.type = VideoFrameExternalResources::HOLE; | 123 external_resources.type = VideoFrameExternalResources::HOLE; |
109 return external_resources; | 124 return external_resources; |
110 } | 125 } |
111 #endif | 126 #endif |
112 | 127 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 TextureMailbox(mailbox, | 297 TextureMailbox(mailbox, |
283 callback_to_free_resource, | 298 callback_to_free_resource, |
284 plane_resources[i].sync_point)); | 299 plane_resources[i].sync_point)); |
285 } | 300 } |
286 | 301 |
287 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; | 302 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; |
288 return external_resources; | 303 return external_resources; |
289 } | 304 } |
290 | 305 |
291 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( | 306 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( |
292 const scoped_refptr<media::VideoFrame>& video_frame, | 307 const scoped_refptr<media::VideoFrame>& video_frame) { |
293 const TextureMailbox::ReleaseCallback& release_callback) { | |
294 if (!VerifyFrame(video_frame)) | |
295 return VideoFrameExternalResources(); | |
296 | |
297 media::VideoFrame::Format frame_format = video_frame->format(); | 308 media::VideoFrame::Format frame_format = video_frame->format(); |
298 | 309 |
299 DCHECK_EQ(frame_format, media::VideoFrame::NATIVE_TEXTURE); | 310 DCHECK_EQ(frame_format, media::VideoFrame::NATIVE_TEXTURE); |
300 if (frame_format != media::VideoFrame::NATIVE_TEXTURE) | 311 if (frame_format != media::VideoFrame::NATIVE_TEXTURE) |
301 return VideoFrameExternalResources(); | 312 return VideoFrameExternalResources(); |
302 | 313 |
303 WebKit::WebGraphicsContext3D* context = | 314 WebKit::WebGraphicsContext3D* context = |
304 resource_provider_->GraphicsContext3D(); | 315 resource_provider_->GraphicsContext3D(); |
305 if (!context) | 316 if (!context) |
306 return VideoFrameExternalResources(); | 317 return VideoFrameExternalResources(); |
307 | 318 |
308 VideoFrameExternalResources external_resources; | 319 VideoFrameExternalResources external_resources; |
309 switch (video_frame->texture_target()) { | 320 switch (video_frame->texture_target()) { |
310 case GL_TEXTURE_2D: | 321 case GL_TEXTURE_2D: |
311 external_resources.type = VideoFrameExternalResources::RGB_RESOURCE; | 322 external_resources.type = VideoFrameExternalResources::RGB_RESOURCE; |
312 break; | 323 break; |
313 case GL_TEXTURE_EXTERNAL_OES: | 324 case GL_TEXTURE_EXTERNAL_OES: |
314 external_resources.type = | 325 external_resources.type = |
315 VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE; | 326 VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE; |
316 break; | 327 break; |
317 case GL_TEXTURE_RECTANGLE_ARB: | 328 case GL_TEXTURE_RECTANGLE_ARB: |
318 external_resources.type = VideoFrameExternalResources::IO_SURFACE; | 329 external_resources.type = VideoFrameExternalResources::IO_SURFACE; |
319 break; | 330 break; |
320 default: | 331 default: |
321 NOTREACHED(); | 332 NOTREACHED(); |
322 return VideoFrameExternalResources(); | 333 return VideoFrameExternalResources(); |
323 } | 334 } |
324 | 335 |
325 gpu::Mailbox mailbox; | 336 #ifndef VIDEO_FRAME_MAILBOX |
326 GLC(context, context->genMailboxCHROMIUM(mailbox.name)); | 337 ResourceProvider::ResourceId hardware_resource = 0; |
327 GLC(context, context->bindTexture(GL_TEXTURE_2D, video_frame->texture_id())); | 338 hardware_resource = resource_provider_->CreateResourceFromExternalTexture( |
328 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name)); | 339 video_frame->texture_id()); |
329 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0)); | 340 #endif |
330 | 341 |
| 342 // Hold a reference to the VideoFrame in the callback, so the frame stays |
| 343 // alive while the texture is in use. As long as the frame is alive, the |
| 344 // texture inside it will not be reused by the decoder. |
331 TextureMailbox::ReleaseCallback callback_to_return_resource = | 345 TextureMailbox::ReleaseCallback callback_to_return_resource = |
| 346 #ifdef VIDEO_FRAME_MAILBOX |
| 347 base::Bind(&ReturnTexture, video_frame); |
| 348 #else |
332 base::Bind(&ReturnTexture, | 349 base::Bind(&ReturnTexture, |
| 350 video_frame, |
333 base::Unretained(resource_provider_), | 351 base::Unretained(resource_provider_), |
334 release_callback, | 352 hardware_resource); |
335 video_frame->texture_id(), | 353 #endif |
336 mailbox); | 354 |
337 external_resources.mailboxes.push_back( | 355 #ifdef VIDEO_FRAME_MAILBOX |
338 TextureMailbox(mailbox, callback_to_return_resource)); | 356 external_resources.mailboxes.push_back( |
| 357 TextureMailbox(video_frame->texture_mailbox(), |
| 358 callback_to_return_resource, |
| 359 video_frame->texture_mailbox_sync_point())); |
| 360 #else |
| 361 external_resources.hardware_resource = hardware_resource; |
| 362 external_resources.hardware_release_callback = callback_to_return_resource; |
| 363 #endif |
339 return external_resources; | 364 return external_resources; |
340 } | 365 } |
341 | 366 |
342 // static | 367 // static |
343 void VideoResourceUpdater::ReturnTexture( | 368 void VideoResourceUpdater::ReturnTexture( |
| 369 scoped_refptr<media::VideoFrame> video_frame, |
| 370 #ifndef VIDEO_FRAME_MAILBOX |
344 ResourceProvider* resource_provider, | 371 ResourceProvider* resource_provider, |
345 TextureMailbox::ReleaseCallback callback, | 372 unsigned resource_id, |
346 unsigned texture_id, | 373 #endif |
347 gpu::Mailbox mailbox, | |
348 unsigned sync_point, | 374 unsigned sync_point, |
349 bool lost_resource) { | 375 bool lost_resource) { |
350 WebKit::WebGraphicsContext3D* context = | 376 #ifndef VIDEO_FRAME_MAILBOX |
351 resource_provider->GraphicsContext3D(); | 377 resource_provider->DeleteResource(resource_id); |
352 GLC(context, context->bindTexture(GL_TEXTURE_2D, texture_id)); | 378 #else |
353 GLC(context, context->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name)); | 379 video_frame->set_texture_mailbox_sync_point(sync_point); |
354 GLC(context, context->bindTexture(GL_TEXTURE_2D, 0)); | 380 #endif |
355 callback.Run(sync_point, lost_resource); | 381 |
| 382 // Dropping the reference to VideoFrame here releases the texture back to the |
| 383 // decoder. |
356 } | 384 } |
357 | 385 |
358 // static | 386 // static |
359 void VideoResourceUpdater::RecycleResource( | 387 void VideoResourceUpdater::RecycleResource( |
360 base::WeakPtr<VideoResourceUpdater> updater, | 388 base::WeakPtr<VideoResourceUpdater> updater, |
361 ResourceProvider* resource_provider, | 389 ResourceProvider* resource_provider, |
362 RecycleResourceData data, | 390 RecycleResourceData data, |
363 unsigned sync_point, | 391 unsigned sync_point, |
364 bool lost_resource) { | 392 bool lost_resource) { |
365 WebKit::WebGraphicsContext3D* context = | 393 WebKit::WebGraphicsContext3D* context = |
(...skipping 24 matching lines...) Expand all Loading... |
390 } | 418 } |
391 | 419 |
392 PlaneResource recycled_resource(data.resource_id, | 420 PlaneResource recycled_resource(data.resource_id, |
393 data.resource_size, | 421 data.resource_size, |
394 data.resource_format, | 422 data.resource_format, |
395 sync_point); | 423 sync_point); |
396 updater->recycled_resources_.push_back(recycled_resource); | 424 updater->recycled_resources_.push_back(recycled_resource); |
397 } | 425 } |
398 | 426 |
399 } // namespace cc | 427 } // namespace cc |
OLD | NEW |