Bug 911046 - Part 1: Support external codec in VideoConduit. r=jesup
authorJohn Lin <jolin@mozilla.com>
Mon, 21 Apr 2014 23:40:00 +0200
changeset 179911 29791e7f84ba8ba70e68cf3087a997425456b194
parent 179910 4672ae9dd0c8d06f410c20eabd0c0bc50c597e72
child 179912 5f761a1905ca31ae767aa25eeba3554658cf06c8
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersjesup
bugs911046
milestone31.0a1
Bug 911046 - Part 1: Support external codec in VideoConduit. r=jesup
media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
media/webrtc/signaling/src/media-conduit/VideoConduit.h
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
+++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
@@ -157,16 +157,32 @@ public:
   virtual bool GetRTCPSenderReport(DOMHighResTimeStamp* timestamp,
                                    unsigned int* packetsSent,
                                    uint64_t* bytesSent) = 0;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaSessionConduit)
 
 };
 
+// Abstract base classes for external encoder/decoder.
+class VideoEncoder
+{
+public:
+  virtual ~VideoEncoder() {};
+
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoEncoder);
+};
+
+class VideoDecoder
+{
+public:
+  virtual ~VideoDecoder() {};
+
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoder);
+};
 
 /**
  * MediaSessionConduit for video
  * Refer to the comments on MediaSessionConduit above for overall
  * information
  */
 class VideoSessionConduit : public MediaSessionConduit
 {
@@ -236,16 +252,31 @@ public:
    * @param sendSessionConfig: CodecConfiguration
    * NOTE: This API can be invoked multiple time. Invoking this API may involve restarting
    *        reception sub-system on the engine
    *
    */
   virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
                                 const std::vector<VideoCodecConfig* >& recvCodecConfigList) = 0;
 
+  /**
+   * Set an external encoder
+   * @param encoder
+   * @result: on success, we will use the specified encoder
+   */
+  virtual MediaConduitErrorCode SetExternalSendCodec(int pltype,
+                                                     VideoEncoder* encoder) = 0;
+
+  /**
+   * Set an external decoder
+   * @param decoder
+   * @result: on success, we will use the specified decoder
+   */
+  virtual MediaConduitErrorCode SetExternalRecvCodec(int pltype,
+                                                     VideoDecoder* decoder) = 0;
 
   /**
    * These methods allow unit tests to double-check that the
    * max-fs and max-fr related settings are as expected.
    */
   virtual unsigned short SendingWidth() = 0;
 
   virtual unsigned short SendingHeight() = 0;
@@ -356,12 +387,8 @@ public:
     * @param id: id to be used for this rtp header extension
     * NOTE: See AudioConduit for more information
     */
   virtual MediaConduitErrorCode EnableAudioLevelExtension(bool enabled, uint8_t id) = 0;
 
 };
 }
 #endif
-
-
-
-
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -120,16 +120,17 @@ WebrtcVideoConduit::~WebrtcVideoConduit(
     // We can't delete the VideoEngine until all these are released!
     // And we can't use a Scoped ptr, since the order is arbitrary
     mPtrViEBase = nullptr;
     mPtrViECapture = nullptr;
     mPtrViECodec = nullptr;
     mPtrViENetwork = nullptr;
     mPtrViERender = nullptr;
     mPtrRTP = nullptr;
+    mPtrExtCodec = nullptr;
 
     // only one opener can call Delete.  Have it be the last to close.
     if(mVideoEngine)
     {
       webrtc::VideoEngine::Delete(mVideoEngine);
     }
   }
 }
@@ -279,16 +280,23 @@ MediaConduitErrorCode WebrtcVideoConduit
   }
 
   if( !(mPtrRTP = webrtc::ViERTP_RTCP::GetInterface(mVideoEngine)))
   {
     CSFLogError(logTag, "%s Unable to get video RTCP interface ", __FUNCTION__);
     return kMediaConduitSessionNotInited;
   }
 
+  if ( !(mPtrExtCodec = webrtc::ViEExternalCodec::GetInterface(mVideoEngine)))
+  {
+    CSFLogError(logTag, "%s Unable to get external codec interface %d ",
+                __FUNCTION__, mPtrViEBase->LastError());
+    return kMediaConduitSessionNotInited;
+  }
+
   if (other) {
     mChannel = other->mChannel;
     mPtrExtCapture = other->mPtrExtCapture;
     mCapId = other->mCapId;
   } else {
     CSFLogDebug(logTag, "%s Engine Created: Init'ng the interfaces ",__FUNCTION__);
 
     if(mPtrViEBase->Init() == -1)
@@ -840,16 +848,35 @@ WebrtcVideoConduit::SelectSendResolution
       CSFLogDebug(logTag, "%s: Encoder resolution changed to %ux%u",
                   __FUNCTION__, width, height);
     } // else no change; mSendingWidth likely was 0
   }
   return true;
 }
 
 MediaConduitErrorCode
+WebrtcVideoConduit::SetExternalSendCodec(int pltype,
+                                         VideoEncoder* encoder) {
+  int ret = mPtrExtCodec->RegisterExternalSendCodec(mChannel,
+                                                    pltype,
+                                                    static_cast<WebrtcVideoEncoder*>(encoder),
+                                                    false);
+  return ret ? kMediaConduitInvalidSendCodec : kMediaConduitNoError;
+}
+
+MediaConduitErrorCode
+WebrtcVideoConduit::SetExternalRecvCodec(int pltype,
+                                         VideoDecoder* decoder) {
+  int ret = mPtrExtCodec->RegisterExternalReceiveCodec(mChannel,
+                                                       pltype,
+                                                       static_cast<WebrtcVideoDecoder*>(decoder));
+  return ret ? kMediaConduitInvalidReceiveCodec : kMediaConduitNoError;
+}
+
+MediaConduitErrorCode
 WebrtcVideoConduit::SendVideoFrame(unsigned char* video_frame,
                                    unsigned int video_frame_length,
                                    unsigned short width,
                                    unsigned short height,
                                    VideoType video_type,
                                    uint64_t capture_time)
 {
   CSFLogDebug(logTag,  "%s ", __FUNCTION__);
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -7,39 +7,54 @@
 
 #include "mozilla/Attributes.h"
 
 #include "MediaConduitInterface.h"
 #include "MediaEngineWrapper.h"
 
 // Video Engine Includes
 #include "webrtc/common_types.h"
+#ifdef FF
+#undef FF // Avoid name collision between scoped_ptr.h and nsCRTGlue.h.
+#endif
+#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
 #include "webrtc/video_engine/include/vie_base.h"
 #include "webrtc/video_engine/include/vie_capture.h"
 #include "webrtc/video_engine/include/vie_codec.h"
+#include "webrtc/video_engine/include/vie_external_codec.h"
 #include "webrtc/video_engine/include/vie_render.h"
 #include "webrtc/video_engine/include/vie_network.h"
 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
 
 /** This file hosts several structures identifying different aspects
  * of a RTP Session.
  */
 
  using  webrtc::ViEBase;
  using  webrtc::ViENetwork;
  using  webrtc::ViECodec;
  using  webrtc::ViECapture;
  using  webrtc::ViERender;
  using  webrtc::ViEExternalCapture;
-
+ using  webrtc::ViEExternalCodec;
 
 namespace mozilla {
 
 class WebrtcAudioConduit;
 
+// Interface of external video encoder for WebRTC.
+class WebrtcVideoEncoder:public VideoEncoder
+                         ,public webrtc::VideoEncoder
+{};
+
+// Interface of external video decoder for WebRTC.
+class WebrtcVideoDecoder:public VideoDecoder
+                         ,public webrtc::VideoDecoder
+{};
+
 /**
  * Concrete class for Video session. Hooks up
  *  - media-source and target to external transport
  */
 class WebrtcVideoConduit:public VideoSessionConduit
                          ,public webrtc::Transport
                          ,public webrtc::ExternalRenderer
 {
@@ -122,16 +137,29 @@ public:
    */
   virtual MediaConduitErrorCode SendVideoFrame(unsigned char* video_frame,
                                                 unsigned int video_frame_length,
                                                 unsigned short width,
                                                 unsigned short height,
                                                 VideoType video_type,
                                                 uint64_t capture_time);
 
+  /**
+   * Set an external encoder object |encoder| to the payload type |pltype|
+   * for sender side codec.
+   */
+  virtual MediaConduitErrorCode SetExternalSendCodec(int pltype,
+                                                     VideoEncoder* encoder);
+
+  /**
+   * Set an external decoder object |decoder| to the payload type |pltype|
+   * for receiver side codec.
+   */
+  virtual MediaConduitErrorCode SetExternalRecvCodec(int pltype,
+                                                     VideoDecoder* decoder);
 
 
   /**
    * Webrtc transport implementation to send and receive RTP packet.
    * VideoConduit registers itself as ExternalTransport to the VideoEngine
    */
   virtual int SendPacket(int channel, const void *data, int len) ;
 
@@ -260,16 +288,17 @@ private:
   mozilla::RefPtr<VideoRenderer> mRenderer;
 
   ScopedCustomReleasePtr<webrtc::ViEBase> mPtrViEBase;
   ScopedCustomReleasePtr<webrtc::ViECapture> mPtrViECapture;
   ScopedCustomReleasePtr<webrtc::ViECodec> mPtrViECodec;
   ScopedCustomReleasePtr<webrtc::ViENetwork> mPtrViENetwork;
   ScopedCustomReleasePtr<webrtc::ViERender> mPtrViERender;
   ScopedCustomReleasePtr<webrtc::ViERTP_RTCP> mPtrRTP;
+  ScopedCustomReleasePtr<webrtc::ViEExternalCodec> mPtrExtCodec;
 
   webrtc::ViEExternalCapture* mPtrExtCapture; // shared
 
   // Engine state we are concerned with.
   bool mEngineTransmitting; //If true ==> Transmit Sub-system is up and running
   bool mEngineReceiving;    // if true ==> Receive Sus-sysmtem up and running
 
   int mChannel; // Video Channel for this conduit