1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h"
6
7 #include <memory>
8 #include "base/bind.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "base/trace_event/trace_event.h"
11 #include "components/viz/client/client_resource_provider.h"
12 #include "components/viz/common/gpu/raster_context_provider.h"
13 #include "components/viz/common/quads/render_pass.h"
14 #include "components/viz/common/quads/solid_color_draw_quad.h"
15 #include "components/viz/common/quads/texture_draw_quad.h"
16 #include "components/viz/common/quads/yuv_video_draw_quad.h"
17 #include "media/base/video_frame.h"
18 #include "media/renderers/video_resource_updater.h"
19 #include "third_party/blink/public/platform/web_vector.h"
20
21 namespace blink {
22
VideoFrameResourceProvider(const cc::LayerTreeSettings & settings,bool use_sync_primitives)23 VideoFrameResourceProvider::VideoFrameResourceProvider(
24 const cc::LayerTreeSettings& settings,
25 bool use_sync_primitives)
26 : settings_(settings), use_sync_primitives_(use_sync_primitives) {}
27
~VideoFrameResourceProvider()28 VideoFrameResourceProvider::~VideoFrameResourceProvider() {
29 // Drop all resources before closing the ClientResourceProvider.
30 resource_updater_ = nullptr;
31 if (resource_provider_)
32 resource_provider_->ShutdownAndReleaseAllResources();
33 }
34
Initialize(viz::RasterContextProvider * media_context_provider,viz::SharedBitmapReporter * shared_bitmap_reporter)35 void VideoFrameResourceProvider::Initialize(
36 viz::RasterContextProvider* media_context_provider,
37 viz::SharedBitmapReporter* shared_bitmap_reporter) {
38 context_provider_ = media_context_provider;
39 resource_provider_ = std::make_unique<viz::ClientResourceProvider>();
40
41 int max_texture_size;
42 if (context_provider_) {
43 max_texture_size =
44 context_provider_->ContextCapabilities().max_texture_size;
45 } else {
46 // Pick an arbitrary limit here similar to what hardware might.
47 max_texture_size = 16 * 1024;
48 }
49
50 resource_updater_ = std::make_unique<media::VideoResourceUpdater>(
51 nullptr, media_context_provider, shared_bitmap_reporter,
52 resource_provider_.get(), settings_.use_stream_video_draw_quad,
53 settings_.resource_settings.use_gpu_memory_buffer_resources,
54 settings_.resource_settings.use_r16_texture, max_texture_size);
55 }
56
OnContextLost()57 void VideoFrameResourceProvider::OnContextLost() {
58 // Drop all resources before closing the ClientResourceProvider.
59 resource_updater_ = nullptr;
60 if (resource_provider_)
61 resource_provider_->ShutdownAndReleaseAllResources();
62 resource_provider_ = nullptr;
63 context_provider_ = nullptr;
64 }
65
AppendQuads(viz::RenderPass * render_pass,scoped_refptr<media::VideoFrame> frame,media::VideoRotation rotation,bool is_opaque)66 void VideoFrameResourceProvider::AppendQuads(
67 viz::RenderPass* render_pass,
68 scoped_refptr<media::VideoFrame> frame,
69 media::VideoRotation rotation,
70 bool is_opaque) {
71 TRACE_EVENT0("media", "VideoFrameResourceProvider::AppendQuads");
72 DCHECK(resource_updater_);
73 DCHECK(resource_provider_);
74
75 // When obtaining frame resources, we end up having to wait. See
76 // https://crbug/878070.
77 // Unfortunately, we have no idea if blocking is allowed on the current thread
78 // or not. If we're on the cc impl thread, the answer is yes, and further
79 // the thread is marked as not allowing blocking primitives. On the various
80 // media threads, however, blocking is not allowed but the blocking scopes
81 // are. So, we use ScopedAllow only if we're told that we should do so.
82 if (use_sync_primitives_) {
83 base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
84 resource_updater_->ObtainFrameResources(frame);
85 } else {
86 resource_updater_->ObtainFrameResources(frame);
87 }
88
89 gfx::Transform transform = gfx::Transform();
90 // The quad's rect is in pre-transform space so that applying the transform on
91 // it will produce the bounds in target space.
92 gfx::Rect quad_rect = gfx::Rect(frame->natural_size());
93
94 switch (rotation) {
95 case media::VIDEO_ROTATION_90:
96 transform.Rotate(90.0);
97 transform.Translate(0.0, -quad_rect.height());
98 break;
99 case media::VIDEO_ROTATION_180:
100 transform.Rotate(180.0);
101 transform.Translate(-quad_rect.width(), -quad_rect.height());
102 break;
103 case media::VIDEO_ROTATION_270:
104 transform.Rotate(270.0);
105 transform.Translate(-quad_rect.width(), 0);
106 break;
107 case media::VIDEO_ROTATION_0:
108 break;
109 }
110
111 gfx::Rect visible_quad_rect = quad_rect;
112 gfx::Rect clip_rect;
113 gfx::RRectF rounded_corner_bounds;
114 bool is_clipped = false;
115 float draw_opacity = 1.0f;
116 int sorting_context_id = 0;
117
118 resource_updater_->AppendQuads(render_pass, std::move(frame), transform,
119 quad_rect, visible_quad_rect,
120 rounded_corner_bounds, clip_rect, is_clipped,
121 is_opaque, draw_opacity, sorting_context_id);
122 }
123
ReleaseFrameResources()124 void VideoFrameResourceProvider::ReleaseFrameResources() {
125 resource_updater_->ReleaseFrameResources();
126 }
127
PrepareSendToParent(const WebVector<viz::ResourceId> & resource_ids,WebVector<viz::TransferableResource> * transferable_resources)128 void VideoFrameResourceProvider::PrepareSendToParent(
129 const WebVector<viz::ResourceId>& resource_ids,
130 WebVector<viz::TransferableResource>* transferable_resources) {
131 std::vector<viz::TransferableResource> resources_list;
132 resource_provider_->PrepareSendToParent(
133 const_cast<WebVector<viz::ResourceId>&>(resource_ids).ReleaseVector(),
134 &resources_list, context_provider_);
135 *transferable_resources = std::move(resources_list);
136 }
137
ReceiveReturnsFromParent(const Vector<viz::ReturnedResource> & transferable_resources)138 void VideoFrameResourceProvider::ReceiveReturnsFromParent(
139 const Vector<viz::ReturnedResource>& transferable_resources) {
140 resource_provider_->ReceiveReturnsFromParent(
141 WebVector<viz::ReturnedResource>(transferable_resources).ReleaseVector());
142 }
143
144 } // namespace blink
145