1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include "MediaCodecDataDecoder.h"
6 
7 #include "AndroidBridge.h"
8 #include "AndroidSurfaceTexture.h"
9 #include "GeneratedJNINatives.h"
10 #include "GLImages.h"
11 
12 #include "MediaData.h"
13 #include "MediaInfo.h"
14 #include "VPXDecoder.h"
15 
16 #include "nsThreadUtils.h"
17 #include "nsPromiseFlatString.h"
18 #include "nsIGfxInfo.h"
19 
20 #include "prlog.h"
21 
22 #include <jni.h>
23 
24 #undef LOG
25 #define LOG(arg, ...) MOZ_LOG(sAndroidDecoderModuleLog, \
26     mozilla::LogLevel::Debug, ("MediaCodecDataDecoder(%p)::%s: " arg, \
27       this, __func__, ##__VA_ARGS__))
28 
29 using namespace mozilla;
30 using namespace mozilla::gl;
31 using namespace mozilla::java;
32 using namespace mozilla::java::sdk;
33 using media::TimeUnit;
34 
35 namespace mozilla {
36 
37 #define INVOKE_CALLBACK(Func, ...) \
38   if (mCallback) { \
39     mCallback->Func(__VA_ARGS__); \
40   } else { \
41     NS_WARNING("Callback not set"); \
42   }
43 
44 static MediaCodec::LocalRef
CreateDecoder(const nsACString & aMimeType)45 CreateDecoder(const nsACString& aMimeType)
46 {
47   MediaCodec::LocalRef codec;
48   NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(TranslateMimeType(aMimeType),
49                     &codec), nullptr);
50   return codec;
51 }
52 
53 class VideoDataDecoder : public MediaCodecDataDecoder
54 {
55 public:
VideoDataDecoder(const VideoInfo & aConfig,MediaFormat::Param aFormat,MediaDataDecoderCallback * aCallback,layers::ImageContainer * aImageContainer)56   VideoDataDecoder(const VideoInfo& aConfig,
57                    MediaFormat::Param aFormat,
58                    MediaDataDecoderCallback* aCallback,
59                    layers::ImageContainer* aImageContainer)
60     : MediaCodecDataDecoder(MediaData::Type::VIDEO_DATA, aConfig.mMimeType,
61                             aFormat, aCallback)
62     , mImageContainer(aImageContainer)
63     , mConfig(aConfig)
64   {
65 
66   }
67 
GetDescriptionName() const68   const char* GetDescriptionName() const override
69   {
70     return "Android MediaCodec video decoder";
71   }
72 
Init()73   RefPtr<InitPromise> Init() override
74   {
75     mSurfaceTexture = AndroidSurfaceTexture::Create();
76     if (!mSurfaceTexture) {
77       NS_WARNING("Failed to create SurfaceTexture for video decode\n");
78       return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
79     }
80 
81     if (NS_FAILED(InitDecoder(mSurfaceTexture->JavaSurface()))) {
82       return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
83     }
84 
85     return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
86   }
87 
Cleanup()88   void Cleanup() override
89   {
90   }
91 
PostOutput(BufferInfo::Param aInfo,MediaFormat::Param aFormat,const TimeUnit & aDuration)92   nsresult PostOutput(BufferInfo::Param aInfo, MediaFormat::Param aFormat,
93                       const TimeUnit& aDuration) override
94   {
95     RefPtr<layers::Image> img =
96       new SurfaceTextureImage(mSurfaceTexture.get(), mConfig.mDisplay,
97                               gl::OriginPos::BottomLeft);
98 
99     nsresult rv;
100     int32_t flags;
101     NS_ENSURE_SUCCESS(rv = aInfo->Flags(&flags), rv);
102 
103     bool isSync = !!(flags & MediaCodec::BUFFER_FLAG_SYNC_FRAME);
104 
105     int32_t offset;
106     NS_ENSURE_SUCCESS(rv = aInfo->Offset(&offset), rv);
107 
108     int64_t presentationTimeUs;
109     NS_ENSURE_SUCCESS(rv = aInfo->PresentationTimeUs(&presentationTimeUs), rv);
110 
111     RefPtr<VideoData> v =
112       VideoData::CreateFromImage(mConfig,
113                                  offset,
114                                  presentationTimeUs,
115                                  aDuration.ToMicroseconds(),
116                                  img,
117                                  isSync,
118                                  presentationTimeUs,
119                                  gfx::IntRect(0, 0,
120                                               mConfig.mDisplay.width,
121                                               mConfig.mDisplay.height));
122     INVOKE_CALLBACK(Output, v);
123     return NS_OK;
124   }
125 
126 protected:
127   layers::ImageContainer* mImageContainer;
128   const VideoInfo& mConfig;
129   RefPtr<AndroidSurfaceTexture> mSurfaceTexture;
130 };
131 
132 class AudioDataDecoder : public MediaCodecDataDecoder
133 {
134 public:
AudioDataDecoder(const AudioInfo & aConfig,MediaFormat::Param aFormat,MediaDataDecoderCallback * aCallback)135   AudioDataDecoder(const AudioInfo& aConfig, MediaFormat::Param aFormat,
136                    MediaDataDecoderCallback* aCallback)
137     : MediaCodecDataDecoder(MediaData::Type::AUDIO_DATA, aConfig.mMimeType,
138                             aFormat, aCallback)
139   {
140     JNIEnv* const env = jni::GetEnvForThread();
141 
142     jni::ByteBuffer::LocalRef buffer(env);
143     NS_ENSURE_SUCCESS_VOID(aFormat->GetByteBuffer(NS_LITERAL_STRING("csd-0"),
144                                                   &buffer));
145 
146     if (!buffer && aConfig.mCodecSpecificConfig->Length() >= 2) {
147       buffer = jni::ByteBuffer::New(
148           aConfig.mCodecSpecificConfig->Elements(),
149           aConfig.mCodecSpecificConfig->Length());
150       NS_ENSURE_SUCCESS_VOID(aFormat->SetByteBuffer(NS_LITERAL_STRING("csd-0"),
151                                                     buffer));
152     }
153   }
154 
GetDescriptionName() const155   const char* GetDescriptionName() const override
156   {
157     return "android audio decoder";
158   }
159 
Output(BufferInfo::Param aInfo,void * aBuffer,MediaFormat::Param aFormat,const TimeUnit & aDuration)160   nsresult Output(BufferInfo::Param aInfo, void* aBuffer,
161                   MediaFormat::Param aFormat, const TimeUnit& aDuration)
162   {
163     // The output on Android is always 16-bit signed
164     nsresult rv;
165     int32_t numChannels;
166     NS_ENSURE_SUCCESS(rv =
167         aFormat->GetInteger(NS_LITERAL_STRING("channel-count"), &numChannels), rv);
168     AudioConfig::ChannelLayout layout(numChannels);
169     if (!layout.IsValid()) {
170       return NS_ERROR_FAILURE;
171     }
172 
173     int32_t sampleRate;
174     NS_ENSURE_SUCCESS(rv =
175         aFormat->GetInteger(NS_LITERAL_STRING("sample-rate"), &sampleRate), rv);
176 
177     int32_t size;
178     NS_ENSURE_SUCCESS(rv = aInfo->Size(&size), rv);
179 
180     int32_t offset;
181     NS_ENSURE_SUCCESS(rv = aInfo->Offset(&offset), rv);
182 
183 #ifdef MOZ_SAMPLE_TYPE_S16
184     const int32_t numSamples = size / 2;
185 #else
186 #error We only support 16-bit integer PCM
187 #endif
188 
189     const int32_t numFrames = numSamples / numChannels;
190     AlignedAudioBuffer audio(numSamples);
191     if (!audio) {
192       return NS_ERROR_OUT_OF_MEMORY;
193     }
194 
195     const uint8_t* bufferStart = static_cast<uint8_t*>(aBuffer) + offset;
196     PodCopy(audio.get(), reinterpret_cast<const AudioDataValue*>(bufferStart),
197             numSamples);
198 
199     int64_t presentationTimeUs;
200     NS_ENSURE_SUCCESS(rv = aInfo->PresentationTimeUs(&presentationTimeUs), rv);
201 
202     RefPtr<AudioData> data = new AudioData(0, presentationTimeUs,
203                                            aDuration.ToMicroseconds(),
204                                            numFrames,
205                                            Move(audio),
206                                            numChannels,
207                                            sampleRate);
208     INVOKE_CALLBACK(Output, data);
209     return NS_OK;
210   }
211 };
212 
213 MediaDataDecoder*
CreateAudioDecoder(const AudioInfo & aConfig,MediaFormat::Param aFormat,MediaDataDecoderCallback * aCallback)214 MediaCodecDataDecoder::CreateAudioDecoder(const AudioInfo& aConfig,
215                                           MediaFormat::Param aFormat,
216                                           MediaDataDecoderCallback* aCallback)
217 {
218   return new AudioDataDecoder(aConfig, aFormat, aCallback);
219 }
220 
221 MediaDataDecoder*
CreateVideoDecoder(const VideoInfo & aConfig,MediaFormat::Param aFormat,MediaDataDecoderCallback * aCallback,layers::ImageContainer * aImageContainer)222 MediaCodecDataDecoder::CreateVideoDecoder(const VideoInfo& aConfig,
223                                           MediaFormat::Param aFormat,
224                                           MediaDataDecoderCallback* aCallback,
225                                           layers::ImageContainer* aImageContainer)
226 {
227   return new VideoDataDecoder(aConfig, aFormat, aCallback, aImageContainer);
228 }
229 
MediaCodecDataDecoder(MediaData::Type aType,const nsACString & aMimeType,MediaFormat::Param aFormat,MediaDataDecoderCallback * aCallback)230 MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
231                                              const nsACString& aMimeType,
232                                              MediaFormat::Param aFormat,
233                                              MediaDataDecoderCallback* aCallback)
234   : mType(aType)
235   , mMimeType(aMimeType)
236   , mFormat(aFormat)
237   , mCallback(aCallback)
238   , mInputBuffers(nullptr)
239   , mOutputBuffers(nullptr)
240   , mMonitor("MediaCodecDataDecoder::mMonitor")
241   , mState(ModuleState::kDecoding)
242 {
243 
244 }
245 
~MediaCodecDataDecoder()246 MediaCodecDataDecoder::~MediaCodecDataDecoder()
247 {
248   Shutdown();
249 }
250 
251 RefPtr<MediaDataDecoder::InitPromise>
Init()252 MediaCodecDataDecoder::Init()
253 {
254   nsresult rv = InitDecoder(nullptr);
255 
256   TrackInfo::TrackType type =
257     (mType == MediaData::AUDIO_DATA ? TrackInfo::TrackType::kAudioTrack
258                                     : TrackInfo::TrackType::kVideoTrack);
259 
260   return NS_SUCCEEDED(rv) ?
261            InitPromise::CreateAndResolve(type, __func__) :
262            InitPromise::CreateAndReject(
263                NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
264 }
265 
266 nsresult
InitDecoder(Surface::Param aSurface)267 MediaCodecDataDecoder::InitDecoder(Surface::Param aSurface)
268 {
269   mDecoder = CreateDecoder(mMimeType);
270   if (!mDecoder) {
271     INVOKE_CALLBACK(Error,
272                     MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__));
273     return NS_ERROR_FAILURE;
274   }
275 
276   nsresult rv;
277   NS_ENSURE_SUCCESS(rv = mDecoder->Configure(mFormat, aSurface, nullptr, 0), rv);
278   NS_ENSURE_SUCCESS(rv = mDecoder->Start(), rv);
279 
280   NS_ENSURE_SUCCESS(rv = ResetInputBuffers(), rv);
281   NS_ENSURE_SUCCESS(rv = ResetOutputBuffers(), rv);
282 
283   nsCOMPtr<nsIRunnable> r = NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop);
284   rv = NS_NewNamedThread("MC Decoder", getter_AddRefs(mThread), r);
285 
286   return rv;
287 }
288 
289 // This is in usec, so that's 10ms.
290 static const int64_t kDecoderTimeout = 10000;
291 
292 #define BREAK_ON_DECODER_ERROR() \
293   if (NS_FAILED(res)) { \
294     NS_WARNING("Exiting decoder loop due to exception"); \
295     if (mState == ModuleState::kDrainDecoder) { \
296       INVOKE_CALLBACK(DrainComplete); \
297       SetState(ModuleState::kDecoding); \
298     } \
299     INVOKE_CALLBACK(Error, MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__)); \
300     break; \
301   }
302 
303 nsresult
GetInputBuffer(JNIEnv * aEnv,int aIndex,jni::Object::LocalRef * aBuffer)304 MediaCodecDataDecoder::GetInputBuffer(
305     JNIEnv* aEnv, int aIndex, jni::Object::LocalRef* aBuffer)
306 {
307   MOZ_ASSERT(aEnv);
308   MOZ_ASSERT(!*aBuffer);
309 
310   int numTries = 2;
311 
312   while (numTries--) {
313     *aBuffer = jni::Object::LocalRef::Adopt(
314         aEnv->GetObjectArrayElement(mInputBuffers.Get(), aIndex));
315     if (*aBuffer) {
316       return NS_OK;
317     }
318     nsresult res = ResetInputBuffers();
319     if (NS_FAILED(res)) {
320       return res;
321     }
322   }
323   return NS_ERROR_FAILURE;
324 }
325 
326 bool
WaitForInput()327 MediaCodecDataDecoder::WaitForInput()
328 {
329   MonitorAutoLock lock(mMonitor);
330 
331   while (mState ==  ModuleState::kDecoding && mQueue.empty()) {
332     // Signal that we require more input.
333     INVOKE_CALLBACK(InputExhausted);
334     lock.Wait();
335   }
336 
337   return mState != ModuleState::kStopping;
338 }
339 
340 
341 already_AddRefed<MediaRawData>
PeekNextSample()342 MediaCodecDataDecoder::PeekNextSample()
343 {
344   MonitorAutoLock lock(mMonitor);
345 
346   if (mState == ModuleState::kFlushing) {
347     mDecoder->Flush();
348     ClearQueue();
349     SetState(ModuleState::kDecoding);
350     lock.Notify();
351     return nullptr;
352   }
353 
354   if (mQueue.empty()) {
355     if (mState == ModuleState::kDrainQueue) {
356       SetState(ModuleState::kDrainDecoder);
357     }
358     return nullptr;
359   }
360 
361   // We're not stopping or flushing, so try to get a sample.
362   return RefPtr<MediaRawData>(mQueue.front()).forget();
363 }
364 
365 nsresult
QueueSample(const MediaRawData * aSample)366 MediaCodecDataDecoder::QueueSample(const MediaRawData* aSample)
367 {
368   MOZ_ASSERT(aSample);
369   AutoLocalJNIFrame frame(jni::GetEnvForThread(), 1);
370 
371   // We have a sample, try to feed it to the decoder.
372   int32_t inputIndex = -1;
373   nsresult res = mDecoder->DequeueInputBuffer(kDecoderTimeout, &inputIndex);
374   if (NS_FAILED(res)) {
375     return res;
376   }
377 
378   if (inputIndex < 0) {
379     // There is no valid input buffer available.
380     return NS_ERROR_FAILURE;
381   }
382 
383   jni::Object::LocalRef buffer(frame.GetEnv());
384   res = GetInputBuffer(frame.GetEnv(), inputIndex, &buffer);
385   if (NS_FAILED(res)) {
386     return res;
387   }
388 
389   void* directBuffer = frame.GetEnv()->GetDirectBufferAddress(buffer.Get());
390 
391   MOZ_ASSERT(frame.GetEnv()->GetDirectBufferCapacity(buffer.Get()) >=
392              aSample->Size(),
393              "Decoder buffer is not large enough for sample");
394 
395   PodCopy(static_cast<uint8_t*>(directBuffer), aSample->Data(), aSample->Size());
396 
397   CryptoInfo::LocalRef cryptoInfo = GetCryptoInfoFromSample(aSample);
398   if (cryptoInfo) {
399     res = mDecoder->QueueSecureInputBuffer(inputIndex, 0, cryptoInfo,
400                                            aSample->mTime, 0);
401   } else {
402     res = mDecoder->QueueInputBuffer(inputIndex, 0, aSample->Size(),
403                                      aSample->mTime, 0);
404   }
405 
406   if (NS_FAILED(res)) {
407     return res;
408   }
409 
410   mDurations.push_back(TimeUnit::FromMicroseconds(aSample->mDuration));
411   return NS_OK;
412 }
413 
414 nsresult
QueueEOS()415 MediaCodecDataDecoder::QueueEOS()
416 {
417   mMonitor.AssertCurrentThreadOwns();
418 
419   nsresult res = NS_OK;
420   int32_t inputIndex = -1;
421   res = mDecoder->DequeueInputBuffer(kDecoderTimeout, &inputIndex);
422   if (NS_FAILED(res) || inputIndex < 0) {
423     return res;
424   }
425 
426   res = mDecoder->QueueInputBuffer(inputIndex, 0, 0, 0,
427                                    MediaCodec::BUFFER_FLAG_END_OF_STREAM);
428   if (NS_SUCCEEDED(res)) {
429     SetState(ModuleState::kDrainWaitEOS);
430     mMonitor.Notify();
431   }
432   return res;
433 }
434 
435 void
HandleEOS(int32_t aOutputStatus)436 MediaCodecDataDecoder::HandleEOS(int32_t aOutputStatus)
437 {
438   MonitorAutoLock lock(mMonitor);
439 
440   if (mState ==  ModuleState::kDrainWaitEOS) {
441     SetState(ModuleState::kDecoding);
442     mMonitor.Notify();
443 
444     INVOKE_CALLBACK(DrainComplete);
445   }
446 
447   mDecoder->ReleaseOutputBuffer(aOutputStatus, false);
448 }
449 
450 Maybe<TimeUnit>
GetOutputDuration()451 MediaCodecDataDecoder::GetOutputDuration()
452 {
453   if (mDurations.empty()) {
454     return Nothing();
455   }
456   const Maybe<TimeUnit> duration = Some(mDurations.front());
457   mDurations.pop_front();
458   return duration;
459 }
460 
461 nsresult
ProcessOutput(BufferInfo::Param aInfo,MediaFormat::Param aFormat,int32_t aStatus)462 MediaCodecDataDecoder::ProcessOutput(
463     BufferInfo::Param aInfo, MediaFormat::Param aFormat, int32_t aStatus)
464 {
465   AutoLocalJNIFrame frame(jni::GetEnvForThread(), 1);
466 
467   const Maybe<TimeUnit> duration = GetOutputDuration();
468   if (!duration) {
469     // Some devices report failure in QueueSample while actually succeeding at
470     // it, in which case we get an output buffer without having a cached duration
471     // (bug 1273523).
472     return NS_OK;
473   }
474 
475   const auto buffer = jni::Object::LocalRef::Adopt(
476       frame.GetEnv()->GetObjectArrayElement(mOutputBuffers.Get(), aStatus));
477 
478   if (buffer) {
479     // The buffer will be null on Android L if we are decoding to a Surface.
480     void* directBuffer = frame.GetEnv()->GetDirectBufferAddress(buffer.Get());
481     Output(aInfo, directBuffer, aFormat, duration.value());
482   }
483 
484   // The Surface will be updated at this point (for video).
485   mDecoder->ReleaseOutputBuffer(aStatus, true);
486   PostOutput(aInfo, aFormat, duration.value());
487 
488   return NS_OK;
489 }
490 
491 void
DecoderLoop()492 MediaCodecDataDecoder::DecoderLoop()
493 {
494   bool isOutputDone = false;
495   AutoLocalJNIFrame frame(jni::GetEnvForThread(), 1);
496   MediaFormat::LocalRef outputFormat(frame.GetEnv());
497   nsresult res = NS_OK;
498 
499   while (WaitForInput()) {
500     RefPtr<MediaRawData> sample = PeekNextSample();
501 
502     {
503       MonitorAutoLock lock(mMonitor);
504       if (mState == ModuleState::kDrainDecoder) {
505         MOZ_ASSERT(!sample, "Shouldn't have a sample when pushing EOF frame");
506         res = QueueEOS();
507         BREAK_ON_DECODER_ERROR();
508       }
509     }
510 
511     if (sample) {
512       res = QueueSample(sample);
513       if (NS_SUCCEEDED(res)) {
514         // We've fed this into the decoder, so remove it from the queue.
515         MonitorAutoLock lock(mMonitor);
516         MOZ_RELEASE_ASSERT(mQueue.size(), "Queue may not be empty");
517         mQueue.pop_front();
518         isOutputDone = false;
519       }
520     }
521 
522     if (isOutputDone) {
523       continue;
524     }
525 
526     BufferInfo::LocalRef bufferInfo;
527     nsresult res = BufferInfo::New(&bufferInfo);
528     BREAK_ON_DECODER_ERROR();
529 
530     int32_t outputStatus = -1;
531     res = mDecoder->DequeueOutputBuffer(bufferInfo, kDecoderTimeout,
532                                         &outputStatus);
533     BREAK_ON_DECODER_ERROR();
534 
535     if (outputStatus == MediaCodec::INFO_TRY_AGAIN_LATER) {
536       // We might want to call mCallback->InputExhausted() here, but there seems
537       // to be some possible bad interactions here with the threading.
538     } else if (outputStatus == MediaCodec::INFO_OUTPUT_BUFFERS_CHANGED) {
539       res = ResetOutputBuffers();
540       BREAK_ON_DECODER_ERROR();
541     } else if (outputStatus == MediaCodec::INFO_OUTPUT_FORMAT_CHANGED) {
542       res = mDecoder->GetOutputFormat(ReturnTo(&outputFormat));
543       BREAK_ON_DECODER_ERROR();
544     } else if (outputStatus < 0) {
545       NS_WARNING("Unknown error from decoder!");
546       INVOKE_CALLBACK(Error,
547                       MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
548                                        __func__));
549       // Don't break here just in case it's recoverable. If it's not, other
550       // stuff will fail later and we'll bail out.
551     } else {
552       // We have a valid buffer index >= 0 here.
553       int32_t flags;
554       nsresult res = bufferInfo->Flags(&flags);
555       BREAK_ON_DECODER_ERROR();
556 
557       if (flags & MediaCodec::BUFFER_FLAG_END_OF_STREAM) {
558         HandleEOS(outputStatus);
559         isOutputDone = true;
560         // We only queue empty EOF frames, so we're done for now.
561         continue;
562       }
563 
564       res = ProcessOutput(bufferInfo, outputFormat, outputStatus);
565       BREAK_ON_DECODER_ERROR();
566     }
567   }
568 
569   Cleanup();
570 
571   // We're done.
572   MonitorAutoLock lock(mMonitor);
573   SetState(ModuleState::kShutdown);
574   mMonitor.Notify();
575 }
576 
577 const char*
ModuleStateStr(ModuleState aState)578 MediaCodecDataDecoder::ModuleStateStr(ModuleState aState) {
579     switch (aState) {
580       case ModuleState::kDecoding:     return "Decoding";
581       case ModuleState::kFlushing:     return "Flushing";
582       case ModuleState::kDrainQueue:   return "DrainQueue";
583       case ModuleState::kDrainDecoder: return "DrainDecoder";
584       case ModuleState::kDrainWaitEOS: return "DrainWaitEOS";
585       case ModuleState::kStopping:     return "Stopping";
586       case ModuleState::kShutdown:     return "Shutdown";
587       default: MOZ_ASSERT_UNREACHABLE("Invalid state.");
588     }
589     return "Unknown";
590 }
591 
592 bool
SetState(ModuleState aState)593 MediaCodecDataDecoder::SetState(ModuleState aState)
594 {
595   bool ok = true;
596 
597   if (mState == ModuleState::kShutdown) {
598     ok = false;
599   } else if (mState == ModuleState::kStopping) {
600     ok = aState == ModuleState::kShutdown;
601   } else if (aState == ModuleState::kDrainDecoder) {
602     ok = mState == ModuleState::kDrainQueue;
603   } else if (aState == ModuleState::kDrainWaitEOS) {
604     ok = mState == ModuleState::kDrainDecoder;
605   }
606 
607   if (ok) {
608     LOG("%s -> %s", ModuleStateStr(mState), ModuleStateStr(aState));
609     mState = aState;
610   } else {
611     LOG("Fail to transit from %s to %s state", ModuleStateStr(mState), ModuleStateStr(aState));
612   }
613 
614   return ok;
615 }
616 
617 void
ClearQueue()618 MediaCodecDataDecoder::ClearQueue()
619 {
620   mMonitor.AssertCurrentThreadOwns();
621 
622   mQueue.clear();
623   mDurations.clear();
624 }
625 
626 void
Input(MediaRawData * aSample)627 MediaCodecDataDecoder::Input(MediaRawData* aSample)
628 {
629   MonitorAutoLock lock(mMonitor);
630   mQueue.push_back(aSample);
631   lock.NotifyAll();
632 }
633 
634 nsresult
ResetInputBuffers()635 MediaCodecDataDecoder::ResetInputBuffers()
636 {
637   return mDecoder->GetInputBuffers(ReturnTo(&mInputBuffers));
638 }
639 
640 nsresult
ResetOutputBuffers()641 MediaCodecDataDecoder::ResetOutputBuffers()
642 {
643   return mDecoder->GetOutputBuffers(ReturnTo(&mOutputBuffers));
644 }
645 
646 void
Flush()647 MediaCodecDataDecoder::Flush()
648 {
649   MonitorAutoLock lock(mMonitor);
650   if (!SetState(ModuleState::kFlushing)) {
651     return;
652   }
653   lock.Notify();
654 
655   while (mState == ModuleState::kFlushing) {
656     lock.Wait();
657   }
658 }
659 
660 void
Drain()661 MediaCodecDataDecoder::Drain()
662 {
663   MonitorAutoLock lock(mMonitor);
664   if (mState == ModuleState::kDrainDecoder ||
665       mState == ModuleState::kDrainQueue) {
666     return;
667   }
668 
669   SetState(ModuleState::kDrainQueue);
670   lock.Notify();
671 }
672 
673 
674 void
Shutdown()675 MediaCodecDataDecoder::Shutdown()
676 {
677   MonitorAutoLock lock(mMonitor);
678 
679   SetState(ModuleState::kStopping);
680   lock.Notify();
681 
682   while (mThread && mState != ModuleState::kShutdown) {
683     lock.Wait();
684   }
685 
686   if (mThread) {
687     mThread->Shutdown();
688     mThread = nullptr;
689   }
690 
691   if (mDecoder) {
692     mDecoder->Stop();
693     mDecoder->Release();
694     mDecoder = nullptr;
695   }
696 }
697 
698 } // mozilla
699