1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
media / renderers / video_resource_updater.h [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_RENDERERS_VIDEO_RESOURCE_UPDATER_H_
#define MEDIA_RENDERERS_VIDEO_RESOURCE_UPDATER_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <optional>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/unguessable_token.h"
#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "media/base/media_export.h"
#include "media/base/video_frame.h"
#include "ui/gfx/geometry/size.h"
namespace gfx {
class Rect;
class Transform;
class MaskFilterInfo;
} // namespace gfx
namespace viz {
class ClientResourceProvider;
class RasterContextProvider;
class CompositorRenderPass;
} // namespace viz
namespace gpu {
class SharedImageInterface;
} // namespace gpu
namespace media {
class PaintCanvasVideoRenderer;
// Specifies what type of data is contained in the mailbox.
enum class VideoFrameResourceType {
NONE,
RGB,
RGBA_PREMULTIPLIED,
STREAM_TEXTURE,
// The VideoFrame is merely a hint to compositor that a hole must be made
// transparent so the video underlay will be visible.
// Used by Chromecast only.
VIDEO_HOLE,
};
class MEDIA_EXPORT VideoFrameExternalResource {
public:
VideoFrameResourceType type = VideoFrameResourceType::NONE;
viz::TransferableResource resource;
viz::ReleaseCallback release_callback;
uint32_t bits_per_channel = 8;
VideoFrameExternalResource();
VideoFrameExternalResource(VideoFrameExternalResource&& other);
VideoFrameExternalResource& operator=(VideoFrameExternalResource&& other);
~VideoFrameExternalResource();
};
// VideoResourceUpdater is used by the video system to produce frame content as
// resources consumable by the display compositor.
class MEDIA_EXPORT VideoResourceUpdater
: public base::trace_event::MemoryDumpProvider {
public:
// For GPU compositing |context_provider| should be provided and for software
// compositing |shared_image_interface| should be provided. If there is a
// non-null |context_provider| we assume GPU compositing.
VideoResourceUpdater(
viz::RasterContextProvider* context_provider,
viz::ClientResourceProvider* resource_provider,
scoped_refptr<gpu::SharedImageInterface> shared_image_interface,
bool use_stream_video_draw_quad,
bool use_gpu_memory_buffer_resources,
int max_resource_size);
VideoResourceUpdater(const VideoResourceUpdater&) = delete;
VideoResourceUpdater& operator=(const VideoResourceUpdater&) = delete;
~VideoResourceUpdater() override;
// For each CompositorFrame the following sequence is expected:
// 1. ObtainFrameResource(): Import resource for the next video frame with
// viz::ClientResourceProvider. This will reuse existing GPU or
// SharedMemory buffers if possible, otherwise it will allocate new ones.
// 2. AppendQuad(): Add DrawQuad to CompositorFrame for video.
// 3. ReleaseFrameResource(): After the CompositorFrame has been submitted,
// remove imported resource from viz::ClientResourceProvider.
void ObtainFrameResource(scoped_refptr<VideoFrame> video_frame);
void ReleaseFrameResource();
// Appends a quad representing |frame| to |render_pass|.
// At most one quad is expected to be appended, this is enforced by the users
// of this class (e.g: VideoFrameSubmitter). Producing only one quad will
// allow viz to optimize compositing when the only content changing per-frame
// is the video.
void AppendQuad(viz::CompositorRenderPass* render_pass,
scoped_refptr<VideoFrame> frame,
gfx::Transform transform,
gfx::Rect quad_rect,
gfx::Rect visible_quad_rect,
const gfx::MaskFilterInfo& mask_filter_info,
std::optional<gfx::Rect> clip_rect,
bool context_opaque,
float draw_opacity,
int sorting_context_id);
// TODO(kylechar): This is only public for testing, make private.
VideoFrameExternalResource CreateExternalResourceFromVideoFrame(
scoped_refptr<VideoFrame> video_frame);
viz::SharedImageFormat YuvSharedImageFormat(int bits_per_channel);
scoped_refptr<gpu::SharedImageInterface> shared_image_interface() const;
private:
class PlaneResource;
class HardwarePlaneResource;
class SoftwarePlaneResource;
bool software_compositor() const { return context_provider_ == nullptr; }
// Reallocate |upload_pixels_| with the requested size.
bool ReallocateUploadPixels(size_t needed_size, size_t plane);
// Obtain a resource of the right format by either recycling an
// unreferenced but appropriately formatted resource, or by
// allocating a new resource.
// Additionally, if the |unique_id| matches, then it is assumed that the
// resource has the right data already and will only be used for reading, and
// so is returned even if it is still referenced.
PlaneResource* RecycleOrAllocateResource(const gfx::Size& resource_size,
viz::SharedImageFormat si_format,
const gfx::ColorSpace& color_space,
VideoFrame::ID unique_id);
PlaneResource* AllocateResource(const gfx::Size& plane_size,
viz::SharedImageFormat format,
const gfx::ColorSpace& color_space);
// Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D
// texture. This is used when there are multiple GPU threads (Android WebView)
// and the source video frame texture can't be used on the output GL context.
// https://crbug.com/582170
void CopyHardwarePlane(VideoFrame* video_frame,
VideoFrameExternalResource* external_resources);
// Get resource ready to be appended into DrawQuad. This is used for GPU
// compositing most of the time, except for the cases mentioned in
// CreateForSoftwarePlanes().
VideoFrameExternalResource CreateForHardwarePlanes(
scoped_refptr<VideoFrame> video_frame);
// Get the shared image format for creating resource which is used for
// software compositing or GPU compositing with video frames without textures
// (pixel upload).
viz::SharedImageFormat GetSoftwareOutputFormat(
VideoPixelFormat input_frame_format,
int bits_per_channel,
const gfx::ColorSpace& input_frame_color_space,
bool& texture_needs_rgb_conversion_out);
// Transfer RGB pixels from the video frame to software resource through
// canvas via PaintCanvasVideoRenderer.
void TransferRGBPixelsToPaintCanvas(scoped_refptr<VideoFrame> video_frame,
PlaneResource* plane_resource);
// Write/copy RGB pixels from video frame to hardware resource through
// WritePixels or TexSubImage2D.
bool WriteRGBPixelsToTexture(scoped_refptr<VideoFrame> video_frame,
PlaneResource* plane_resource,
viz::SharedImageFormat output_si_format);
// Write/copy YUV pixels for all planes from video frame to hardware resource
// through WritePixelsYUV. Also perform bit downshifting for
// channel format mismatch between input frame and supported shared image
// format.
bool WriteYUVPixelsForAllPlanesToTexture(
scoped_refptr<VideoFrame> video_frame,
HardwarePlaneResource* resource,
size_t bits_per_channel);
// Get resource ready to be appended into DrawQuad. This is always used for
// software compositing. This is also used for GPU compositing when the input
// video frame has no textures.
VideoFrameExternalResource CreateForSoftwarePlanes(
scoped_refptr<VideoFrame> video_frame);
gpu::raster::RasterInterface* RasterInterface();
void RecycleResource(uint32_t plane_resource_id,
const gpu::SyncToken& sync_token,
bool lost_resource);
void ReturnTexture(scoped_refptr<VideoFrame> video_frame,
const gpu::SyncToken& original_release_token,
const gpu::SyncToken& new_release_token,
bool lost_resource);
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
const raw_ptr<viz::RasterContextProvider> context_provider_;
scoped_refptr<gpu::SharedImageInterface> shared_image_interface_;
const raw_ptr<viz::ClientResourceProvider, DanglingUntriaged>
resource_provider_;
const bool use_stream_video_draw_quad_;
const bool use_gpu_memory_buffer_resources_;
const int max_resource_size_;
const int tracing_id_;
std::unique_ptr<PaintCanvasVideoRenderer> video_renderer_;
uint32_t next_plane_resource_id_ = 1;
// Temporary pixel buffers when converting between formats.
std::unique_ptr<uint8_t[], base::UncheckedFreeDeleter>
upload_pixels_[SkYUVAInfo::kMaxPlanes] = {};
size_t upload_pixels_size_[SkYUVAInfo::kMaxPlanes] = {};
VideoFrameResourceType frame_resource_type_;
// Id of resource that will be placed into quad by the next call to
// AppendDrawQuads().
viz::ResourceId frame_resource_id_;
// If the video resource is a hole punching VideoFrame sent by Chromecast,
// the VideoFrame carries an |overlay_plane_id_| to activate the video
// overlay, but there is no video content to display within VideoFrame.
base::UnguessableToken overlay_plane_id_;
// Resources allocated by VideoResourceUpdater. Used to recycle resources so
// we can reduce the number of allocations and data transfers.
std::vector<std::unique_ptr<PlaneResource>> all_resources_;
base::WeakPtrFactory<VideoResourceUpdater> weak_ptr_factory_{this};
};
} // namespace media
#endif // MEDIA_RENDERERS_VIDEO_RESOURCE_UPDATER_H_