Bug 1020760 - Pass GMP codec specific info as a uint8_t[], and pass buffer type separately. r=jesup
authorChris Pearce <cpearce@mozilla.com>
Fri, 11 Jul 2014 15:36:21 +1200
changeset 214322 a95fee89e4be813283f495bda7978af682a7faf8
parent 214321 54bd83c54daf91ea8df2799e9122c28c489cfeb3
child 214323 17cd99be695f4cc7534a98c9aab6fd8195c2757e
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1020760
milestone33.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 1020760 - Pass GMP codec specific info as a uint8_t[], and pass buffer type separately. r=jesup
content/media/gmp/GMPMessageUtils.h
content/media/gmp/GMPVideoDecoderChild.cpp
content/media/gmp/GMPVideoDecoderChild.h
content/media/gmp/GMPVideoDecoderParent.cpp
content/media/gmp/GMPVideoDecoderParent.h
content/media/gmp/GMPVideoDecoderProxy.h
content/media/gmp/GMPVideoEncoderChild.cpp
content/media/gmp/GMPVideoEncoderChild.h
content/media/gmp/GMPVideoEncoderParent.cpp
content/media/gmp/GMPVideoEncoderParent.h
content/media/gmp/GMPVideoEncoderProxy.h
content/media/gmp/PGMPVideoDecoder.ipdl
content/media/gmp/PGMPVideoEncoder.ipdl
content/media/gmp/gmp-api/gmp-video-decode.h
content/media/gmp/gmp-api/gmp-video-encode.h
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
--- a/content/media/gmp/GMPMessageUtils.h
+++ b/content/media/gmp/GMPMessageUtils.h
@@ -186,147 +186,11 @@ struct ParamTraits<GMPVideoCodec>
     }
     aLog->append(StringPrintf(L"[%s, %u, %u]",
                               codecName,
                               aParam.mWidth,
                               aParam.mHeight));
   }
 };
 
-template <>
-struct ParamTraits<GMPCodecSpecificInfoVP8>
-{
-  typedef GMPCodecSpecificInfoVP8 paramType;
-
-  static void Write(Message* aMsg, const paramType& aParam)
-  {
-    WriteParam(aMsg, aParam.mHasReceivedSLI);
-    WriteParam(aMsg, aParam.mPictureIdSLI);
-    WriteParam(aMsg, aParam.mHasReceivedRPSI);
-    WriteParam(aMsg, aParam.mPictureIdRPSI);
-    WriteParam(aMsg, aParam.mPictureId);
-    WriteParam(aMsg, aParam.mNonReference);
-    WriteParam(aMsg, aParam.mSimulcastIdx);
-    WriteParam(aMsg, aParam.mTemporalIdx);
-    WriteParam(aMsg, aParam.mLayerSync);
-    WriteParam(aMsg, aParam.mTL0PicIdx);
-    WriteParam(aMsg, aParam.mKeyIdx);
-  }
-
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
-  {
-    if (ReadParam(aMsg, aIter, &(aResult->mHasReceivedSLI)) &&
-        ReadParam(aMsg, aIter, &(aResult->mPictureIdSLI)) &&
-        ReadParam(aMsg, aIter, &(aResult->mHasReceivedRPSI)) &&
-        ReadParam(aMsg, aIter, &(aResult->mPictureIdRPSI)) &&
-        ReadParam(aMsg, aIter, &(aResult->mPictureId)) &&
-        ReadParam(aMsg, aIter, &(aResult->mNonReference)) &&
-        ReadParam(aMsg, aIter, &(aResult->mSimulcastIdx)) &&
-        ReadParam(aMsg, aIter, &(aResult->mTemporalIdx)) &&
-        ReadParam(aMsg, aIter, &(aResult->mLayerSync)) &&
-        ReadParam(aMsg, aIter, &(aResult->mTL0PicIdx)) &&
-        ReadParam(aMsg, aIter, &(aResult->mKeyIdx))) {
-      return true;
-    }
-    return false;
-  }
-
-  static void Log(const paramType& aParam, std::wstring* aLog)
-  {
-    aLog->append(StringPrintf(L"[%d, %u, %d, %u, %d, %d, %u, %u, %d, %d, %d]",
-                              aParam.mHasReceivedSLI,
-                              aParam.mPictureIdSLI,
-                              aParam.mHasReceivedRPSI,
-                              aParam.mPictureIdRPSI,
-                              aParam.mPictureId,
-                              aParam.mNonReference,
-                              aParam.mSimulcastIdx,
-                              aParam.mTemporalIdx,
-                              aParam.mLayerSync,
-                              aParam.mTL0PicIdx,
-                              aParam.mKeyIdx));
-  }
-};
-
-template <>
-struct ParamTraits<GMPCodecSpecificInfoH264>
-{
-  typedef GMPCodecSpecificInfoH264 paramType;
-
-  static void Write(Message* aMsg, const paramType& aParam)
-  {
-    WriteParam(aMsg, aParam.mSimulcastIdx);
-  }
-
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
-  {
-    if (ReadParam(aMsg, aIter, &(aResult->mSimulcastIdx))) {
-      return true;
-    }
-    return false;
-  }
-
-  static void Log(const paramType& aParam, std::wstring* aLog)
-  {
-    aLog->append(StringPrintf(L"[%u]",
-                              aParam.mSimulcastIdx));
-  }
-};
-
-template <>
-struct ParamTraits<GMPCodecSpecificInfo>
-{
-  typedef GMPCodecSpecificInfo paramType;
-
-  static void Write(Message* aMsg, const paramType& aParam)
-  {
-    WriteParam(aMsg, aParam.mCodecType);
-    WriteParam(aMsg, aParam.mBufferType);
-    if (aParam.mCodecType == kGMPVideoCodecVP8) {
-      WriteParam(aMsg, aParam.mCodecSpecific.mVP8);
-    } else if (aParam.mCodecType == kGMPVideoCodecH264) {
-      WriteParam(aMsg, aParam.mCodecSpecific.mH264);
-    } else {
-      MOZ_ASSERT(false, "Serializing unknown codec type!");
-    }
-  }
-
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
-  {
-    if (!ReadParam(aMsg, aIter, &(aResult->mCodecType))) {
-      return false;
-    }
-    if (!ReadParam(aMsg, aIter, &(aResult->mBufferType))) {
-      return false;
-    }
-
-    if (aResult->mCodecType == kGMPVideoCodecVP8) {
-      if (!ReadParam(aMsg, aIter, &(aResult->mCodecSpecific.mVP8))) {
-        return false;
-      }
-    } else if (aResult->mCodecType == kGMPVideoCodecH264) {
-      if (!ReadParam(aMsg, aIter, &(aResult->mCodecSpecific.mH264))) {
-        return false;
-      }
-    } else {
-      MOZ_ASSERT(false, "De-serializing unknown codec type!");
-      return false;
-    }
-
-    return true;
-  }
-
-  static void Log(const paramType& aParam, std::wstring* aLog)
-  {
-    const char* codecName = nullptr;
-    if (aParam.mCodecType == kGMPVideoCodecVP8) {
-      codecName = "VP8";
-    }
-    else if (aParam.mCodecType == kGMPVideoCodecH264) {
-      codecName = "H264";
-    }
-    aLog->append(StringPrintf(L"[%s]", codecName));
-  }
-};
-
 } // namespace IPC
 
 #endif // GMPMessageUtils_h_
--- a/content/media/gmp/GMPVideoDecoderChild.cpp
+++ b/content/media/gmp/GMPVideoDecoderChild.cpp
@@ -118,27 +118,33 @@ GMPVideoDecoderChild::RecvInitDecode(con
                             this,
                             aCoreCount);
   return true;
 }
 
 bool
 GMPVideoDecoderChild::RecvDecode(const GMPVideoEncodedFrameData& aInputFrame,
                                  const bool& aMissingFrames,
-                                 const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                                 const GMPBufferType& aBufferType,
+                                 const nsTArray<uint8_t>& aCodecSpecificInfo,
                                  const int64_t& aRenderTimeMs)
 {
   if (!mVideoDecoder) {
     return false;
   }
 
   auto f = new GMPVideoEncodedFrameImpl(aInputFrame, &mVideoHost);
 
   // Ignore any return code. It is OK for this to fail without killing the process.
-  mVideoDecoder->Decode(f, aMissingFrames, aCodecSpecificInfo, aRenderTimeMs);
+  mVideoDecoder->Decode(f,
+                        aMissingFrames,
+                        aBufferType,
+                        aCodecSpecificInfo.Elements(),
+                        aCodecSpecificInfo.Length(),
+                        aRenderTimeMs);
 
   return true;
 }
 
 bool
 GMPVideoDecoderChild::RecvChildShmemForPool(Shmem& aFrameBuffer)
 {
   if (aFrameBuffer.IsWritable()) {
--- a/content/media/gmp/GMPVideoDecoderChild.h
+++ b/content/media/gmp/GMPVideoDecoderChild.h
@@ -57,23 +57,24 @@ public:
     SendParentShmemForPool(aMem);
 #else
     DeallocShmem(aMem);
 #endif
   }
 
 private:
   // PGMPVideoDecoderChild
-  virtual bool RecvInitDecode(const GMPVideoCodec& codecSettings,
+  virtual bool RecvInitDecode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
-                              const int32_t& coreCount) MOZ_OVERRIDE;
-  virtual bool RecvDecode(const GMPVideoEncodedFrameData& inputFrame,
-                          const bool& missingFrames,
-                          const GMPCodecSpecificInfo& codecSpecificInfo,
-                          const int64_t& renderTimeMs) MOZ_OVERRIDE;
+                              const int32_t& aCoreCount) MOZ_OVERRIDE;
+  virtual bool RecvDecode(const GMPVideoEncodedFrameData& aInputFrame,
+                          const bool& aMissingFrames,
+                          const GMPBufferType& aBufferType,
+                          const nsTArray<uint8_t>& aCodecSpecificInfo,
+                          const int64_t& aRenderTimeMs) MOZ_OVERRIDE;
   virtual bool RecvChildShmemForPool(Shmem& aFrameBuffer) MOZ_OVERRIDE;
   virtual bool RecvReset() MOZ_OVERRIDE;
   virtual bool RecvDrain() MOZ_OVERRIDE;
   virtual bool RecvDecodingComplete() MOZ_OVERRIDE;
 
   GMPChild* mPlugin;
   GMPVideoDecoder* mVideoDecoder;
   GMPVideoHostImpl mVideoHost;
--- a/content/media/gmp/GMPVideoDecoderParent.cpp
+++ b/content/media/gmp/GMPVideoDecoderParent.cpp
@@ -67,17 +67,18 @@ GMPVideoDecoderParent::InitDecode(const 
 
   // Async IPC, we don't have access to a return value.
   return NS_OK;
 }
 
 nsresult
 GMPVideoDecoderParent::Decode(GMPVideoEncodedFrame* aInputFrame,
                               bool aMissingFrames,
-                              const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                              GMPBufferType aBufferType,
+                              const nsTArray<uint8_t>& aCodecSpecificInfo,
                               int64_t aRenderTimeMs)
 {
   nsAutoRef<GMPVideoEncodedFrame> autoDestroy(aInputFrame);
 
   if (!mCanSendMessages) {
     NS_WARNING("Trying to use an invalid GMP video decoder!");
     return NS_ERROR_FAILURE;
   }
@@ -94,16 +95,17 @@ GMPVideoDecoderParent::Decode(GMPVideoEn
   // 3* is because we're using 3 buffers per frame for i420 data for now.
   if (NumInUse(kGMPFrameData) > 3*GMPSharedMemManager::kGMPBufLimit ||
       NumInUse(kGMPEncodedData) > GMPSharedMemManager::kGMPBufLimit) {
     return NS_ERROR_FAILURE;
   }
 
   if (!SendDecode(frameData,
                   aMissingFrames,
+                  aBufferType,
                   aCodecSpecificInfo,
                   aRenderTimeMs)) {
     return NS_ERROR_FAILURE;
   }
 
   // Async IPC, we don't have access to a return value.
   return NS_OK;
 }
--- a/content/media/gmp/GMPVideoDecoderParent.h
+++ b/content/media/gmp/GMPVideoDecoderParent.h
@@ -29,24 +29,25 @@ public:
   GMPVideoDecoderParent(GMPParent *aPlugin);
 
   GMPVideoHostImpl& Host();
 
   // GMPVideoDecoder
   virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
                               GMPVideoDecoderCallback* aCallback,
-                              int32_t aCoreCount);
+                              int32_t aCoreCount) MOZ_OVERRIDE;
   virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame,
                           bool aMissingFrames,
-                          const GMPCodecSpecificInfo& aCodecSpecificInfo,
-                          int64_t aRenderTimeMs = -1);
-  virtual nsresult Reset();
-  virtual nsresult Drain();
-  virtual nsresult DecodingComplete();
+                          GMPBufferType aBufferType,
+                          const nsTArray<uint8_t>& aCodecSpecificInfo,
+                          int64_t aRenderTimeMs = -1) MOZ_OVERRIDE;
+  virtual nsresult Reset() MOZ_OVERRIDE;
+  virtual nsresult Drain() MOZ_OVERRIDE;
+  virtual nsresult DecodingComplete() MOZ_OVERRIDE;
 
   // GMPSharedMemManager
   virtual void CheckThread();
   virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
   {
 #ifdef GMP_SAFE_SHMEM
     return AllocShmem(aSize, aType, aMem);
 #else
--- a/content/media/gmp/GMPVideoDecoderProxy.h
+++ b/content/media/gmp/GMPVideoDecoderProxy.h
@@ -18,16 +18,17 @@
 class GMPVideoDecoderProxy {
 public:
   virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
                               GMPVideoDecoderCallback* aCallback,
                               int32_t aCoreCount) = 0;
   virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame,
                           bool aMissingFrames,
-                          const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                          GMPBufferType aBufferType,
+                          const nsTArray<uint8_t>& aCodecSpecificInfo,
                           int64_t aRenderTimeMs = -1) = 0;
   virtual nsresult Reset() = 0;
   virtual nsresult Drain() = 0;
   virtual nsresult DecodingComplete() = 0;
 };
 
 #endif
--- a/content/media/gmp/GMPVideoEncoderChild.cpp
+++ b/content/media/gmp/GMPVideoEncoderChild.cpp
@@ -35,26 +35,30 @@ GMPVideoEncoderChild::Init(GMPVideoEncod
 GMPVideoHostImpl&
 GMPVideoEncoderChild::Host()
 {
   return mVideoHost;
 }
 
 void
 GMPVideoEncoderChild::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
-                              const GMPCodecSpecificInfo& aCodecSpecificInfo)
+                              GMPBufferType aBufferType,
+                              const uint8_t* aCodecSpecificInfo,
+                              uint32_t aCodecSpecificInfoLength)
 {
   MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
 
   auto ef = static_cast<GMPVideoEncodedFrameImpl*>(aEncodedFrame);
 
   GMPVideoEncodedFrameData frameData;
   ef->RelinquishFrameData(frameData);
 
-  SendEncoded(frameData, aCodecSpecificInfo);
+  nsTArray<uint8_t> codecSpecific;
+  codecSpecific.AppendElements(aCodecSpecificInfo, aCodecSpecificInfoLength);
+  SendEncoded(frameData, aBufferType, codecSpecific);
 
   aEncodedFrame->Destroy();
 }
 
 void
 GMPVideoEncoderChild::CheckThread()
 {
   MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
@@ -78,27 +82,31 @@ GMPVideoEncoderChild::RecvInitEncode(con
                             aNumberOfCores,
                             aMaxPayloadSize);
 
   return true;
 }
 
 bool
 GMPVideoEncoderChild::RecvEncode(const GMPVideoi420FrameData& aInputFrame,
-                                 const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                                 const nsTArray<uint8_t>& aCodecSpecificInfo,
                                  const nsTArray<GMPVideoFrameType>& aFrameTypes)
 {
   if (!mVideoEncoder) {
     return false;
   }
 
   auto f = new GMPVideoi420FrameImpl(aInputFrame, &mVideoHost);
 
   // Ignore any return code. It is OK for this to fail without killing the process.
-  mVideoEncoder->Encode(f, aCodecSpecificInfo, aFrameTypes.Elements(), aFrameTypes.Length());
+  mVideoEncoder->Encode(f,
+                        aCodecSpecificInfo.Elements(),
+                        aCodecSpecificInfo.Length(),
+                        aFrameTypes.Elements(),
+                        aFrameTypes.Length());
 
   return true;
 }
 
 bool
 GMPVideoEncoderChild::RecvChildShmemForPool(Shmem& aEncodedBuffer)
 {
   if (aEncodedBuffer.IsWritable()) {
--- a/content/media/gmp/GMPVideoEncoderChild.h
+++ b/content/media/gmp/GMPVideoEncoderChild.h
@@ -25,17 +25,19 @@ public:
   GMPVideoEncoderChild(GMPChild* aPlugin);
   virtual ~GMPVideoEncoderChild();
 
   void Init(GMPVideoEncoder* aEncoder);
   GMPVideoHostImpl& Host();
 
   // GMPVideoEncoderCallback
   virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
-                       const GMPCodecSpecificInfo& aCodecSpecificInfo) MOZ_OVERRIDE;
+                       GMPBufferType aBufferType,
+                       const uint8_t* aCodecSpecificInfo,
+                       uint32_t aCodecSpecificInfoLength) MOZ_OVERRIDE;
 
   // GMPSharedMemManager
   virtual void CheckThread();
   virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
   {
 #ifndef SHMEM_ALLOC_IN_CHILD
     return CallNeedShmem(aSize, aMem);
 #else
@@ -57,17 +59,17 @@ public:
 
 private:
   // PGMPVideoEncoderChild
   virtual bool RecvInitEncode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
                               const int32_t& aNumberOfCores,
                               const uint32_t& aMaxPayloadSize) MOZ_OVERRIDE;
   virtual bool RecvEncode(const GMPVideoi420FrameData& aInputFrame,
-                          const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                          const nsTArray<uint8_t>& aCodecSpecificInfo,
                           const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
   virtual bool RecvChildShmemForPool(Shmem& aEncodedBuffer) MOZ_OVERRIDE;
   virtual bool RecvSetChannelParameters(const uint32_t& aPacketLoss,
                                         const uint32_t& aRTT) MOZ_OVERRIDE;
   virtual bool RecvSetRates(const uint32_t& aNewBitRate,
                             const uint32_t& aFrameRate) MOZ_OVERRIDE;
   virtual bool RecvSetPeriodicKeyFrames(const bool& aEnable) MOZ_OVERRIDE;
   virtual bool RecvEncodingComplete() MOZ_OVERRIDE;
--- a/content/media/gmp/GMPVideoEncoderParent.cpp
+++ b/content/media/gmp/GMPVideoEncoderParent.cpp
@@ -41,17 +41,17 @@ GMPVideoHostImpl&
 GMPVideoEncoderParent::Host()
 {
   return mVideoHost;
 }
 
 GMPErr
 GMPVideoEncoderParent::InitEncode(const GMPVideoCodec& aCodecSettings,
                                   const nsTArray<uint8_t>& aCodecSpecific,
-                                  GMPVideoEncoderCallback* aCallback,
+                                  GMPVideoEncoderCallbackProxy* aCallback,
                                   int32_t aNumberOfCores,
                                   uint32_t aMaxPayloadSize)
 {
   if (!mCanSendMessages) {
     NS_WARNING("Trying to use an invalid GMP video encoder!");
     return GMPGenericErr;
   }
 
@@ -67,17 +67,17 @@ GMPVideoEncoderParent::InitEncode(const 
   }
 
   // Async IPC, we don't have access to a return value.
   return GMPNoErr;
 }
 
 GMPErr
 GMPVideoEncoderParent::Encode(GMPVideoi420Frame* aInputFrame,
-                              const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                              const nsTArray<uint8_t>& aCodecSpecificInfo,
                               const nsTArray<GMPVideoFrameType>& aFrameTypes)
 {
   nsAutoRef<GMPVideoi420Frame> frameRef(aInputFrame);
 
   if (!mCanSendMessages) {
     NS_WARNING("Trying to use an invalid GMP video encoder!");
     return GMPGenericErr;
   }
@@ -198,26 +198,27 @@ GMPVideoEncoderParent::ActorDestroy(Acto
 void
 GMPVideoEncoderParent::CheckThread()
 {
   MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
 }
 
 bool
 GMPVideoEncoderParent::RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame,
-                                   const GMPCodecSpecificInfo& aCodecSpecificInfo)
+                                   const GMPBufferType& aBufferType,
+                                   const nsTArray<uint8_t>& aCodecSpecificInfo)
 {
   if (!mCallback) {
     return false;
   }
 
   auto f = new GMPVideoEncodedFrameImpl(aEncodedFrame, &mVideoHost);
 
   // Ignore any return code. It is OK for this to fail without killing the process.
-  mCallback->Encoded(f, aCodecSpecificInfo);
+  mCallback->Encoded(f, aBufferType, aCodecSpecificInfo);
 
   // Return SHM to sender to recycle
   //SendEncodedReturn(aEncodedFrame, aCodecSpecificInfo);
   return true;
 }
 
 bool
 GMPVideoEncoderParent::RecvParentShmemForPool(Shmem& aFrameBuffer)
--- a/content/media/gmp/GMPVideoEncoderParent.h
+++ b/content/media/gmp/GMPVideoEncoderParent.h
@@ -28,21 +28,21 @@ public:
 
   GMPVideoEncoderParent(GMPParent *aPlugin);
 
   GMPVideoHostImpl& Host();
 
   // GMPVideoEncoderProxy
   virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
                             const nsTArray<uint8_t>& aCodecSpecific,
-                            GMPVideoEncoderCallback* aCallback,
+                            GMPVideoEncoderCallbackProxy* aCallback,
                             int32_t aNumberOfCores,
                             uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
   virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
-                        const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                        const nsTArray<uint8_t>& aCodecSpecificInfo,
                         const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
   virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) MOZ_OVERRIDE;
   virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
   virtual GMPErr SetPeriodicKeyFrames(bool aEnable) MOZ_OVERRIDE;
   virtual void EncodingComplete() MOZ_OVERRIDE;
 
   // GMPSharedMemManager
   virtual void CheckThread();
@@ -60,24 +60,25 @@ public:
   }
 
 private:
   virtual ~GMPVideoEncoderParent();
 
   // PGMPVideoEncoderParent
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
   virtual bool RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame,
-                           const GMPCodecSpecificInfo& aCodecSpecificInfo) MOZ_OVERRIDE;
+                           const GMPBufferType& aBufferType,
+                           const nsTArray<uint8_t>& aCodecSpecificInfo) MOZ_OVERRIDE;
   virtual bool RecvParentShmemForPool(Shmem& aFrameBuffer) MOZ_OVERRIDE;
   virtual bool AnswerNeedShmem(const uint32_t& aEncodedBufferSize,
                                Shmem* aMem) MOZ_OVERRIDE;
   virtual bool Recv__delete__() MOZ_OVERRIDE;
 
   bool mCanSendMessages;
   GMPParent* mPlugin;
-  GMPVideoEncoderCallback* mCallback;
+  GMPVideoEncoderCallbackProxy* mCallback;
   GMPVideoHostImpl mVideoHost;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPVideoEncoderParent_h_
--- a/content/media/gmp/GMPVideoEncoderProxy.h
+++ b/content/media/gmp/GMPVideoEncoderProxy.h
@@ -6,29 +6,36 @@
 #ifndef GMPVideoEncoderProxy_h_
 #define GMPVideoEncoderProxy_h_
 
 #include "nsTArray.h"
 #include "gmp-video-encode.h"
 #include "gmp-video-frame-i420.h"
 #include "gmp-video-frame-encoded.h"
 
+class GMPVideoEncoderCallbackProxy {
+public:
+  virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
+                       GMPBufferType aBufferType,
+                       const nsTArray<uint8_t>& aCodecSpecificInfo) = 0;
+};
+
 // A proxy to GMPVideoEncoder in the child process.
 // GMPVideoEncoderParent exposes this to users the GMP.
 // This enables Gecko to pass nsTArrays to the child GMP and avoid
 // an extra copy when doing so.
 class GMPVideoEncoderProxy {
 public:
   virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
                             const nsTArray<uint8_t>& aCodecSpecific,
-                            GMPVideoEncoderCallback* aCallback,
+                            GMPVideoEncoderCallbackProxy* aCallback,
                             int32_t aNumberOfCores,
                             uint32_t aMaxPayloadSize) = 0;
   virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
-                        const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                        const nsTArray<uint8_t>& aCodecSpecificInfo,
                         const nsTArray<GMPVideoFrameType>& aFrameTypes) = 0;
   virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
   virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
   virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
   virtual void EncodingComplete() = 0;
 };
 
 #endif // GMPVideoEncoderProxy_h_
--- a/content/media/gmp/PGMPVideoDecoder.ipdl
+++ b/content/media/gmp/PGMPVideoDecoder.ipdl
@@ -2,33 +2,34 @@
 /* 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/. */
 
 include protocol PGMP;
 include GMPTypes;
 
 using GMPVideoCodec from "gmp-video-codec.h";
-using GMPCodecSpecificInfo from "gmp-video-codec.h";
+using GMPBufferType from "gmp-video-codec.h";
 
 include "GMPMessageUtils.h";
 
 namespace mozilla {
 namespace gmp {
 
 intr protocol PGMPVideoDecoder
 {
   manager PGMP;
 child:
   async InitDecode(GMPVideoCodec aCodecSettings,
                    uint8_t[] aCodecSpecific,
                    int32_t aCoreCount);
   async Decode(GMPVideoEncodedFrameData aInputFrame,
                bool aMissingFrames,
-               GMPCodecSpecificInfo aCodecSpecificInfo,
+               GMPBufferType aBufferType,
+               uint8_t[] aCodecSpecificInfo,
                int64_t aRenderTimeMs);
   async Reset();
   async Drain();
   async DecodingComplete();
   async ChildShmemForPool(Shmem aFrameBuffer);
 
 parent:
   async __delete__();
--- a/content/media/gmp/PGMPVideoEncoder.ipdl
+++ b/content/media/gmp/PGMPVideoEncoder.ipdl
@@ -2,45 +2,46 @@
 /* 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/. */
 
 include protocol PGMP;
 include GMPTypes;
 
 using GMPVideoCodec from "gmp-video-codec.h";
-using GMPCodecSpecificInfo from "gmp-video-codec.h";
 using GMPVideoFrameType from "gmp-video-frame-encoded.h";
+using GMPBufferType from "gmp-video-codec.h";
 
 include "GMPMessageUtils.h";
 
 namespace mozilla {
 namespace gmp {
 
 intr protocol PGMPVideoEncoder
 {
   manager PGMP;
 child:
   async InitEncode(GMPVideoCodec aCodecSettings,
                    uint8_t[] aCodecSpecific,
                    int32_t aNumberOfCores,
                    uint32_t aMaxPayloadSize);
   async Encode(GMPVideoi420FrameData aInputFrame,
-               GMPCodecSpecificInfo aCodecSpecificInfo,
+               uint8_t[] aCodecSpecificInfo,
                GMPVideoFrameType[] aFrameTypes);
   async SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT);
   async SetRates(uint32_t aNewBitRate, uint32_t aFrameRate);
   async SetPeriodicKeyFrames(bool aEnable);
   async EncodingComplete();
   async ChildShmemForPool(Shmem aEncodedBuffer);
 
 parent:
   async __delete__();
   async Encoded(GMPVideoEncodedFrameData aEncodedFrame,
-                GMPCodecSpecificInfo aCodecSpecificInfo);
+                GMPBufferType aBufferType,
+                uint8_t[] aCodecSpecificInfo);
   async ParentShmemForPool(Shmem aFrameBuffer);
   // MUST be intr - if sync and we create a new Shmem, when the returned
   // Shmem is received in the Child it will fail to Deserialize
   intr NeedShmem(uint32_t aEncodedBufferSize) returns (Shmem aMem);
 };
 
 } // namespace gmp
 } // namespace mozilla
--- a/content/media/gmp/gmp-api/gmp-video-decode.h
+++ b/content/media/gmp/gmp-api/gmp-video-decode.h
@@ -60,42 +60,47 @@ public:
 };
 
 // ALL METHODS MUST BE CALLED ON THE MAIN THREAD
 class GMPVideoDecoder
 {
 public:
   virtual ~GMPVideoDecoder() {}
 
-  // aCallback: Subclass should retain reference to it until DecodingComplete
-  //            is called. Do not attempt to delete it, host retains ownership.
+  // - aCodecSettings: Details of decoder to create.
+  // - aCodecSpecific: codec specific data, cast to a GMPVideoCodecXXX struct
+  //                   to get codec specific config data.
+  // - aCodecSpecificLength: number of bytes in aCodecSpecific.
+  // - aCallback: Subclass should retain reference to it until DecodingComplete
+  //              is called. Do not attempt to delete it, host retains ownership.
+  // aCoreCount: number of CPU cores.
   virtual GMPErr InitDecode(const GMPVideoCodec& aCodecSettings,
                             const uint8_t* aCodecSpecific,
                             uint32_t aCodecSpecificLength,
                             GMPVideoDecoderCallback* aCallback,
                             int32_t aCoreCount) = 0;
 
   // Decode encoded frame (as a part of a video stream). The decoded frame
   // will be returned to the user through the decode complete callback.
   //
-  // inputFrame:        Frame to decode.
-  //
-  // missingFrames:     True if one or more frames have been lost since the previous decode call.
-  //
-  // fragmentation:     Specifies where the encoded frame can be split into separate fragments.
-  //                    The meaning of fragment is codec specific, but often means that each
-  //                    fragment is decodable by itself.
-  //
-  // codecSpecificInfo: Codec-specific data
-  //
-  // renderTimeMs :     System time to render in milliseconds. Only used by decoders with internal
-  //                    rendering.
+  // - aInputFrame: Frame to decode. Call Destroy() on frame when it's decoded.
+  // - aMissingFrames: True if one or more frames have been lost since the
+  //                   previous decode call.
+  // - aBufferType : type of frame to encode
+  // - aCodecSpecificInfo : codec specific data, pointer to a
+  //                        GMPCodecSpecificInfo structure appropriate for
+  //                        this codec type.
+  // - aCodecSpecificInfoLength : number of bytes in aCodecSpecificInfo
+  // - renderTimeMs : System time to render in milliseconds. Only used by
+  //                  decoders with internal rendering.
   virtual GMPErr Decode(GMPVideoEncodedFrame* aInputFrame,
                         bool aMissingFrames,
-                        const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                        GMPBufferType aBufferType,
+                        const uint8_t* aCodecSpecificInfo,
+                        uint32_t aCodecSpecificInfoLength,
                         int64_t aRenderTimeMs = -1) = 0;
 
   // Reset decoder state and prepare for a new call to Decode(...).
   // Flushes the decoder pipeline.
   // The decoder should enqueue a task to run ResetComplete() on the main
   // thread once the reset has finished.
   virtual GMPErr Reset() = 0;
 
--- a/content/media/gmp/gmp-api/gmp-video-encode.h
+++ b/content/media/gmp/gmp-api/gmp-video-encode.h
@@ -44,30 +44,34 @@
 
 // ALL METHODS MUST BE CALLED ON THE MAIN THREAD
 class GMPVideoEncoderCallback
 {
 public:
   virtual ~GMPVideoEncoderCallback() {}
 
   virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
-                       const GMPCodecSpecificInfo& aCodecSpecificInfo) = 0;
+                       GMPBufferType aBufferType,
+                       const uint8_t* aCodecSpecificInfo,
+                       uint32_t aCodecSpecificInfoLength) = 0;
 };
 
 // ALL METHODS MUST BE CALLED ON THE MAIN THREAD
 class GMPVideoEncoder
 {
 public:
   virtual ~GMPVideoEncoder() {}
 
   // Initialize the encoder with the information from the VideoCodec.
   //
   // Input:
   // - codecSettings : Codec settings
-  // - aCodecSpecific : codec specific data
+  // - aCodecSpecific : codec specific data, pointer to a
+  //                    GMPCodecSpecific structure appropriate for
+  //                    this codec type.
   // - aCodecSpecificLength : number of bytes in aCodecSpecific
   // - aCallback: Subclass should retain reference to it until EncodingComplete
   //              is called. Do not attempt to delete it, host retains ownership.
   // - aNnumberOfCores : Number of cores available for the encoder
   // - aMaxPayloadSize : The maximum size each payload is allowed
   //                    to have. Usually MTU - overhead.
   virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
                             const uint8_t* aCodecSpecific,
@@ -76,21 +80,25 @@ public:
                             int32_t aNumberOfCores,
                             uint32_t aMaxPayloadSize) = 0;
 
   // Encode an I420 frame (as a part of a video stream). The encoded frame
   // will be returned to the user through the encode complete callback.
   //
   // Input:
   // - aInputFrame : Frame to be encoded
-  // - aCodecSpecificInfo : Pointer to codec specific data
+  // - aCodecSpecificInfo : codec specific data, pointer to a
+  //                        GMPCodecSpecificInfo structure appropriate for
+  //                        this codec type.
+  // - aCodecSpecificInfoLength : number of bytes in aCodecSpecific
   // - aFrameTypes : The frame type to encode
   // - aFrameTypesLength : The number of elements in aFrameTypes array.
   virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
-                        const GMPCodecSpecificInfo& aCodecSpecificInfo,
+                        const uint8_t* aCodecSpecificInfo,
+                        uint32_t aCodecSpecificInfoLength,
                         const GMPVideoFrameType* aFrameTypes,
                         uint32_t aFrameTypesLength) = 0;
 
   // Inform the encoder about the packet loss and round trip time on the
   // network used to decide the best pattern and signaling.
   //
   // - packetLoss : Fraction lost (loss rate in percent =
   // 100 * packetLoss / 255)
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
@@ -237,31 +237,33 @@ WebrtcGmpVideoEncoder::Encode_g(const we
   }
   frame->SetTimestamp((aInputImage->timestamp() * 1000ll)/90); // note: rounds down!
   //frame->SetDuration(1000000ll/30); // XXX base duration on measured current FPS - or don't bother
 
   // Bug XXXXXX: Set codecSpecific info
   GMPCodecSpecificInfo info;
   memset(&info, 0, sizeof(info));
   info.mCodecType = kGMPVideoCodecH264;
+  nsTArray<uint8_t> codecSpecificInfo;
+  codecSpecificInfo.AppendElements((uint8_t*)&info, sizeof(GMPCodecSpecificInfo));
 
   nsTArray<GMPVideoFrameType> gmp_frame_types;
   for (auto it = aFrameTypes->begin(); it != aFrameTypes->end(); ++it) {
     GMPVideoFrameType ft;
 
     int32_t ret = WebrtcFrameTypeToGmpFrameType(*it, &ft);
     if (ret != WEBRTC_VIDEO_CODEC_OK) {
       return ret;
     }
 
     gmp_frame_types.AppendElement(ft);
   }
 
   LOGD(("GMP Encode: %llu", (aInputImage->timestamp() * 1000ll)/90));
-  err = mGMP->Encode(frame, info, gmp_frame_types);
+  err = mGMP->Encode(frame, codecSpecificInfo, gmp_frame_types);
   if (err != GMPNoErr) {
     return err;
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 
@@ -310,35 +312,35 @@ WebrtcGmpVideoEncoder::SetRates_g(uint32
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 // GMPVideoEncoderCallback virtual functions.
 void
 WebrtcGmpVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
-                               const GMPCodecSpecificInfo& aCodecSpecificInfo)
+                               GMPBufferType aBufferType,
+                               const nsTArray<uint8_t>& aCodecSpecificInfo)
 {
   if (mCallback) { // paranoia
     webrtc::VideoFrameType ft;
     GmpFrameTypeToWebrtcFrameType(aEncodedFrame->FrameType(), &ft);
-    GMPBufferType type = aCodecSpecificInfo.mBufferType;
     uint32_t timestamp = (aEncodedFrame->TimeStamp() * 90ll + 999)/1000;
 
-    LOGD(("GMP Encoded: %llu, type %d, len %d", aEncodedFrame->TimeStamp(), type,
+    LOGD(("GMP Encoded: %llu, type %d, len %d", aEncodedFrame->TimeStamp(), aBufferType,
          aEncodedFrame->Size()));
 
     // Right now makes one Encoded() callback per unit
     // XXX convert to FragmentationHeader format (array of offsets and sizes plus a buffer) in
     // combination with H264 packetization changes in webrtc/trunk code
     uint8_t *buffer = aEncodedFrame->Buffer();
     uint8_t *end = aEncodedFrame->Buffer() + aEncodedFrame->Size();
     uint32_t size;
     while (buffer < end) {
-      switch (type) {
+      switch (aBufferType) {
         case GMP_BufferSingle:
           size = aEncodedFrame->Size();
           break;
         case GMP_BufferLength8:
           size = *buffer++;
           break;
         case GMP_BufferLength16:
           // presumes we can do unaligned loads
@@ -355,17 +357,17 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoE
           break;
         case GMP_BufferLength32:
           // presumes we can do unaligned loads
           size = *(reinterpret_cast<uint32_t*>(buffer));
           buffer += 4;
           break;
         default:
           // really that it's not in the enum; gives more readable error
-          MOZ_ASSERT(aCodecSpecificInfo.mBufferType != GMP_BufferSingle);
+          MOZ_ASSERT(aBufferType != GMP_BufferSingle);
           aEncodedFrame->Destroy();
           return;
       }
       webrtc::EncodedImage unit(buffer, size, size);
       unit._frameType = ft;
       unit._timeStamp = timestamp;
       unit._completeFrame = true;
 
@@ -508,21 +510,26 @@ WebrtcGmpVideoDecoder::Decode_g(const we
   if (ret != WEBRTC_VIDEO_CODEC_OK) {
     return ret;
   }
 
   // Bug XXXXXX: Set codecSpecific info
   GMPCodecSpecificInfo info;
   memset(&info, 0, sizeof(info));
   info.mCodecType = kGMPVideoCodecH264;
-  info.mBufferType = GMP_BufferLength32;
   info.mCodecSpecific.mH264.mSimulcastIdx = 0;
+  nsTArray<uint8_t> codecSpecificInfo;
+  codecSpecificInfo.AppendElements((uint8_t*)&info, sizeof(GMPCodecSpecificInfo));
 
   LOGD(("GMP Decode: %llu, len %d", frame->TimeStamp(), aInputImage._length));
-  nsresult rv = mGMP->Decode(frame, aMissingFrames, info, aRenderTimeMs);
+  nsresult rv = mGMP->Decode(frame,
+                             aMissingFrames,
+                             GMP_BufferLength32,
+                             codecSpecificInfo,
+                             aRenderTimeMs);
   if (NS_FAILED(rv)) {
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
@@ -33,17 +33,17 @@
 #include "GMPVideoDecoderProxy.h"
 #include "GMPVideoEncoderProxy.h"
 
 #include "WebrtcGmpVideoCodec.h"
 
 namespace mozilla {
 
 class WebrtcGmpVideoEncoder : public WebrtcVideoEncoder,
-                              public GMPVideoEncoderCallback
+                              public GMPVideoEncoderCallbackProxy
 {
 public:
   WebrtcGmpVideoEncoder();
   virtual ~WebrtcGmpVideoEncoder() {}
 
   // Implement VideoEncoder interface.
   virtual int32_t InitEncode(const webrtc::VideoCodec* aCodecSettings,
                              int32_t aNumberOfCores,
@@ -61,17 +61,18 @@ public:
   virtual int32_t SetChannelParameters(uint32_t aPacketLoss,
                                        int aRTT) MOZ_OVERRIDE;
 
   virtual int32_t SetRates(uint32_t aNewBitRate,
                            uint32_t aFrameRate) MOZ_OVERRIDE;
 
   // GMPVideoEncoderCallback virtual functions.
   virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
-                       const GMPCodecSpecificInfo& aCodecSpecificInfo) MOZ_OVERRIDE;
+                       GMPBufferType aBufferType,
+                       const nsTArray<uint8_t>& aCodecSpecificInfo) MOZ_OVERRIDE;
 
 
 private:
   virtual int32_t InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
                                int32_t aNumberOfCores,
                                uint32_t aMaxPayloadSize);
 
   virtual int32_t Encode_g(const webrtc::I420VideoFrame* aInputImage,