Bug 1094614 - Release codec resource properly. r=sotaro
authorBlake Wu <bwu@mozilla.com>
Thu, 20 Nov 2014 17:09:48 +0800
changeset 241135 5261b6dd5487ba8b086fa04ff6f9fe50436af210
parent 241134 565121755b114d1652434822fa93ca92cc737322
child 241136 794b5fca57b02ec6d0e9275431b90262c6d962a1
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1094614
milestone36.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 1094614 - Release codec resource properly. r=sotaro
dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
dom/media/fmp4/gonk/GonkMediaDataDecoder.h
dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
dom/media/fmp4/gonk/GonkVideoDecoderManager.h
dom/media/omx/MediaCodecProxy.cpp
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
@@ -157,17 +157,18 @@ GonkMediaDataDecoder::Drain()
 
 bool
 GonkMediaDataDecoder::IsWaitingMediaResources() {
   return mDecoder->IsWaitingResources();
 }
 
 bool
 GonkMediaDataDecoder::IsDormantNeeded() {
-  return mDecoder->IsDormantNeeded();
+
+  return mDecoder.get() ? true : false;
 }
 
 void
 GonkMediaDataDecoder::ReleaseMediaResources() {
-  mDecoder->ReleaseMediaResources();
+  mManager->ReleaseMediaResources();
 }
 
 } // namespace mozilla
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
@@ -29,16 +29,17 @@ public:
   // is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
   // if there's not enough data to produce more output. If this returns a failure
   // code other than NS_ERROR_NOT_AVAILABLE, an error will be reported to the
   // MP4Reader.
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) = 0;
 
+  virtual void ReleaseMediaResources() {};
 };
 
 // Samples are decoded using the GonkDecoder (MediaCodec)
 // created by the GonkDecoderManager. This class implements
 // the higher-level logic that drives mapping the Gonk to the async
 // MediaDataDecoder interface. The specifics of decoding the exact stream
 // type are handled by GonkDecoderManager and the GonkDecoder it creates.
 class GonkMediaDataDecoder : public MediaDataDecoder {
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -450,29 +450,30 @@ GonkVideoDecoderManager::codecCanceled()
 void
 GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
 {
   switch (aMessage->what()) {
     case kNotifyCodecReserved:
     {
       // Our decode may have acquired the hardware resource that it needs
       // to start. Notify the state machine to resume loading metadata.
+      ALOG("CodecReserved!");
       mReaderCallback->NotifyResourcesStatusChanged();
       break;
     }
 
     case kNotifyCodecCanceled:
     {
       mReaderCallback->ReleaseMediaResources();
       break;
     }
 
     case kNotifyPostReleaseBuffer:
     {
-      ReleaseAllPendingVideoBuffersLocked();
+      ReleaseAllPendingVideoBuffers();
       break;
     }
 
     default:
       TRESPASS();
       break;
   }
 }
@@ -557,17 +558,17 @@ void GonkVideoDecoderManager::PostReleas
     }
   }
   sp<AMessage> notify =
             new AMessage(kNotifyPostReleaseBuffer, mHandler->id());
   notify->post();
 
 }
 
-void GonkVideoDecoderManager::ReleaseAllPendingVideoBuffersLocked()
+void GonkVideoDecoderManager::ReleaseAllPendingVideoBuffers()
 {
   Vector<android::MediaBuffer*> releasingVideoBuffers;
   {
     MutexAutoLock autoLock(mPendingVideoBuffersLock);
     int size = mPendingVideoBuffers.length();
     for (int i = 0; i < size; i++) {
       releasingVideoBuffers.append(mPendingVideoBuffers[i]);
     }
@@ -579,9 +580,14 @@ void GonkVideoDecoderManager::ReleaseAll
     android::MediaBuffer *buffer;
     buffer = releasingVideoBuffers[i];
     mDecoder->ReleaseMediaBuffer(buffer);
     buffer = nullptr;
   }
   releasingVideoBuffers.clear();
 }
 
+void GonkVideoDecoderManager::ReleaseMediaResources() {
+  ALOG("ReleseMediaResources");
+  ReleaseAllPendingVideoBuffers();
+  mDecoder->ReleaseMediaResources();
+}
 } // namespace mozilla
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
@@ -45,17 +45,20 @@ public:
 
   virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
+  virtual void ReleaseMediaResources();
+
   static void RecycleCallback(TextureClient* aClient, void* aClosure);
+
 private:
   struct FrameInfo
   {
     int32_t mWidth = 0;
     int32_t mHeight = 0;
     int32_t mStride = 0;
     int32_t mSliceHeight = 0;
     int32_t mColorFormat = 0;
@@ -107,17 +110,17 @@ private:
   void ReleaseVideoBuffer();
   uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
 
   // For codec resource management
   void codecReserved();
   void codecCanceled();
   void onMessageReceived(const sp<AMessage> &aMessage);
 
-  void ReleaseAllPendingVideoBuffersLocked();
+  void ReleaseAllPendingVideoBuffers();
   void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer);
 
   uint32_t mVideoWidth;
   uint32_t mVideoHeight;
   uint32_t mDisplayWidth;
   uint32_t mDisplayHeight;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
--- a/dom/media/omx/MediaCodecProxy.cpp
+++ b/dom/media/omx/MediaCodecProxy.cpp
@@ -105,20 +105,16 @@ MediaCodecProxy::MediaCodecProxy(sp<ALoo
   } else {
     allocateCodec();
   }
 }
 
 MediaCodecProxy::~MediaCodecProxy()
 {
   releaseCodec();
-
-  // Complete all pending Binder ipc transactions
-  IPCThreadState::self()->flushCommands();
-
   cancelResource();
 }
 
 bool
 MediaCodecProxy::requestResource()
 {
   if (mResourceHandler == nullptr) {
     return false;
@@ -176,25 +172,30 @@ MediaCodecProxy::releaseCodec()
   {
     // Write Lock for mCodec
     RWLock::AutoWLock awl(mCodecLock);
 
     codec = mCodec;
 
     // Release MediaCodec
     if (mCodec != nullptr) {
+      status_t err = mCodec->stop();
       mCodec->release();
       mCodec = nullptr;
     }
   }
 
   while (codec.promote() != nullptr) {
     // this value come from stagefright's AwesomePlayer.
     usleep(1000);
   }
+
+  // Complete all pending Binder ipc transactions
+  IPCThreadState::self()->flushCommands();
+
 }
 
 bool
 MediaCodecProxy::allocated() const
 {
   // Read Lock for mCodec
   RWLock::AutoRLock arl(mCodecLock);
 
@@ -592,31 +593,30 @@ status_t MediaCodecProxy::Output(MediaBu
   if (flags & MediaCodec::BUFFER_FLAG_EOS) {
     return ERROR_END_OF_STREAM;
   }
   return err;
 }
 
 bool MediaCodecProxy::IsWaitingResources()
 {
+  // Write Lock for mCodec
+  RWLock::AutoWLock awl(mCodecLock);
   return mCodec == nullptr;
 }
 
 bool MediaCodecProxy::IsDormantNeeded()
 {
   return mCodecLooper.get() ? true : false;
 }
 
 void MediaCodecProxy::ReleaseMediaResources()
 {
-  if (mCodec.get()) {
-    mCodec->stop();
-    mCodec->release();
-    mCodec.clear();
-  }
+  releaseCodec();
+  cancelResource();
 }
 
 void MediaCodecProxy::ReleaseMediaBuffer(MediaBuffer* aBuffer) {
   if (aBuffer) {
     sp<MetaData> metaData = aBuffer->meta_data();
     int32_t index;
     metaData->findInt32(kKeyBufferIndex, &index);
     aBuffer->release();