Bug 1059765: handle incoming resolution changes in GMP video encode r=pkerr a=sylvestre
authorRandell Jesup <rjesup@jesup.org>
Fri, 29 Aug 2014 11:26:34 -0400
changeset 217747 2ec53377f6b4e9cee6590e8cf0ac1942875320b5
parent 217746 1d9cbbf6af8c9135dcbe9b2756a64f7e229b1cdb
child 217748 8c42c04e31a72f6c4ed4786532e9956057afa6a9
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspkerr, sylvestre
bugs1059765
milestone33.0a2
Bug 1059765: handle incoming resolution changes in GMP video encode r=pkerr a=sylvestre
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
@@ -137,22 +137,23 @@ GmpFrameTypeToWebrtcFrameType(GMPVideoFr
 }
 
 
 int32_t
 WebrtcGmpVideoEncoder::InitEncode(const webrtc::VideoCodec* aCodecSettings,
                                   int32_t aNumberOfCores,
                                   uint32_t aMaxPayloadSize)
 {
-  mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
+  if (!mMPS) {
+    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))))) {
-      mMPS = nullptr;
       return WEBRTC_VIDEO_CODEC_ERROR;
     }
   }
 
   int32_t ret;
   mGMPThread->Dispatch(WrapRunnableRet(this,
                                        &WebrtcGmpVideoEncoder::InitEncode_g,
                                        aCodecSettings,
@@ -176,41 +177,40 @@ WebrtcGmpVideoEncoder::InitEncode_g(cons
                                                     &mHost,
                                                     &mGMP)))) {
     mMPS = nullptr;
     mGMP = nullptr;
     mGMPThread = nullptr;
     mHost = nullptr;
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
-  mMPS = nullptr;
 
   if (!mGMP || !mHost) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
   // Bug XXXXXX: transfer settings from codecSettings to codec.
-  GMPVideoCodec codec;
-  memset(&codec, 0, sizeof(codec));
+  memset(&mCodecParams, 0, sizeof(mCodecParams));
 
-  codec.mGMPApiVersion = 33;
-  codec.mWidth = aCodecSettings->width;
-  codec.mHeight = aCodecSettings->height;
-  codec.mStartBitrate = aCodecSettings->startBitrate;
-  codec.mMinBitrate = aCodecSettings->minBitrate;
-  codec.mMaxBitrate = aCodecSettings->maxBitrate;
-  codec.mMaxFramerate = aCodecSettings->maxFramerate;
+  mCodecParams.mGMPApiVersion = 33;
+  mCodecParams.mWidth = aCodecSettings->width;
+  mCodecParams.mHeight = aCodecSettings->height;
+  mCodecParams.mStartBitrate = aCodecSettings->startBitrate;
+  mCodecParams.mMinBitrate = aCodecSettings->minBitrate;
+  mCodecParams.mMaxBitrate = aCodecSettings->maxBitrate;
+  mCodecParams.mMaxFramerate = aCodecSettings->maxFramerate;
+  mMaxPayloadSize = aMaxPayloadSize;
   if (aCodecSettings->codecSpecific.H264.packetizationMode == 1) {
-    aMaxPayloadSize = 4*1024*1024; // insanely large
+    mMaxPayloadSize = 4*1024*1024; // insanely large
   }
 
   // Pass dummy codecSpecific data for now...
   nsTArray<uint8_t> codecSpecific;
 
-  GMPErr err = mGMP->InitEncode(codec, codecSpecific, this, 1, aMaxPayloadSize);
+  GMPErr err = mGMP->InitEncode(mCodecParams, codecSpecific, this, 1, mMaxPayloadSize);
   if (err != GMPNoErr) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 
@@ -239,16 +239,48 @@ WebrtcGmpVideoEncoder::Encode_g(const we
                                 const std::vector<webrtc::VideoFrameType>* aFrameTypes)
 {
   MOZ_ASSERT(mHost);
   if (!mGMP) {
     // destroyed via Terminate()
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
+  if (aInputImage->width() != mCodecParams.mWidth ||
+      aInputImage->height() != mCodecParams.mHeight) {
+    LOGD(("GMP Encode: resolution change from %ux%u to %ux%u",
+          mCodecParams.mWidth, mCodecParams.mHeight, aInputImage->width(), aInputImage->height()));
+
+    mGMP->Close();
+
+    // 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"));
+    if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoEncoder(&tags,
+                                                      NS_LITERAL_STRING(""),
+                                                      &mHost,
+                                                      &mGMP)))) {
+      mGMP = nullptr;
+      mHost = nullptr;
+      return WEBRTC_VIDEO_CODEC_ERROR;
+    }
+
+    mCodecParams.mWidth = aInputImage->width();
+    mCodecParams.mHeight = aInputImage->height();
+    // Pass dummy codecSpecific data for now...
+    nsTArray<uint8_t> codecSpecific;
+
+    GMPErr err = mGMP->InitEncode(mCodecParams, codecSpecific, this, 1, mMaxPayloadSize);
+    if (err != GMPNoErr) {
+      return WEBRTC_VIDEO_CODEC_ERROR;
+    }
+  }
+
   GMPVideoFrame* ftmp = nullptr;
   GMPErr err = mHost->CreateFrame(kGMPI420VideoFrame, &ftmp);
   if (err != GMPNoErr) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
   GMPVideoi420Frame* frame = static_cast<GMPVideoi420Frame*>(ftmp);
 
   err = frame->CreateFrame(aInputImage->allocated_size(webrtc::kYPlane),
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
@@ -85,16 +85,18 @@ private:
 
   virtual int32_t SetRates_g(uint32_t aNewBitRate,
                              uint32_t aFrameRate);
 
   nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
   nsCOMPtr<nsIThread> mGMPThread;
   GMPVideoEncoderProxy* mGMP;
   GMPVideoHost* mHost;
+  GMPVideoCodec mCodecParams;
+  uint32_t mMaxPayloadSize;
   webrtc::EncodedImageCallback* mCallback;
   uint64_t mCachedPluginId;
 };
 
 
 class WebrtcGmpVideoDecoder : public WebrtcVideoDecoder,
                               public GMPVideoDecoderCallbackProxy
 {