tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

OmxPromiseLayer.h (7516B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #if !defined(OmxPromiseLayer_h_)
      8 #  define OmxPromiseLayer_h_
      9 
     10 #  include "OMX_Core.h"
     11 #  include "OMX_Types.h"
     12 #  include "mozilla/MozPromise.h"
     13 #  include "mozilla/TaskQueue.h"
     14 
     15 namespace mozilla {
     16 
     17 namespace layers {
     18 class ImageContainer;
     19 }
     20 
     21 class MediaData;
     22 class MediaRawData;
     23 class OmxDataDecoder;
     24 class OmxPlatformLayer;
     25 class TrackInfo;
     26 
     27 /* This class acts as a middle layer between OmxDataDecoder and the underlying
     28 * OmxPlatformLayer.
     29 *
     30 * This class has two purposes:
     31 * 1. Using promise instead of OpenMax async callback function.
     32 *    For example, OmxCommandPromise is used for OpenMax IL SendCommand.
     33 * 2. Manage the buffer exchanged between client and component.
     34 *    Because omx buffer works crossing threads, so each omx buffer has its own
     35 *    promise, it is defined in BufferData.
     36 *
     37 * All of functions and members in this class should be run in the same
     38 * TaskQueue.
     39 */
     40 class OmxPromiseLayer {
     41 protected:
     42  virtual ~OmxPromiseLayer() = default;
     43 
     44 public:
     45  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OmxPromiseLayer)
     46 
     47  OmxPromiseLayer(TaskQueue* aTaskQueue, OmxDataDecoder* aDataDecoder,
     48                  layers::ImageContainer* aImageContainer);
     49 
     50  class BufferData;
     51 
     52  typedef nsTArray<RefPtr<BufferData>> BUFFERLIST;
     53 
     54  class OmxBufferFailureHolder {
     55   public:
     56    OmxBufferFailureHolder(OMX_ERRORTYPE aError, BufferData* aBuffer)
     57        : mError(aError), mBuffer(aBuffer) {}
     58 
     59    OMX_ERRORTYPE mError;
     60    BufferData* mBuffer;
     61  };
     62 
     63  typedef MozPromise<BufferData*, OmxBufferFailureHolder,
     64                     /* IsExclusive = */ false>
     65      OmxBufferPromise;
     66 
     67  class OmxCommandFailureHolder {
     68   public:
     69    OmxCommandFailureHolder(OMX_ERRORTYPE aErrorType,
     70                            OMX_COMMANDTYPE aCommandType)
     71        : mErrorType(aErrorType), mCommandType(aCommandType) {}
     72 
     73    OMX_ERRORTYPE mErrorType;
     74    OMX_COMMANDTYPE mCommandType;
     75  };
     76 
     77  typedef MozPromise<OMX_COMMANDTYPE, OmxCommandFailureHolder,
     78                     /* IsExclusive = */ true>
     79      OmxCommandPromise;
     80 
     81  typedef MozPromise<uint32_t, bool, /* IsExclusive = */ true>
     82      OmxPortConfigPromise;
     83 
     84  // TODO: maybe a generic promise is good enough for this case?
     85  RefPtr<OmxCommandPromise> Init(const TrackInfo* aInfo);
     86 
     87  OMX_ERRORTYPE Config();
     88 
     89  RefPtr<OmxBufferPromise> FillBuffer(BufferData* aData);
     90 
     91  RefPtr<OmxBufferPromise> EmptyBuffer(BufferData* aData);
     92 
     93  RefPtr<OmxCommandPromise> SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1,
     94                                        OMX_PTR aCmdData);
     95 
     96  nsresult AllocateOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBuffers);
     97 
     98  nsresult ReleaseOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBuffers);
     99 
    100  OMX_STATETYPE GetState();
    101 
    102  OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE aParamIndex,
    103                             OMX_PTR aComponentParameterStructure,
    104                             OMX_U32 aComponentParameterSize);
    105 
    106  OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE nIndex,
    107                             OMX_PTR aComponentParameterStructure,
    108                             OMX_U32 aComponentParameterSize);
    109 
    110  OMX_U32 InputPortIndex();
    111 
    112  OMX_U32 OutputPortIndex();
    113 
    114  nsresult Shutdown();
    115 
    116  // BufferData maintains the status of OMX buffer (OMX_BUFFERHEADERTYPE).
    117  // mStatus tracks the buffer owner.
    118  // And a promise because OMX buffer working among different threads.
    119  class BufferData {
    120   protected:
    121    virtual ~BufferData() = default;
    122 
    123   public:
    124    explicit BufferData(OMX_BUFFERHEADERTYPE* aBuffer)
    125        : mEos(false), mStatus(BufferStatus::FREE), mBuffer(aBuffer) {}
    126 
    127    typedef void* BufferID;
    128 
    129    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BufferData)
    130 
    131    // In most cases, the ID of this buffer is the pointer address of mBuffer.
    132    // However, on some platforms it may be another value.
    133    virtual BufferID ID() { return mBuffer; }
    134 
    135    // Return the platform dependent MediaData().
    136    // For example, it returns the MediaData with Gralloc texture.
    137    // If it returns nullptr, then caller uses the normal way to
    138    // create MediaData().
    139    virtual already_AddRefed<MediaData> GetPlatformMediaData() {
    140      return nullptr;
    141    }
    142 
    143    // The buffer could be used by several objects. And only one object owns the
    144    // buffer the same time.
    145    //   FREE:
    146    //     nobody uses it.
    147    //
    148    //   OMX_COMPONENT:
    149    //     buffer is used by OMX component (OmxPlatformLayer).
    150    //
    151    //   OMX_CLIENT:
    152    //     buffer is used by client which is wait for audio/video playing
    153    //     (OmxDataDecoder)
    154    //
    155    //   OMX_CLIENT_OUTPUT:
    156    //     used by client to output decoded data (for example, Gecko layer in
    157    //     this case)
    158    //
    159    // For output port buffer, the status transition is:
    160    // FREE -> OMX_COMPONENT -> OMX_CLIENT -> OMX_CLIENT_OUTPUT -> FREE
    161    //
    162    // For input port buffer, the status transition is:
    163    // FREE -> OMX_COMPONENT -> OMX_CLIENT -> FREE
    164    //
    165    enum BufferStatus {
    166      FREE,
    167      OMX_COMPONENT,
    168      OMX_CLIENT,
    169      OMX_CLIENT_OUTPUT,
    170      INVALID
    171    };
    172 
    173    bool mEos;
    174 
    175    // The raw keeps in OmxPromiseLayer after EmptyBuffer and then passing to
    176    // output decoded buffer in EmptyFillBufferDone. It is used to keep the
    177    // records of the original data from demuxer, like duration, stream
    178    // offset...etc.
    179    RefPtr<MediaRawData> mRawData;
    180 
    181    // Because OMX buffer works across threads, so it uses a promise
    182    // for each buffer when the buffer is used by Omx component.
    183    MozPromiseHolder<OmxBufferPromise> mPromise;
    184    BufferStatus mStatus;
    185    OMX_BUFFERHEADERTYPE* mBuffer;
    186  };
    187 
    188  void EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData::BufferID aID);
    189 
    190  void EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData* aData);
    191 
    192  already_AddRefed<BufferData> FindBufferById(OMX_DIRTYPE aType,
    193                                              BufferData::BufferID aId);
    194 
    195  already_AddRefed<BufferData> FindAndRemoveBufferHolder(
    196      OMX_DIRTYPE aType, BufferData::BufferID aId);
    197 
    198  // Return true if event is handled.
    199  bool Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2);
    200 
    201 protected:
    202  struct FlushCommand {
    203    OMX_DIRTYPE type;
    204    OMX_PTR cmd;
    205  };
    206 
    207  BUFFERLIST* GetBufferHolders(OMX_DIRTYPE aType);
    208 
    209  already_AddRefed<MediaRawData> FindAndRemoveRawData(OMX_TICKS aTimecode);
    210 
    211  RefPtr<TaskQueue> mTaskQueue;
    212 
    213  MozPromiseHolder<OmxCommandPromise> mCommandStatePromise;
    214 
    215  MozPromiseHolder<OmxCommandPromise> mPortDisablePromise;
    216 
    217  MozPromiseHolder<OmxCommandPromise> mPortEnablePromise;
    218 
    219  MozPromiseHolder<OmxCommandPromise> mFlushPromise;
    220 
    221  nsTArray<FlushCommand> mFlushCommands;
    222 
    223  UniquePtr<OmxPlatformLayer> mPlatformLayer;
    224 
    225 private:
    226  // Elements are added to holders when FillBuffer() or FillBuffer(). And
    227  // removing element when the promise is resolved. Buffers in these lists
    228  // should NOT be used by other component; for example, output it to audio
    229  // output. These lists should be empty when engine is about to shutdown.
    230  //
    231  // Note:
    232  //      There bufferlist should not be used by other class directly.
    233  BUFFERLIST mInbufferHolders;
    234 
    235  BUFFERLIST mOutbufferHolders;
    236 
    237  nsTArray<RefPtr<MediaRawData>> mRawDatas;
    238 };
    239 
    240 }  // namespace mozilla
    241 
    242 #endif /* OmxPromiseLayer_h_ */