Ocean
Loading...
Searching...
No Matches
VideoEncoder.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_MEDIA_ANDROID_VIDEO_ENCODER_H
9#define META_OCEAN_MEDIA_ANDROID_VIDEO_ENCODER_H
10
11#if defined(__ANDROID_API__) && __ANDROID_API__ >= 24
12
13#ifndef OCEAN_MEDIA_ANDROID_VIDEOENCODER_AVAILABLE
14 #define OCEAN_MEDIA_ANDROID_VIDEOENCODER_AVAILABLE
15#endif
16
19
20#include "ocean/base/Frame.h"
21#include "ocean/base/Lock.h"
22
23#include "ocean/math/Numeric.h"
24
25namespace Ocean
26{
27
28namespace Media
29{
30
31namespace Android
32{
33
34/**
35 * This class implements a simple video encoder for Android using Ocean::Frame objects as input.
36 *
37 * Usage:
38 * @code
39 * // a function which is e.g., running in a separate thread
40 * void threadRun()
41 * {
42 * VideoEncoder videoEncoder;
43 * *
44 * if (!videoEncoder.initialize(1920u, 1080u))
45 * {
46 * // handle error
47 * }
48 *
49 * if (!videoEncoder.start())
50 * {
51 * // handle error
52 * }
53 *
54 * unsigned int frameIndex = 0u;
55 * double frameRate = 30.0;
56 *
57 * while (true)
58 * {
59 * Frame frame;
60 *
61 * // external function: function needs to provide frames from an external source - e.g., from a camera, a video stream, etc.
62 * if (doesNewFrameExist(frame))
63 * {
64 * // presentation time in microseconds
65 * uint64_t presentationTime = uint64_t(1.0e6 * double(frameIndex) / frameRate);
66 *
67 * // we forward the frame to the encoder, eventually it will be encoded and will be available through popSample()
68 * if (!videoEncoder.pushFrame(frame, presentationTime))
69 * {
70 * // handle error
71 * }
72 *
73 * ++frameIndex;
74 * }
75 *
76 * // we simply check whether another sample has been encoded
77 * VideoEncoder::Sample encodedSample = videoEncoder.popSample();
78 *
79 * if (encodedSample.isValid())
80 * {
81 * // external function: receiving encoded samples and processes them
82 * sendSampleToReceiver(std::move(encodedSample));
83 * }
84 * }
85 * }
86 * @endcode
87 * @ingroup mediaandroid
88 */
90{
91 public:
92
93 /// Definition of a 1 Mbps bit rate
94 static constexpr int bitrateMbps1_ = 1000 * 1000;
95
96 /// Definition of a 2 Mbps bit rate
97 static constexpr int bitrateMbps2_ = bitrateMbps1_ * 2;
98
99 /// Definition of a 5 Mbps bit rate
100 static constexpr int bitrateMbps5_ = bitrateMbps1_ * 5;
101
102 /// Definition of a 10 Mbps bit rate
103 static constexpr int bitrateMbps10_ = bitrateMbps1_ * 10;
104
105 /**
106 * Definition of individual MediaCodec buffer flag constants.
107 * From Android MediaCodec.BufferInfo: https://developer.android.com/reference/android/media/MediaCodec.BufferInfo
108 */
109 enum MediaCodecBufferFlags : uint32_t
110 {
111 /// The buffer has no special property.
113 /// Indicates that the (encoded) buffer marked as such contains the data for a key frame.
115 /// Indicates that the buffer marked as such contains codec initialization / codec specific data instead of media data.
117 /// Indicates that the buffer is the last buffer in the stream.
119 /// Indicates that the buffer only contains part of a frame.
121 };
122
123 /**
124 * Definition of an encoded sample.
125 */
126 class Sample
127 {
128 friend class VideoEncoder;
129
130 public:
131
132 /**
133 * Creates an invalid sample.
134 */
135 Sample() = default;
136
137 /**
138 * Move constructor.
139 * @param sample The sample to be moved
140 */
141 inline Sample(Sample&& sample) noexcept;
142
143 /**
144 * Returns whether this sample is valid.
145 * @return True, if so
146 */
147 inline bool isValid() const;
148
149 /**
150 * Returns the encoded data.
151 * @return The encoded data
152 */
153 inline const std::vector<uint8_t>& data() const;
154
155 /**
156 * Returns the presentation time in microseconds.
157 * @return The presentation time
158 */
159 inline int64_t presentationTime() const;
160
161 /**
162 * Returns whether this sample is a key frame.
163 * @return True, if so
164 */
165 inline bool isKeyFrame() const;
166
167 /**
168 * Returns whether this sample contains codec configuration data instead of media data.
169 * @return True, if so
170 */
171 inline bool isConfiguration() const;
172
173 /**
174 * Returns whether this sample marks the end of the stream.
175 * @return True, if so
176 */
177 inline bool isEndOfStream() const;
178
179 /**
180 * Returns whether this sample contains only part of a frame.
181 * @return True, if so
182 */
183 inline bool isPartialFrame() const;
184
185 /**
186 * Move operator.
187 * @param sample The sample to be moved
188 * @return Reference to this object
189 */
190 inline Sample& operator=(Sample&& sample) noexcept;
191
192 /**
193 * Returns whether this sample is valid.
194 * @return True, if so
195 */
196 inline explicit operator bool() const;
197
198 protected:
199
200 /**
201 * Creates a sample with specified data.
202 * @param data The encoded data, will be moved
203 * @param presentationTime The presentation time in microseconds, with range [0, infinity)
204 * @param bufferFlags The buffer flags of the sample
205 */
206 inline Sample(std::vector<uint8_t>&& data, const int64_t presentationTime, const MediaCodecBufferFlags bufferFlags);
207
208 /**
209 * Disabled copy constructor.
210 */
211 Sample(const Sample&) = delete;
212
213 /**
214 * Disabled copy operator.
215 * @return Reference to this object
216 */
217 Sample& operator=(const Sample&) = delete;
218
219 protected:
220
221 /// The encoded data.
222 std::vector<uint8_t> data_;
223
224 /// The presentation time in microseconds.
226
228 };
229
230 /**
231 * Definition of a vector holding sample objects.
232 */
233 using Samples = std::vector<Media::Android::VideoEncoder::Sample>;
234
235 protected:
236
237 /// Definition of the maximal image width.
238 static constexpr unsigned int maximalWidth_ = 1920u * 8u;
239
240 /// Definition of the maximal image height.
241 static constexpr unsigned int maximalHeight_ = 1080u * 8u;
242
243 /// Definition of the maximal bit rate.
244 static constexpr int maximalBitrate_ = bitrateMbps10_ * 10;
245
246 public:
247
248 /**
249 * Default constructor creating an un-initialized encoder.
250 */
252
253 /**
254 * Move constructor.
255 * @param videoEncoder The encoder to be moved
256 */
257 inline VideoEncoder(VideoEncoder&& videoEncoder) noexcept;
258
259 /**
260 * Destructs the video encoder and releases all associated resources.
261 */
263
264 /**
265 * Initializes the video encoder with the specified configuration.
266 * @param width The width of the video to be encoded, in pixel, with range [1, infinity)
267 * @param height The height of the video to be encoded, in pixel, with range [1, infinity)
268 * @param mime The MIME type (Multipurpose Internet Mail Extensions) of the video to be encoded, e.g., "video/avc", "video/hevc", ...
269 * @param frameRate The target frame rate in frames per second, with range (0, infinity), e.g., 30.0
270 * @param bitrate The target bitrate in bits per second, with range [1, infinity), e.g., 5000000 for 5 Mbps
271 * @param iFrameInterval The interval between I-frames (key frames) in seconds: negative value = no key frames after first frame, 0 = all frames are key frames, positive value = key frames every N seconds
272 * @param preferredPixelFormat The preferred pixel format the encoded uses internally
273 * @return True, if succeeded
274 * @see isInitialized().
275 */
276 bool initialize(const unsigned int width, const unsigned int height, const std::string& mime = "video/avc", const double frameRate = 30.0, const unsigned int bitrate = bitrateMbps2_, const int iFrameInterval = 1, const FrameType::PixelFormat preferredPixelFormat = FrameType::FORMAT_Y_UV12_LIMITED_RANGE);
277
278 /**
279 * Starts the video encoder.
280 * @return True, if succeeded
281 * @see isStarted().
282 */
283 bool start();
284
285 /**
286 * Stops the video encoder.
287 * @return True, if succeeded
288 */
289 bool stop();
290
291 /**
292 * Adds a new frame which needs to be encoded to the video encoder.
293 * The encoder needs to be initialized and started.<br>
294 * The presentation time is mainly intended to allow associating the provided frame with the resulting encoded sample when calling popSample().<br>
295 * However, it's recommended to define a reasonable presentation time for each frame (e.g., let the first frame start at 0 and increment the time by 1^6/fps for each following frame).
296 * @param frame The frame to be encoded, must be valid
297 * @param presentationTime The presentation time of the frame, in microseconds, with range [0, infinity)
298 * @return True, if succeeded
299 * @see start(), isInitialized(), isStarted().
300 */
301 bool pushFrame(const Frame& frame, const uint64_t presentationTime);
302
303 /**
304 * Returns the next encoded sample if available.
305 * @return The resulting encoded sample, invalid if currently no encoded sample is available
306 * @see pushFrame().
307 */
309
310 /**
311 * Returns whether this encoder is initialized.
312 * @return True, if so
313 * @see initialize().
314 */
315 inline bool isInitialized() const;
316
317 /**
318 * Returns whether this encoder is currently running.
319 * @return True, if so
320 * @see start().
321 */
322 inline bool isStarted() const;
323
324 /**
325 * Explicitly releases this video encoder.
326 * If the encoder is still running, the encoder will be stopped as well.
327 */
328 void release();
329
330 /**
331 * Move operator.
332 * @param videoEncoder The video encoder to be moved
333 * @return Reference to this object
334 */
335 inline VideoEncoder& operator=(VideoEncoder&& videoEncoder) noexcept;
336
337 protected:
338
339 /**
340 * Disabled copy constructor.
341 */
342 VideoEncoder(const VideoEncoder&) = delete;
343
344 /**
345 * Disabled copy operator.
346 * @return Reference to this object
347 */
349
350 /**
351 * Creates a Frame object from a raw buffer provided by the Android MediaCodec.
352 * This function wraps the raw buffer memory into a Frame object with the appropriate pixel format and plane layout.
353 * The function supports YUV420 formats in both semi-planar (Y_UV12) and planar (Y_U_V12) layouts.
354 * @param width The width of the frame in pixels, must be even, with range [2, infinity)
355 * @param height The height of the frame in pixels, must be even, with range [2, infinity)
356 * @param buffer The raw buffer containing the frame data, must be valid
357 * @param size The size of the buffer in bytes, with range [1, infinity)
358 * @param androidFormat The Android MediaCodec color format constant
359 * @param androidColorRange The Android MediaFormat color range constant
360 * @return The resulting Frame object wrapping the buffer, invalid if the parameters are invalid or the format is not supported
361 */
362 static Frame frameFromBuffer(const unsigned int width, const unsigned int height, uint8_t* const buffer, size_t size, const int32_t androidFormat, const int32_t androidColorRange);
363
364 protected:
365
366 /// The subscription for the native media library.
368
369 /// The Android media encoder used to encode the video.
371
372 /// True, if the encoder is currently started.
373 bool isStarted_ = false;
374
375 /// The encoder's lock.
376 mutable Lock lock_;
377};
378
379inline VideoEncoder::Sample::Sample(std::vector<uint8_t>&& data, const int64_t presentationTime, const MediaCodecBufferFlags bufferFlags) :
380 data_(std::move(data)),
381 presentationTime_(presentationTime),
382 bufferFlags_(bufferFlags)
383{
384 // nothing to do here
385}
386
387inline VideoEncoder::Sample::Sample(Sample&& sample) noexcept
388{
389 *this = std::move(sample);
390}
391
393{
394 return !data_.empty();
395}
396
397inline const std::vector<uint8_t>& VideoEncoder::Sample::data() const
398{
399 return data_;
400}
401
403{
404 return presentationTime_;
405}
406
408{
409 return bufferFlags_ & BUFFER_FLAG_KEY_FRAME;
410}
411
413{
414 return bufferFlags_ & BUFFER_FLAG_CODEC_CONFIG;
415}
416
418{
419 return bufferFlags_ & BUFFER_FLAG_END_OF_STREAM;
420}
421
423{
424 return bufferFlags_ & BUFFER_FLAG_PARTIAL_FRAME;
425}
426
428{
429 if (this != &sample)
430 {
431 data_ = std::move(sample.data_);
432 presentationTime_ = sample.presentationTime_;
433 bufferFlags_ = sample.bufferFlags_;
434
435 sample.presentationTime_ = -1;
436 sample.bufferFlags_ = BUFFER_FLAG_NONE;
437 }
438
439 return *this;
440}
441
442inline VideoEncoder::Sample::operator bool() const
443{
444 return isValid();
445}
446
447inline VideoEncoder::VideoEncoder(VideoEncoder&& videoEncoder) noexcept
448{
449 *this = std::move(videoEncoder);
450}
451
453{
454 const ScopedLock scopedLock(lock_);
455
456 return encoder_.isValid();
457}
458
459inline bool VideoEncoder::isStarted() const
460{
461 const ScopedLock scopedLock(lock_);
462
463 ocean_assert(!isStarted_ || isInitialized());
464
465 return isStarted_;
466}
467
468inline VideoEncoder& VideoEncoder::operator=(VideoEncoder&& videoEncoder) noexcept
469{
470 if (this != &videoEncoder)
471 {
472 release();
473
474 encoder_ = std::move(videoEncoder.encoder_);
475
476 isStarted_ = videoEncoder.isStarted_;
477 videoEncoder.isStarted_ = false;
478 }
479
480 return *this;
481}
482
483}
484
485}
486
487}
488
489#endif // defined(__ANDROID_API__) && __ANDROID_API__ >= 24
490
491#endif // META_OCEAN_MEDIA_ANDROID_VIDEO_ENCODER_H
This class implements Ocean's image class.
Definition Frame.h:1879
PixelFormat
Definition of all pixel formats available in the Ocean framework.
Definition Frame.h:183
@ FORMAT_Y_UV12_LIMITED_RANGE
Pixel format with 8 bits Y frame as entire block, followed by 8 bits 2x2 sub-sampled U and V zipped (...
Definition Frame.h:808
This class implements a recursive lock object.
Definition Lock.h:31
Definition of a scoped object for AMediaCodec objects.
Definition NativeMediaLibrary.h:79
Definition of an encoded sample.
Definition VideoEncoder.h:127
Sample & operator=(const Sample &)=delete
Disabled copy operator.
std::vector< uint8_t > data_
The encoded data.
Definition VideoEncoder.h:222
const std::vector< uint8_t > & data() const
Returns the encoded data.
Definition VideoEncoder.h:397
bool isKeyFrame() const
Returns whether this sample is a key frame.
Definition VideoEncoder.h:407
bool isPartialFrame() const
Returns whether this sample contains only part of a frame.
Definition VideoEncoder.h:422
Sample & operator=(Sample &&sample) noexcept
Move operator.
Definition VideoEncoder.h:427
Sample(const Sample &)=delete
Disabled copy constructor.
bool isEndOfStream() const
Returns whether this sample marks the end of the stream.
Definition VideoEncoder.h:417
bool isConfiguration() const
Returns whether this sample contains codec configuration data instead of media data.
Definition VideoEncoder.h:412
Sample()=default
Creates an invalid sample.
int64_t presentationTime() const
Returns the presentation time in microseconds.
Definition VideoEncoder.h:402
MediaCodecBufferFlags bufferFlags_
Definition VideoEncoder.h:227
int64_t presentationTime_
The presentation time in microseconds.
Definition VideoEncoder.h:225
bool isValid() const
Returns whether this sample is valid.
Definition VideoEncoder.h:392
This class implements a simple video encoder for Android using Ocean::Frame objects as input.
Definition VideoEncoder.h:90
static constexpr int bitrateMbps1_
Definition of a 1 Mbps bit rate.
Definition VideoEncoder.h:94
Sample popSample()
Returns the next encoded sample if available.
NativeMediaLibrary::ScopedSubscription nativeMediaLibrarySubscription_
The subscription for the native media library.
Definition VideoEncoder.h:367
bool initialize(const unsigned int width, const unsigned int height, const std::string &mime="video/avc", const double frameRate=30.0, const unsigned int bitrate=bitrateMbps2_, const int iFrameInterval=1, const FrameType::PixelFormat preferredPixelFormat=FrameType::FORMAT_Y_UV12_LIMITED_RANGE)
Initializes the video encoder with the specified configuration.
static constexpr int bitrateMbps5_
Definition of a 5 Mbps bit rate.
Definition VideoEncoder.h:100
Lock lock_
The encoder's lock.
Definition VideoEncoder.h:376
bool isInitialized() const
Returns whether this encoder is initialized.
Definition VideoEncoder.h:452
bool stop()
Stops the video encoder.
static constexpr unsigned int maximalWidth_
Definition of the maximal image width.
Definition VideoEncoder.h:238
NativeMediaLibrary::ScopedAMediaCodec encoder_
The Android media encoder used to encode the video.
Definition VideoEncoder.h:370
bool isStarted() const
Returns whether this encoder is currently running.
Definition VideoEncoder.h:459
bool pushFrame(const Frame &frame, const uint64_t presentationTime)
Adds a new frame which needs to be encoded to the video encoder.
VideoEncoder(const VideoEncoder &)=delete
Disabled copy constructor.
void release()
Explicitly releases this video encoder.
bool start()
Starts the video encoder.
MediaCodecBufferFlags
Definition of individual MediaCodec buffer flag constants.
Definition VideoEncoder.h:110
@ BUFFER_FLAG_PARTIAL_FRAME
Indicates that the buffer only contains part of a frame.
Definition VideoEncoder.h:120
@ BUFFER_FLAG_END_OF_STREAM
Indicates that the buffer is the last buffer in the stream.
Definition VideoEncoder.h:118
@ BUFFER_FLAG_NONE
The buffer has no special property.
Definition VideoEncoder.h:112
@ BUFFER_FLAG_CODEC_CONFIG
Indicates that the buffer marked as such contains codec initialization / codec specific data instead ...
Definition VideoEncoder.h:116
@ BUFFER_FLAG_KEY_FRAME
Indicates that the (encoded) buffer marked as such contains the data for a key frame.
Definition VideoEncoder.h:114
VideoEncoder()
Default constructor creating an un-initialized encoder.
~VideoEncoder()
Destructs the video encoder and releases all associated resources.
static constexpr int bitrateMbps10_
Definition of a 10 Mbps bit rate.
Definition VideoEncoder.h:103
VideoEncoder & operator=(const VideoEncoder &)=delete
Disabled copy operator.
static Frame frameFromBuffer(const unsigned int width, const unsigned int height, uint8_t *const buffer, size_t size, const int32_t androidFormat, const int32_t androidColorRange)
Creates a Frame object from a raw buffer provided by the Android MediaCodec.
VideoEncoder & operator=(VideoEncoder &&videoEncoder) noexcept
Move operator.
Definition VideoEncoder.h:468
static constexpr unsigned int maximalHeight_
Definition of the maximal image height.
Definition VideoEncoder.h:241
static constexpr int bitrateMbps2_
Definition of a 2 Mbps bit rate.
Definition VideoEncoder.h:97
bool isStarted_
True, if the encoder is currently started.
Definition VideoEncoder.h:373
static constexpr int maximalBitrate_
Definition of the maximal bit rate.
Definition VideoEncoder.h:244
std::vector< Media::Android::VideoEncoder::Sample > Samples
Definition of a vector holding sample objects.
Definition VideoEncoder.h:233
static constexpr T minValue()
Returns the min scalar value.
Definition Numeric.h:3259
This class implements a scoped lock object for recursive lock objects.
Definition Lock.h:147
bool isValid() const
Returns whether this scoped object holds a valid release function (which will be invoked once the obj...
Definition ScopedObject.h:351
The namespace covering the entire Ocean framework.
Definition Accessor.h:15