Bug 1256065. r=gerald,a=ritu
authorChris Pearce <cpearce@mozilla.com>
Wed, 16 Mar 2016 13:49:26 +0800
changeset 323474 c4a154a8765550da45b4a477673fcd35754f80bf
parent 323473 5a5f9c53b6aa4c4ce0da90b713f6936ad1915636
child 323475 7f0c41c49f0e359e27d18016665dbe2b95fd13f7
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald, ritu
bugs1256065
milestone47.0a2
Bug 1256065. r=gerald,a=ritu
dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp
dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h
dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h
--- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp
@@ -137,18 +137,26 @@ nsCString
 GMPAudioDecoder::GetNodeId()
 {
   return SHARED_GMP_DECODING_NODE_ID;
 }
 
 void
 GMPAudioDecoder::GMPInitDone(GMPAudioDecoderProxy* aGMP)
 {
+  MOZ_ASSERT(IsOnGMPThread());
+
   if (!aGMP) {
-    mInitPromise.Reject(MediaDataDecoder::DecoderFailureReason::INIT_ERROR, __func__);
+    mInitPromise.RejectIfExists(MediaDataDecoder::DecoderFailureReason::INIT_ERROR, __func__);
+    return;
+  }
+  if (mInitPromise.IsEmpty()) {
+    // GMP must have been shutdown while we were waiting for Init operation
+    // to complete.
+    aGMP->Close();
     return;
   }
   nsTArray<uint8_t> codecSpecific;
   codecSpecific.AppendElements(mConfig.mCodecSpecificConfig->Elements(),
                                mConfig.mCodecSpecificConfig->Length());
 
   nsresult rv = aGMP->InitDecode(kGMPAudioCodecAAC,
                                  mConfig.mChannels,
@@ -236,15 +244,16 @@ GMPAudioDecoder::Drain()
 
 nsresult
 GMPAudioDecoder::Shutdown()
 {
   mInitPromise.RejectIfExists(MediaDataDecoder::DecoderFailureReason::CANCELED, __func__);
   if (!mGMP) {
     return NS_ERROR_FAILURE;
   }
+  // Note this unblocks flush and drain operations waiting for callbacks.
   mGMP->Close();
   mGMP = nullptr;
 
   return NS_OK;
 }
 
 } // namespace mozilla
--- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h
+++ b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h
@@ -98,17 +98,17 @@ private:
       mDecoder->GMPInitDone(aGMP);
     }
 
   private:
     RefPtr<GMPAudioDecoder> mDecoder;
   };
   void GMPInitDone(GMPAudioDecoderProxy* aGMP);
 
-  const AudioInfo& mConfig;
+  const AudioInfo mConfig;
   MediaDataDecoderCallbackProxy* mCallback;
   nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
   GMPAudioDecoderProxy* mGMP;
   nsAutoPtr<AudioCallbackAdapter> mAdapter;
   MozPromiseHolder<InitPromise> mInitPromise;
 };
 
 } // namespace mozilla
--- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
@@ -162,22 +162,31 @@ GMPVideoDecoder::CreateFrame(MediaRawDat
   frame->SetFrameType(aSample->mKeyframe ? kGMPKeyFrame : kGMPDeltaFrame);
 
   return frame;
 }
 
 void
 GMPVideoDecoder::GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost)
 {
+  MOZ_ASSERT(IsOnGMPThread());
+
   if (!aGMP) {
-    mInitPromise.Reject(MediaDataDecoder::DecoderFailureReason::INIT_ERROR, __func__);
+    mInitPromise.RejectIfExists(MediaDataDecoder::DecoderFailureReason::INIT_ERROR, __func__);
     return;
   }
   MOZ_ASSERT(aHost);
 
+  if (mInitPromise.IsEmpty()) {
+    // GMP must have been shutdown while we were waiting for Init operation
+    // to complete.
+    aGMP->Close();
+    return;
+  }
+
   GMPVideoCodec codec;
   memset(&codec, 0, sizeof(codec));
 
   codec.mGMPApiVersion = kGMPVersion33;
 
   codec.mCodecType = kGMPVideoCodecH264;
   codec.mWidth = mConfig.mDisplay.width;
   codec.mHeight = mConfig.mDisplay.height;
@@ -289,15 +298,16 @@ GMPVideoDecoder::Drain()
 nsresult
 GMPVideoDecoder::Shutdown()
 {
   mInitPromise.RejectIfExists(MediaDataDecoder::DecoderFailureReason::CANCELED, __func__);
   // Note that this *may* be called from the proxy thread also.
   if (!mGMP) {
     return NS_ERROR_FAILURE;
   }
+  // Note this unblocks flush and drain operations waiting for callbacks.
   mGMP->Close();
   mGMP = nullptr;
 
   return NS_OK;
 }
 
 } // namespace mozilla
--- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h
+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h
@@ -114,17 +114,17 @@ private:
       mDecoder->GMPInitDone(aGMP, aHost);
     }
 
   private:
     RefPtr<GMPVideoDecoder> mDecoder;
   };
   void GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost);
 
-  const VideoInfo& mConfig;
+  const VideoInfo mConfig;
   MediaDataDecoderCallbackProxy* mCallback;
   nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
   GMPVideoDecoderProxy* mGMP;
   GMPVideoHost* mHost;
   nsAutoPtr<VideoCallbackAdapter> mAdapter;
   bool mConvertNALUnitLengths;
   MozPromiseHolder<InitPromise> mInitPromise;
 };