| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bit_cast.h" | 13 #include "base/bit_cast.h" |
| 14 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
| 15 #include "cc/base/math_util.h" | 15 #include "cc/base/math_util.h" |
| 16 #include "cc/output/gl_renderer.h" | 16 #include "cc/output/gl_renderer.h" |
| 17 #include "cc/resources/resource_provider.h" | 17 #include "cc/resources/resource_provider.h" |
| 18 #include "gpu/GLES2/gl2extchromium.h" | 18 #include "gpu/GLES2/gl2extchromium.h" |
| 19 #include "gpu/command_buffer/client/gles2_interface.h" | 19 #include "gpu/command_buffer/client/gles2_interface.h" |
| 20 #include "media/base/video_frame.h" | 20 #include "media/base/video_frame.h" |
| 21 #include "media/renderers/skcanvas_video_renderer.h" | 21 #include "media/renderers/skcanvas_video_renderer.h" |
| 22 #include "third_party/khronos/GLES2/gl2.h" | 22 #include "third_party/khronos/GLES2/gl2.h" |
| 23 #include "third_party/khronos/GLES2/gl2ext.h" | 23 #include "third_party/khronos/GLES2/gl2ext.h" |
| 24 #include "ui/gfx/geometry/size_conversions.h" | 24 #include "ui/gfx/geometry/size_conversions.h" |
| 25 | 25 |
| 26 #if DCHECK_IS_ON() |
| 27 #include "base/single_thread_task_runner.h" |
| 28 #include "base/thread_task_runner_handle.h" |
| 29 #endif |
| 30 |
| 26 namespace cc { | 31 namespace cc { |
| 27 | 32 |
| 28 namespace { | 33 namespace { |
| 29 | 34 |
| 30 const ResourceFormat kRGBResourceFormat = RGBA_8888; | 35 const ResourceFormat kRGBResourceFormat = RGBA_8888; |
| 31 | 36 |
| 32 VideoFrameExternalResources::ResourceType ResourceTypeForVideoFrame( | 37 VideoFrameExternalResources::ResourceType ResourceTypeForVideoFrame( |
| 33 media::VideoFrame* video_frame) { | 38 media::VideoFrame* video_frame) { |
| 34 switch (video_frame->format()) { | 39 switch (video_frame->format()) { |
| 35 case media::PIXEL_FORMAT_ARGB: | 40 case media::PIXEL_FORMAT_ARGB: |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 sync_token_.Clear(); | 110 sync_token_.Clear(); |
| 106 } | 111 } |
| 107 } | 112 } |
| 108 } | 113 } |
| 109 | 114 |
| 110 private: | 115 private: |
| 111 gpu::gles2::GLES2Interface* gl_; | 116 gpu::gles2::GLES2Interface* gl_; |
| 112 gpu::SyncToken sync_token_; | 117 gpu::SyncToken sync_token_; |
| 113 }; | 118 }; |
| 114 | 119 |
| 120 #if DCHECK_IS_ON() |
| 121 void OnVideoFrameDestruct( |
| 122 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 123 const base::Closure& task) { |
| 124 task_runner->PostTask(FROM_HERE, task); |
| 125 } |
| 126 #endif |
| 127 |
| 115 } // namespace | 128 } // namespace |
| 116 | 129 |
| 117 VideoResourceUpdater::PlaneResource::PlaneResource( | 130 VideoResourceUpdater::PlaneResource::PlaneResource( |
| 118 unsigned int resource_id, | 131 unsigned int resource_id, |
| 119 const gfx::Size& resource_size, | 132 const gfx::Size& resource_size, |
| 120 ResourceFormat resource_format, | 133 ResourceFormat resource_format, |
| 121 gpu::Mailbox mailbox) | 134 gpu::Mailbox mailbox) |
| 122 : resource_id(resource_id), | 135 : resource_id(resource_id), |
| 123 resource_size(resource_size), | 136 resource_size(resource_size), |
| 124 resource_format(resource_format), | 137 resource_format(resource_format), |
| 125 mailbox(mailbox), | 138 mailbox(mailbox), |
| 126 ref_count(0), | 139 ref_count(0), |
| 127 frame_ptr(nullptr), | 140 frame_ptr(nullptr), |
| 141 #if DCHECK_IS_ON() |
| 142 destructed(false), |
| 143 #endif |
| 128 plane_index(0u) { | 144 plane_index(0u) { |
| 129 } | 145 } |
| 130 | 146 |
| 131 VideoResourceUpdater::PlaneResource::PlaneResource(const PlaneResource& other) = | 147 VideoResourceUpdater::PlaneResource::PlaneResource(const PlaneResource& other) = |
| 132 default; | 148 default; |
| 133 | 149 |
| 134 bool VideoResourceUpdater::PlaneResourceMatchesUniqueID( | 150 bool VideoResourceUpdater::PlaneResourceMatchesUniqueID( |
| 135 const PlaneResource& plane_resource, | 151 const PlaneResource& plane_resource, |
| 136 const media::VideoFrame* video_frame, | 152 const media::VideoFrame* video_frame, |
| 137 size_t plane_index) { | 153 size_t plane_index) { |
| 138 return plane_resource.frame_ptr == video_frame && | 154 bool matched = plane_resource.frame_ptr == video_frame && |
| 139 plane_resource.plane_index == plane_index && | 155 plane_resource.plane_index == plane_index && |
| 140 plane_resource.timestamp == video_frame->timestamp(); | 156 plane_resource.timestamp == video_frame->timestamp(); |
| 157 #if DCHECK_IS_ON() |
| 158 if ((plane_index == 0) && matched) { |
| 159 DCHECK(!plane_resource.destructed) |
| 160 << "ERROR: reused the destructed resource." |
| 161 << " timestamp = " << plane_resource.timestamp; |
| 162 } |
| 163 #endif |
| 164 return matched; |
| 141 } | 165 } |
| 142 | 166 |
| 143 void VideoResourceUpdater::SetPlaneResourceUniqueId( | 167 void VideoResourceUpdater::SetPlaneResourceUniqueId( |
| 144 const media::VideoFrame* video_frame, | 168 const media::VideoFrame* video_frame, |
| 145 size_t plane_index, | 169 size_t plane_index, |
| 146 PlaneResource* plane_resource) { | 170 PlaneResource* plane_resource) { |
| 147 plane_resource->frame_ptr = video_frame; | 171 plane_resource->frame_ptr = video_frame; |
| 148 plane_resource->plane_index = plane_index; | 172 plane_resource->plane_index = plane_index; |
| 149 plane_resource->timestamp = video_frame->timestamp(); | 173 plane_resource->timestamp = video_frame->timestamp(); |
| 174 #if DCHECK_IS_ON() |
| 175 plane_resource->destructed = false; |
| 176 #endif |
| 150 } | 177 } |
| 151 | 178 |
| 152 VideoFrameExternalResources::VideoFrameExternalResources() | 179 VideoFrameExternalResources::VideoFrameExternalResources() |
| 153 : type(NONE), | 180 : type(NONE), |
| 154 read_lock_fences_enabled(false), | 181 read_lock_fences_enabled(false), |
| 155 offset(0.0f), | 182 offset(0.0f), |
| 156 multiplier(1.0f) {} | 183 multiplier(1.0f) {} |
| 157 | 184 |
| 158 VideoFrameExternalResources::VideoFrameExternalResources( | 185 VideoFrameExternalResources::VideoFrameExternalResources( |
| 159 const VideoFrameExternalResources& other) = default; | 186 const VideoFrameExternalResources& other) = default; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 if (!video_renderer_) | 413 if (!video_renderer_) |
| 387 video_renderer_.reset(new media::SkCanvasVideoRenderer); | 414 video_renderer_.reset(new media::SkCanvasVideoRenderer); |
| 388 | 415 |
| 389 ResourceProvider::ScopedWriteLockSoftware lock( | 416 ResourceProvider::ScopedWriteLockSoftware lock( |
| 390 resource_provider_, plane_resource.resource_id); | 417 resource_provider_, plane_resource.resource_id); |
| 391 SkCanvas canvas(lock.sk_bitmap()); | 418 SkCanvas canvas(lock.sk_bitmap()); |
| 392 // This is software path, so canvas and video_frame are always backed | 419 // This is software path, so canvas and video_frame are always backed |
| 393 // by software. | 420 // by software. |
| 394 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); | 421 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); |
| 395 SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resource); | 422 SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resource); |
| 423 #if DCHECK_IS_ON() |
| 424 // Add VideoFrame destructor callback. |
| 425 video_frame->AddDestructionObserver(base::Bind( |
| 426 &OnVideoFrameDestruct, base::ThreadTaskRunnerHandle::Get(), |
| 427 base::Bind(&VideoResourceUpdater::MarkOldResource, AsWeakPtr(), |
| 428 base::Unretained(video_frame.get()), |
| 429 video_frame->timestamp()))); |
| 430 #endif |
| 396 } | 431 } |
| 397 | 432 |
| 398 external_resources.software_resources.push_back(plane_resource.resource_id); | 433 external_resources.software_resources.push_back(plane_resource.resource_id); |
| 399 external_resources.software_release_callback = | 434 external_resources.software_release_callback = |
| 400 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id); | 435 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id); |
| 401 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 436 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; |
| 402 return external_resources; | 437 return external_resources; |
| 403 } | 438 } |
| 404 | 439 |
| 405 for (size_t i = 0; i < plane_resources.size(); ++i) { | 440 for (size_t i = 0; i < plane_resources.size(); ++i) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 video_frame->data(i) + (video_stride_bytes * row); | 516 video_frame->data(i) + (video_stride_bytes * row); |
| 482 memcpy(dst, src, bytes_per_row); | 517 memcpy(dst, src, bytes_per_row); |
| 483 } | 518 } |
| 484 } | 519 } |
| 485 pixels = &upload_pixels_[0]; | 520 pixels = &upload_pixels_[0]; |
| 486 } | 521 } |
| 487 | 522 |
| 488 resource_provider_->CopyToResource(plane_resource.resource_id, pixels, | 523 resource_provider_->CopyToResource(plane_resource.resource_id, pixels, |
| 489 resource_size_pixels); | 524 resource_size_pixels); |
| 490 SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resource); | 525 SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resource); |
| 526 #if DCHECK_IS_ON() |
| 527 // Add VideoFrame destructor callback. |
| 528 if (i == 0) { |
| 529 video_frame->AddDestructionObserver(base::Bind( |
| 530 &OnVideoFrameDestruct, base::ThreadTaskRunnerHandle::Get(), |
| 531 base::Bind(&VideoResourceUpdater::MarkOldResource, AsWeakPtr(), |
| 532 base::Unretained(video_frame.get()), |
| 533 video_frame->timestamp()))); |
| 534 } |
| 535 #endif |
| 491 } | 536 } |
| 492 | 537 |
| 493 if (plane_resource.resource_format == LUMINANCE_F16) { | 538 if (plane_resource.resource_format == LUMINANCE_F16) { |
| 494 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the | 539 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the |
| 495 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75). | 540 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75). |
| 496 // | 541 // |
| 497 // Half-floats are evaluated as: | 542 // Half-floats are evaluated as: |
| 498 // float value = pow(2.0, exponent - 25) * (0x400 + fraction); | 543 // float value = pow(2.0, exponent - 25) * (0x400 + fraction); |
| 499 // | 544 // |
| 500 // In our case the exponent is 14 (since we or with 0x3800) and | 545 // In our case the exponent is 14 (since we or with 0x3800) and |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 if (lost_resource) { | 734 if (lost_resource) { |
| 690 resource_it->ref_count = 0; | 735 resource_it->ref_count = 0; |
| 691 updater->DeleteResource(resource_it); | 736 updater->DeleteResource(resource_it); |
| 692 return; | 737 return; |
| 693 } | 738 } |
| 694 | 739 |
| 695 --resource_it->ref_count; | 740 --resource_it->ref_count; |
| 696 DCHECK_GE(resource_it->ref_count, 0); | 741 DCHECK_GE(resource_it->ref_count, 0); |
| 697 } | 742 } |
| 698 | 743 |
| 744 #if DCHECK_IS_ON() |
| 745 // static |
| 746 void VideoResourceUpdater::MarkOldResource( |
| 747 base::WeakPtr<VideoResourceUpdater> updater, |
| 748 const media::VideoFrame* video_frame_ptr, |
| 749 base::TimeDelta timestamp) { |
| 750 if (!updater) |
| 751 return; |
| 752 const ResourceList::iterator resource_it = std::find_if( |
| 753 updater->all_resources_.begin(), updater->all_resources_.end(), |
| 754 [video_frame_ptr, timestamp](const PlaneResource& plane_resource) { |
| 755 return plane_resource.frame_ptr == video_frame_ptr && |
| 756 plane_resource.timestamp == timestamp && |
| 757 plane_resource.plane_index == 0; |
| 758 }); |
| 759 if (resource_it == updater->all_resources_.end()) |
| 760 return; |
| 761 |
| 762 resource_it->destructed = true; |
| 763 } |
| 764 #endif |
| 765 |
| 699 } // namespace cc | 766 } // namespace cc |
| OLD | NEW |