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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
media / video / video_decode_accelerator.h [blame]
// Copyright 2012 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_VIDEO_VIDEO_DECODE_ACCELERATOR_H_
#define MEDIA_VIDEO_VIDEO_DECODE_ACCELERATOR_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <vector>
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/unguessable_token.h"
#include "media/base/bitstream_buffer.h"
#include "media/base/cdm_context.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decoder_status.h"
#include "media/base/encryption_scheme.h"
#include "media/base/overlay_info.h"
#include "media/base/video_decoder_config.h"
#include "media/video/picture.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h"
typedef unsigned int GLenum;
namespace base {
class SequencedTaskRunner;
}
namespace media {
// Video decoder interface.
// This interface is extended by the various components that ultimately
// implement the backend of PPB_VideoDecoder_Dev.
class MEDIA_EXPORT VideoDecodeAccelerator {
public:
// Specification of a decoding profile supported by a decoder.
// |max_resolution| and |min_resolution| are inclusive.
struct MEDIA_EXPORT SupportedProfile {
SupportedProfile();
~SupportedProfile();
VideoCodecProfile profile;
gfx::Size max_resolution;
gfx::Size min_resolution;
bool encrypted_only;
};
using SupportedProfiles = std::vector<SupportedProfile>;
struct MEDIA_EXPORT Capabilities {
Capabilities();
Capabilities(const Capabilities& other);
~Capabilities();
std::string AsHumanReadableString() const;
// Flags that can be associated with a VDA.
enum Flags {
NO_FLAGS = 0,
// Normally, the VDA is required to be able to provide all PictureBuffers
// to the client via PictureReady(), even if the client does not return
// any of them via ReusePictureBuffer(). The client is only required to
// return PictureBuffers when it holds all of them, if it wants to get
// more decoded output. See VideoDecoder::CanReadWithoutStalling for
// more context.
// If this flag is set, then the VDA does not make this guarantee. The
// client must return PictureBuffers to be sure that new frames will be
// provided via PictureReady.
NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE = 1 << 0,
// Whether the VDA supports being configured with an output surface for
// it to render frames to. For example, SurfaceViews on Android.
SUPPORTS_EXTERNAL_OUTPUT_SURFACE = 1 << 1,
// If set, the VDA will use deferred initialization if the config
// indicates that the client supports it as well. Refer to
// NotifyInitializationComplete for more details.
SUPPORTS_DEFERRED_INITIALIZATION = 1 << 2,
// If set, video frames will have COPY_REQUIRED flag which will cause
// an extra texture copy during composition.
REQUIRES_TEXTURE_COPY = 1 << 3,
// Whether the VDA supports encrypted streams or not.
SUPPORTS_ENCRYPTED_STREAMS = 1 << 4,
// If set the decoder does not require a restart in order to switch to
// using an external output surface.
SUPPORTS_SET_EXTERNAL_OUTPUT_SURFACE = 1 << 5,
};
SupportedProfiles supported_profiles;
uint32_t flags;
};
// Enumeration of potential errors generated by the API.
// Note: Keep these in sync with PP_VideoDecodeError_Dev.
enum Error {
// An operation was attempted during an incompatible decoder state.
ILLEGAL_STATE = 1,
// Invalid argument was passed to an API method.
INVALID_ARGUMENT,
// Encoded input is unreadable.
UNREADABLE_INPUT,
// A failure occurred at the browser layer or one of its dependencies.
// Examples of such failures include GPU hardware failures, GPU driver
// failures, GPU library failures, browser programming errors, and so on.
PLATFORM_FAILURE,
// Largest used enum. This should be adjusted when new errors are added.
ERROR_MAX = PLATFORM_FAILURE,
};
// Config structure contains parameters required for the VDA initialization.
struct MEDIA_EXPORT Config {
// Specifies the allocation and handling mode for output PictureBuffers.
// When set to kAllocate, the VDA is expected to allocate backing memory
// for PictureBuffers at the time of AssignPictureBuffers() call.
// When set to kImport, the VDA will not allocate, but after receiving
// AssignPictureBuffers() call, it will expect a call to
// ImportBufferForPicture() for each PictureBuffer before use.
enum class OutputMode {
kAllocate,
kImport,
};
Config();
Config(const Config& config);
explicit Config(VideoCodecProfile profile);
~Config();
std::string AsHumanReadableString() const;
bool is_encrypted() const {
return encryption_scheme != EncryptionScheme::kUnencrypted;
}
// The video codec and profile.
VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
// Whether the stream is encrypted, and, if so, the scheme used.
EncryptionScheme encryption_scheme = EncryptionScheme::kUnencrypted;
// The CDM that the VDA should use to decode encrypted streams. Must be
// set to a valid ID if |is_encrypted|.
std::optional<base::UnguessableToken> cdm_id;
// Whether the client supports deferred initialization.
bool is_deferred_initialization_allowed = false;
// Optional overlay info available at startup, rather than waiting for the
// VDA to receive a callback.
OverlayInfo overlay_info;
// Coded size of the video frame hint, subject to change.
gfx::Size initial_expected_coded_size = gfx::Size(320, 240);
OutputMode output_mode = OutputMode::kAllocate;
// The H264 SPS and PPS configuration data. Not all clients populate these
// fields, so they should be parsed from the bitstream instead, if required.
// Each SPS and PPS is prefixed with the Annex B framing bytes: 0, 0, 0, 1.
std::vector<uint8_t> sps;
std::vector<uint8_t> pps;
// Color space specified by the container.
VideoColorSpace container_color_space;
// Target color space.
// Used as a hint to the decoder. Outputting VideoFrames in this color space
// may avoid extra conversion steps.
gfx::ColorSpace target_color_space;
// HDR metadata specified by the container.
std::optional<gfx::HDRMetadata> hdr_metadata;
};
// Interface for collaborating with picture interface to provide memory for
// output picture and blitting them. These callbacks will not be made unless
// Initialize() has returned successfully.
// This interface is extended by the various layers that relay messages back
// to the plugin, through the PPP_VideoDecoder_Dev interface the plugin
// implements.
class MEDIA_EXPORT Client {
public:
// Notify the client that deferred initialization has completed successfully
// or not. This is required if and only if deferred initialization is
// supported by the VDA (see Capabilities), and it is supported by the
// client (see Config::is_deferred_initialization_allowed), and the initial
// call to VDA::Initialize returns true.
// The default implementation is a NOTREACHED, since deferred initialization
// is not supported by default.
virtual void NotifyInitializationComplete(DecoderStatus status);
// Callback to tell client how many and what size of buffers to provide.
// Note that the actual count provided through AssignPictureBuffers() can be
// larger than the value requested.
// |format| indicates what format the decoded frames will be produced in
// by the VDA, or PIXEL_FORMAT_UNKNOWN if the underlying platform handles
// this transparently.
virtual void ProvidePictureBuffersWithVisibleRect(
uint32_t requested_num_of_buffers,
VideoPixelFormat format,
const gfx::Size& dimensions,
const gfx::Rect& visible_rect) = 0;
// Callback to dismiss picture buffer that was assigned earlier.
virtual void DismissPictureBuffer(int32_t picture_buffer_id) = 0;
// Callback to deliver decoded pictures ready to be displayed.
// Note: the decoded pictures might be sent to the client more than once.
// The client should call ReusePictureBuffer() once for each PictureReady().
// For example, VDA calls Client::PictureReady() twice for a picture buffer.
// Then the client should also call VDA::ReusePictureBuffer() twice.
// Until that, VDA cannot reuse the picture buffer.
virtual void PictureReady(const Picture& picture) = 0;
// Callback to notify that decoded has decoded the end of the current
// bitstream buffer.
virtual void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) = 0;
// Flush completion callback.
virtual void NotifyFlushDone() = 0;
// Reset completion callback.
virtual void NotifyResetDone() = 0;
// Callback to notify about decoding errors. Note that errors in
// Initialize() will not be reported here, but will instead be indicated by
// a false return value there.
virtual void NotifyError(Error error) = 0;
protected:
virtual ~Client() {}
};
// Video decoder functions.
// Initializes the video decoder with specific configuration. Called once per
// decoder construction. This call is synchronous and returns true iff
// initialization is successful, unless deferred initialization is used.
//
// By default, deferred initialization is not used. However, if Config::
// is_deferred_initialization_allowed is set by the client, and if
// Capabilities::Flags::SUPPORTS_DEFERRED_INITIALIZATION is set by the VDA,
// and if VDA::Initialize returns true, then the client can expect a call to
// NotifyInitializationComplete with the actual success / failure of
// initialization. Note that a return value of false from VDA::Initialize
// indicates that initialization definitely failed, and no callback is needed.
//
// For encrypted video, only deferred initialization is supported and |config|
// must contain a valid |cdm_id|.
//
// Parameters:
// |config| contains the initialization parameters.
// |client| is the client of this video decoder. Does not take ownership of
// |client| which must be valid until Destroy() is called.
virtual bool Initialize(const Config& config, Client* client) = 0;
// Decodes given bitstream buffer that contains at most one frame. Once
// decoder is done with processing |bitstream_buffer| it will call
// NotifyEndOfBitstreamBuffer() with the bitstream buffer id.
// Parameters:
// |bitstream_buffer| is the input bitstream that is sent for decoding.
virtual void Decode(BitstreamBuffer bitstream_buffer) = 0;
// Decodes given decoder buffer that contains at most one frame. Once
// decoder is done with processing |buffer| it will call
// NotifyEndOfBitstreamBuffer() with the bitstream id.
// Parameters:
// |buffer| is the input buffer that is sent for decoding.
// |bitstream_id| identifies the buffer for PictureReady() and
// NotifyEndOfBitstreamBuffer()
virtual void Decode(scoped_refptr<DecoderBuffer> buffer,
int32_t bitstream_id);
// Assigns a set of picture buffers to the video decoder.
//
// Ownership of each picture buffer remains with the client, but the client
// is not allowed to deallocate the buffer before the DismissPictureBuffer
// callback has been initiated for a given buffer.
//
// Parameters:
// |buffers| contains the allocated picture buffers for the output. Note
// that the count of buffers may be larger than the count requested through
// the call to Client::ProvidePictureBuffers().
virtual void AssignPictureBuffers(
const std::vector<PictureBuffer>& buffers) = 0;
// Imports |gpu_memory_buffer_handle|, pointing to a buffer in |pixel_format|,
// as backing memory for picture buffer associated with |picture_buffer_id|.
// This can only be be used if the VDA has been Initialize()d with
// config.output_mode = IMPORT, and should be preceded by a call to
// AssignPictureBuffers() to set up the number of PictureBuffers and their
// details.
// The |pixel_format| used here may be different from the |pixel_format|
// required in ProvidePictureBuffers(). If the buffer cannot be imported an
// error should be notified via NotifyError().
// After this call, the VDA becomes the owner of the GpuMemoryBufferHandle,
// and is responsible for closing it after use, also on import failure.
virtual void ImportBufferForPicture(
int32_t picture_buffer_id,
VideoPixelFormat pixel_format,
gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle);
// Sends picture buffers to be reused by the decoder. This needs to be called
// for each buffer that has been processed so that decoder may know onto which
// picture buffers it can write the output to.
// Note: the decoded pictures might be sent to the client more than once.
// The client should call ReusePictureBuffer() once for each PictureReady().
// For example, VDA calls Client::PictureReady() twice for a picture buffer.
// Then the client should also call VDA::ReusePictureBuffer() twice.
// Until that, VDA can really reuse the picture buffer.
//
// Parameters:
// |picture_buffer_id| id of the picture buffer that is to be reused.
virtual void ReusePictureBuffer(int32_t picture_buffer_id) = 0;
// Flushes the decoder: all pending inputs will be decoded and pictures handed
// back to the client, followed by NotifyFlushDone() being called on the
// client. Can be used to implement "end of stream" notification.
virtual void Flush() = 0;
// Resets the decoder: all pending inputs are dropped immediately and the
// decoder returned to a state ready for further Decode()s, followed by
// NotifyResetDone() being called on the client. Can be used to implement
// "seek". After Flush is called, it is OK to call Reset before receiving
// NotifyFlushDone() and VDA should cancel the flush. Note NotifyFlushDone()
// may be on the way to the client. If client gets NotifyFlushDone(), it
// should be before NotifyResetDone().
virtual void Reset() = 0;
// An optional graphics surface that the VDA should render to. For setting
// an output SurfaceView on Android. Passing |kNoSurfaceID| will clear any
// previously set surface in favor of an internally generated texture.
// |routing_token| is an optional AndroidOverlay routing token. At most one
// should be non-empty.
virtual void SetOverlayInfo(const OverlayInfo& overlay_info);
// Destroys the decoder: all pending inputs are dropped immediately and the
// component is freed. This call may asynchornously free system resources,
// but its client-visible effects are synchronous. After this method returns
// no more callbacks will be made on the client. Deletes |this|
// unconditionally, so make sure to drop all pointers to it!
virtual void Destroy() = 0;
// TO BE CALLED IN THE SAME PROCESS AS THE VDA IMPLEMENTATION ONLY.
//
// A decode "task" is a sequence that includes a Decode() call from Client,
// as well as corresponding callbacks to return the input BitstreamBuffer
// after use, and the resulting output Picture(s).
//
// If the Client can support running these three calls on a separate thread,
// it may call this method to try to set up the VDA implementation to do so.
// If the VDA can support this as well, return true, otherwise return false.
// If true is returned, the client may submit each Decode() call (but no other
// calls) on |decode_task_runner|, and should then expect that
// NotifyEndOfBitstreamBuffer() and PictureReady() callbacks may come on
// |decode_task_runner| as well, called on |decode_client|, instead of client
// provided to Initialize().
//
// This method may be called at any time.
//
// NOTE 1: some callbacks may still have to come on the main thread and the
// Client should handle both callbacks coming on main and |decode_task_runner|
// thread.
//
// NOTE 2: VDA implementations of Decode() must return as soon as possible and
// never block, as |decode_task_runner| may be a latency critical thread
// (such as the GPU IO thread).
//
// One application of this is offloading the GPU Child thread. In general,
// calls to VDA in GPU process have to be done on the GPU Child thread, as
// they may require GL context to be current. However, some VDAs may be able
// to run decode operations without GL context, which helps reduce latency and
// offloads the GPU Child thread.
virtual bool TryToSetupDecodeOnSeparateSequence(
const base::WeakPtr<Client>& decode_client,
const scoped_refptr<base::SequencedTaskRunner>& decode_task_runner);
protected:
// Do not delete directly; use Destroy() or own it with a scoped_ptr, which
// will Destroy() it properly by default.
virtual ~VideoDecodeAccelerator();
};
} // namespace media
namespace std {
// Specialize std::default_delete so that
// std::unique_ptr<VideoDecodeAccelerator> uses "Destroy()" instead of trying to
// use the destructor.
template <>
struct MEDIA_EXPORT default_delete<media::VideoDecodeAccelerator> {
void operator()(media::VideoDecodeAccelerator* vda) const;
};
} // namespace std
#endif // MEDIA_VIDEO_VIDEO_DECODE_ACCELERATOR_H_