content/media/omx/OMXCodecWrapper.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/media/omx/OMXCodecWrapper.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,319 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef OMXCodecWrapper_h_
    1.10 +#define OMXCodecWrapper_h_
    1.11 +
    1.12 +#include <gui/Surface.h>
    1.13 +#include <stagefright/foundation/ABuffer.h>
    1.14 +#include <stagefright/foundation/AMessage.h>
    1.15 +#include <stagefright/MediaCodec.h>
    1.16 +
    1.17 +#include "AudioSegment.h"
    1.18 +#include "GonkNativeWindow.h"
    1.19 +#include "GonkNativeWindowClient.h"
    1.20 +
    1.21 +#include <speex/speex_resampler.h>
    1.22 +
    1.23 +namespace android {
    1.24 +
    1.25 +class OMXAudioEncoder;
    1.26 +class OMXVideoEncoder;
    1.27 +
    1.28 +/**
    1.29 + * This class (and its subclasses) wraps the video and audio codec from
    1.30 + * MediaCodec API in libstagefright. Currently only AVC/H.264 video encoder and
    1.31 + * AAC audio encoder are supported.
    1.32 + *
    1.33 + * OMXCodecWrapper has static creator functions that returns actual codec
    1.34 + * instances for different types of codec supported and serves as superclass to
    1.35 + * provide a function to read encoded data as byte array from codec. Two
    1.36 + * subclasses, OMXAudioEncoder and OMXVideoEncoder, respectively provides
    1.37 + * functions for encoding data from audio and video track.
    1.38 + *
    1.39 + * A typical usage is as follows:
    1.40 + * - Call one of the creator function Create...() to get either a
    1.41 + *   OMXAudioEncoder or OMXVideoEncoder object.
    1.42 + * - Configure codec by providing characteristics of input raw data, such as
    1.43 + *   video frame width and height, using Configure().
    1.44 + * - Send raw data (and notify end of stream) with Encode().
    1.45 + * - Get encoded data through GetNextEncodedFrame().
    1.46 + * - Repeat previous 2 steps until end of stream.
    1.47 + * - Destroy the object.
    1.48 + *
    1.49 + * The lifecycle of underlying OMX codec is binded with construction and
    1.50 + * destruction of OMXCodecWrapper and subclass objects. For some types of
    1.51 + * codecs, such as HW accelerated AVC/H.264 encoder, there can be only one
    1.52 + * instance system-wise at a time, attempting to create another instance will
    1.53 + * fail.
    1.54 + */
    1.55 +class OMXCodecWrapper
    1.56 +{
    1.57 +public:
    1.58 +  // Codec types.
    1.59 +  enum CodecType {
    1.60 +    AAC_ENC, // AAC encoder.
    1.61 +    AMR_NB_ENC, // AMR_NB encoder.
    1.62 +    AVC_ENC, // AVC/H.264 encoder.
    1.63 +    TYPE_COUNT
    1.64 +  };
    1.65 +
    1.66 +  // Input and output flags.
    1.67 +  enum {
    1.68 +    // For Encode() and Encode, it indicates the end of input stream;
    1.69 +    // For GetNextEncodedFrame(), it indicates the end of output
    1.70 +    // stream.
    1.71 +    BUFFER_EOS = MediaCodec::BUFFER_FLAG_EOS,
    1.72 +    // For GetNextEncodedFrame(). It indicates the output buffer is an I-frame.
    1.73 +    BUFFER_SYNC_FRAME = MediaCodec::BUFFER_FLAG_SYNCFRAME,
    1.74 +    // For GetNextEncodedFrame(). It indicates that the output buffer contains
    1.75 +    // codec specific configuration info. (SPS & PPS for AVC/H.264;
    1.76 +    // DecoderSpecificInfo for AAC)
    1.77 +    BUFFER_CODEC_CONFIG = MediaCodec::BUFFER_FLAG_CODECCONFIG,
    1.78 +  };
    1.79 +
    1.80 +  // Hard-coded values for AAC DecoderConfigDescriptor in libstagefright.
    1.81 +  // See MPEG4Writer::Track::writeMp4aEsdsBox()
    1.82 +  // Exposed for the need of MP4 container writer.
    1.83 +  enum {
    1.84 +    kAACBitrate = 96000,      // kbps
    1.85 +    kAACFrameSize = 768,      // bytes
    1.86 +    kAACFrameDuration = 1024, // How many samples per AAC frame.
    1.87 +  };
    1.88 +
    1.89 +  /** Create a AAC audio encoder. Returns nullptr when failed. */
    1.90 +  static OMXAudioEncoder* CreateAACEncoder();
    1.91 +
    1.92 +  /** Create a AMR audio encoder. Returns nullptr when failed. */
    1.93 +  static OMXAudioEncoder* CreateAMRNBEncoder();
    1.94 +
    1.95 +  /** Create a AVC/H.264 video encoder. Returns nullptr when failed. */
    1.96 +  static OMXVideoEncoder* CreateAVCEncoder();
    1.97 +
    1.98 +  virtual ~OMXCodecWrapper();
    1.99 +
   1.100 +  /**
   1.101 +   * Get the next available encoded data from MediaCodec. The data will be
   1.102 +   * copied into aOutputBuf array, with its timestamp (in microseconds) in
   1.103 +   * aOutputTimestamp.
   1.104 +   * Wait at most aTimeout microseconds to dequeue a output buffer.
   1.105 +   */
   1.106 +  nsresult GetNextEncodedFrame(nsTArray<uint8_t>* aOutputBuf,
   1.107 +                               int64_t* aOutputTimestamp, int* aOutputFlags,
   1.108 +                               int64_t aTimeOut);
   1.109 +  /*
   1.110 +   * Get the codec type
   1.111 +   */
   1.112 +  int GetCodecType() { return mCodecType; }
   1.113 +protected:
   1.114 +  /**
   1.115 +   * See whether the object has been initialized successfully and is ready to
   1.116 +   * use.
   1.117 +   */
   1.118 +  virtual bool IsValid() { return mCodec != nullptr; }
   1.119 +
   1.120 +  /**
   1.121 +   * Construct codec specific configuration blob with given data aData generated
   1.122 +   * by media codec and append it into aOutputBuf. Needed by MP4 container
   1.123 +   * writer for generating decoder config box, or WebRTC for generating RTP
   1.124 +   * packets. Returns OK if succeed.
   1.125 +   */
   1.126 +  virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
   1.127 +                                       ABuffer* aData) = 0;
   1.128 +
   1.129 +  /**
   1.130 +   * Append encoded frame data generated by media codec (stored in aData and
   1.131 +   * is aSize bytes long) into aOutputBuf. Subclasses can override this function
   1.132 +   * to process the data for specific container writer.
   1.133 +   */
   1.134 +  virtual void AppendFrame(nsTArray<uint8_t>* aOutputBuf,
   1.135 +                           const uint8_t* aData, size_t aSize)
   1.136 +  {
   1.137 +    aOutputBuf->AppendElements(aData, aSize);
   1.138 +  }
   1.139 +
   1.140 +private:
   1.141 +  // Hide these. User should always use creator functions to get a media codec.
   1.142 +  OMXCodecWrapper() MOZ_DELETE;
   1.143 +  OMXCodecWrapper(const OMXCodecWrapper&) MOZ_DELETE;
   1.144 +  OMXCodecWrapper& operator=(const OMXCodecWrapper&) MOZ_DELETE;
   1.145 +
   1.146 +  /**
   1.147 +   * Create a media codec of given type. It will be a AVC/H.264 video encoder if
   1.148 +   * aCodecType is CODEC_AVC_ENC, or AAC audio encoder if aCodecType is
   1.149 +   * CODEC_AAC_ENC.
   1.150 +   */
   1.151 +  OMXCodecWrapper(CodecType aCodecType);
   1.152 +
   1.153 +  // For subclasses to access hidden constructor and implementation details.
   1.154 +  friend class OMXAudioEncoder;
   1.155 +  friend class OMXVideoEncoder;
   1.156 +
   1.157 +  /**
   1.158 +   * Start the media codec.
   1.159 +   */
   1.160 +  status_t Start();
   1.161 +
   1.162 +  /**
   1.163 +   * Stop the media codec.
   1.164 +   */
   1.165 +  status_t Stop();
   1.166 +
   1.167 +  // The actual codec instance provided by libstagefright.
   1.168 +  sp<MediaCodec> mCodec;
   1.169 +
   1.170 +  // A dedicate message loop with its own thread used by MediaCodec.
   1.171 +  sp<ALooper> mLooper;
   1.172 +
   1.173 +  Vector<sp<ABuffer> > mInputBufs;  // MediaCodec buffers to hold input data.
   1.174 +  Vector<sp<ABuffer> > mOutputBufs; // MediaCodec buffers to hold output data.
   1.175 +
   1.176 +  int mCodecType;
   1.177 +  bool mStarted; // Has MediaCodec been started?
   1.178 +  bool mAMRCSDProvided;
   1.179 +};
   1.180 +
   1.181 +/**
   1.182 + * Audio encoder.
   1.183 + */
   1.184 +class OMXAudioEncoder MOZ_FINAL : public OMXCodecWrapper
   1.185 +{
   1.186 +public:
   1.187 +  /**
   1.188 +   * Configure audio codec parameters and start media codec. It must be called
   1.189 +   * before calling Encode() and GetNextEncodedFrame().
   1.190 +   * aReSamplingRate = 0 means no resampler required
   1.191 +   */
   1.192 +  nsresult Configure(int aChannelCount, int aInputSampleRate, int aEncodedSampleRate);
   1.193 +
   1.194 +  /**
   1.195 +   * Encode 16-bit PCM audio samples stored in aSegment. To notify end of
   1.196 +   * stream, set aInputFlags to BUFFER_EOS. Since encoder has limited buffers,
   1.197 +   * this function might not be able to encode all chunks in one call, however
   1.198 +   * it will remove chunks it consumes from aSegment.
   1.199 +   */
   1.200 +  nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
   1.201 +
   1.202 +  ~OMXAudioEncoder();
   1.203 +protected:
   1.204 +  virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
   1.205 +                                       ABuffer* aData) MOZ_OVERRIDE;
   1.206 +private:
   1.207 +  // Hide these. User should always use creator functions to get a media codec.
   1.208 +  OMXAudioEncoder() MOZ_DELETE;
   1.209 +  OMXAudioEncoder(const OMXAudioEncoder&) MOZ_DELETE;
   1.210 +  OMXAudioEncoder& operator=(const OMXAudioEncoder&) MOZ_DELETE;
   1.211 +
   1.212 +  /**
   1.213 +   * Create a audio codec. It will be a AAC encoder if aCodecType is
   1.214 +   * CODEC_AAC_ENC.
   1.215 +   */
   1.216 +  OMXAudioEncoder(CodecType aCodecType)
   1.217 +    : OMXCodecWrapper(aCodecType)
   1.218 +    , mResampler(nullptr)
   1.219 +    , mChannels(0)
   1.220 +    , mTimestamp(0)
   1.221 +    , mSampleDuration(0)
   1.222 +    , mResamplingRatio(0) {}
   1.223 +
   1.224 +  // For creator function to access hidden constructor.
   1.225 +  friend class OMXCodecWrapper;
   1.226 +
   1.227 +  /**
   1.228 +   * If the input sample rate does not divide 48kHz evenly, the input data are
   1.229 +   * resampled.
   1.230 +   */
   1.231 +  SpeexResamplerState* mResampler;
   1.232 +  // Number of audio channels.
   1.233 +  size_t mChannels;
   1.234 +
   1.235 +  float mResamplingRatio;
   1.236 +  // The total duration of audio samples that have been encoded in microseconds.
   1.237 +  int64_t mTimestamp;
   1.238 +  // Time per audio sample in microseconds.
   1.239 +  int64_t mSampleDuration;
   1.240 +};
   1.241 +
   1.242 +/**
   1.243 + * Video encoder.
   1.244 + */
   1.245 +class OMXVideoEncoder MOZ_FINAL : public OMXCodecWrapper
   1.246 +{
   1.247 +  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OMXVideoEncoder)
   1.248 +public:
   1.249 +  // Types of output blob format.
   1.250 +  enum BlobFormat {
   1.251 +    AVC_MP4, // MP4 file config descripter (defined in ISO/IEC 14496-15 5.2.4.1.1)
   1.252 +    AVC_NAL  // NAL (Network Abstract Layer) (defined in ITU-T H.264 7.4.1)
   1.253 +  };
   1.254 +
   1.255 +  /**
   1.256 +   * Configure video codec parameters and start media codec. It must be called
   1.257 +   * before calling Encode() and GetNextEncodedFrame().
   1.258 +   * aBlobFormat specifies output blob format provided by encoder. It can be
   1.259 +   * AVC_MP4 or AVC_NAL.
   1.260 +   */
   1.261 +  nsresult Configure(int aWidth, int aHeight, int aFrameRate,
   1.262 +                     BlobFormat aBlobFormat = BlobFormat::AVC_MP4);
   1.263 +
   1.264 +  /**
   1.265 +   * Encode a aWidth pixels wide and aHeight pixels tall video frame of
   1.266 +   * semi-planar YUV420 format stored in the buffer of aImage. aTimestamp gives
   1.267 +   * the frame timestamp/presentation time (in microseconds). To notify end of
   1.268 +   * stream, set aInputFlags to BUFFER_EOS.
   1.269 +   */
   1.270 +  nsresult Encode(const mozilla::layers::Image* aImage, int aWidth, int aHeight,
   1.271 +                  int64_t aTimestamp, int aInputFlags = 0);
   1.272 +
   1.273 +#if ANDROID_VERSION >= 18
   1.274 +  /** Set encoding bitrate (in kbps). */
   1.275 +  nsresult SetBitrate(int32_t aKbps);
   1.276 +#endif
   1.277 +
   1.278 +  /**
   1.279 +   * Get current AVC codec config blob. The output format depends on the
   1.280 +   * aBlobFormat argument given when Configure() was called.
   1.281 +   */
   1.282 +  nsresult GetCodecConfig(nsTArray<uint8_t>* aOutputBuf);
   1.283 +
   1.284 +protected:
   1.285 +  virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
   1.286 +                                       ABuffer* aData) MOZ_OVERRIDE;
   1.287 +
   1.288 +  // If configured to output MP4 format blob, AVC/H.264 encoder has to replace
   1.289 +  // NAL unit start code with the unit length as specified in
   1.290 +  // ISO/IEC 14496-15 5.2.3.
   1.291 +  virtual void AppendFrame(nsTArray<uint8_t>* aOutputBuf,
   1.292 +                           const uint8_t* aData, size_t aSize) MOZ_OVERRIDE;
   1.293 +
   1.294 +private:
   1.295 +  // Hide these. User should always use creator functions to get a media codec.
   1.296 +  OMXVideoEncoder() MOZ_DELETE;
   1.297 +  OMXVideoEncoder(const OMXVideoEncoder&) MOZ_DELETE;
   1.298 +  OMXVideoEncoder& operator=(const OMXVideoEncoder&) MOZ_DELETE;
   1.299 +
   1.300 +  /**
   1.301 +   * Create a video codec. It will be a AVC/H.264 encoder if aCodecType is
   1.302 +   * CODEC_AVC_ENC.
   1.303 +   */
   1.304 +  OMXVideoEncoder(CodecType aCodecType)
   1.305 +    : OMXCodecWrapper(aCodecType)
   1.306 +    , mWidth(0)
   1.307 +    , mHeight(0)
   1.308 +    , mBlobFormat(BlobFormat::AVC_MP4)
   1.309 +    , mHasConfigBlob(false)
   1.310 +  {}
   1.311 +
   1.312 +  // For creator function to access hidden constructor.
   1.313 +  friend class OMXCodecWrapper;
   1.314 +
   1.315 +  int mWidth;
   1.316 +  int mHeight;
   1.317 +  BlobFormat mBlobFormat;
   1.318 +  bool mHasConfigBlob;
   1.319 +};
   1.320 +
   1.321 +} // namespace android
   1.322 +#endif // OMXCodecWrapper_h_

mercurial