content/media/omx/OMXCodecWrapper.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial