Bug 1296198 - Somewhat of improvement on MediaCodecDataDecoder on Fennec. r?jwwang draft
authorJames Cheng <jacheng@mozilla.com>
Thu, 18 Aug 2016 14:21:55 +0800
changeset 402435 0a1f9269fd1d7fa5c85842a5964533a3ab1efa70
parent 402150 97a52326b06a07930216ebefa5af333271578904
child 528666 e07e3124cddc16d5ca2c588989cb578be120c763
push id26652
push userbmo:jacheng@mozilla.com
push dateThu, 18 Aug 2016 06:44:02 +0000
reviewersjwwang
bugs1296198
milestone51.0a1
Bug 1296198 - Somewhat of improvement on MediaCodecDataDecoder on Fennec. r?jwwang MozReview-Commit-ID: 12z9ySoa0xv
dom/media/platforms/android/MediaCodecDataDecoder.cpp
dom/media/platforms/android/MediaCodecDataDecoder.h
--- a/dom/media/platforms/android/MediaCodecDataDecoder.cpp
+++ b/dom/media/platforms/android/MediaCodecDataDecoder.cpp
@@ -238,17 +238,17 @@ MediaCodecDataDecoder::MediaCodecDataDec
                                              MediaDataDecoderCallback* aCallback)
   : mType(aType)
   , mMimeType(aMimeType)
   , mFormat(aFormat)
   , mCallback(aCallback)
   , mInputBuffers(nullptr)
   , mOutputBuffers(nullptr)
   , mMonitor("MediaCodecDataDecoder::mMonitor")
-  , mState(kDecoding)
+  , mState(ModuleState::kDecoding)
 {
 
 }
 
 MediaCodecDataDecoder::~MediaCodecDataDecoder()
 {
   Shutdown();
 }
@@ -291,19 +291,19 @@ MediaCodecDataDecoder::InitDecoder(Surfa
 }
 
 // This is in usec, so that's 10ms.
 static const int64_t kDecoderTimeout = 10000;
 
 #define BREAK_ON_DECODER_ERROR() \
   if (NS_FAILED(res)) { \
     NS_WARNING("Exiting decoder loop due to exception"); \
-    if (State() == kDrainDecoder) { \
+    if (mState == ModuleState::kDrainDecoder) { \
       INVOKE_CALLBACK(DrainComplete); \
-      State(kDecoding); \
+      SetState(ModuleState::kDecoding); \
     } \
     INVOKE_CALLBACK(Error, MediaDataDecoderError::FATAL_ERROR); \
     break; \
   }
 
 nsresult
 MediaCodecDataDecoder::GetInputBuffer(
     JNIEnv* aEnv, int aIndex, jni::Object::LocalRef* aBuffer)
@@ -327,42 +327,42 @@ MediaCodecDataDecoder::GetInputBuffer(
   return NS_ERROR_FAILURE;
 }
 
 bool
 MediaCodecDataDecoder::WaitForInput()
 {
   MonitorAutoLock lock(mMonitor);
 
-  while (State() == kDecoding && mQueue.empty()) {
+  while (mState ==  ModuleState::kDecoding && mQueue.empty()) {
     // Signal that we require more input.
     INVOKE_CALLBACK(InputExhausted);
     lock.Wait();
   }
 
-  return State() != kStopping;
+  return mState != ModuleState::kStopping;
 }
 
 
 already_AddRefed<MediaRawData>
 MediaCodecDataDecoder::PeekNextSample()
 {
   MonitorAutoLock lock(mMonitor);
 
-  if (State() == kFlushing) {
+  if (mState == ModuleState::kFlushing) {
     mDecoder->Flush();
     ClearQueue();
-    State(kDecoding);
+    SetState(ModuleState::kDecoding);
     lock.Notify();
     return nullptr;
   }
 
   if (mQueue.empty()) {
-    if (State() == kDrainQueue) {
-      State(kDrainDecoder);
+    if (mState == ModuleState::kDrainQueue) {
+      SetState(ModuleState::kDrainDecoder);
     }
     return nullptr;
   }
 
   // We're not stopping or flushing, so try to get a sample.
   return RefPtr<MediaRawData>(mQueue.front()).forget();
 }
 
@@ -418,29 +418,29 @@ MediaCodecDataDecoder::QueueEOS()
   res = mDecoder->DequeueInputBuffer(kDecoderTimeout, &inputIndex);
   if (NS_FAILED(res) || inputIndex < 0) {
     return res;
   }
 
   res = mDecoder->QueueInputBuffer(inputIndex, 0, 0, 0,
                                    MediaCodec::BUFFER_FLAG_END_OF_STREAM);
   if (NS_SUCCEEDED(res)) {
-    State(kDrainWaitEOS);
+    SetState(ModuleState::kDrainWaitEOS);
     mMonitor.Notify();
   }
   return res;
 }
 
 void
 MediaCodecDataDecoder::HandleEOS(int32_t aOutputStatus)
 {
   MonitorAutoLock lock(mMonitor);
 
-  if (State() == kDrainWaitEOS) {
-    State(kDecoding);
+  if (mState ==  ModuleState::kDrainWaitEOS) {
+    SetState(ModuleState::kDecoding);
     mMonitor.Notify();
 
     INVOKE_CALLBACK(DrainComplete);
   }
 
   mDecoder->ReleaseOutputBuffer(aOutputStatus, false);
 }
 
@@ -493,17 +493,17 @@ MediaCodecDataDecoder::DecoderLoop()
   MediaFormat::LocalRef outputFormat(frame.GetEnv());
   nsresult res = NS_OK;
 
   while (WaitForInput()) {
     RefPtr<MediaRawData> sample = PeekNextSample();
 
     {
       MonitorAutoLock lock(mMonitor);
-      if (State() == kDrainDecoder) {
+      if (mState == ModuleState::kDrainDecoder) {
         MOZ_ASSERT(!sample, "Shouldn't have a sample when pushing EOF frame");
         res = QueueEOS();
         BREAK_ON_DECODER_ERROR();
       }
     }
 
     if (sample) {
       res = QueueSample(sample);
@@ -560,55 +560,55 @@ MediaCodecDataDecoder::DecoderLoop()
       BREAK_ON_DECODER_ERROR();
     }
   }
 
   Cleanup();
 
   // We're done.
   MonitorAutoLock lock(mMonitor);
-  State(kShutdown);
+  SetState(ModuleState::kShutdown);
   mMonitor.Notify();
 }
 
 const char*
 MediaCodecDataDecoder::ModuleStateStr(ModuleState aState) {
-  static const char* kStr[] = {
-    "Decoding", "Flushing", "DrainQueue", "DrainDecoder", "DrainWaitEOS",
-    "Stopping", "Shutdown"
-  };
-
-  MOZ_ASSERT(aState < sizeof(kStr) / sizeof(kStr[0]));
-  return kStr[aState];
-}
-
-MediaCodecDataDecoder::ModuleState
-MediaCodecDataDecoder::State() const
-{
-  return mState;
+    switch (aState) {
+      case ModuleState::kDecoding:     return "Decoding";
+      case ModuleState::kFlushing:     return "Flushing";
+      case ModuleState::kDrainQueue:   return "DrainQueue";
+      case ModuleState::kDrainDecoder: return "DrainDecoder";
+      case ModuleState::kDrainWaitEOS: return "DrainWaitEOS";
+      case ModuleState::kStopping:     return "Stopping";
+      case ModuleState::kShutdown:     return "Shutdown";
+      default: MOZ_ASSERT_UNREACHABLE("Invalid state.");
+    }
+    return "Unknown";
 }
 
 bool
-MediaCodecDataDecoder::State(ModuleState aState)
+MediaCodecDataDecoder::SetState(ModuleState aState)
 {
   bool ok = true;
 
-  if (mState == kShutdown) {
+  if (mState == ModuleState::kShutdown) {
     ok = false;
-  } else if (mState == kStopping) {
-    ok = aState == kShutdown;
-  } else if (aState == kDrainDecoder) {
-    ok = mState == kDrainQueue;
-  } else if (aState == kDrainWaitEOS) {
-    ok = mState == kDrainDecoder;
+  } else if (mState == ModuleState::kStopping) {
+    ok = aState == ModuleState::kShutdown;
+  } else if (aState == ModuleState::kDrainDecoder) {
+    ok = mState == ModuleState::kDrainQueue;
+  } else if (aState == ModuleState::kDrainWaitEOS) {
+    ok = mState == ModuleState::kDrainDecoder;
   }
 
   if (ok) {
     LOG("%s -> %s", ModuleStateStr(mState), ModuleStateStr(aState));
     mState = aState;
+  } else {
+    LOG("Fail to transit from %s to %s state", ModuleStateStr(mState), ModuleStateStr(aState));
   }
 
   return ok;
 }
 
 void
 MediaCodecDataDecoder::ClearQueue()
 {
@@ -639,52 +639,53 @@ MediaCodecDataDecoder::ResetOutputBuffer
 {
   return mDecoder->GetOutputBuffers(ReturnTo(&mOutputBuffers));
 }
 
 nsresult
 MediaCodecDataDecoder::Flush()
 {
   MonitorAutoLock lock(mMonitor);
-  if (!State(kFlushing)) {
+  if (!SetState(ModuleState::kFlushing)) {
     return NS_OK;
   }
   lock.Notify();
 
-  while (State() == kFlushing) {
+  while (mState == ModuleState::kFlushing) {
     lock.Wait();
   }
 
   return NS_OK;
 }
 
 nsresult
 MediaCodecDataDecoder::Drain()
 {
   MonitorAutoLock lock(mMonitor);
-  if (State() == kDrainDecoder || State() == kDrainQueue) {
+  if (mState == ModuleState::kDrainDecoder ||
+      mState == ModuleState::kDrainQueue) {
     return NS_OK;
   }
 
-  State(kDrainQueue);
+  SetState(ModuleState::kDrainQueue);
   lock.Notify();
 
   return NS_OK;
 }
 
 
 nsresult
 MediaCodecDataDecoder::Shutdown()
 {
   MonitorAutoLock lock(mMonitor);
 
-  State(kStopping);
+  SetState(ModuleState::kStopping);
   lock.Notify();
 
-  while (mThread && State() != kShutdown) {
+  while (mThread && mState != ModuleState::kShutdown) {
     lock.Wait();
   }
 
   if (mThread) {
     mThread->Shutdown();
     mThread = nullptr;
   }
 
--- a/dom/media/platforms/android/MediaCodecDataDecoder.h
+++ b/dom/media/platforms/android/MediaCodecDataDecoder.h
@@ -38,17 +38,17 @@ public:
   nsresult Shutdown() override;
   nsresult Input(MediaRawData* aSample) override;
   const char* GetDescriptionName() const override
   {
     return "Android MediaCodec decoder";
   }
 
 protected:
-  enum ModuleState {
+  enum class ModuleState : uint8_t {
     kDecoding = 0,
     kFlushing,
     kDrainQueue,
     kDrainDecoder,
     kDrainWaitEOS,
     kStopping,
     kShutdown
   };
@@ -86,19 +86,18 @@ protected:
   already_AddRefed<MediaRawData> PeekNextSample();
   nsresult QueueSample(const MediaRawData* aSample);
   nsresult QueueEOS();
   void HandleEOS(int32_t aOutputStatus);
   Maybe<media::TimeUnit> GetOutputDuration();
   nsresult ProcessOutput(java::sdk::BufferInfo::Param aInfo,
                          java::sdk::MediaFormat::Param aFormat,
                          int32_t aStatus);
-  ModuleState State() const;
   // Sets decoder state and returns whether the new state has become effective.
-  bool State(ModuleState aState);
+  bool SetState(ModuleState aState);
   void DecoderLoop();
 
   virtual void ClearQueue();
 
   MediaData::Type mType;
 
   nsAutoCString mMimeType;
   java::sdk::MediaFormat::GlobalRef mFormat;