Backed out changeset 49fc56608294 (bug 1182289) for Android crashes/asserts.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 27 Jul 2015 16:27:20 -0400
changeset 275459 8866651b440e312449aae29b3740debd671a0ee2
parent 275458 df90f57c5003ef49a88aa08eab7af7724c7c788b
child 275460 4743f6c6cd8162294ae3da7bbf05f20acb7fcbe8
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1182289
milestone40.0
backs out49fc56608294d954943af191a17af21b7f0db8db
Backed out changeset 49fc56608294 (bug 1182289) for Android crashes/asserts.
media/webrtc/signaling/src/media-conduit/GmpVideoCodec.cpp
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
--- a/media/webrtc/signaling/src/media-conduit/GmpVideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/GmpVideoCodec.cpp
@@ -3,16 +3,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebrtcGmpVideoCodec.h"
 #include "GmpVideoCodec.h"
 
 namespace mozilla {
 
 VideoEncoder* GmpVideoCodec::CreateEncoder() {
-  return static_cast<VideoEncoder*>(new WebrtcVideoEncoderProxy());
+  return static_cast<VideoEncoder*>(new WebrtcGmpVideoEncoder());
 }
 
 VideoDecoder* GmpVideoCodec::CreateDecoder() {
-  return static_cast<VideoDecoder*>(new WebrtcVideoDecoderProxy());
+  return static_cast<VideoDecoder*>(new WebrtcGmpVideoDecoder());
 }
 
 }
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
@@ -13,17 +13,16 @@
 #include "VideoConduit.h"
 #include "AudioConduit.h"
 #include "runnable_utils.h"
 
 #include "mozIGeckoMediaPluginService.h"
 #include "nsServiceManagerUtils.h"
 #include "GMPVideoDecoderProxy.h"
 #include "GMPVideoEncoderProxy.h"
-#include "MainThreadUtils.h"
 
 #include "gmp-video-host.h"
 #include "gmp-video-frame-i420.h"
 #include "gmp-video-frame-encoded.h"
 
 #include "webrtc/video_engine/include/vie_external_codec.h"
 
 namespace mozilla {
@@ -48,71 +47,41 @@ GetGMPLog()
 #endif
 #define LOGD(msg) PR_LOG(GetGMPLog(), PR_LOG_DEBUG, msg)
 #define LOG(level, msg) PR_LOG(GetGMPLog(), (level), msg)
 #else
 #define LOGD(msg)
 #define LOG(level, msg)
 #endif
 
-WebrtcGmpPCHandleSetter::WebrtcGmpPCHandleSetter(const std::string& aPCHandle)
-{
-  if (!NS_IsMainThread()) {
-    MOZ_ASSERT(false, "WebrtcGmpPCHandleSetter can only be used on main");
-    return;
-  }
-  MOZ_ASSERT(sCurrentHandle.empty());
-  sCurrentHandle = aPCHandle;
-}
-
-WebrtcGmpPCHandleSetter::~WebrtcGmpPCHandleSetter()
-{
-  if (!NS_IsMainThread()) {
-    MOZ_ASSERT(false, "WebrtcGmpPCHandleSetter can only be used on main");
-    return;
-  }
-
-  sCurrentHandle.clear();
-}
-
-/* static */ std::string
-WebrtcGmpPCHandleSetter::GetCurrentHandle()
-{
-  if (!NS_IsMainThread()) {
-    MOZ_ASSERT(false, "WebrtcGmpPCHandleSetter can only be used on main");
-    return "";
-  }
-
-  return sCurrentHandle;
-}
-
-std::string WebrtcGmpPCHandleSetter::sCurrentHandle = "";
-
 // Encoder.
 WebrtcGmpVideoEncoder::WebrtcGmpVideoEncoder()
   : mGMP(nullptr)
-  , mInitting(false)
   , mHost(nullptr)
-  , mMaxPayloadSize(0)
-  , mCallbackMutex("WebrtcGmpVideoEncoder encoded callback mutex")
   , mCallback(nullptr)
   , mCachedPluginId(0)
+{}
+
+static void
+Encoder_Close_g(GMPVideoEncoderProxy* aGMP)
 {
-#ifdef MOZILLA_INTERNAL_API
-  if (mPCHandle.empty()) {
-    mPCHandle = WebrtcGmpPCHandleSetter::GetCurrentHandle();
-  }
-  MOZ_ASSERT(!mPCHandle.empty());
-#endif
+  aGMP->Close();
 }
 
 WebrtcGmpVideoEncoder::~WebrtcGmpVideoEncoder()
 {
-  // We should not have been destroyed if we never closed our GMP
-  MOZ_ASSERT(!mGMP);
+  // Note: we only use SyncRunnables to access mGMP
+  // Callbacks may occur at any time until we call Close (or receive
+  // Terminated()), so call Close here synchronously.
+  // Do NOT touch the refcount of 'this'!
+  if (mGMPThread && mGMP) {
+    mozilla::SyncRunnable::DispatchToThread(mGMPThread,
+                                            WrapRunnableNM(&Encoder_Close_g, mGMP));
+    mGMP = nullptr;
+  }
 }
 
 static int
 WebrtcFrameTypeToGmpFrameType(webrtc::VideoFrameType aIn,
                               GMPVideoFrameType *aOut)
 {
   MOZ_ASSERT(aOut);
   switch(aIn) {
@@ -177,234 +146,189 @@ WebrtcGmpVideoEncoder::InitEncode(const 
   MOZ_ASSERT(mMPS);
 
   if (!mGMPThread) {
     if (NS_WARN_IF(NS_FAILED(mMPS->GetThread(getter_AddRefs(mGMPThread))))) {
       return WEBRTC_VIDEO_CODEC_ERROR;
     }
   }
 
-  // Bug XXXXXX: transfer settings from codecSettings to codec.
-  GMPVideoCodec codecParams;
-  memset(&codecParams, 0, sizeof(codecParams));
+  nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
+  MOZ_ASSERT(currentThread != mGMPThread);
+
+  nsRefPtr<InitDoneRunnable> initDone(new InitDoneRunnable());
+  mGMPThread->Dispatch(WrapRunnable(this,
+                                    &WebrtcGmpVideoEncoder::InitEncode_g,
+                                    aCodecSettings,
+                                    aNumberOfCores,
+                                    aMaxPayloadSize,
+                                    initDone),
+                       NS_DISPATCH_NORMAL);
+
+
+  while (!initDone->IsDone()) {
+    NS_ProcessNextEvent(currentThread, true);
+  }
+
+  return initDone->Result();
+}
 
-  codecParams.mGMPApiVersion = 33;
-  codecParams.mStartBitrate = aCodecSettings->startBitrate;
-  codecParams.mMinBitrate = aCodecSettings->minBitrate;
-  codecParams.mMaxBitrate = aCodecSettings->maxBitrate;
-  codecParams.mMaxFramerate = aCodecSettings->maxFramerate;
+void
+WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
+                                    int32_t aNumberOfCores,
+                                    uint32_t aMaxPayloadSize,
+                                    InitDoneRunnable* aInitDone)
+{
+  nsTArray<nsCString> tags;
+  tags.AppendElement(NS_LITERAL_CSTRING("h264"));
+  UniquePtr<GetGMPVideoEncoderCallback> callback(
+    new InitDoneCallback(this, aInitDone, aCodecSettings, aMaxPayloadSize));
+  nsresult rv = mMPS->GetGMPVideoEncoder(&tags,
+                                         NS_LITERAL_CSTRING(""),
+                                         Move(callback));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mMPS = nullptr;
+    mGMP = nullptr;
+    mGMPThread = nullptr;
+    mHost = nullptr;
+    aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR);
+    return;
+  }
+}
+
+int32_t
+WebrtcGmpVideoEncoder::GmpInitDone(GMPVideoEncoderProxy* aGMP,
+                                   GMPVideoHost* aHost,
+                                   const webrtc::VideoCodec* aCodecSettings,
+                                   uint32_t aMaxPayloadSize)
+{
+  mGMP = aGMP;
+  mHost = aHost;
+  if (!mGMP || !mHost) {
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+
+  // Bug XXXXXX: transfer settings from codecSettings to codec.
+  memset(&mCodecParams, 0, sizeof(mCodecParams));
+
+  mCodecParams.mGMPApiVersion = 33;
+  mCodecParams.mStartBitrate = aCodecSettings->startBitrate;
+  mCodecParams.mMinBitrate = aCodecSettings->minBitrate;
+  mCodecParams.mMaxBitrate = aCodecSettings->maxBitrate;
+  mCodecParams.mMaxFramerate = aCodecSettings->maxFramerate;
   mMaxPayloadSize = aMaxPayloadSize;
   if (aCodecSettings->codecSpecific.H264.packetizationMode == 1) {
     mMaxPayloadSize = 0; // No limit.
   }
 
   if (aCodecSettings->mode == webrtc::kScreensharing) {
-    codecParams.mMode = kGMPScreensharing;
+    mCodecParams.mMode = kGMPScreensharing;
   } else {
-    codecParams.mMode = kGMPRealtimeVideo;
+    mCodecParams.mMode = kGMPRealtimeVideo;
   }
 
-  codecParams.mWidth = aCodecSettings->width;
-  codecParams.mHeight = aCodecSettings->height;
-
-  nsRefPtr<GmpInitDoneRunnable> initDone(new GmpInitDoneRunnable(mPCHandle));
-  mGMPThread->Dispatch(WrapRunnableNM(WebrtcGmpVideoEncoder::InitEncode_g,
-                                      nsRefPtr<WebrtcGmpVideoEncoder>(this),
-                                      codecParams,
-                                      aNumberOfCores,
-                                      aMaxPayloadSize,
-                                      initDone),
-                       NS_DISPATCH_NORMAL);
-
-  // Since init of the GMP encoder is a multi-step async dispatch (including
-  // dispatches to main), and since this function is invoked on main, there's
-  // no safe way to block until this init is done. If an error occurs, we'll
-  // handle it later.
-  return WEBRTC_VIDEO_CODEC_OK;
-}
-
-/* static */
-void
-WebrtcGmpVideoEncoder::InitEncode_g(
-    const nsRefPtr<WebrtcGmpVideoEncoder>& aThis,
-    const GMPVideoCodec& aCodecParams,
-    int32_t aNumberOfCores,
-    uint32_t aMaxPayloadSize,
-    const nsRefPtr<GmpInitDoneRunnable>& aInitDone)
-{
-  nsTArray<nsCString> tags;
-  tags.AppendElement(NS_LITERAL_CSTRING("h264"));
-  UniquePtr<GetGMPVideoEncoderCallback> callback(
-    new InitDoneCallback(aThis, aInitDone, aCodecParams, aMaxPayloadSize));
-  aThis->mInitting = true;
-  nsresult rv = aThis->mMPS->GetGMPVideoEncoder(&tags,
-                                                NS_LITERAL_CSTRING(""),
-                                                Move(callback));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    LOGD(("GMP Encode: GetGMPVideoEncoder failed"));
-    aThis->Close_g();
-    aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR,
-                        "GMP Encode: GetGMPVideoEncoder failed");
-  }
+  return InitEncoderForSize(aCodecSettings->width, aCodecSettings->height);
 }
 
 int32_t
-WebrtcGmpVideoEncoder::GmpInitDone(GMPVideoEncoderProxy* aGMP,
-                                   GMPVideoHost* aHost,
-                                   std::string* aErrorOut)
-{
-  if (!mInitting || !aGMP || !aHost) {
-    *aErrorOut = "GMP Encode: Either init was aborted, "
-                 "or init failed to supply either a GMP Encoder or GMP host.";
-    if (aGMP) {
-      // This could destroy us, since aGMP may be the last thing holding a ref
-      // Return immediately.
-      aGMP->Close();
-    }
-    return WEBRTC_VIDEO_CODEC_ERROR;
-  }
-
-  mInitting = false;
-
-  if (mGMP && mGMP != aGMP) {
-    Close_g();
-  }
-
-  mGMP = aGMP;
-  mHost = aHost;
-  mCachedPluginId = mGMP->GetPluginId();
-  return WEBRTC_VIDEO_CODEC_OK;
-}
-
-int32_t
-WebrtcGmpVideoEncoder::GmpInitDone(GMPVideoEncoderProxy* aGMP,
-                                   GMPVideoHost* aHost,
-                                   const GMPVideoCodec& aCodecParams,
-                                   uint32_t aMaxPayloadSize,
-                                   std::string* aErrorOut)
-{
-  int32_t r = GmpInitDone(aGMP, aHost, aErrorOut);
-  if (r != WEBRTC_VIDEO_CODEC_OK) {
-    // We might have been destroyed if GmpInitDone failed.
-    // Return immediately.
-    return r;
-  }
-  mCodecParams = aCodecParams;
-  return InitEncoderForSize(aCodecParams.mWidth,
-                            aCodecParams.mHeight,
-                            aErrorOut);
-}
-
-void
-WebrtcGmpVideoEncoder::Close_g()
-{
-  GMPVideoEncoderProxy* gmp(mGMP);
-  mGMP = nullptr;
-  mHost = nullptr;
-  mInitting = false;
-
-  if (gmp) {
-    // Do this last, since this could cause us to be destroyed
-    gmp->Close();
-  }
-}
-
-int32_t
-WebrtcGmpVideoEncoder::InitEncoderForSize(unsigned short aWidth,
-                                          unsigned short aHeight,
-                                          std::string* aErrorOut)
+WebrtcGmpVideoEncoder::InitEncoderForSize(unsigned short aWidth, unsigned short aHeight)
 {
   mCodecParams.mWidth = aWidth;
   mCodecParams.mHeight = aHeight;
   // Pass dummy codecSpecific data for now...
   nsTArray<uint8_t> codecSpecific;
 
   GMPErr err = mGMP->InitEncode(mCodecParams, codecSpecific, this, 1, mMaxPayloadSize);
   if (err != GMPNoErr) {
-    *aErrorOut = "GMP Encode: InitEncode failed";
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 
 int32_t
 WebrtcGmpVideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
                               const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
                               const std::vector<webrtc::VideoFrameType>* aFrameTypes)
 {
+  MOZ_ASSERT(mHost);
+  if (!mGMP) {
+    // destroyed via Terminate()
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+
   MOZ_ASSERT(aInputImage.width() >= 0 && aInputImage.height() >= 0);
-  // Would be really nice to avoid this sync dispatch, but it would require a
-  // copy of the frame, since it doesn't appear to actually have a refcount.
-  mGMPThread->Dispatch(
+  if (static_cast<uint32_t>(aInputImage.width()) != mCodecParams.mWidth ||
+      static_cast<uint32_t>(aInputImage.height()) != mCodecParams.mHeight) {
+    LOGD(("GMP Encode: resolution change from %ux%u to %dx%d",
+          mCodecParams.mWidth, mCodecParams.mHeight, aInputImage.width(), aInputImage.height()));
+
+    nsRefPtr<InitDoneRunnable> initDone(new InitDoneRunnable());
+    nsCOMPtr<nsIRunnable> task(
       WrapRunnable(this,
-                   &WebrtcGmpVideoEncoder::Encode_g,
+                   &WebrtcGmpVideoEncoder::RegetEncoderForResolutionChange,
                    &aInputImage,
-                   aCodecSpecificInfo,
-                   aFrameTypes),
-      NS_DISPATCH_SYNC);
+                   initDone));
+    mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+
+    nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
+    while (!initDone->IsDone()) {
+      NS_ProcessNextEvent(currentThread, true);
+    }
 
-  return WEBRTC_VIDEO_CODEC_OK;
+    if (initDone->Result() != WEBRTC_VIDEO_CODEC_OK) {
+      return initDone->Result();
+    }
+  }
+
+  int32_t ret;
+  mozilla::SyncRunnable::DispatchToThread(mGMPThread,
+                WrapRunnableRet(this,
+                                &WebrtcGmpVideoEncoder::Encode_g,
+                                &aInputImage,
+                                aCodecSpecificInfo,
+                                aFrameTypes,
+                                &ret));
+
+  return ret;
 }
 
 void
-WebrtcGmpVideoEncoder::RegetEncoderForResolutionChange(
-    uint32_t aWidth,
-    uint32_t aHeight,
-    const nsRefPtr<GmpInitDoneRunnable>& aInitDone)
+WebrtcGmpVideoEncoder::RegetEncoderForResolutionChange(const webrtc::I420VideoFrame* aInputImage,
+                                                       InitDoneRunnable* aInitDone)
 {
-  Close_g();
+  mGMP->Close();
 
   UniquePtr<GetGMPVideoEncoderCallback> callback(
-    new InitDoneForResolutionChangeCallback(this,
-                                            aInitDone,
-                                            aWidth,
-                                            aHeight));
+    new InitDoneForResolutionChangeCallback(this, aInitDone,
+                                            aInputImage->width(),
+                                            aInputImage->height()));
 
   // OpenH264 codec (at least) can't handle dynamic input resolution changes
   // re-init the plugin when the resolution changes
   // XXX allow codec to indicate it doesn't need re-init!
   nsTArray<nsCString> tags;
   tags.AppendElement(NS_LITERAL_CSTRING("h264"));
-  mInitting = true;
   if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoEncoder(&tags,
                                                     NS_LITERAL_CSTRING(""),
                                                     Move(callback))))) {
-    aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR,
-                        "GMP Encode: GetGMPVideoEncoder failed");
+    mGMP = nullptr;
+    mHost = nullptr;
+    aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR);
   }
 }
 
 int32_t
 WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
                                 const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
                                 const std::vector<webrtc::VideoFrameType>* aFrameTypes)
 {
-  if (!mGMP) {
-    // destroyed via Terminate(), failed to init, or just not initted yet
-    LOGD(("GMP Encode: not initted yet"));
-    return WEBRTC_VIDEO_CODEC_ERROR;
-  }
   MOZ_ASSERT(mHost);
-
-  if (static_cast<uint32_t>(aInputImage->width()) != mCodecParams.mWidth ||
-      static_cast<uint32_t>(aInputImage->height()) != mCodecParams.mHeight) {
-    LOGD(("GMP Encode: resolution change from %ux%u to %dx%d",
-          mCodecParams.mWidth, mCodecParams.mHeight, aInputImage->width(), aInputImage->height()));
-
-    nsRefPtr<GmpInitDoneRunnable> initDone(new GmpInitDoneRunnable(mPCHandle));
-    RegetEncoderForResolutionChange(aInputImage->width(),
-                                    aInputImage->height(),
-                                    initDone);
-    if (!mGMP) {
-      // We needed to go async to re-get the encoder. Bail.
-      return WEBRTC_VIDEO_CODEC_ERROR;
-    }
-  }
+  MOZ_ASSERT(mGMP);
 
   GMPVideoFrame* ftmp = nullptr;
   GMPErr err = mHost->CreateFrame(kGMPI420VideoFrame, &ftmp);
   if (err != GMPNoErr) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
   GMPUniquePtr<GMPVideoi420Frame> frame(static_cast<GMPVideoi420Frame*>(ftmp));
 
@@ -451,98 +375,93 @@ WebrtcGmpVideoEncoder::Encode_g(const we
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcGmpVideoEncoder::RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback* aCallback)
 {
-  MutexAutoLock lock(mCallbackMutex);
   mCallback = aCallback;
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
-/* static */ void
-WebrtcGmpVideoEncoder::ReleaseGmp_g(nsRefPtr<WebrtcGmpVideoEncoder>& aEncoder)
-{
-  aEncoder->Close_g();
-}
-
 int32_t
-WebrtcGmpVideoEncoder::ReleaseGmp()
+WebrtcGmpVideoEncoder::Release()
 {
   LOGD(("GMP Released:"));
-  if (mGMPThread) {
-    mGMPThread->Dispatch(
-        WrapRunnableNM(&WebrtcGmpVideoEncoder::ReleaseGmp_g,
-                       nsRefPtr<WebrtcGmpVideoEncoder>(this)),
-        NS_DISPATCH_NORMAL);
+  // Note: we only use SyncRunnables to access mGMP
+  // Callbacks may occur at any time until we call Close (or receive
+  // Terminated()), so call Close here synchronously.
+  if (mGMPThread && mGMP) {
+    mozilla::SyncRunnable::DispatchToThread(mGMPThread,
+                                            WrapRunnableNM(&Encoder_Close_g, mGMP));
   }
+  // Now safe to forget things
+  mMPS = nullptr;
+  mGMP = nullptr;
+  mHost = nullptr;
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcGmpVideoEncoder::SetChannelParameters(uint32_t aPacketLoss, int aRTT)
 {
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcGmpVideoEncoder::SetRates(uint32_t aNewBitRate, uint32_t aFrameRate)
 {
+  int32_t ret;
   MOZ_ASSERT(mGMPThread);
-  MOZ_ASSERT(!NS_IsMainThread());
-  mGMPThread->Dispatch(WrapRunnableNM(&WebrtcGmpVideoEncoder::SetRates_g,
-                                      nsRefPtr<WebrtcGmpVideoEncoder>(this),
-                                      aNewBitRate,
-                                      aFrameRate),
-                       NS_DISPATCH_NORMAL);
+  mozilla::SyncRunnable::DispatchToThread(mGMPThread,
+                WrapRunnableRet(this,
+                                &WebrtcGmpVideoEncoder::SetRates_g,
+                                aNewBitRate, aFrameRate,
+                                &ret));
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
-/* static */ int32_t
-WebrtcGmpVideoEncoder::SetRates_g(nsRefPtr<WebrtcGmpVideoEncoder> aThis,
-                                  uint32_t aNewBitRate,
-                                  uint32_t aFrameRate)
+int32_t
+WebrtcGmpVideoEncoder::SetRates_g(uint32_t aNewBitRate, uint32_t aFrameRate)
 {
-  if (!aThis->mGMP) {
+  if (!mGMP) {
     // destroyed via Terminate()
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
-  GMPErr err = aThis->mGMP->SetRates(aNewBitRate, aFrameRate);
+  GMPErr err = mGMP->SetRates(aNewBitRate, aFrameRate);
   if (err != GMPNoErr) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 // GMPVideoEncoderCallback virtual functions.
 void
 WebrtcGmpVideoEncoder::Terminated()
 {
   LOGD(("GMP Encoder Terminated: %p", (void *)this));
+  mCachedPluginId = PluginID();
 
+  // We need to drop our reference to this
   mGMP->Close();
   mGMP = nullptr;
-  mHost = nullptr;
-  mInitting = false;
   // Could now notify that it's dead
 }
 
 void
 WebrtcGmpVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
                                const nsTArray<uint8_t>& aCodecSpecificInfo)
 {
-  MutexAutoLock lock(mCallbackMutex);
-  if (mCallback) {
+  if (mCallback) { // paranoia
     webrtc::VideoFrameType ft;
     GmpFrameTypeToWebrtcFrameType(aEncodedFrame->FrameType(), &ft);
     uint32_t timestamp = (aEncodedFrame->TimeStamp() * 90ll + 999)/1000;
 
     LOGD(("GMP Encoded: %llu, type %d, len %d",
          aEncodedFrame->TimeStamp(),
          aEncodedFrame->BufferType(),
          aEncodedFrame->Size()));
@@ -642,162 +561,135 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoE
       }
 
       webrtc::EncodedImage unit(aEncodedFrame->Buffer(), size, size);
       unit._frameType = ft;
       unit._timeStamp = timestamp;
       unit._completeFrame = true;
 
       mCallback->Encoded(unit, nullptr, &fragmentation);
+
     }
   }
 }
 
 // Decoder.
 WebrtcGmpVideoDecoder::WebrtcGmpVideoDecoder() :
   mGMP(nullptr),
-  mInitting(false),
   mHost(nullptr),
-  mCallbackMutex("WebrtcGmpVideoDecoder decoded callback mutex"),
   mCallback(nullptr),
   mCachedPluginId(0),
-  mDecoderStatus(GMPNoErr)
+  mDecoderStatus(GMPNoErr){}
+
+static void
+Decoder_Close_g(GMPVideoDecoderProxy* aGMP)
 {
-#ifdef MOZILLA_INTERNAL_API
-  if (mPCHandle.empty()) {
-    mPCHandle = WebrtcGmpPCHandleSetter::GetCurrentHandle();
-  }
-  MOZ_ASSERT(!mPCHandle.empty());
-#endif
+  aGMP->Close();
 }
 
 WebrtcGmpVideoDecoder::~WebrtcGmpVideoDecoder()
 {
-  // We should not have been destroyed if we never closed our GMP
-  MOZ_ASSERT(!mGMP);
+  // Note: we only use SyncRunnables to access mGMP
+  // Callbacks may occur at any time until we call Close (or receive
+  // Terminated()), so call Close here synchronously.
+  // Do NOT touch the refcount of 'this'!
+  if (mGMPThread && mGMP) {
+    mozilla::SyncRunnable::DispatchToThread(mGMPThread,
+                                            WrapRunnableNM(&Decoder_Close_g, mGMP));
+    mGMP = nullptr;
+  }
 }
 
 int32_t
 WebrtcGmpVideoDecoder::InitDecode(const webrtc::VideoCodec* aCodecSettings,
                                   int32_t aNumberOfCores)
 {
-  if (!mMPS) {
-    mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
-  }
+  mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   MOZ_ASSERT(mMPS);
 
   if (!mGMPThread) {
     if (NS_WARN_IF(NS_FAILED(mMPS->GetThread(getter_AddRefs(mGMPThread))))) {
       return WEBRTC_VIDEO_CODEC_ERROR;
     }
   }
 
-  nsRefPtr<GmpInitDoneRunnable> initDone(new GmpInitDoneRunnable(mPCHandle));
-  mGMPThread->Dispatch(WrapRunnableNM(&WebrtcGmpVideoDecoder::InitDecode_g,
-                                      nsRefPtr<WebrtcGmpVideoDecoder>(this),
-                                      aCodecSettings,
-                                      aNumberOfCores,
-                                      initDone),
+  nsRefPtr<InitDoneRunnable> initDone(new InitDoneRunnable());
+  mGMPThread->Dispatch(WrapRunnable(this,
+                                    &WebrtcGmpVideoDecoder::InitDecode_g,
+                                    aCodecSettings,
+                                    aNumberOfCores,
+                                    initDone.get()),
                        NS_DISPATCH_NORMAL);
 
-  return WEBRTC_VIDEO_CODEC_OK;
+  nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
+  while (!initDone->IsDone()) {
+    NS_ProcessNextEvent(currentThread, true);
+  }
+
+  return initDone->Result();
 }
 
-/* static */ void
-WebrtcGmpVideoDecoder::InitDecode_g(
-    const nsRefPtr<WebrtcGmpVideoDecoder>& aThis,
-    const webrtc::VideoCodec* aCodecSettings,
-    int32_t aNumberOfCores,
-    const nsRefPtr<GmpInitDoneRunnable>& aInitDone)
+void
+WebrtcGmpVideoDecoder::InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
+                                    int32_t aNumberOfCores,
+                                    InitDoneRunnable* aInitDone)
 {
   nsTArray<nsCString> tags;
   tags.AppendElement(NS_LITERAL_CSTRING("h264"));
   UniquePtr<GetGMPVideoDecoderCallback> callback(
-    new InitDoneCallback(aThis, aInitDone));
-  aThis->mInitting = true;
-  nsresult rv = aThis->mMPS->GetGMPVideoDecoder(&tags,
-                                                NS_LITERAL_CSTRING(""),
-                                                Move(callback));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    LOGD(("GMP Decode: GetGMPVideoDecoder failed"));
-    aThis->Close_g();
-    aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR,
-                        "GMP Decode: GetGMPVideoDecoder failed.");
+    new InitDoneCallback(this, aInitDone));
+  if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoDecoder(&tags,
+                                                    NS_LITERAL_CSTRING(""),
+                                                    Move(callback))))) {
+    mMPS = nullptr;
+    mGMP = nullptr;
+    mGMPThread = nullptr;
+    mHost = nullptr;
+    aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR);
   }
 }
 
 int32_t
 WebrtcGmpVideoDecoder::GmpInitDone(GMPVideoDecoderProxy* aGMP,
-                                   GMPVideoHost* aHost,
-                                   std::string* aErrorOut)
+                                   GMPVideoHost* aHost)
 {
-  if (!mInitting || !aGMP || !aHost) {
-    *aErrorOut = "GMP Decode: Either init was aborted, "
-                 "or init failed to supply either a GMP decoder or GMP host.";
-    if (aGMP) {
-      // This could destroy us, since aGMP may be the last thing holding a ref
-      // Return immediately.
-      aGMP->Close();
-    }
+  mGMP = aGMP;
+  mHost = aHost;
+  mMPS = nullptr;
+
+  if (!mGMP || !mHost) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
-  mInitting = false;
-
-  if (mGMP && mGMP != aGMP) {
-    Close_g();
-  }
-
-  mGMP = aGMP;
-  mHost = aHost;
-  mCachedPluginId = mGMP->GetPluginId();
   // Bug XXXXXX: transfer settings from codecSettings to codec.
   GMPVideoCodec codec;
   memset(&codec, 0, sizeof(codec));
   codec.mGMPApiVersion = 33;
 
   // XXX this is currently a hack
   //GMPVideoCodecUnion codecSpecific;
   //memset(&codecSpecific, 0, sizeof(codecSpecific));
   nsTArray<uint8_t> codecSpecific;
   nsresult rv = mGMP->InitDecode(codec, codecSpecific, this, 1);
   if (NS_FAILED(rv)) {
-    *aErrorOut = "GMP Decode: InitDecode failed";
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
-void
-WebrtcGmpVideoDecoder::Close_g()
-{
-  GMPVideoDecoderProxy* gmp(mGMP);
-  mGMP = nullptr;
-  mHost = nullptr;
-  mInitting = false;
-
-  if (gmp) {
-    // Do this last, since this could cause us to be destroyed
-    gmp->Close();
-  }
-}
-
 int32_t
 WebrtcGmpVideoDecoder::Decode(const webrtc::EncodedImage& aInputImage,
                               bool aMissingFrames,
                               const webrtc::RTPFragmentationHeader* aFragmentation,
                               const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
                               int64_t aRenderTimeMs)
 {
   int32_t ret;
   MOZ_ASSERT(mGMPThread);
-  MOZ_ASSERT(!NS_IsMainThread());
-  // Would be really nice to avoid this sync dispatch, but it would require a
-  // copy of the frame, since it doesn't appear to actually have a refcount.
   mozilla::SyncRunnable::DispatchToThread(mGMPThread,
                 WrapRunnableRet(this,
                                 &WebrtcGmpVideoDecoder::Decode_g,
                                 aInputImage,
                                 aMissingFrames,
                                 aFragmentation,
                                 aCodecSpecificInfo,
                                 aRenderTimeMs,
@@ -808,22 +700,21 @@ WebrtcGmpVideoDecoder::Decode(const webr
 
 int32_t
 WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage,
                                 bool aMissingFrames,
                                 const webrtc::RTPFragmentationHeader* aFragmentation,
                                 const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
                                 int64_t aRenderTimeMs)
 {
+  MOZ_ASSERT(mHost);
   if (!mGMP) {
-    // destroyed via Terminate(), failed to init, or just not initted yet
-    LOGD(("GMP Decode: not initted yet"));
+    // destroyed via Terminate()
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
-  MOZ_ASSERT(mHost);
 
   if (!aInputImage._length) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
   GMPVideoFrame* ftmp = nullptr;
   GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
   if (err != GMPNoErr) {
@@ -876,66 +767,62 @@ WebrtcGmpVideoDecoder::Decode_g(const we
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcGmpVideoDecoder::RegisterDecodeCompleteCallback( webrtc::DecodedImageCallback* aCallback)
 {
-  MutexAutoLock lock(mCallbackMutex);
   mCallback = aCallback;
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 
-/* static */ void
-WebrtcGmpVideoDecoder::ReleaseGmp_g(nsRefPtr<WebrtcGmpVideoDecoder>& aDecoder)
+int32_t
+WebrtcGmpVideoDecoder::Release()
 {
-  aDecoder->Close_g();
-}
-
-int32_t
-WebrtcGmpVideoDecoder::ReleaseGmp()
-{
-  LOGD(("GMP Released:"));
-  if (mGMPThread) {
-    mGMPThread->Dispatch(
-        WrapRunnableNM(&WebrtcGmpVideoDecoder::ReleaseGmp_g,
-                       nsRefPtr<WebrtcGmpVideoDecoder>(this)),
-        NS_DISPATCH_NORMAL);
+  // Note: we only use SyncRunnables to access mGMP
+  // Callbacks may occur at any time until we call Close (or receive
+  // Terminated()), so call Close here synchronously.
+  if (mGMPThread && mGMP) {
+    mozilla::SyncRunnable::DispatchToThread(mGMPThread,
+                                            WrapRunnableNM(&Decoder_Close_g, mGMP));
   }
+  // Now safe to forget things
+  mMPS = nullptr;
+  mGMP = nullptr;
+  mGMPThread = nullptr;
+  mHost = nullptr;
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcGmpVideoDecoder::Reset()
 {
   // XXX ?
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 void
 WebrtcGmpVideoDecoder::Terminated()
 {
   LOGD(("GMP Decoder Terminated: %p", (void *)this));
+  mCachedPluginId = PluginID();
 
   mGMP->Close();
   mGMP = nullptr;
-  mHost = nullptr;
-  mInitting = false;
   // Could now notify that it's dead
 }
 
 void
 WebrtcGmpVideoDecoder::Decoded(GMPVideoi420Frame* aDecodedFrame)
 {
-  MutexAutoLock lock(mCallbackMutex);
-  if (mCallback) {
+  if (mCallback) { // paranioa
     webrtc::I420VideoFrame image;
     int ret = image.CreateFrame(aDecodedFrame->AllocatedSize(kGMPYPlane),
                                 aDecodedFrame->Buffer(kGMPYPlane),
                                 aDecodedFrame->AllocatedSize(kGMPUPlane),
                                 aDecodedFrame->Buffer(kGMPUPlane),
                                 aDecodedFrame->AllocatedSize(kGMPVPlane),
                                 aDecodedFrame->Buffer(kGMPVPlane),
                                 aDecodedFrame->Width(),
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
@@ -14,359 +14,242 @@
  */
 
 
 #ifndef WEBRTCGMPVIDEOCODEC_H_
 #define WEBRTCGMPVIDEOCODEC_H_
 
 #include <iostream>
 #include <queue>
-#include <string>
 
 #include "nsThreadUtils.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Mutex.h"
 
 #include "mozIGeckoMediaPluginService.h"
 #include "MediaConduitInterface.h"
 #include "AudioConduit.h"
 #include "VideoConduit.h"
 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
 
 #include "gmp-video-host.h"
 #include "GMPVideoDecoderProxy.h"
 #include "GMPVideoEncoderProxy.h"
 
-#include "PeerConnectionImpl.h"
-
 namespace mozilla {
 
-// Class that allows code on the other side of webrtc.org to tell
-// WebrtcGmpVideoEncoder/Decoder what PC they should send errors to.
-// This is necessary because webrtc.org gives us no way to plumb the handle
-// through, nor does it give us any way to inform it of an error that will
-// make it back to the PC that cares (except for errors encountered
-// synchronously in functions like InitEncode/Decode, which will not happen
-// because GMP init is async).
-// Right now, this is used in MediaPipelineFactory.
-class WebrtcGmpPCHandleSetter
+class WebrtcGmpVideoEncoder : public WebrtcVideoEncoder,
+                              public GMPVideoEncoderCallbackProxy
 {
-  public:
-    explicit WebrtcGmpPCHandleSetter(const std::string& aPCHandle);
+public:
+  WebrtcGmpVideoEncoder();
+  virtual ~WebrtcGmpVideoEncoder();
+
+  // Implement VideoEncoder interface.
+  virtual const uint64_t PluginID() override
+  {
+    return mGMP ? mGMP->GetPluginId() : mCachedPluginId;
+  }
+
+  virtual void Terminated() override;
+
+  virtual int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
+                             int32_t aNumberOfCores,
+                             uint32_t aMaxPayloadSize) override;
+
+  virtual int32_t Encode(const webrtc::I420VideoFrame& aInputImage,
+                         const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
+                         const std::vector<webrtc::VideoFrameType>* aFrameTypes) override;
 
-    ~WebrtcGmpPCHandleSetter();
+  virtual int32_t RegisterEncodeCompleteCallback(
+    webrtc::EncodedImageCallback* aCallback) override;
+
+  virtual int32_t Release() override;
 
-    static std::string GetCurrentHandle();
+  virtual int32_t SetChannelParameters(uint32_t aPacketLoss,
+                                       int aRTT) override;
+
+  virtual int32_t SetRates(uint32_t aNewBitRate,
+                           uint32_t aFrameRate) override;
 
-  private:
-    static std::string sCurrentHandle;
-};
+  // GMPVideoEncoderCallback virtual functions.
+  virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
+                       const nsTArray<uint8_t>& aCodecSpecificInfo) override;
+
+  virtual void Error(GMPErr aError) override {
+  }
 
-class GmpInitDoneRunnable : public nsRunnable
-{
+private:
+  class InitDoneRunnable : public nsRunnable
+  {
   public:
-    explicit GmpInitDoneRunnable(const std::string& aPCHandle) :
-      mResult(WEBRTC_VIDEO_CODEC_OK),
-      mPCHandle(aPCHandle)
+    InitDoneRunnable()
+      : mInitDone(false),
+        mResult(WEBRTC_VIDEO_CODEC_OK),
+        mThread(do_GetCurrentThread())
     {
     }
 
     NS_IMETHOD Run()
     {
-      if (mResult == WEBRTC_VIDEO_CODEC_OK) {
-        // Might be useful to notify the PeerConnection about successful init
-        // someday.
-        return NS_OK;
-      }
-
-      PeerConnectionWrapper wrapper(mPCHandle);
-      if (wrapper.impl()) {
-        wrapper.impl()->OnMediaError(mError);
-      }
+      MOZ_ASSERT(mThread == nsCOMPtr<nsIThread>(do_GetCurrentThread()));
+      mInitDone = true;
       return NS_OK;
     }
 
-    void Dispatch(int32_t aResult, const std::string& aError = "")
+    void Dispatch(int32_t aResult)
     {
       mResult = aResult;
-      mError = aError;
-      nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
-      if (mainThread) {
-        // For some reason, the compiler on CI is treating |this| as a const
-        // pointer, despite the fact that we're in a non-const function. And,
-        // interestingly enough, correcting this doesn't require a const_cast.
-        mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
-      }
+      mThread->Dispatch(this, NS_DISPATCH_NORMAL);
+    }
+
+    bool IsDone()
+    {
+      MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
+      return mInitDone;
     }
 
     int32_t Result()
     {
       return mResult;
     }
 
   private:
+    bool mInitDone;
     int32_t mResult;
-    std::string mPCHandle;
-    std::string mError;
-};
-
-class WebrtcGmpVideoEncoder : public GMPVideoEncoderCallbackProxy
-{
-public:
-  WebrtcGmpVideoEncoder();
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcGmpVideoEncoder);
-
-  // Implement VideoEncoder interface, sort of.
-  // (We cannot use |Release|, since that's needed for nsRefPtr)
-  virtual const uint64_t PluginID()
-  {
-    return mCachedPluginId;
-  }
-
-  virtual int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
-                             int32_t aNumberOfCores,
-                             uint32_t aMaxPayloadSize);
-
-  virtual int32_t Encode(const webrtc::I420VideoFrame& aInputImage,
-                         const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
-                         const std::vector<webrtc::VideoFrameType>* aFrameTypes);
-
-  virtual int32_t RegisterEncodeCompleteCallback(
-    webrtc::EncodedImageCallback* aCallback);
-
-  virtual int32_t ReleaseGmp();
+    nsCOMPtr<nsIThread> mThread;
+  };
 
-  virtual int32_t SetChannelParameters(uint32_t aPacketLoss,
-                                       int aRTT);
-
-  virtual int32_t SetRates(uint32_t aNewBitRate,
-                           uint32_t aFrameRate);
-
-  // GMPVideoEncoderCallback virtual functions.
-  virtual void Terminated() override;
-
-  virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
-                       const nsTArray<uint8_t>& aCodecSpecificInfo) override;
-
-  virtual void Error(GMPErr aError) override {
-  }
-
-private:
-  virtual ~WebrtcGmpVideoEncoder();
-
-  static void InitEncode_g(const nsRefPtr<WebrtcGmpVideoEncoder>& aThis,
-                           const GMPVideoCodec& aCodecParams,
-                           int32_t aNumberOfCores,
-                           uint32_t aMaxPayloadSize,
-                           const nsRefPtr<GmpInitDoneRunnable>& aInitDone);
+  void InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
+                    int32_t aNumberOfCores,
+                    uint32_t aMaxPayloadSize,
+                    InitDoneRunnable* aInitDone);
   int32_t GmpInitDone(GMPVideoEncoderProxy* aGMP, GMPVideoHost* aHost,
-                      const GMPVideoCodec& aCodecParams,
-                      uint32_t aMaxPayloadSize,
-                      std::string* aErrorOut);
-  int32_t GmpInitDone(GMPVideoEncoderProxy* aGMP,
-                      GMPVideoHost* aHost,
-                      std::string* aErrorOut);
-  int32_t InitEncoderForSize(unsigned short aWidth,
-                             unsigned short aHeight,
-                             std::string* aErrorOut);
-  static void ReleaseGmp_g(nsRefPtr<WebrtcGmpVideoEncoder>& aEncoder);
-  void Close_g();
+                      const webrtc::VideoCodec* aCodecSettings,
+                      uint32_t aMaxPayloadSize);
+  int32_t InitEncoderForSize(unsigned short aWidth, unsigned short aHeight);
 
   class InitDoneCallback : public GetGMPVideoEncoderCallback
   {
   public:
-    InitDoneCallback(const nsRefPtr<WebrtcGmpVideoEncoder>& aEncoder,
-                     const nsRefPtr<GmpInitDoneRunnable>& aInitDone,
-                     const GMPVideoCodec& aCodecParams,
+    InitDoneCallback(WebrtcGmpVideoEncoder* aEncoder,
+                     InitDoneRunnable* aInitDone,
+                     const webrtc::VideoCodec* aCodecSettings,
                      uint32_t aMaxPayloadSize)
       : mEncoder(aEncoder),
         mInitDone(aInitDone),
-        mCodecParams(aCodecParams),
+        mCodecSettings(aCodecSettings),
         mMaxPayloadSize(aMaxPayloadSize)
     {
     }
 
     virtual void Done(GMPVideoEncoderProxy* aGMP, GMPVideoHost* aHost) override
     {
-      std::string errorOut;
-      int32_t result = mEncoder->GmpInitDone(aGMP,
-                                             aHost,
-                                             mCodecParams,
-                                             mMaxPayloadSize,
-                                             &errorOut);
+      mEncoder->mGMP = aGMP;
+      mEncoder->mHost = aHost;
+      int32_t result;
+      if (aGMP || aHost) {
+        result = mEncoder->GmpInitDone(aGMP, aHost, mCodecSettings,
+                                       mMaxPayloadSize);
+      } else {
+        result = WEBRTC_VIDEO_CODEC_ERROR;
+      }
 
-      mInitDone->Dispatch(result, errorOut);
+      mInitDone->Dispatch(result);
     }
 
   private:
-    nsRefPtr<WebrtcGmpVideoEncoder> mEncoder;
-    nsRefPtr<GmpInitDoneRunnable> mInitDone;
-    GMPVideoCodec mCodecParams;
+    WebrtcGmpVideoEncoder* mEncoder;
+    nsRefPtr<InitDoneRunnable> mInitDone;
+    const webrtc::VideoCodec* mCodecSettings;
     uint32_t mMaxPayloadSize;
   };
 
   int32_t Encode_g(const webrtc::I420VideoFrame* aInputImage,
                    const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
                    const std::vector<webrtc::VideoFrameType>* aFrameTypes);
-  void RegetEncoderForResolutionChange(
-      uint32_t aWidth,
-      uint32_t aHeight,
-      const nsRefPtr<GmpInitDoneRunnable>& aInitDone);
+  void RegetEncoderForResolutionChange(const webrtc::I420VideoFrame* aInputImage,
+                                       InitDoneRunnable* aInitDone);
 
   class InitDoneForResolutionChangeCallback : public GetGMPVideoEncoderCallback
   {
   public:
-    InitDoneForResolutionChangeCallback(
-        const nsRefPtr<WebrtcGmpVideoEncoder>& aEncoder,
-        const nsRefPtr<GmpInitDoneRunnable>& aInitDone,
-        uint32_t aWidth,
-        uint32_t aHeight)
+    InitDoneForResolutionChangeCallback(WebrtcGmpVideoEncoder* aEncoder,
+                                        InitDoneRunnable* aInitDone,
+                                        uint32_t aWidth,
+                                        uint32_t aHeight)
       : mEncoder(aEncoder),
         mInitDone(aInitDone),
         mWidth(aWidth),
         mHeight(aHeight)
     {
     }
 
     virtual void Done(GMPVideoEncoderProxy* aGMP, GMPVideoHost* aHost) override
     {
-      std::string errorOut;
-      int32_t result = mEncoder->GmpInitDone(aGMP, aHost, &errorOut);
-      if (result != WEBRTC_VIDEO_CODEC_OK) {
-        mInitDone->Dispatch(result, errorOut);
-        return;
+      mEncoder->mGMP = aGMP;
+      mEncoder->mHost = aHost;
+      int32_t result;
+      if (aGMP && aHost) {
+        result = mEncoder->InitEncoderForSize(mWidth, mHeight);
+      } else {
+        result = WEBRTC_VIDEO_CODEC_ERROR;
       }
 
-      result = mEncoder->InitEncoderForSize(mWidth, mHeight, &errorOut);
-      mInitDone->Dispatch(result, errorOut);
+      mInitDone->Dispatch(result);
     }
 
   private:
-    nsRefPtr<WebrtcGmpVideoEncoder> mEncoder;
-    nsRefPtr<GmpInitDoneRunnable> mInitDone;
+    WebrtcGmpVideoEncoder* mEncoder;
+    nsRefPtr<InitDoneRunnable> mInitDone;
     uint32_t mWidth;
     uint32_t mHeight;
   };
 
-  static int32_t SetRates_g(nsRefPtr<WebrtcGmpVideoEncoder> aThis,
-                             uint32_t aNewBitRate,
+  virtual int32_t SetRates_g(uint32_t aNewBitRate,
                              uint32_t aFrameRate);
 
   nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
   nsCOMPtr<nsIThread> mGMPThread;
   GMPVideoEncoderProxy* mGMP;
-  // Used to handle a race where Release() is called while init is in progress
-  bool mInitting;
   GMPVideoHost* mHost;
   GMPVideoCodec mCodecParams;
   uint32_t mMaxPayloadSize;
-  // Protects mCallback
-  Mutex mCallbackMutex;
   webrtc::EncodedImageCallback* mCallback;
   uint64_t mCachedPluginId;
-  std::string mPCHandle;
 };
 
 
-// Basically a strong ref to a WebrtcGmpVideoEncoder, that also translates
-// from Release() to WebrtcGmpVideoEncoder::ReleaseGmp(), since we need
-// WebrtcGmpVideoEncoder::Release() for managing the refcount.
-// The webrtc.org code gets one of these, so it doesn't unilaterally delete
-// the "real" encoder.
-class WebrtcVideoEncoderProxy : public WebrtcVideoEncoder
-{
-  public:
-    WebrtcVideoEncoderProxy() :
-      mEncoderImpl(new WebrtcGmpVideoEncoder)
-    {}
-
-    virtual ~WebrtcVideoEncoderProxy()
-    {
-      RegisterEncodeCompleteCallback(nullptr);
-    }
-
-    const uint64_t PluginID() override
-    {
-      return mEncoderImpl->PluginID();
-    }
-
-    int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
-                       int32_t aNumberOfCores,
-                       uint32_t aMaxPayloadSize) override
-    {
-      return mEncoderImpl->InitEncode(aCodecSettings,
-                                      aNumberOfCores,
-                                      aMaxPayloadSize);
-    }
-
-    int32_t Encode(
-        const webrtc::I420VideoFrame& aInputImage,
-        const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
-        const std::vector<webrtc::VideoFrameType>* aFrameTypes) override
-    {
-      return mEncoderImpl->Encode(aInputImage,
-                                  aCodecSpecificInfo,
-                                  aFrameTypes);
-    }
-
-    int32_t RegisterEncodeCompleteCallback(
-      webrtc::EncodedImageCallback* aCallback) override
-    {
-      return mEncoderImpl->RegisterEncodeCompleteCallback(aCallback);
-    }
-
-    int32_t Release() override
-    {
-      return mEncoderImpl->ReleaseGmp();
-    }
-
-    int32_t SetChannelParameters(uint32_t aPacketLoss,
-                                 int aRTT) override
-    {
-      return mEncoderImpl->SetChannelParameters(aPacketLoss, aRTT);
-    }
-
-    int32_t SetRates(uint32_t aNewBitRate,
-                     uint32_t aFrameRate) override
-    {
-      return mEncoderImpl->SetRates(aNewBitRate, aFrameRate);
-    }
-
-  private:
-    nsRefPtr<WebrtcGmpVideoEncoder> mEncoderImpl;
-};
-
-class WebrtcGmpVideoDecoder : public GMPVideoDecoderCallbackProxy
+class WebrtcGmpVideoDecoder : public WebrtcVideoDecoder,
+                              public GMPVideoDecoderCallbackProxy
 {
 public:
   WebrtcGmpVideoDecoder();
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcGmpVideoDecoder);
+  virtual ~WebrtcGmpVideoDecoder();
 
-  // Implement VideoEncoder interface, sort of.
-  // (We cannot use |Release|, since that's needed for nsRefPtr)
-  virtual const uint64_t PluginID()
+  // Implement VideoDecoder interface.
+  virtual const uint64_t PluginID() override
   {
-    return mCachedPluginId;
+    return mGMP ? mGMP->GetPluginId() : mCachedPluginId;
   }
 
+  virtual void Terminated() override;
+
   virtual int32_t InitDecode(const webrtc::VideoCodec* aCodecSettings,
-                             int32_t aNumberOfCores);
+                             int32_t aNumberOfCores) override;
   virtual int32_t Decode(const webrtc::EncodedImage& aInputImage,
                          bool aMissingFrames,
                          const webrtc::RTPFragmentationHeader* aFragmentation,
-                         const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
-                         int64_t aRenderTimeMs);
-  virtual int32_t RegisterDecodeCompleteCallback(webrtc::DecodedImageCallback* aCallback);
+                         const webrtc::CodecSpecificInfo* aCodecSpecificInfo = nullptr,
+                         int64_t aRenderTimeMs = -1) override;
+  virtual int32_t RegisterDecodeCompleteCallback(webrtc::DecodedImageCallback* aCallback) override;
 
-  virtual int32_t ReleaseGmp();
+  virtual int32_t Release() override;
 
-  virtual int32_t Reset();
-
-  // GMPVideoDecoderCallbackProxy
-  virtual void Terminated() override;
+  virtual int32_t Reset() override;
 
   virtual void Decoded(GMPVideoi420Frame* aDecodedFrame) override;
 
   virtual void ReceivedDecodedReferenceFrame(const uint64_t aPictureId) override {
     MOZ_CRASH();
   }
 
   virtual void ReceivedDecodedFrame(const uint64_t aPictureId) override {
@@ -382,129 +265,93 @@ public:
   virtual void ResetComplete() override {
   }
 
   virtual void Error(GMPErr aError) override {
      mDecoderStatus = aError;
   }
 
 private:
-  virtual ~WebrtcGmpVideoDecoder();
+  class InitDoneRunnable : public nsRunnable
+  {
+  public:
+    InitDoneRunnable()
+      : mInitDone(false),
+        mResult(WEBRTC_VIDEO_CODEC_OK),
+        mThread(do_GetCurrentThread())
+    {
+    }
+
+    NS_IMETHOD Run()
+    {
+      MOZ_ASSERT(mThread == nsCOMPtr<nsIThread>(do_GetCurrentThread()));
+      mInitDone = true;
+      return NS_OK;
+    }
 
-  static void InitDecode_g(
-      const nsRefPtr<WebrtcGmpVideoDecoder>& aThis,
-      const webrtc::VideoCodec* aCodecSettings,
-      int32_t aNumberOfCores,
-      const nsRefPtr<GmpInitDoneRunnable>& aInitDone);
-  int32_t GmpInitDone(GMPVideoDecoderProxy* aGMP,
-                      GMPVideoHost* aHost,
-                      std::string* aErrorOut);
-  static void ReleaseGmp_g(nsRefPtr<WebrtcGmpVideoDecoder>& aDecoder);
-  void Close_g();
+    void Dispatch(int32_t aResult)
+    {
+      mResult = aResult;
+      mThread->Dispatch(this, NS_DISPATCH_NORMAL);
+    }
+
+    bool IsDone()
+    {
+      MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
+      return mInitDone;
+    }
+
+    int32_t Result()
+    {
+      return mResult;
+    }
+
+  private:
+    bool mInitDone;
+    int32_t mResult;
+    nsCOMPtr<nsIThread> mThread;
+  };
+
+  void InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
+                    int32_t aNumberOfCores,
+                    InitDoneRunnable* aInitDone);
+  int32_t GmpInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost);
 
   class InitDoneCallback : public GetGMPVideoDecoderCallback
   {
   public:
     explicit InitDoneCallback(WebrtcGmpVideoDecoder* aDecoder,
-                              const nsRefPtr<GmpInitDoneRunnable>& aInitDone)
+                              InitDoneRunnable* aInitDone)
       : mDecoder(aDecoder),
         mInitDone(aInitDone)
     {
     }
 
     virtual void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost)
     {
-      std::string errorOut;
-      int32_t result = mDecoder->GmpInitDone(aGMP, aHost, &errorOut);
+      int32_t result = mDecoder->GmpInitDone(aGMP, aHost);
 
-      mInitDone->Dispatch(result, errorOut);
+      mInitDone->Dispatch(result);
     }
 
   private:
     WebrtcGmpVideoDecoder* mDecoder;
-    nsRefPtr<GmpInitDoneRunnable> mInitDone;
-  };
+    nsRefPtr<InitDoneRunnable> mInitDone;
+};
 
   virtual int32_t Decode_g(const webrtc::EncodedImage& aInputImage,
                            bool aMissingFrames,
                            const webrtc::RTPFragmentationHeader* aFragmentation,
                            const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
                            int64_t aRenderTimeMs);
 
   nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
   nsCOMPtr<nsIThread> mGMPThread;
   GMPVideoDecoderProxy* mGMP; // Addref is held for us
-  // Used to handle a race where Release() is called while init is in progress
-  bool mInitting;
   GMPVideoHost* mHost;
-  // Protects mCallback
-  Mutex mCallbackMutex;
   webrtc::DecodedImageCallback* mCallback;
-  Atomic<uint64_t> mCachedPluginId;
+  uint64_t mCachedPluginId;
   GMPErr mDecoderStatus;
-  std::string mPCHandle;
-};
-
-// Basically a strong ref to a WebrtcGmpVideoDecoder, that also translates
-// from Release() to WebrtcGmpVideoDecoder::ReleaseGmp(), since we need
-// WebrtcGmpVideoDecoder::Release() for managing the refcount.
-// The webrtc.org code gets one of these, so it doesn't unilaterally delete
-// the "real" encoder.
-class WebrtcVideoDecoderProxy : public WebrtcVideoDecoder
-{
-  public:
-    WebrtcVideoDecoderProxy() :
-      mDecoderImpl(new WebrtcGmpVideoDecoder)
-    {}
-
-    virtual ~WebrtcVideoDecoderProxy()
-    {
-      RegisterDecodeCompleteCallback(nullptr);
-    }
-
-    const uint64_t PluginID() override
-    {
-      return mDecoderImpl->PluginID();
-    }
-
-    int32_t InitDecode(const webrtc::VideoCodec* aCodecSettings,
-                       int32_t aNumberOfCores) override
-    {
-      return mDecoderImpl->InitDecode(aCodecSettings, aNumberOfCores);
-    }
-
-    int32_t Decode(
-        const webrtc::EncodedImage& aInputImage,
-        bool aMissingFrames,
-        const webrtc::RTPFragmentationHeader* aFragmentation,
-        const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
-        int64_t aRenderTimeMs) override
-    {
-      return mDecoderImpl->Decode(aInputImage,
-                                  aMissingFrames,
-                                  aFragmentation,
-                                  aCodecSpecificInfo,
-                                  aRenderTimeMs);
-    }
-
-    int32_t RegisterDecodeCompleteCallback(
-      webrtc::DecodedImageCallback* aCallback) override
-    {
-      return mDecoderImpl->RegisterDecodeCompleteCallback(aCallback);
-    }
-
-    int32_t Release() override
-    {
-      return mDecoderImpl->ReleaseGmp();
-    }
-
-    int32_t Reset() override
-    {
-      return mDecoderImpl->Reset();
-    }
-
-  private:
-    nsRefPtr<WebrtcGmpVideoDecoder> mDecoderImpl;
 };
 
 }
 
 #endif
--- a/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
+++ b/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
@@ -35,20 +35,16 @@
 #ifdef MOZ_WEBRTC_MEDIACODEC
 #include "MediaCodecVideoCodec.h"
 #endif
 
 #ifdef MOZILLA_INTERNAL_API
 #include "mozilla/Preferences.h"
 #endif
 
-#if !defined(MOZILLA_EXTERNAL_LINKAGE)
-#include "WebrtcGmpVideoCodec.h"
-#endif
-
 #include <stdlib.h>
 
 namespace mozilla {
 
 MOZ_MTLOG_MODULE("MediaPipelineFactory")
 
 static nsresult
 JsepCodecDescToCodecConfig(const JsepCodecDescription& aCodec,
@@ -314,24 +310,16 @@ MediaPipelineFactory::GetTransportParame
   return NS_OK;
 }
 
 nsresult
 MediaPipelineFactory::CreateOrUpdateMediaPipeline(
     const JsepTrackPair& aTrackPair,
     const JsepTrack& aTrack)
 {
-#if !defined(MOZILLA_EXTERNAL_LINKAGE)
-  // The GMP code is all the way on the other side of webrtc.org, and it is not
-  // feasible to plumb this information all the way through. So, we set it (for
-  // the duration of this call) in a global variable. This allows the GMP code
-  // to report errors to the PC.
-  WebrtcGmpPCHandleSetter setter(mPC->GetHandle());
-#endif
-
   MOZ_ASSERT(aTrackPair.mRtpTransport);
 
   bool receiving =
       aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
 
   size_t level;
   RefPtr<TransportFlow> rtpFlow;
   RefPtr<TransportFlow> rtcpFlow;
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -1956,23 +1956,16 @@ PeerConnectionImpl::GetStreamId(const DO
   nsString wideStreamId;
   aStream.GetId(wideStreamId);
   return NS_ConvertUTF16toUTF8(wideStreamId).get();
 #else
   return aStream.GetId();
 #endif
 }
 
-void
-PeerConnectionImpl::OnMediaError(const std::string& aError)
-{
-  CSFLogError(logTag, "Encountered media error! %s", aError.c_str());
-  // TODO: Let content know about this somehow.
-}
-
 nsresult
 PeerConnectionImpl::AddTrack(MediaStreamTrack& aTrack,
                              const Sequence<OwningNonNull<DOMMediaStream>>& aStreams)
 {
   PC_AUTO_ENTER_API_CALL(true);
 
   if (!aStreams.Length()) {
     CSFLogError(logTag, "%s: At least one stream arg required", __FUNCTION__);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -600,18 +600,16 @@ public:
   nsresult GetRemoteTrackId(const std::string streamId,
                             TrackID numericTrackId,
                             std::string* trackId) const;
 #endif
 
   static std::string GetStreamId(const DOMMediaStream& aStream);
   static std::string GetTrackId(const dom::MediaStreamTrack& track);
 
-  void OnMediaError(const std::string& aError);
-
 private:
   virtual ~PeerConnectionImpl();
   PeerConnectionImpl(const PeerConnectionImpl&rhs);
   PeerConnectionImpl& operator=(PeerConnectionImpl);
   NS_IMETHODIMP Initialize(PeerConnectionObserver& aObserver,
                            nsGlobalWindow* aWindow,
                            const IceConfiguration* aConfiguration,
                            const RTCConfiguration* aRTCConfiguration,