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
media / base / video_encoder.h [blame]
// Copyright 2020 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_BASE_VIDEO_ENCODER_H_
#define MEDIA_BASE_VIDEO_ENCODER_H_
#include <cstdint>
#include <optional>
#include <vector>
#include "base/containers/heap_array.h"
#include "base/functional/callback.h"
#include "base/task/bind_post_task.h"
#include "base/time/time.h"
#include "media/base/bitrate.h"
#include "media/base/encoder_status.h"
#include "media/base/media_export.h"
#include "media/base/svc_scalability_mode.h"
#include "media/base/video_codecs.h"
#include "media/base/video_types.h"
#include "third_party/abseil-cpp/absl/container/inlined_vector.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
namespace media {
struct VideoEncoderInfo;
class VideoFrame;
// Returns the drop frame threshold for media::VideoEncoder used in WebCodecs.
MEDIA_EXPORT uint8_t GetDefaultVideoEncoderDropFrameThreshold();
MEDIA_EXPORT uint32_t GetDefaultVideoEncodeBitrate(gfx::Size frame_size,
uint32_t framerate);
MEDIA_EXPORT int GetNumberOfThreadsForSoftwareEncoding(gfx::Size frame_size);
// Encoded video frame, its data and metadata.
struct MEDIA_EXPORT VideoEncoderOutput {
VideoEncoderOutput();
VideoEncoderOutput(VideoEncoderOutput&&);
~VideoEncoderOutput();
// Feel free take these buffers out and use underlying memory as is without
// copying.
base::HeapArray<uint8_t> data;
base::HeapArray<uint8_t> alpha_data;
base::TimeDelta timestamp;
bool key_frame = false;
int temporal_id = 0;
gfx::ColorSpace color_space;
// Some platforms may adjust the encoding size to meet hardware requirements.
// If not set, the encoded size is the same as configured.
std::optional<gfx::Size> encoded_size;
};
class MEDIA_EXPORT VideoEncoder {
public:
// TODO: Move this to a new file if there are more codec specific options.
struct MEDIA_EXPORT AvcOptions {
bool produce_annexb = false;
};
struct MEDIA_EXPORT HevcOptions {
bool produce_annexb = false;
};
enum class LatencyMode { Realtime, Quality };
enum class ContentHint { Camera, Screen };
struct MEDIA_EXPORT Options {
Options();
Options(const Options&);
~Options();
std::string ToString();
std::optional<Bitrate> bitrate;
std::optional<double> framerate;
gfx::Size frame_size;
std::optional<int> keyframe_interval = 10000;
LatencyMode latency_mode = LatencyMode::Realtime;
std::optional<SVCScalabilityMode> scalability_mode;
std::optional<ContentHint> content_hint;
// Controls encoded pixel format.
std::optional<VideoChromaSampling> subsampling;
// Controls encoded bit depth.
std::optional<uint8_t> bit_depth;
// Only used for H264 encoding.
AvcOptions avc;
// Only used for HEVC encoding.
HevcOptions hevc;
// Allow clients to choose reference pattern for frames.
bool manual_reference_buffer_control = false;
};
struct MEDIA_EXPORT EncodeOptions {
explicit EncodeOptions(bool key_frame);
EncodeOptions();
EncodeOptions(const EncodeOptions&);
~EncodeOptions();
bool key_frame = false;
// Per-frame codec-specific quantizer value.
// Should only be used when encoder configured with kExternal bitrate mode.
std::optional<int> quantizer;
// Ids of the encoder's buffers (past frames) that this frame can reference
// for inter-frame prediction.
// Valid values: [0..VideoEncoderInfo::number_of_manual_reference_buffers)
absl::InlinedVector<uint8_t, 4> reference_buffers;
// Id of the encoder's buffer where this frame should be kept after
// encoding. This frames can later be referenced via `reference_buffers`.
// If empty, this frame can't be used for inter-frame prediction by future
// frames.
// Valid values: [0..VideoEncoderInfo::number_of_manual_reference_buffers)
std::optional<uint8_t> update_buffer;
};
// A sequence of codec specific bytes, commonly known as extradata.
// If available, it should be given to the decoder as part of the
// decoder config.
using CodecDescription = std::vector<uint8_t>;
// Provides the VideoEncoder client with information about the specific
// encoder implementation.
using EncoderInfoCB =
base::RepeatingCallback<void(const VideoEncoderInfo& encoder_info)>;
// Callback for VideoEncoder to report an encoded video frame whenever it
// becomes available.
using OutputCB =
base::RepeatingCallback<void(VideoEncoderOutput output,
std::optional<CodecDescription>)>;
// Callback to report success and errors in encoder calls.
using EncoderStatusCB = base::OnceCallback<void(EncoderStatus error)>;
struct MEDIA_EXPORT PendingEncode {
PendingEncode();
PendingEncode(PendingEncode&&);
~PendingEncode();
EncoderStatusCB done_callback;
scoped_refptr<VideoFrame> frame;
EncodeOptions options;
};
VideoEncoder();
VideoEncoder(const VideoEncoder&) = delete;
VideoEncoder& operator=(const VideoEncoder&) = delete;
virtual ~VideoEncoder();
// Initializes a VideoEncoder with the given |options|, executing the
// |done_cb| upon completion. |output_cb| is called for each encoded frame
// produced by the coder.
//
// Note:
// 1) Can't be called more than once for the same instance of the encoder.
// 2) No VideoEncoder calls should be made before |done_cb| is executed.
virtual void Initialize(VideoCodecProfile profile,
const Options& options,
EncoderInfoCB info_cb,
OutputCB output_cb,
EncoderStatusCB done_cb) = 0;
// Requests a |frame| to be encoded. The status of the encoder and the frame
// are returned via the provided callback |done_cb|.
//
// |done_cb| will not be called from within this method, and that it will be
// called even if Encode() is never called again.
// After the frame, or several frames, are encoded the encoder calls
// |output_cb| specified in Initialize() for available VideoEncoderOutput.
// |output_cb| may be called before or after |done_cb|,
// including before Encode() returns.
// Encode() does not expect EOS frames, use Flush() to finalize the stream
// and harvest the outputs.
virtual void Encode(scoped_refptr<VideoFrame> frame,
const EncodeOptions& options,
EncoderStatusCB done_cb) = 0;
// Adjust encoder options and the output callback for future frames, executing
// the |done_cb| upon completion.
//
// Note:
// 1. Not all options can be changed on the fly.
// 2. ChangeOptions() should be called after calling Flush() and waiting
// for it to finish.
virtual void ChangeOptions(const Options& options,
OutputCB output_cb,
EncoderStatusCB done_cb) = 0;
// Requests all outputs for already encoded frames to be
// produced via |output_cb| and calls |dene_cb| after that.
virtual void Flush(EncoderStatusCB done_cb) = 0;
// Normally VideoEncoder implementations aren't supposed to call
// EncoderInfoCB, OutputCB, and EncoderStatusCB directly from inside any of
// VideoEncoder's methods. This method tells VideoEncoder that all callbacks
// can be called directly from within its methods. It saves extra thread hops
// if it's known that all callbacks already point to a task runner different
// from the current one.
virtual void DisablePostedCallbacks();
protected:
template <typename Callback>
Callback BindCallbackToCurrentLoopIfNeeded(Callback callback) {
return post_callbacks_
? base::BindPostTaskToCurrentDefault(std::move(callback))
: std::move(callback);
}
private:
bool post_callbacks_ = true;
};
} // namespace media
#endif // MEDIA_BASE_VIDEO_ENCODER_H_