content/media/omx/OMXCodecWrapper.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef OMXCodecWrapper_h_
michael@0 7 #define OMXCodecWrapper_h_
michael@0 8
michael@0 9 #include <gui/Surface.h>
michael@0 10 #include <stagefright/foundation/ABuffer.h>
michael@0 11 #include <stagefright/foundation/AMessage.h>
michael@0 12 #include <stagefright/MediaCodec.h>
michael@0 13
michael@0 14 #include "AudioSegment.h"
michael@0 15 #include "GonkNativeWindow.h"
michael@0 16 #include "GonkNativeWindowClient.h"
michael@0 17
michael@0 18 #include <speex/speex_resampler.h>
michael@0 19
michael@0 20 namespace android {
michael@0 21
michael@0 22 class OMXAudioEncoder;
michael@0 23 class OMXVideoEncoder;
michael@0 24
michael@0 25 /**
michael@0 26 * This class (and its subclasses) wraps the video and audio codec from
michael@0 27 * MediaCodec API in libstagefright. Currently only AVC/H.264 video encoder and
michael@0 28 * AAC audio encoder are supported.
michael@0 29 *
michael@0 30 * OMXCodecWrapper has static creator functions that returns actual codec
michael@0 31 * instances for different types of codec supported and serves as superclass to
michael@0 32 * provide a function to read encoded data as byte array from codec. Two
michael@0 33 * subclasses, OMXAudioEncoder and OMXVideoEncoder, respectively provides
michael@0 34 * functions for encoding data from audio and video track.
michael@0 35 *
michael@0 36 * A typical usage is as follows:
michael@0 37 * - Call one of the creator function Create...() to get either a
michael@0 38 * OMXAudioEncoder or OMXVideoEncoder object.
michael@0 39 * - Configure codec by providing characteristics of input raw data, such as
michael@0 40 * video frame width and height, using Configure().
michael@0 41 * - Send raw data (and notify end of stream) with Encode().
michael@0 42 * - Get encoded data through GetNextEncodedFrame().
michael@0 43 * - Repeat previous 2 steps until end of stream.
michael@0 44 * - Destroy the object.
michael@0 45 *
michael@0 46 * The lifecycle of underlying OMX codec is binded with construction and
michael@0 47 * destruction of OMXCodecWrapper and subclass objects. For some types of
michael@0 48 * codecs, such as HW accelerated AVC/H.264 encoder, there can be only one
michael@0 49 * instance system-wise at a time, attempting to create another instance will
michael@0 50 * fail.
michael@0 51 */
michael@0 52 class OMXCodecWrapper
michael@0 53 {
michael@0 54 public:
michael@0 55 // Codec types.
michael@0 56 enum CodecType {
michael@0 57 AAC_ENC, // AAC encoder.
michael@0 58 AMR_NB_ENC, // AMR_NB encoder.
michael@0 59 AVC_ENC, // AVC/H.264 encoder.
michael@0 60 TYPE_COUNT
michael@0 61 };
michael@0 62
michael@0 63 // Input and output flags.
michael@0 64 enum {
michael@0 65 // For Encode() and Encode, it indicates the end of input stream;
michael@0 66 // For GetNextEncodedFrame(), it indicates the end of output
michael@0 67 // stream.
michael@0 68 BUFFER_EOS = MediaCodec::BUFFER_FLAG_EOS,
michael@0 69 // For GetNextEncodedFrame(). It indicates the output buffer is an I-frame.
michael@0 70 BUFFER_SYNC_FRAME = MediaCodec::BUFFER_FLAG_SYNCFRAME,
michael@0 71 // For GetNextEncodedFrame(). It indicates that the output buffer contains
michael@0 72 // codec specific configuration info. (SPS & PPS for AVC/H.264;
michael@0 73 // DecoderSpecificInfo for AAC)
michael@0 74 BUFFER_CODEC_CONFIG = MediaCodec::BUFFER_FLAG_CODECCONFIG,
michael@0 75 };
michael@0 76
michael@0 77 // Hard-coded values for AAC DecoderConfigDescriptor in libstagefright.
michael@0 78 // See MPEG4Writer::Track::writeMp4aEsdsBox()
michael@0 79 // Exposed for the need of MP4 container writer.
michael@0 80 enum {
michael@0 81 kAACBitrate = 96000, // kbps
michael@0 82 kAACFrameSize = 768, // bytes
michael@0 83 kAACFrameDuration = 1024, // How many samples per AAC frame.
michael@0 84 };
michael@0 85
michael@0 86 /** Create a AAC audio encoder. Returns nullptr when failed. */
michael@0 87 static OMXAudioEncoder* CreateAACEncoder();
michael@0 88
michael@0 89 /** Create a AMR audio encoder. Returns nullptr when failed. */
michael@0 90 static OMXAudioEncoder* CreateAMRNBEncoder();
michael@0 91
michael@0 92 /** Create a AVC/H.264 video encoder. Returns nullptr when failed. */
michael@0 93 static OMXVideoEncoder* CreateAVCEncoder();
michael@0 94
michael@0 95 virtual ~OMXCodecWrapper();
michael@0 96
michael@0 97 /**
michael@0 98 * Get the next available encoded data from MediaCodec. The data will be
michael@0 99 * copied into aOutputBuf array, with its timestamp (in microseconds) in
michael@0 100 * aOutputTimestamp.
michael@0 101 * Wait at most aTimeout microseconds to dequeue a output buffer.
michael@0 102 */
michael@0 103 nsresult GetNextEncodedFrame(nsTArray<uint8_t>* aOutputBuf,
michael@0 104 int64_t* aOutputTimestamp, int* aOutputFlags,
michael@0 105 int64_t aTimeOut);
michael@0 106 /*
michael@0 107 * Get the codec type
michael@0 108 */
michael@0 109 int GetCodecType() { return mCodecType; }
michael@0 110 protected:
michael@0 111 /**
michael@0 112 * See whether the object has been initialized successfully and is ready to
michael@0 113 * use.
michael@0 114 */
michael@0 115 virtual bool IsValid() { return mCodec != nullptr; }
michael@0 116
michael@0 117 /**
michael@0 118 * Construct codec specific configuration blob with given data aData generated
michael@0 119 * by media codec and append it into aOutputBuf. Needed by MP4 container
michael@0 120 * writer for generating decoder config box, or WebRTC for generating RTP
michael@0 121 * packets. Returns OK if succeed.
michael@0 122 */
michael@0 123 virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
michael@0 124 ABuffer* aData) = 0;
michael@0 125
michael@0 126 /**
michael@0 127 * Append encoded frame data generated by media codec (stored in aData and
michael@0 128 * is aSize bytes long) into aOutputBuf. Subclasses can override this function
michael@0 129 * to process the data for specific container writer.
michael@0 130 */
michael@0 131 virtual void AppendFrame(nsTArray<uint8_t>* aOutputBuf,
michael@0 132 const uint8_t* aData, size_t aSize)
michael@0 133 {
michael@0 134 aOutputBuf->AppendElements(aData, aSize);
michael@0 135 }
michael@0 136
michael@0 137 private:
michael@0 138 // Hide these. User should always use creator functions to get a media codec.
michael@0 139 OMXCodecWrapper() MOZ_DELETE;
michael@0 140 OMXCodecWrapper(const OMXCodecWrapper&) MOZ_DELETE;
michael@0 141 OMXCodecWrapper& operator=(const OMXCodecWrapper&) MOZ_DELETE;
michael@0 142
michael@0 143 /**
michael@0 144 * Create a media codec of given type. It will be a AVC/H.264 video encoder if
michael@0 145 * aCodecType is CODEC_AVC_ENC, or AAC audio encoder if aCodecType is
michael@0 146 * CODEC_AAC_ENC.
michael@0 147 */
michael@0 148 OMXCodecWrapper(CodecType aCodecType);
michael@0 149
michael@0 150 // For subclasses to access hidden constructor and implementation details.
michael@0 151 friend class OMXAudioEncoder;
michael@0 152 friend class OMXVideoEncoder;
michael@0 153
michael@0 154 /**
michael@0 155 * Start the media codec.
michael@0 156 */
michael@0 157 status_t Start();
michael@0 158
michael@0 159 /**
michael@0 160 * Stop the media codec.
michael@0 161 */
michael@0 162 status_t Stop();
michael@0 163
michael@0 164 // The actual codec instance provided by libstagefright.
michael@0 165 sp<MediaCodec> mCodec;
michael@0 166
michael@0 167 // A dedicate message loop with its own thread used by MediaCodec.
michael@0 168 sp<ALooper> mLooper;
michael@0 169
michael@0 170 Vector<sp<ABuffer> > mInputBufs; // MediaCodec buffers to hold input data.
michael@0 171 Vector<sp<ABuffer> > mOutputBufs; // MediaCodec buffers to hold output data.
michael@0 172
michael@0 173 int mCodecType;
michael@0 174 bool mStarted; // Has MediaCodec been started?
michael@0 175 bool mAMRCSDProvided;
michael@0 176 };
michael@0 177
michael@0 178 /**
michael@0 179 * Audio encoder.
michael@0 180 */
michael@0 181 class OMXAudioEncoder MOZ_FINAL : public OMXCodecWrapper
michael@0 182 {
michael@0 183 public:
michael@0 184 /**
michael@0 185 * Configure audio codec parameters and start media codec. It must be called
michael@0 186 * before calling Encode() and GetNextEncodedFrame().
michael@0 187 * aReSamplingRate = 0 means no resampler required
michael@0 188 */
michael@0 189 nsresult Configure(int aChannelCount, int aInputSampleRate, int aEncodedSampleRate);
michael@0 190
michael@0 191 /**
michael@0 192 * Encode 16-bit PCM audio samples stored in aSegment. To notify end of
michael@0 193 * stream, set aInputFlags to BUFFER_EOS. Since encoder has limited buffers,
michael@0 194 * this function might not be able to encode all chunks in one call, however
michael@0 195 * it will remove chunks it consumes from aSegment.
michael@0 196 */
michael@0 197 nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
michael@0 198
michael@0 199 ~OMXAudioEncoder();
michael@0 200 protected:
michael@0 201 virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
michael@0 202 ABuffer* aData) MOZ_OVERRIDE;
michael@0 203 private:
michael@0 204 // Hide these. User should always use creator functions to get a media codec.
michael@0 205 OMXAudioEncoder() MOZ_DELETE;
michael@0 206 OMXAudioEncoder(const OMXAudioEncoder&) MOZ_DELETE;
michael@0 207 OMXAudioEncoder& operator=(const OMXAudioEncoder&) MOZ_DELETE;
michael@0 208
michael@0 209 /**
michael@0 210 * Create a audio codec. It will be a AAC encoder if aCodecType is
michael@0 211 * CODEC_AAC_ENC.
michael@0 212 */
michael@0 213 OMXAudioEncoder(CodecType aCodecType)
michael@0 214 : OMXCodecWrapper(aCodecType)
michael@0 215 , mResampler(nullptr)
michael@0 216 , mChannels(0)
michael@0 217 , mTimestamp(0)
michael@0 218 , mSampleDuration(0)
michael@0 219 , mResamplingRatio(0) {}
michael@0 220
michael@0 221 // For creator function to access hidden constructor.
michael@0 222 friend class OMXCodecWrapper;
michael@0 223
michael@0 224 /**
michael@0 225 * If the input sample rate does not divide 48kHz evenly, the input data are
michael@0 226 * resampled.
michael@0 227 */
michael@0 228 SpeexResamplerState* mResampler;
michael@0 229 // Number of audio channels.
michael@0 230 size_t mChannels;
michael@0 231
michael@0 232 float mResamplingRatio;
michael@0 233 // The total duration of audio samples that have been encoded in microseconds.
michael@0 234 int64_t mTimestamp;
michael@0 235 // Time per audio sample in microseconds.
michael@0 236 int64_t mSampleDuration;
michael@0 237 };
michael@0 238
michael@0 239 /**
michael@0 240 * Video encoder.
michael@0 241 */
michael@0 242 class OMXVideoEncoder MOZ_FINAL : public OMXCodecWrapper
michael@0 243 {
michael@0 244 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OMXVideoEncoder)
michael@0 245 public:
michael@0 246 // Types of output blob format.
michael@0 247 enum BlobFormat {
michael@0 248 AVC_MP4, // MP4 file config descripter (defined in ISO/IEC 14496-15 5.2.4.1.1)
michael@0 249 AVC_NAL // NAL (Network Abstract Layer) (defined in ITU-T H.264 7.4.1)
michael@0 250 };
michael@0 251
michael@0 252 /**
michael@0 253 * Configure video codec parameters and start media codec. It must be called
michael@0 254 * before calling Encode() and GetNextEncodedFrame().
michael@0 255 * aBlobFormat specifies output blob format provided by encoder. It can be
michael@0 256 * AVC_MP4 or AVC_NAL.
michael@0 257 */
michael@0 258 nsresult Configure(int aWidth, int aHeight, int aFrameRate,
michael@0 259 BlobFormat aBlobFormat = BlobFormat::AVC_MP4);
michael@0 260
michael@0 261 /**
michael@0 262 * Encode a aWidth pixels wide and aHeight pixels tall video frame of
michael@0 263 * semi-planar YUV420 format stored in the buffer of aImage. aTimestamp gives
michael@0 264 * the frame timestamp/presentation time (in microseconds). To notify end of
michael@0 265 * stream, set aInputFlags to BUFFER_EOS.
michael@0 266 */
michael@0 267 nsresult Encode(const mozilla::layers::Image* aImage, int aWidth, int aHeight,
michael@0 268 int64_t aTimestamp, int aInputFlags = 0);
michael@0 269
michael@0 270 #if ANDROID_VERSION >= 18
michael@0 271 /** Set encoding bitrate (in kbps). */
michael@0 272 nsresult SetBitrate(int32_t aKbps);
michael@0 273 #endif
michael@0 274
michael@0 275 /**
michael@0 276 * Get current AVC codec config blob. The output format depends on the
michael@0 277 * aBlobFormat argument given when Configure() was called.
michael@0 278 */
michael@0 279 nsresult GetCodecConfig(nsTArray<uint8_t>* aOutputBuf);
michael@0 280
michael@0 281 protected:
michael@0 282 virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
michael@0 283 ABuffer* aData) MOZ_OVERRIDE;
michael@0 284
michael@0 285 // If configured to output MP4 format blob, AVC/H.264 encoder has to replace
michael@0 286 // NAL unit start code with the unit length as specified in
michael@0 287 // ISO/IEC 14496-15 5.2.3.
michael@0 288 virtual void AppendFrame(nsTArray<uint8_t>* aOutputBuf,
michael@0 289 const uint8_t* aData, size_t aSize) MOZ_OVERRIDE;
michael@0 290
michael@0 291 private:
michael@0 292 // Hide these. User should always use creator functions to get a media codec.
michael@0 293 OMXVideoEncoder() MOZ_DELETE;
michael@0 294 OMXVideoEncoder(const OMXVideoEncoder&) MOZ_DELETE;
michael@0 295 OMXVideoEncoder& operator=(const OMXVideoEncoder&) MOZ_DELETE;
michael@0 296
michael@0 297 /**
michael@0 298 * Create a video codec. It will be a AVC/H.264 encoder if aCodecType is
michael@0 299 * CODEC_AVC_ENC.
michael@0 300 */
michael@0 301 OMXVideoEncoder(CodecType aCodecType)
michael@0 302 : OMXCodecWrapper(aCodecType)
michael@0 303 , mWidth(0)
michael@0 304 , mHeight(0)
michael@0 305 , mBlobFormat(BlobFormat::AVC_MP4)
michael@0 306 , mHasConfigBlob(false)
michael@0 307 {}
michael@0 308
michael@0 309 // For creator function to access hidden constructor.
michael@0 310 friend class OMXCodecWrapper;
michael@0 311
michael@0 312 int mWidth;
michael@0 313 int mHeight;
michael@0 314 BlobFormat mBlobFormat;
michael@0 315 bool mHasConfigBlob;
michael@0 316 };
michael@0 317
michael@0 318 } // namespace android
michael@0 319 #endif // OMXCodecWrapper_h_

mercurial