Bug 1448863: Stop sync dispatching in Decode. r=jesup
authorByron Campen [:bwc] <docfaraday@gmail.com>
Mon, 26 Mar 2018 10:19:31 -0500
changeset 468080 549f0b8075d587eca29a6a72b1b62caf84d4b4fc
parent 468079 1733aac27257cd771e55d04a5d89150937327489
child 468081 90a06cdcb48f86ddc4c32df3b5443f818adf8d81
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1448863
milestone61.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 1448863: Stop sync dispatching in Decode. r=jesup MozReview-Commit-ID: 3EK0zAsFpHz
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
media/webrtc/webrtc.mozbuild
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
@@ -765,24 +765,18 @@ WebrtcGmpVideoDecoder::GmpInitDone(GMPVi
   }
 
   // now release any frames that got queued waiting for InitDone
   if (!mQueuedFrames.IsEmpty()) {
     // So we're safe to call Decode_g(), which asserts it's empty
     nsTArray<UniquePtr<GMPDecodeData>> temp;
     temp.SwapElements(mQueuedFrames);
     for (auto& queued : temp) {
-      int rv = Decode_g(queued->mImage,
-                        queued->mMissingFrames,
-                        nullptr,
-                        nullptr,
-                        queued->mRenderTimeMs);
-      if (rv) {
-        return rv;
-      }
+      Decode_g(RefPtr<WebrtcGmpVideoDecoder>(this),
+               nsAutoPtr<GMPDecodeData>(queued.release()));
     }
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 void
 WebrtcGmpVideoDecoder::Close_g()
@@ -800,114 +794,116 @@ WebrtcGmpVideoDecoder::Close_g()
 
 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.
-  // Passing 'this' is safe since this is synchronous.
-  mozilla::SyncRunnable::DispatchToThread(mGMPThread,
-                WrapRunnableRet(&ret, this,
-                                &WebrtcGmpVideoDecoder::Decode_g,
-                                aInputImage,
-                                aMissingFrames,
-                                aFragmentation,
-                                aCodecSpecificInfo,
-                                aRenderTimeMs));
-
-  return ret;
-}
-
-int32_t
-WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage,
-                                bool aMissingFrames,
-                                const webrtc::RTPFragmentationHeader* aFragmentation,
-                                const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
-                                int64_t aRenderTimeMs)
-{
-  if (!mGMP) {
-    if (mInitting) {
-      // InitDone hasn't been called yet (race)
-      GMPDecodeData *data = new GMPDecodeData(aInputImage,
-                                              aMissingFrames,
-                                              aRenderTimeMs);
-      mQueuedFrames.AppendElement(data);
-      return WEBRTC_VIDEO_CODEC_OK;
-    }
-    // destroyed via Terminate(), failed to init, or just not initted yet
-    LOGD(("GMP Decode: not initted yet"));
-    return WEBRTC_VIDEO_CODEC_ERROR;
-  }
-  MOZ_ASSERT(mQueuedFrames.IsEmpty());
-  MOZ_ASSERT(mHost);
-
   if (!aInputImage._length) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
+  nsAutoPtr<GMPDecodeData> decodeData(new GMPDecodeData(aInputImage,
+                                                        aMissingFrames,
+                                                        aRenderTimeMs));
+
+  mGMPThread->Dispatch(WrapRunnableNM(&WebrtcGmpVideoDecoder::Decode_g,
+                                      RefPtr<WebrtcGmpVideoDecoder>(this),
+                                      decodeData),
+                       NS_DISPATCH_NORMAL);
+
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+/* static */
+// Using nsAutoPtr because WrapRunnable doesn't support move semantics
+void
+WebrtcGmpVideoDecoder::Decode_g(const RefPtr<WebrtcGmpVideoDecoder>& aThis,
+                                nsAutoPtr<GMPDecodeData> aDecodeData)
+{
+  if (!aThis->mGMP) {
+    if (aThis->mInitting) {
+      // InitDone hasn't been called yet (race)
+      aThis->mQueuedFrames.AppendElement(aDecodeData.forget());
+      return;
+    }
+    // destroyed via Terminate(), failed to init, or just not initted yet
+    LOGD(("GMP Decode: not initted yet"));
+    return;
+  }
+
+  MOZ_ASSERT(aThis->mQueuedFrames.IsEmpty());
+  MOZ_ASSERT(aThis->mHost);
+
   GMPVideoFrame* ftmp = nullptr;
-  GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
+  GMPErr err = aThis->mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
   if (err != GMPNoErr) {
-    return WEBRTC_VIDEO_CODEC_ERROR;
+    LOG(LogLevel::Error, ("%s: CreateFrame failed (%u)!",
+        __PRETTY_FUNCTION__, static_cast<unsigned>(err)));
+    return;
   }
 
   GMPUniquePtr<GMPVideoEncodedFrame> frame(static_cast<GMPVideoEncodedFrame*>(ftmp));
-  err = frame->CreateEmptyFrame(aInputImage._length);
+  err = frame->CreateEmptyFrame(aDecodeData->mImage._length);
   if (err != GMPNoErr) {
-    return WEBRTC_VIDEO_CODEC_ERROR;
+    LOG(LogLevel::Error, ("%s: CreateEmptyFrame failed (%u)!",
+        __PRETTY_FUNCTION__, static_cast<unsigned>(err)));
+    return;
   }
 
   // XXX At this point, we only will get mode1 data (a single length and a buffer)
   // Session_info.cc/etc code needs to change to support mode 0.
   *(reinterpret_cast<uint32_t*>(frame->Buffer())) = frame->Size();
 
   // XXX It'd be wonderful not to have to memcpy the encoded data!
-  memcpy(frame->Buffer()+4, aInputImage._buffer+4, frame->Size()-4);
+  memcpy(frame->Buffer()+4, aDecodeData->mImage._buffer+4, frame->Size()-4);
 
-  frame->SetEncodedWidth(aInputImage._encodedWidth);
-  frame->SetEncodedHeight(aInputImage._encodedHeight);
-  frame->SetTimeStamp((aInputImage._timeStamp * 1000ll)/90); // rounds down
-  frame->SetCompleteFrame(aInputImage._completeFrame);
+  frame->SetEncodedWidth(aDecodeData->mImage._encodedWidth);
+  frame->SetEncodedHeight(aDecodeData->mImage._encodedHeight);
+  frame->SetTimeStamp((aDecodeData->mImage._timeStamp * 1000ll)/90); // rounds down
+  frame->SetCompleteFrame(aDecodeData->mImage._completeFrame);
   frame->SetBufferType(GMP_BufferLength32);
 
   GMPVideoFrameType ft;
-  int32_t ret = WebrtcFrameTypeToGmpFrameType(aInputImage._frameType, &ft);
+  int32_t ret = WebrtcFrameTypeToGmpFrameType(aDecodeData->mImage._frameType, &ft);
   if (ret != WEBRTC_VIDEO_CODEC_OK) {
-    return ret;
+    LOG(LogLevel::Error, ("%s: WebrtcFrameTypeToGmpFrameType failed (%u)!",
+        __PRETTY_FUNCTION__, static_cast<unsigned>(ret)));
+    return;
   }
 
   // Bug XXXXXX: Set codecSpecific info
   GMPCodecSpecificInfo info;
   memset(&info, 0, sizeof(info));
   info.mCodecType = kGMPVideoCodecH264;
   info.mCodecSpecific.mH264.mSimulcastIdx = 0;
   nsTArray<uint8_t> codecSpecificInfo;
   codecSpecificInfo.AppendElements((uint8_t*)&info, sizeof(GMPCodecSpecificInfo));
 
-  LOGD(("GMP Decode: %" PRIu64 ", len %zu%s", frame->TimeStamp(), aInputImage._length,
-        ft == kGMPKeyFrame ? ", KeyFrame" : ""));
-  nsresult rv = mGMP->Decode(Move(frame),
-                             aMissingFrames,
-                             codecSpecificInfo,
-                             aRenderTimeMs);
+  LOGD(("GMP Decode: %" PRIu64 ", len %zu%s", frame->TimeStamp(),
+        aDecodeData->mImage._length, ft == kGMPKeyFrame ? ", KeyFrame" : ""));
+
+  nsresult rv = aThis->mGMP->Decode(Move(frame),
+                                    aDecodeData->mMissingFrames,
+                                    codecSpecificInfo,
+                                    aDecodeData->mRenderTimeMs);
   if (NS_FAILED(rv)) {
-    return WEBRTC_VIDEO_CODEC_ERROR;
+    LOG(LogLevel::Error, ("%s: Decode failed (rv=%u)!",
+        __PRETTY_FUNCTION__, static_cast<unsigned>(rv)));
   }
-  if(mDecoderStatus != GMPNoErr){
-    mDecoderStatus = GMPNoErr;
-    return WEBRTC_VIDEO_CODEC_ERROR;
+
+  if(aThis->mDecoderStatus != GMPNoErr){
+    aThis->mDecoderStatus = GMPNoErr;
+    LOG(LogLevel::Error, ("%s: Decoder status is bad (%u)!",
+        __PRETTY_FUNCTION__, static_cast<unsigned>(aThis->mDecoderStatus)));
   }
-  return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcGmpVideoDecoder::RegisterDecodeCompleteCallback( webrtc::DecodedImageCallback* aCallback)
 {
   MutexAutoLock lock(mCallbackMutex);
   mCallback = aCallback;
 
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
@@ -464,21 +464,18 @@ private:
       mInitDone->Dispatch(result, errorOut);
     }
 
   private:
     RefPtr<WebrtcGmpVideoDecoder> mDecoder;
     RefPtr<GmpInitDoneRunnable> mInitDone;
   };
 
-  virtual int32_t Decode_g(const webrtc::EncodedImage& aInputImage,
-                           bool aMissingFrames,
-                           const webrtc::RTPFragmentationHeader* aFragmentation,
-                           const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
-                           int64_t aRenderTimeMs);
+  static void Decode_g(const RefPtr<WebrtcGmpVideoDecoder>& aThis,
+                       nsAutoPtr<GMPDecodeData> aDecodeData);
 
   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;
   // Frames queued for decode while mInitting is true
   nsTArray<UniquePtr<GMPDecodeData>> mQueuedFrames;
--- a/media/webrtc/webrtc.mozbuild
+++ b/media/webrtc/webrtc.mozbuild
@@ -1,25 +1,29 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 if CONFIG['MOZ_WEBRTC']:
     DEFINES['HAVE_UINT64_T'] = True
+
     if CONFIG['OS_TARGET'] != 'WINNT':
         DEFINES['WEBRTC_POSIX'] = True
         DEFINES['WEBRTC_BUILD_LIBEVENT'] = True
 
     if CONFIG['OS_TARGET'] == 'Linux':
         DEFINES['WEBRTC_LINUX'] = True
     elif CONFIG['OS_TARGET'] == 'Darwin':
         DEFINES['WEBRTC_MAC'] = True
     elif CONFIG['OS_TARGET'] == 'WINNT':
         DEFINES['WEBRTC_WIN'] = True
         DEFINES['HAVE_WINSOCK2_H'] = True
     elif CONFIG['OS_TARGET'] in ('DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD'):
         DEFINES['WEBRTC_BSD'] = True
     elif CONFIG['OS_TARGET'] == 'Android':
         DEFINES['WEBRTC_ANDROID'] = True
 
+    if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
+        DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__'
+
     if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
         CXXFLAGS += ['-Wno-error=shadow']