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