Ocean
VideoDecoder.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_DECODER_H
9 #define META_OCEAN_MEDIA_ANDROID_VIDEO_DECODER_H
10 
11 #if defined(__ANDROID_API__) && __ANDROID_API__ >= 24
12 
13 #ifndef OCEAN_MEDIA_ANDROID_VIDEODECODER_AVAILABLE
14  #define OCEAN_MEDIA_ANDROID_VIDEODECODER_AVAILABLE
15 #endif
16 
19 
20 #include "ocean/base/Frame.h"
21 #include "ocean/base/Lock.h"
22 
23 namespace Ocean
24 {
25 
26 namespace Media
27 {
28 
29 namespace Android
30 {
31 
32 /**
33  * This class implements a simple video decoder for Android using encoded media samples from memory as input.
34  *
35  * Usage:
36  * @code
37  * // a function which is e.g., running in a separate thread
38  * void threadRun()
39  * {
40  * VideoDecoder videoDecoder;
41  *
42  * // initializing the decoder with the input format of the media samples
43  * if (!videoDecoder.initialize("video/avc", 1920u, 1080u))
44  * {
45  * // handle error
46  * }
47  *
48  * if (!videoDecoder.start())
49  * {
50  * // handle error
51  * }
52  *
53  * unsigned int frameIndex = 0u;
54  * double frameRate = 30.0;
55  *
56  * while (true)
57  * {
58  * void* sampleData = nullptr;
59  * size_t sampleSize = 0;
60  *
61  * // external function: function needs to provide the new media samples from an external source - e.g., from an external webcam, a video stream, etc.
62  * if (doesNewInputSampleExist(sampleData, &sampleSize))
63  * {
64  * // presentation time in microseconds
65  * uint64_t presentationTime = uint64_t(1.0e6 * double(frameIndex) / frameRate);
66  *
67  * // we forward the media sample to the decoder, eventually it will be decoded and will be available through decodedFrame()
68  * if (!videoDecoder.pushSample(sampleData, sampleSize, presentationTime))
69  * {
70  * // handle error
71  * }
72  *
73  * ++frameIndex;
74  * }
75  *
76  * // we simply check whether another frame has been decoded (there may be a delay between
77  * Frame newFrame = videoDecoder.popFrame();
78  *
79  * if (newFrame.isValid())
80  * {
81  * // external function: receiving new frames and processes the frames
82  * sendFrameToReceiver(std::move(newFrame));
83  * }
84  * }
85  * }
86  * @endcode
87  * @ingroup mediaandroid
88  */
90 {
91  public:
92 
93  /**
94  * Default constructor creating an un-initialized decoder.
95  */
97 
98  /**
99  * Move constructor.
100  * @param videoDecoder The decoder to be moved
101  */
102  inline VideoDecoder(VideoDecoder&& videoDecoder) noexcept;
103 
104  /**
105  * Destructs the video decoder and releases all associated resources.
106  */
108 
109  /**
110  * @param mime The MIME type (Multipurpose Internet Mail Extensions) of the video to be decoded, e.g., "video/avc", "video/hevc", ...
111  * @param width The width of the video to be decoded, in pixel, with range [1, infinity)
112  * @param height The height of the video to be decoded, in pixel, with range [1, infinity)
113  * @return True, if succeeded
114  * @see isInitialized().
115  */
116  bool initialize(const std::string& mime, const unsigned int width, const unsigned int height);
117 
118  /**
119  * Starts the video decoder.
120  * @return True, if succeeded
121  * @see isStarted().
122  */
123  bool start();
124 
125  /**
126  * Stops the video decoder.
127  * @return True, if succeeded
128  */
129  bool stop();
130 
131  /**
132  * Adds a new media sample which needs to be decoded to the video decoder.
133  * The decoder needs to be initialized and started.<br>
134  * The presentation time is mainly intended to allow associating the provided encoded media sample with the resulting decoded frame when calling popFrame().<br>
135  * However, it's recommended to define a reasonable presentation time for each sample (e.g., let the first sample start at 0 and increment the time by 1^6/fps for each following sample.
136  * @param data The data of the encoded media sample, must be valid
137  * @param size The size of the encoded media sample, in bytes, with range [1, infinity)
138  * @param presentationTime The presentation time of the sample, in microseconds, with range [0, infinity)
139  * @return True, if succeeded
140  * @see start(), isInitialized(), isStarted().
141  */
142  bool pushSample(const void* data, const size_t size, const uint64_t presentationTime);
143 
144  /**
145  * Optional the frame's presentation time will be returned, this is the presentation time which was used when the corresponding sample was provided in decodedSample().
146  * @param presentationTime Optional resulting presentation time in micro seconds, with range (-infinity, infinity)
147  * @return The resulting frame, invalid if currently no decoded frame is available
148  * @see pushSample().
149  */
150  Frame popFrame(int64_t* presentationTime = nullptr);
151 
152  /**
153  * Returns whether this decode is initialized.
154  * @return True, if so
155  * @see initialize().
156  */
157  inline bool isInitialized() const;
158 
159  /**
160  * Returns whether this decoder is currently running.
161  * @return True, if so
162  * @see start().
163  */
164  inline bool isStarted() const;
165 
166  /**
167  * Explicitly releases this video encoder.
168  * If the encoder is still running, the encoder will be stopped as well.
169  */
170  void release();
171 
172  /**
173  * Move operator.
174  * @param videoDecoder The video decoder to be moved
175  * @return Reference to this object
176  */
177  inline VideoDecoder& operator=(VideoDecoder&& videoDecoder) noexcept;
178 
179  /**
180  * Extracts the video frame from an output buffer of a video codec.
181  * @param mediaCodec The media codec to which the output buffer belongs, must be valid
182  * @param presentationTime Optional resulting presentation time in micro seconds, with range (-infinity, infinity)
183  * @return The resulting extracted frame, invalid if the frame could not be extracted
184  */
185  static Frame extractVideoFrameFromCodecOutputBuffer(AMediaCodec* const mediaCodec, int64_t* presentationTime = nullptr);
186 
187  protected:
188 
189  /**
190  * Disabled copy constructor.
191  */
192  VideoDecoder(const VideoDecoder&) = delete;
193 
194  /**
195  * Disabled copy operator.
196  * @return Reference to this object
197  */
199 
200  protected:
201 
202  /// The subscription for the native media library.
204 
205  /// The Android media decoder used to decode the video.
207 
208  /// True, if the decoder is currently started.
209  bool isStarted_ = false;
210 
211  /// The decoder's lock.
212  mutable Lock lock_;
213 };
214 
215 inline VideoDecoder::VideoDecoder(VideoDecoder&& videoDecoder) noexcept
216 {
217  *this = std::move(videoDecoder);
218 }
219 
220 inline bool VideoDecoder::isInitialized() const
221 {
222  const ScopedLock scopedLock(lock_);
223 
224  return decoder_.isValid();
225 }
226 
227 inline bool VideoDecoder::isStarted() const
228 {
229  const ScopedLock scopedLock(lock_);
230 
231  ocean_assert(!isStarted_ || isInitialized());
232 
233  return isStarted_;
234 }
235 
236 inline VideoDecoder& VideoDecoder::operator=(VideoDecoder&& videoDecoder) noexcept
237 {
238  if (this != &videoDecoder)
239  {
240  release();
241 
242  decoder_ = std::move(videoDecoder.decoder_);
243 
244  isStarted_ = videoDecoder.isStarted_;
245  videoDecoder.isStarted_ = false;
246  }
247 
248  return *this;
249 }
250 
251 }
252 
253 }
254 
255 }
256 
257 #endif // defined(__ANDROID_API__) && __ANDROID_API__ >= 24
258 
259 #endif // META_OCEAN_MEDIA_ANDROID_VIDEO_DECODER_H
This class implements Ocean's image class.
Definition: Frame.h:1760
This class implements a recursive lock object.
Definition: Lock.h:31
Definition of a scoped object for AMediaCodec objects.
Definition: NativeMediaLibrary.h:79
This class implements a simple video decoder for Android using encoded media samples from memory as i...
Definition: VideoDecoder.h:90
bool initialize(const std::string &mime, const unsigned int width, const unsigned int height)
VideoDecoder(const VideoDecoder &)=delete
Disabled copy constructor.
static Frame extractVideoFrameFromCodecOutputBuffer(AMediaCodec *const mediaCodec, int64_t *presentationTime=nullptr)
Extracts the video frame from an output buffer of a video codec.
NativeMediaLibrary::ScopedAMediaCodec decoder_
The Android media decoder used to decode the video.
Definition: VideoDecoder.h:206
VideoDecoder & operator=(VideoDecoder &&videoDecoder) noexcept
Move operator.
Definition: VideoDecoder.h:236
void release()
Explicitly releases this video encoder.
VideoDecoder()
Default constructor creating an un-initialized decoder.
Lock lock_
The decoder's lock.
Definition: VideoDecoder.h:212
~VideoDecoder()
Destructs the video decoder and releases all associated resources.
bool isStarted_
True, if the decoder is currently started.
Definition: VideoDecoder.h:209
NativeMediaLibrary::ScopedSubscription nativeMediaLibrarySubscription_
The subscription for the native media library.
Definition: VideoDecoder.h:203
bool isInitialized() const
Returns whether this decode is initialized.
Definition: VideoDecoder.h:220
bool isStarted() const
Returns whether this decoder is currently running.
Definition: VideoDecoder.h:227
bool stop()
Stops the video decoder.
VideoDecoder & operator=(const VideoDecoder &)=delete
Disabled copy operator.
bool pushSample(const void *data, const size_t size, const uint64_t presentationTime)
Adds a new media sample which needs to be decoded to the video decoder.
Frame popFrame(int64_t *presentationTime=nullptr)
Optional the frame's presentation time will be returned, this is the presentation time which was used...
bool start()
Starts the video decoder.
This class implements a scoped lock object for recursive lock objects.
Definition: Lock.h:135
bool isValid() const
Returns whether this scoped object holds a valid release function (which will be invoked once the obj...
Definition: ScopedObject.h:351
void release(T *object)
This functions allows to release a DirectShow object if it does exist.
Definition: DSObject.h:266
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15