Bug 1238878 - Reset decoder EOS by calling flush. r=sotaro
authorAlfredo Yang <ayang@mozilla.com>
Fri, 15 Jan 2016 01:35:00 -0500
changeset 280271 9f02ddf848139a33ca5ed38197e04f0ed7e2cb5a
parent 280270 0d81d238adba2407e83f21a424b75621ad2f93c8
child 280272 eb7671c54fffcea9a94d43461bfd0f479130d56c
push id29906
push userryanvm@gmail.com
push dateSun, 17 Jan 2016 19:40:11 +0000
treeherdermozilla-central@b92f5032b4fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1238878
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1238878 - Reset decoder EOS by calling flush. r=sotaro
dom/media/platforms/omx/GonkOmxPlatformLayer.cpp
dom/media/platforms/omx/OmxDataDecoder.cpp
dom/media/platforms/omx/OmxPromiseLayer.cpp
--- a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp
+++ b/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp
@@ -20,17 +20,17 @@
 #include <cutils/properties.h>
 
 extern mozilla::LogModule* GetPDMLog();
 
 #ifdef LOG
 #undef LOG
 #endif
 
-#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer:: " arg, ##__VA_ARGS__))
+#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 
 #define CHECK_ERR(err)                    \
   if (err != OK)                       {  \
     LOG("error %d at %s", err, __func__); \
     return NS_ERROR_FAILURE;              \
   }                                       \
 
 using namespace android;
@@ -309,27 +309,29 @@ GonkBufferData::GetPlatformMediaData()
                                              mGonkPlatformLayer->GetImageContainer(),
                                              0,
                                              mBuffer->nTimeStamp,
                                              1,
                                              mTextureClientRecycleHandler->GetTextureClient(),
                                              false,
                                              0,
                                              info.mImage);
-  LOG("GetMediaData: %p, disp width %d, height %d, pic width %d, height %d, time %ld",
+  LOG("%p, disp width %d, height %d, pic width %d, height %d, time %ld",
       this, info.mDisplay.width, info.mDisplay.height,
       info.mImage.width, info.mImage.height, mBuffer->nTimeStamp);
 
   // Get TextureClient Promise here to wait for resolved.
   RefPtr<GonkBufferData> self(this);
   mTextureClientRecycleHandler->WaitforRecycle()
     ->Then(mGonkPlatformLayer->GetTaskQueue(), __func__,
            [self] () {
              // Waiting for texture to be freed.
-             self->mTextureClientRecycleHandler->GetTextureClient()->WaitForBufferOwnership();
+             if (self->mTextureClientRecycleHandler) {
+               self->mTextureClientRecycleHandler->GetTextureClient()->WaitForBufferOwnership();
+             }
              self->mPromise.ResolveIfExists(self, __func__);
            },
            [self] () {
              OmxBufferFailureHolder failure(OMX_ErrorUndefined, self);
              self->mPromise.RejectIfExists(failure, __func__);
            });
 
   return data.forget();
--- a/dom/media/platforms/omx/OmxDataDecoder.cpp
+++ b/dom/media/platforms/omx/OmxDataDecoder.cpp
@@ -8,19 +8,27 @@
 #include "OMX_Types.h"
 #include "OMX_Component.h"
 #include "OMX_Audio.h"
 
 extern mozilla::LogModule* GetPDMLog();
 
 #ifdef LOG
 #undef LOG
+#undef LOGL
 #endif
 
-#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("OmxDataDecoder::%s: " arg, __func__, ##__VA_ARGS__))
+#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("OmxDataDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
+
+#define LOGL(arg, ...)                                                     \
+  {                                                                        \
+    void* p = self;                                              \
+    MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug,                         \
+            ("OmxDataDecoder(%p)::%s: " arg, p, __func__, ##__VA_ARGS__)); \
+  }
 
 #define CHECK_OMX_ERR(err)     \
   if (err != OMX_ErrorNone) {  \
     NotifyError(err, __func__);\
     return;                    \
   }                            \
 
 // There should be a better way to calculate it.
@@ -112,54 +120,60 @@ OmxDataDecoder::OmxDataDecoder(const Tra
   , mOmxState(OMX_STATETYPE::OMX_StateInvalid, "OmxDataDecoder::mOmxState")
   , mTrackInfo(aTrackInfo.Clone())
   , mFlushing(false)
   , mShuttingDown(false)
   , mCheckingInputExhausted(false)
   , mPortSettingsChanged(-1, "OmxDataDecoder::mPortSettingsChanged")
   , mCallback(aCallback)
 {
-  LOG("(%p)", this);
+  LOG("");
   mOmxLayer = new OmxPromiseLayer(mOmxTaskQueue, this, aImageContainer);
 
   nsCOMPtr<nsIRunnable> r =
     NS_NewRunnableMethod(this, &OmxDataDecoder::InitializationTask);
   mOmxTaskQueue->Dispatch(r.forget());
 }
 
 OmxDataDecoder::~OmxDataDecoder()
 {
-  LOG("(%p)", this);
+  LOG("");
 }
 
 void
 OmxDataDecoder::InitializationTask()
 {
   mWatchManager.Watch(mOmxState, &OmxDataDecoder::OmxStateRunner);
   mWatchManager.Watch(mPortSettingsChanged, &OmxDataDecoder::PortSettingsChanged);
 }
 
 void
 OmxDataDecoder::EndOfStream()
 {
-  LOG("(%p)", this);
+  LOG("");
   MOZ_ASSERT(mOmxTaskQueue->IsCurrentThreadIn());
 
+  mFlushing = true;
   RefPtr<OmxDataDecoder> self = this;
-  nsCOMPtr<nsIRunnable> r =
-    NS_NewRunnableFunction([self] () {
-      self->mCallback->DrainComplete();
-    });
-  mReaderTaskQueue->Dispatch(r.forget());
+  mOmxLayer->SendCommand(OMX_CommandFlush, OMX_ALL, nullptr)
+    ->Then(mReaderTaskQueue, __func__,
+        [self] () {
+          self->mFlushing = false;
+          self->mCallback->DrainComplete();
+        },
+        [self] () {
+          self->mFlushing = false;
+          self->mCallback->DrainComplete();
+        });
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 OmxDataDecoder::Init()
 {
-  LOG("(%p)", this);
+  LOG("");
   mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue();
   MOZ_ASSERT(mReaderTaskQueue);
 
   RefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
   RefPtr<OmxDataDecoder> self = this;
 
   // TODO: it needs to get permission from resource manager before allocating
   //       Omx component.
@@ -176,17 +190,17 @@ OmxDataDecoder::Init()
       });
 
   return p;
 }
 
 nsresult
 OmxDataDecoder::Input(MediaRawData* aSample)
 {
-  LOG("(%p) sample %p", this, aSample);
+  LOG("sample %p", aSample);
   MOZ_ASSERT(mInitPromise.IsEmpty());
 
   RefPtr<OmxDataDecoder> self = this;
   RefPtr<MediaRawData> sample = aSample;
 
   nsCOMPtr<nsIRunnable> r =
     NS_NewRunnableFunction([self, sample] () {
       self->mMediaRawDatas.AppendElement(sample);
@@ -200,17 +214,17 @@ OmxDataDecoder::Input(MediaRawData* aSam
   mOmxTaskQueue->Dispatch(r.forget());
 
   return NS_OK;
 }
 
 nsresult
 OmxDataDecoder::Flush()
 {
-  LOG("(%p)", this);
+  LOG("");
 
   mFlushing = true;
 
   nsCOMPtr<nsIRunnable> r =
     NS_NewRunnableMethod(this, &OmxDataDecoder::DoFlush);
   mOmxTaskQueue->Dispatch(r.forget());
 
   // According to the definition of Flush() in PDM:
@@ -222,29 +236,29 @@ OmxDataDecoder::Flush()
   }
 
   return NS_OK;
 }
 
 nsresult
 OmxDataDecoder::Drain()
 {
-  LOG("(%p)", this);
+  LOG("");
 
   nsCOMPtr<nsIRunnable> r =
     NS_NewRunnableMethod(this, &OmxDataDecoder::SendEosBuffer);
   mOmxTaskQueue->Dispatch(r.forget());
 
   return NS_OK;
 }
 
 nsresult
 OmxDataDecoder::Shutdown()
 {
-  LOG("(%p)", this);
+  LOG("");
 
   mShuttingDown = true;
 
   nsCOMPtr<nsIRunnable> r =
     NS_NewRunnableMethod(this, &OmxDataDecoder::DoAsyncShutdown);
   mOmxTaskQueue->Dispatch(r.forget());
 
   {
@@ -261,29 +275,29 @@ OmxDataDecoder::Shutdown()
   mOmxTaskQueue->AwaitShutdownAndIdle();
 
   return NS_OK;
 }
 
 void
 OmxDataDecoder::DoAsyncShutdown()
 {
-  LOG("(%p)", this);
+  LOG("");
   MOZ_ASSERT(mOmxTaskQueue->IsCurrentThreadIn());
   MOZ_ASSERT(!mFlushing);
 
   mWatchManager.Unwatch(mOmxState, &OmxDataDecoder::OmxStateRunner);
   mWatchManager.Unwatch(mPortSettingsChanged, &OmxDataDecoder::PortSettingsChanged);
 
   // Flush to all ports, so all buffers can be returned from component.
   RefPtr<OmxDataDecoder> self = this;
   mOmxLayer->SendCommand(OMX_CommandFlush, OMX_ALL, nullptr)
     ->Then(mOmxTaskQueue, __func__,
            [self] () -> RefPtr<OmxCommandPromise> {
-             LOG("DoAsyncShutdown: flush complete");
+             LOGL("DoAsyncShutdown: flush complete");
              return self->mOmxLayer->SendCommand(OMX_CommandStateSet, OMX_StateIdle, nullptr);
            },
            [self] () {
              self->mOmxLayer->Shutdown();
            })
     ->CompletionPromise()
     ->Then(mOmxTaskQueue, __func__,
            [self] () -> RefPtr<OmxCommandPromise> {
@@ -293,29 +307,29 @@ OmxDataDecoder::DoAsyncShutdown()
              // According to spec 3.1.1.2.2.1:
              // OMX_StateLoaded needs to be sent before releasing buffers.
              // And state transition from OMX_StateIdle to OMX_StateLoaded
              // is completed when all of the buffers have been removed
              // from the component.
              // Here the buffer promises are not resolved due to displaying
              // in layer, it needs to wait before the layer returns the
              // buffers.
-             LOG("DoAsyncShutdown: releasing buffers...");
+             LOGL("DoAsyncShutdown: releasing buffers...");
              self->ReleaseBuffers(OMX_DirInput);
              self->ReleaseBuffers(OMX_DirOutput);
 
              return p;
            },
            [self] () {
              self->mOmxLayer->Shutdown();
            })
     ->CompletionPromise()
     ->Then(mOmxTaskQueue, __func__,
            [self] () {
-             LOG("DoAsyncShutdown: OMX_StateLoaded, it is safe to shutdown omx");
+             LOGL("DoAsyncShutdown: OMX_StateLoaded, it is safe to shutdown omx");
              self->mOmxLayer->Shutdown();
              self->mWatchManager.Shutdown();
              self->mOmxLayer = nullptr;
              self->mMediaDataHelper = nullptr;
 
              MonitorAutoLock lock(self->mMonitor);
              self->mShuttingDown = false;
              self->mMonitor.Notify();
@@ -427,17 +441,17 @@ OmxDataDecoder::EmptyBufferDone(BufferDa
         MOZ_ASSERT(self->mOmxTaskQueue->IsCurrentThreadIn());
 
         self->mCheckingInputExhausted = false;
 
         if (self->mMediaRawDatas.Length()) {
           return;
         }
 
-        LOG("Call InputExhausted()");
+        LOGL("Call InputExhausted()");
         self->mCallback->InputExhausted();
       });
 
     mOmxTaskQueue->Dispatch(r.forget());
   }
 }
 
 void
@@ -516,17 +530,16 @@ OmxDataDecoder::FindAvailableBuffer(OMX_
 {
   BUFFERLIST* buffers = GetBuffers(aType);
 
   for (uint32_t i = 0; i < buffers->Length(); i++) {
     BufferData* buf = buffers->ElementAt(i);
     if (buf->mStatus == BufferData::BufferStatus::FREE) {
       return buf;
     }
-    LOG("buffer is owned by %d, type %d", buf->mStatus, aType);
   }
 
   return nullptr;
 }
 
 nsresult
 OmxDataDecoder::AllocateBuffers(OMX_DIRTYPE aType)
 {
@@ -553,17 +566,17 @@ OmxDataDecoder::GetBuffers(OMX_DIRTYPE a
     return &mInPortBuffers;
   }
   return &mOutPortBuffers;
 }
 
 void
 OmxDataDecoder::ResolveInitPromise(const char* aMethodName)
 {
-  LOG("Resolved InitPromise");
+  LOG("called from %s", aMethodName);
   RefPtr<OmxDataDecoder> self = this;
   nsCOMPtr<nsIRunnable> r =
     NS_NewRunnableFunction([self, aMethodName] () {
       MOZ_ASSERT(self->mReaderTaskQueue->IsCurrentThreadIn());
       self->mInitPromise.ResolveIfExists(self->mTrackInfo->GetType(), aMethodName);
     });
   mReaderTaskQueue->Dispatch(r.forget());
 }
@@ -901,17 +914,17 @@ OmxDataDecoder::PortSettingsChanged()
                return p;
              },
              [self] () {
                self->NotifyError(OMX_ErrorUndefined, __func__);
              })
       ->CompletionPromise()
       ->Then(mOmxTaskQueue, __func__,
              [self] () {
-               LOG("PortSettingsChanged: port settings changed complete");
+               LOGL("PortSettingsChanged: port settings changed complete");
                // finish port setting changed.
                self->mPortSettingsChanged = -1;
                self->FillAndEmptyBuffers();
              },
              [self] () {
                self->NotifyError(OMX_ErrorUndefined, __func__);
              });
 
--- a/dom/media/platforms/omx/OmxPromiseLayer.cpp
+++ b/dom/media/platforms/omx/OmxPromiseLayer.cpp
@@ -13,17 +13,17 @@
 #endif
 
 extern mozilla::LogModule* GetPDMLog();
 
 #ifdef LOG
 #undef LOG
 #endif
 
-#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("OmxPromiseLayer:: " arg, ##__VA_ARGS__))
+#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("OmxPromiseLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 
 namespace mozilla {
 
 extern void GetPortIndex(nsTArray<uint32_t>& aPortIndex);
 
 OmxPromiseLayer::OmxPromiseLayer(TaskQueue* aTaskQueue,
                                  OmxDataDecoder* aDataDecoder,
                                  layers::ImageContainer* aImageContainer)
@@ -57,17 +57,17 @@ OmxPromiseLayer::Init(TaskQueue* aTaskQu
   OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet);
   return OmxCommandPromise::CreateAndReject(failure, __func__);
 }
 
 RefPtr<OmxPromiseLayer::OmxBufferPromise>
 OmxPromiseLayer::FillBuffer(BufferData* aData)
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
-  LOG("FillBuffer: buffer %p", aData->mBuffer);
+  LOG("buffer %p", aData->mBuffer);
 
   RefPtr<OmxBufferPromise> p = aData->mPromise.Ensure(__func__);
 
   OMX_ERRORTYPE err = mPlatformLayer->FillThisBuffer(aData);
 
   if (err != OMX_ErrorNone) {
     OmxBufferFailureHolder failure(err, aData);
     aData->mPromise.Reject(Move(failure), __func__);
@@ -78,17 +78,17 @@ OmxPromiseLayer::FillBuffer(BufferData* 
 
   return p;
 }
 
 RefPtr<OmxPromiseLayer::OmxBufferPromise>
 OmxPromiseLayer::EmptyBuffer(BufferData* aData)
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
-  LOG("EmptyBuffer: buffer %p, size %d", aData->mBuffer, aData->mBuffer->nFilledLen);
+  LOG("buffer %p, size %d", aData->mBuffer, aData->mBuffer->nFilledLen);
 
   RefPtr<OmxBufferPromise> p = aData->mPromise.Ensure(__func__);
 
   OMX_ERRORTYPE err = mPlatformLayer->EmptyThisBuffer(aData);
 
   if (err != OMX_ErrorNone) {
     OmxBufferFailureHolder failure(err, aData);
     aData->mPromise.Reject(Move(failure), __func__);
@@ -164,17 +164,17 @@ OmxPromiseLayer::FindBufferById(OMX_DIRT
 
   return nullptr;
 }
 
 void
 OmxPromiseLayer::EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData* aData)
 {
   MOZ_ASSERT(!!aData);
-  LOG("EmptyFillBufferDone: type %d, buffer %p", aType, aData->mBuffer);
+  LOG("type %d, buffer %p", aType, aData->mBuffer);
   if (aData) {
     if (aType == OMX_DirOutput) {
       aData->mRawData = nullptr;
       aData->mRawData = FindAndRemoveRawData(aData->mBuffer->nTimeStamp);
     }
     aData->mStatus = BufferData::BufferStatus::OMX_CLIENT;
     aData->mPromise.Resolve(aData, __func__);
   }
@@ -217,17 +217,17 @@ OmxPromiseLayer::SendCommand(OMX_COMMAND
         mPlatformLayer->SendCommand(OMX_CommandFlush,
                                     mFlushCommands.ElementAt(0).type,
                                     mFlushCommands.ElementAt(0).cmd);
       if (err != OMX_ErrorNone) {
         OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
         return OmxCommandPromise::CreateAndReject(failure, __func__);
       }
     } else {
-      LOG("SendCommand: OMX_CommandFlush parameter error");
+      LOG("OMX_CommandFlush parameter error");
       OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
       return OmxCommandPromise::CreateAndReject(failure, __func__);
     }
   } else {
     OMX_ERRORTYPE err = mPlatformLayer->SendCommand(aCmd, aParam1, aCmdData);
     if (err != OMX_ErrorNone) {
       OmxCommandFailureHolder failure(OMX_ErrorNotReady, aCmd);
       return OmxCommandPromise::CreateAndReject(failure, __func__);
@@ -239,17 +239,17 @@ OmxPromiseLayer::SendCommand(OMX_COMMAND
     p = mCommandStatePromise.Ensure(__func__);
   } else if (aCmd == OMX_CommandFlush) {
     p = mFlushPromise.Ensure(__func__);
   } else if (aCmd == OMX_CommandPortEnable) {
     p = mPortEnablePromise.Ensure(__func__);
   } else if (aCmd == OMX_CommandPortDisable) {
     p = mPortDisablePromise.Ensure(__func__);
   } else {
-    LOG("SendCommand: error unsupport command");
+    LOG("error unsupport command");
     MOZ_ASSERT(0);
   }
 
   return p;
 }
 
 bool
 OmxPromiseLayer::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2)
@@ -257,17 +257,17 @@ OmxPromiseLayer::Event(OMX_EVENTTYPE aEv
   OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) aData1;
   switch (aEvent) {
     case OMX_EventCmdComplete:
     {
       if (cmd == OMX_CommandStateSet) {
         mCommandStatePromise.Resolve(OMX_CommandStateSet, __func__);
       } else if (cmd == OMX_CommandFlush) {
         MOZ_RELEASE_ASSERT(mFlushCommands.ElementAt(0).type == aData2);
-        LOG("Event: OMX_CommandFlush completed port type %d", aData2);
+        LOG("OMX_CommandFlush completed port type %d", aData2);
         mFlushCommands.RemoveElementAt(0);
 
         // Sending next flush command.
         if (mFlushCommands.Length()) {
           OMX_ERRORTYPE err =
             mPlatformLayer->SendCommand(OMX_CommandFlush,
                                         mFlushCommands.ElementAt(0).type,
                                         mFlushCommands.ElementAt(0).cmd);
@@ -350,16 +350,16 @@ OmxPromiseLayer::SetParameter(OMX_INDEXT
   return mPlatformLayer->SetParameter(aParamIndex,
                                       aComponentParameterStructure,
                                       aComponentParameterSize);
 }
 
 nsresult
 OmxPromiseLayer::Shutdown()
 {
-  LOG("Shutdown");
+  LOG("");
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   MOZ_ASSERT(!GetBufferHolders(OMX_DirInput)->Length());
   MOZ_ASSERT(!GetBufferHolders(OMX_DirOutput)->Length());
   return mPlatformLayer->Shutdown();
 }
 
 }