summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/omx/OmxDataDecoder.h
blob: 69c388ecee4bf010c3cbce0cad745df19119f689 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#if !defined(OmxDataDecoder_h_)
#  define OmxDataDecoder_h_

#  include "AudioCompactor.h"
#  include "ImageContainer.h"
#  include "MediaInfo.h"
#  include "OMX_Component.h"
#  include "OmxPromiseLayer.h"
#  include "PerformanceRecorder.h"
#  include "PlatformDecoderModule.h"
#  include "mozilla/Monitor.h"
#  include "mozilla/StateWatching.h"

namespace mozilla {

class MediaDataHelper;

typedef OmxPromiseLayer::OmxCommandPromise OmxCommandPromise;
typedef OmxPromiseLayer::OmxBufferPromise OmxBufferPromise;
typedef OmxPromiseLayer::OmxBufferFailureHolder OmxBufferFailureHolder;
typedef OmxPromiseLayer::OmxCommandFailureHolder OmxCommandFailureHolder;
typedef OmxPromiseLayer::BufferData BufferData;
typedef OmxPromiseLayer::BUFFERLIST BUFFERLIST;

DDLoggedTypeDeclNameAndBase(OmxDataDecoder, MediaDataDecoder);

/* OmxDataDecoder is the major class which performs followings:
 *   1. Translate PDM function into OMX commands.
 *   2. Keeping the buffers between client and component.
 *   3. Manage the OMX state.
 *
 * From the definition in OpenMax spec. "2.2.1", there are 3 major roles in
 * OpenMax IL.
 *
 * IL client:
 *   "The IL client may be a layer below the GUI application, such as GStreamer,
 *   or may be several layers below the GUI layer."
 *
 *   OmxDataDecoder acts as the IL client.
 *
 * OpenMAX IL component:
 *   "A component that is intended to wrap functionality that is required in the
 *   target system."
 *
 *   OmxPromiseLayer acts as the OpenMAX IL component.
 *
 * OpenMAX IL core:
 *   "Platform-specific code that has the functionality necessary to locate and
 *   then load an OpenMAX IL component into main memory."
 *
 *   OmxPlatformLayer acts as the OpenMAX IL core.
 */
class OmxDataDecoder final : public MediaDataDecoder,
                             public DecoderDoctorLifeLogger<OmxDataDecoder> {
 protected:
  virtual ~OmxDataDecoder();

 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OmxDataDecoder, final);

  OmxDataDecoder(const TrackInfo& aTrackInfo,
                 layers::ImageContainer* aImageContainer,
                 Maybe<TrackingId> aTrackingId);

  RefPtr<InitPromise> Init() override;
  RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
  RefPtr<DecodePromise> Drain() override;
  RefPtr<FlushPromise> Flush() override;
  RefPtr<ShutdownPromise> Shutdown() override;

  nsCString GetDescriptionName() const override { return "omx decoder"_ns; }

  nsCString GetCodecName() const override { return "unknown"_ns; }

  ConversionRequired NeedsConversion() const override {
    return ConversionRequired::kNeedAnnexB;
  }

  // Return true if event is handled.
  bool Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2);

 protected:
  void InitializationTask();

  void ResolveInitPromise(const char* aMethodName);

  void RejectInitPromise(MediaResult aError, const char* aMethodName);

  void OmxStateRunner();

  void FillAndEmptyBuffers();

  void FillBufferDone(BufferData* aData);

  void FillBufferFailure(OmxBufferFailureHolder aFailureHolder);

  void EmptyBufferDone(BufferData* aData);

  void EmptyBufferFailure(OmxBufferFailureHolder aFailureHolder);

  void NotifyError(
      OMX_ERRORTYPE aOmxError, const char* aLine,
      const MediaResult& aError = MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR));

  // Configure audio/video codec.
  // Some codec may just ignore this and rely on codec specific data in
  // FillCodecConfigDataToOmx().
  void ConfigCodec();

  // Sending codec specific data to OMX component. OMX component could send a
  // OMX_EventPortSettingsChanged back to client. And then client needs to
  // disable port and reallocate buffer.
  void FillCodecConfigDataToOmx();

  void SendEosBuffer();

  void EndOfStream();

  // It could be called after codec specific data is sent and component found
  // the port format is changed due to different codec specific.
  void PortSettingsChanged();

  void Output(BufferData* aData);

  // Buffer can be released if its status is not OMX_COMPONENT or
  // OMX_CLIENT_OUTPUT.
  bool BuffersCanBeReleased(OMX_DIRTYPE aType);

  OMX_DIRTYPE GetPortDirection(uint32_t aPortIndex);

  RefPtr<ShutdownPromise> DoAsyncShutdown();

  RefPtr<FlushPromise> DoFlush();

  void FlushComplete(OMX_COMMANDTYPE aCommandType);

  void FlushFailure(OmxCommandFailureHolder aFailureHolder);

  BUFFERLIST* GetBuffers(OMX_DIRTYPE aType);

  nsresult AllocateBuffers(OMX_DIRTYPE aType);

  nsresult ReleaseBuffers(OMX_DIRTYPE aType);

  BufferData* FindAvailableBuffer(OMX_DIRTYPE aType);

  // aType could be OMX_DirMax for all types.
  RefPtr<OmxPromiseLayer::OmxBufferPromise::AllPromiseType>
  CollectBufferPromises(OMX_DIRTYPE aType);

  // The Omx TaskQueue.
  RefPtr<TaskQueue> mOmxTaskQueue;

  nsCOMPtr<nsISerialEventTarget> mThread;
  RefPtr<layers::ImageContainer> mImageContainer;

  WatchManager<OmxDataDecoder> mWatchManager;

  // It is accessed in omx TaskQueue.
  Watchable<OMX_STATETYPE> mOmxState;

  RefPtr<OmxPromiseLayer> mOmxLayer;

  UniquePtr<TrackInfo> mTrackInfo;

  // It is accessed in both omx and reader TaskQueue.
  Atomic<bool> mFlushing;

  // It is accessed in Omx/reader TaskQueue.
  Atomic<bool> mShuttingDown;

  // It is accessed in Omx TaskQeueu.
  bool mCheckingInputExhausted;

  // It is accessed in OMX TaskQueue.
  MozPromiseHolder<InitPromise> mInitPromise;
  MozPromiseHolder<DecodePromise> mDecodePromise;
  MozPromiseHolder<DecodePromise> mDrainPromise;
  MozPromiseHolder<FlushPromise> mFlushPromise;
  MozPromiseHolder<ShutdownPromise> mShutdownPromise;
  // Where decoded samples will be stored until the decode promise is resolved.
  DecodedData mDecodedData;

  void CompleteDrain();

  // It is written in Omx TaskQueue. Read in Omx TaskQueue.
  // It value means the port index which port settings is changed.
  // -1 means no port setting changed.
  //
  // Note: when port setting changed, there should be no buffer operations
  //       via EmptyBuffer or FillBuffer.
  Watchable<int32_t> mPortSettingsChanged;

  // It is access in Omx TaskQueue.
  nsTArray<RefPtr<MediaRawData>> mMediaRawDatas;

  BUFFERLIST mInPortBuffers;

  BUFFERLIST mOutPortBuffers;

  RefPtr<MediaDataHelper> mMediaDataHelper;

  const Maybe<TrackingId> mTrackingId;

  // Accessed on Omx TaskQueue
  PerformanceRecorderMulti<DecodeStage> mPerformanceRecorder;
};

template <class T>
void InitOmxParameter(T* aParam) {
  PodZero(aParam);
  aParam->nSize = sizeof(T);
  aParam->nVersion.s.nVersionMajor = 1;
}

}  // namespace mozilla

#endif /* OmxDataDecoder_h_ */