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(GonkMediaDataDecoder_h_) 8 #define GonkMediaDataDecoder_h_ 9 #include "PlatformDecoderModule.h" 10 #include <stagefright/foundation/AHandler.h> 11 12 namespace android { 13 struct ALooper; 14 class MediaBuffer; 15 class MediaCodecProxy; 16 } // namespace android 17 18 namespace mozilla { 19 class MediaRawData; 20 21 // Manage the data flow from inputting encoded data and outputting decode data. 22 class GonkDecoderManager : public android::AHandler { 23 public: 24 typedef TrackInfo::TrackType TrackType; 25 typedef MediaDataDecoder::InitPromise InitPromise; 26 ~GonkDecoderManager()27 virtual ~GonkDecoderManager() {} 28 29 virtual RefPtr<InitPromise> Init() = 0; 30 virtual const char* GetDescriptionName() const = 0; 31 32 // Asynchronously send sample into mDecoder. If out of input buffer, aSample 33 // will be queued for later re-send. 34 nsresult Input(MediaRawData* aSample); 35 36 // Flush the queued samples and signal decoder to throw all pending input/output away. 37 nsresult Flush(); 38 39 // Shutdown decoder and rejects the init promise. 40 virtual nsresult Shutdown(); 41 42 // How many samples are waiting for processing. 43 size_t NumQueuedSamples(); 44 45 // Set callback for decoder events, such as requesting more input, 46 // returning output, or reporting error. SetDecodeCallback(MediaDataDecoderCallback * aCallback)47 void SetDecodeCallback(MediaDataDecoderCallback* aCallback) 48 { 49 mDecodeCallback = aCallback; 50 } 51 52 protected: GonkDecoderManager()53 GonkDecoderManager() 54 : mMutex("GonkDecoderManager") 55 , mLastTime(INT64_MIN) 56 , mFlushMonitor("GonkDecoderManager::Flush") 57 , mIsFlushing(false) 58 , mDecodeCallback(nullptr) 59 {} 60 61 bool InitLoopers(MediaData::Type aType); 62 63 void onMessageReceived(const android::sp<android::AMessage> &aMessage) override; 64 65 // Produces decoded output. It returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE 66 // when output is not produced yet. 67 // If this returns a failure code other than NS_ERROR_NOT_AVAILABLE, an error 68 // will be reported through mDecodeCallback. 69 virtual nsresult Output(int64_t aStreamOffset, 70 RefPtr<MediaData>& aOutput) = 0; 71 72 // Send queued samples to OMX. It returns how many samples are still in 73 // queue after processing, or negative error code if failed. 74 int32_t ProcessQueuedSamples(); 75 76 void ProcessInput(bool aEndOfStream); 77 virtual void ProcessFlush(); 78 void ProcessToDo(bool aEndOfStream); 79 virtual void ResetEOS(); 80 81 RefPtr<MediaByteBuffer> mCodecSpecificData; 82 83 nsAutoCString mMimeType; 84 85 // MediaCodedc's wrapper that performs the decoding. 86 android::sp<android::MediaCodecProxy> mDecoder; 87 // Looper for mDecoder to run on. 88 android::sp<android::ALooper> mDecodeLooper; 89 // Looper to run decode tasks such as processing input, output, flush, and 90 // recycling output buffers. 91 android::sp<android::ALooper> mTaskLooper; 92 // Message codes for tasks running on mTaskLooper. 93 enum { 94 // Decoder will send this to indicate internal state change such as input or 95 // output buffers availability. Used to run pending input & output tasks. 96 kNotifyDecoderActivity = 'nda ', 97 // Signal the decoder to flush. 98 kNotifyProcessFlush = 'npf ', 99 // Used to process queued samples when there is new input. 100 kNotifyProcessInput = 'npi ', 101 #ifdef DEBUG 102 kNotifyFindLooperId = 'nfli', 103 #endif 104 }; 105 106 MozPromiseHolder<InitPromise> mInitPromise; 107 108 Mutex mMutex; // Protects mQueuedSamples. 109 // A queue that stores the samples waiting to be sent to mDecoder. 110 // Empty element means EOS and there shouldn't be any sample be queued after it. 111 // Samples are queued in caller's thread and dequeued in mTaskLooper. 112 nsTArray<RefPtr<MediaRawData>> mQueuedSamples; 113 114 // The last decoded frame presentation time. Only accessed on mTaskLooper. 115 int64_t mLastTime; 116 117 Monitor mFlushMonitor; // Waits for flushing to complete. 118 bool mIsFlushing; // Protected by mFlushMonitor. 119 120 // Remembers the notification that is currently waiting for the decoder event 121 // to avoid requesting more than one notification at the time, which is 122 // forbidden by mDecoder. 123 android::sp<android::AMessage> mToDo; 124 125 // Stores sample info for output buffer processing later. 126 struct WaitOutputInfo { WaitOutputInfoWaitOutputInfo127 WaitOutputInfo(int64_t aOffset, int64_t aTimestamp, bool aEOS) 128 : mOffset(aOffset) 129 , mTimestamp(aTimestamp) 130 , mEOS(aEOS) 131 {} 132 const int64_t mOffset; 133 const int64_t mTimestamp; 134 const bool mEOS; 135 }; 136 137 nsTArray<WaitOutputInfo> mWaitOutput; 138 139 MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error. 140 141 private: 142 void UpdateWaitingList(int64_t aForgetUpTo); 143 144 #ifdef DEBUG 145 typedef void* LooperId; 146 147 bool OnTaskLooper(); 148 LooperId mTaskLooperId; 149 #endif 150 }; 151 152 class AutoReleaseMediaBuffer 153 { 154 public: AutoReleaseMediaBuffer(android::MediaBuffer * aBuffer,android::MediaCodecProxy * aCodec)155 AutoReleaseMediaBuffer(android::MediaBuffer* aBuffer, android::MediaCodecProxy* aCodec) 156 : mBuffer(aBuffer) 157 , mCodec(aCodec) 158 {} 159 ~AutoReleaseMediaBuffer()160 ~AutoReleaseMediaBuffer() 161 { 162 MOZ_ASSERT(mCodec.get()); 163 if (mBuffer) { 164 mCodec->ReleaseMediaBuffer(mBuffer); 165 } 166 } 167 forget()168 android::MediaBuffer* forget() 169 { 170 android::MediaBuffer* tmp = mBuffer; 171 mBuffer = nullptr; 172 return tmp; 173 } 174 175 private: 176 android::MediaBuffer* mBuffer; 177 android::sp<android::MediaCodecProxy> mCodec; 178 }; 179 180 // Samples are decoded using the GonkDecoder (MediaCodec) 181 // created by the GonkDecoderManager. This class implements 182 // the higher-level logic that drives mapping the Gonk to the async 183 // MediaDataDecoder interface. The specifics of decoding the exact stream 184 // type are handled by GonkDecoderManager and the GonkDecoder it creates. 185 class GonkMediaDataDecoder : public MediaDataDecoder { 186 public: 187 GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager, 188 MediaDataDecoderCallback* aCallback); 189 190 ~GonkMediaDataDecoder(); 191 192 RefPtr<InitPromise> Init() override; 193 194 void Input(MediaRawData* aSample) override; 195 196 void Flush() override; 197 198 void Drain() override; 199 200 void Shutdown() override; 201 GetDescriptionName()202 const char* GetDescriptionName() const override 203 { 204 return "gonk decoder"; 205 } 206 207 private: 208 209 android::sp<GonkDecoderManager> mManager; 210 }; 211 212 } // namespace mozilla 213 214 #endif // GonkMediaDataDecoder_h_ 215