Chromium Code Reviews| 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 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 if (!video_renderer_) | 414 if (!video_renderer_) |
| 388 video_renderer_.reset(new media::SkCanvasVideoRenderer); | 415 video_renderer_.reset(new media::SkCanvasVideoRenderer); |
| 389 | 416 |
| 390 ResourceProvider::ScopedWriteLockSoftware lock( | 417 ResourceProvider::ScopedWriteLockSoftware lock( |
| 391 resource_provider_, plane_resource.resource_id); | 418 resource_provider_, plane_resource.resource_id); |
| 392 SkCanvas canvas(lock.sk_bitmap()); | 419 SkCanvas canvas(lock.sk_bitmap()); |
| 393 // This is software path, so canvas and video_frame are always backed | 420 // This is software path, so canvas and video_frame are always backed |
| 394 // by software. | 421 // by software. |
| 395 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); | 422 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); |
| 396 SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resource); | 423 SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resource); |
| 424 #if DCHECK_IS_ON() | |
| 425 // Add VideoFrame destructor callback. | |
| 426 video_frame->AddDestructionObserver(base::Bind( | |
| 427 &OnVideoFrameDestruct, base::ThreadTaskRunnerHandle::Get(), | |
| 428 base::Bind(&VideoResourceUpdater::MarkOldResource, AsWeakPtr(), | |
| 429 static_cast<void*>(video_frame.get()), | |
|
danakj
2016/03/17 00:00:34
can you base::Unretained() this pointer to avoid t
xjz
2016/03/17 04:57:56
Done.
| |
| 430 video_frame->timestamp()))); | |
| 431 #endif | |
| 397 } | 432 } |
| 398 | 433 |
| 399 external_resources.software_resources.push_back(plane_resource.resource_id); | 434 external_resources.software_resources.push_back(plane_resource.resource_id); |
| 400 external_resources.software_release_callback = | 435 external_resources.software_release_callback = |
| 401 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id); | 436 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id); |
| 402 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 437 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; |
| 403 return external_resources; | 438 return external_resources; |
| 404 } | 439 } |
| 405 | 440 |
| 406 for (size_t i = 0; i < plane_resources.size(); ++i) { | 441 for (size_t i = 0; i < plane_resources.size(); ++i) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 video_frame->data(i) + (video_stride_bytes * row); | 517 video_frame->data(i) + (video_stride_bytes * row); |
| 483 memcpy(dst, src, bytes_per_row); | 518 memcpy(dst, src, bytes_per_row); |
| 484 } | 519 } |
| 485 } | 520 } |
| 486 pixels = &upload_pixels_[0]; | 521 pixels = &upload_pixels_[0]; |
| 487 } | 522 } |
| 488 | 523 |
| 489 resource_provider_->CopyToResource(plane_resource.resource_id, pixels, | 524 resource_provider_->CopyToResource(plane_resource.resource_id, pixels, |
| 490 resource_size_pixels); | 525 resource_size_pixels); |
| 491 SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resource); | 526 SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resource); |
| 527 #if DCHECK_IS_ON() | |
| 528 // Add VideoFrame destructor callback. | |
| 529 if (i == 0) { | |
| 530 video_frame->AddDestructionObserver(base::Bind( | |
| 531 &OnVideoFrameDestruct, base::ThreadTaskRunnerHandle::Get(), | |
| 532 base::Bind(&VideoResourceUpdater::MarkOldResource, AsWeakPtr(), | |
| 533 static_cast<void*>(video_frame.get()), | |
| 534 video_frame->timestamp()))); | |
| 535 } | |
| 536 #endif | |
| 492 } | 537 } |
| 493 | 538 |
| 494 if (plane_resource.resource_format == LUMINANCE_F16) { | 539 if (plane_resource.resource_format == LUMINANCE_F16) { |
| 495 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the | 540 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the |
| 496 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75). | 541 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75). |
| 497 // | 542 // |
| 498 // Half-floats are evaluated as: | 543 // Half-floats are evaluated as: |
| 499 // float value = pow(2.0, exponent - 25) * (0x400 + fraction); | 544 // float value = pow(2.0, exponent - 25) * (0x400 + fraction); |
| 500 // | 545 // |
| 501 // In our case the exponent is 14 (since we or with 0x3800) and | 546 // 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... | |
| 690 if (lost_resource) { | 735 if (lost_resource) { |
| 691 resource_it->ref_count = 0; | 736 resource_it->ref_count = 0; |
| 692 updater->DeleteResource(resource_it); | 737 updater->DeleteResource(resource_it); |
| 693 return; | 738 return; |
| 694 } | 739 } |
| 695 | 740 |
| 696 --resource_it->ref_count; | 741 --resource_it->ref_count; |
| 697 DCHECK_GE(resource_it->ref_count, 0); | 742 DCHECK_GE(resource_it->ref_count, 0); |
| 698 } | 743 } |
| 699 | 744 |
| 745 #if DCHECK_IS_ON() | |
| 746 // static | |
| 747 void VideoResourceUpdater::MarkOldResource( | |
| 748 base::WeakPtr<VideoResourceUpdater> updater, | |
| 749 const void* video_frame_ptr, | |
| 750 base::TimeDelta timestamp) { | |
| 751 if (!updater) | |
| 752 return; | |
| 753 const ResourceList::iterator resource_it = std::find_if( | |
| 754 updater->all_resources_.begin(), updater->all_resources_.end(), | |
| 755 [video_frame_ptr, timestamp](const PlaneResource& plane_resource) { | |
| 756 return plane_resource.frame_ptr == video_frame_ptr && | |
| 757 plane_resource.timestamp == timestamp && | |
| 758 plane_resource.plane_index == 0; | |
| 759 }); | |
| 760 if (resource_it == updater->all_resources_.end()) | |
| 761 return; | |
| 762 | |
| 763 resource_it->destructed = true; | |
| 764 } | |
| 765 #endif | |
| 766 | |
| 700 } // namespace cc | 767 } // namespace cc |
| OLD | NEW |