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