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
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_RENDERERS_SKCANVAS_VIDEO_RENDERER_H_
#define MEDIA_RENDERERS_SKCANVAS_VIDEO_RENDERER_H_
#include <stddef.h>
#include <stdint.h>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_image.h"
#include "media/base/media_export.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_frame.h"
#include "media/base/video_rotation.h"
#include "media/filters/context_3d.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace gfx {
class RectF;
}
namespace gpu {
struct Capabilities;
}
namespace media {
// TODO(enne): rename to PaintCanvasVideoRenderer
// Handles rendering of VideoFrames to PaintCanvases.
class MEDIA_EXPORT SkCanvasVideoRenderer {
public:
SkCanvasVideoRenderer();
~SkCanvasVideoRenderer();
// Paints |video_frame| on |canvas|, scaling and rotating the result to fit
// dimensions specified by |dest_rect|.
// If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d|
// must be provided.
//
// Black will be painted on |canvas| if |video_frame| is null.
void Paint(const scoped_refptr<VideoFrame>& video_frame,
cc::PaintCanvas* canvas,
const gfx::RectF& dest_rect,
cc::PaintFlags& flags,
VideoRotation video_rotation,
const Context3D& context_3d);
// Copy |video_frame| on |canvas|.
// If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d|
// must be provided.
void Copy(const scoped_refptr<VideoFrame>& video_frame,
cc::PaintCanvas* canvas,
const Context3D& context_3d);
// Convert the contents of |video_frame| to raw RGB pixels. |rgb_pixels|
// should point into a buffer large enough to hold as many 32 bit RGBA pixels
// as are in the visible_rect() area of the frame.
static void ConvertVideoFrameToRGBPixels(const media::VideoFrame* video_frame,
void* rgb_pixels,
size_t row_bytes);
enum SingleFrameCopyMode {
SingleFrameForVideoElementOrCanvas,
SingleFrameForWebGL
};
// Copy the contents of texture of |video_frame| to texture |texture|.
// |level|, |internal_format|, |type| specify target texture |texture|.
// The format of |video_frame| must be VideoFrame::NATIVE_TEXTURE.
// |copy_mode| alters how the copy is done, and takes into consideration
// whether the caller will clip the texture to the frame's |visible_rect|,
// or expects this to be done internally.
static void CopyVideoFrameSingleTextureToGLTexture(
gpu::gles2::GLES2Interface* gl,
VideoFrame* video_frame,
SingleFrameCopyMode copy_mode,
unsigned int target,
unsigned int texture,
unsigned int internal_format,
unsigned int format,
unsigned int type,
int level,
bool premultiply_alpha,
bool flip_y);
// Copy the contents of texture of |video_frame| to texture |texture| in
// context |destination_gl|.
// |level|, |internal_format|, |type| specify target texture |texture|.
// The format of |video_frame| must be VideoFrame::NATIVE_TEXTURE.
// |context_3d| has a GrContext that may be used during the copy.
// Returns true on success.
bool CopyVideoFrameTexturesToGLTexture(
const Context3D& context_3d,
gpu::gles2::GLES2Interface* destination_gl,
const scoped_refptr<VideoFrame>& video_frame,
unsigned int target,
unsigned int texture,
unsigned int internal_format,
unsigned int format,
unsigned int type,
int level,
bool premultiply_alpha,
bool flip_y);
// Calls texImage2D where the texture image data source is the contents of
// |video_frame|. Texture |texture| needs to be created and bound to |target|
// before this call and the binding is active upon return.
// This is an optimization of WebGL |video_frame| TexImage2D implementation
// for specific combinations of |video_frame| and |texture| formats; e.g. if
// |frame format| is Y16, optimizes conversion of normalized 16-bit content
// and calls texImage2D to |texture|. |level|, |internal_format|, |format| and
// |type| are WebGL texImage2D parameters.
// Returns false if there is no implementation for given parameters.
static bool TexImage2D(unsigned target,
unsigned texture,
gpu::gles2::GLES2Interface* gl,
const gpu::Capabilities& gpu_capabilities,
VideoFrame* video_frame,
int level,
int internalformat,
unsigned format,
unsigned type,
bool flip_y,
bool premultiply_alpha);
// Calls texSubImage2D where the texture image data source is the contents of
// |video_frame|.
// This is an optimization of WebGL |video_frame| TexSubImage2D implementation
// for specific combinations of |video_frame| and texture |format| and |type|;
// e.g. if |frame format| is Y16, converts unsigned 16-bit value to target
// |format| and calls WebGL texSubImage2D. |level|, |format|, |type|,
// |xoffset| and |yoffset| are texSubImage2D parameters.
// Returns false if there is no implementation for given parameters.
static bool TexSubImage2D(unsigned target,
gpu::gles2::GLES2Interface* gl,
VideoFrame* video_frame,
int level,
unsigned format,
unsigned type,
int xoffset,
int yoffset,
bool flip_y,
bool premultiply_alpha);
// In general, We hold the most recently painted frame to increase the
// performance for the case that the same frame needs to be painted
// repeatedly. Call this function if you are sure the most recent frame will
// never be painted again, so we can release the resource.
void ResetCache();
void CorrectLastImageDimensions(const SkIRect& visible_rect);
// Used for unit test.
SkISize LastImageDimensionsForTesting();
private:
// Update the cache holding the most-recently-painted frame. Returns false
// if the image couldn't be updated.
bool UpdateLastImage(const scoped_refptr<VideoFrame>& video_frame,
const Context3D& context_3d);
// Last image used to draw to the canvas.
sk_sp<SkImage> last_image_;
// Timestamp of the videoframe used to generate |last_image_|.
base::TimeDelta last_timestamp_ = media::kNoTimestamp;
// If |last_image_| is not used for a while, it's deleted to save memory.
base::DelayTimer last_image_deleting_timer_;
// Stable paint image id to provide to draw image calls.
cc::PaintImage::Id renderer_stable_id_;
// Used for DCHECKs to ensure method calls executed in the correct thread.
base::ThreadChecker thread_checker_;
// Used for unit test.
SkISize last_image_dimensions_for_testing_;
DISALLOW_COPY_AND_ASSIGN(SkCanvasVideoRenderer);
};
} // namespace media
#endif // MEDIA_RENDERERS_SKCANVAS_VIDEO_RENDERER_H_
|