Coverage Report

Created: 2018-09-25 14:53

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