Bug 1328142 - enable switching between simulcast receive streams r=jesup
authorPaul Kerr [:pkerr] <pkerr@mozilla.com>
Thu, 05 Jan 2017 18:15:56 -0800
changeset 377348 4ea7585240cfbecfa047fb578ba04478f2f19e1f
parent 377347 45500e7a10c367be371038514a1e5c95ea0adb3f
child 377349 2233e03ef6fcee477e6436f932d7464dff161054
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1328142
milestone53.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 1328142 - enable switching between simulcast receive streams r=jesup
dom/media/tests/mochitest/test_peerConnection_simulcastOffer.html
media/webrtc/signaling/src/media-conduit/AudioConduit.h
media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
--- a/dom/media/tests/mochitest/test_peerConnection_simulcastOffer.html
+++ b/dom/media/tests/mochitest/test_peerConnection_simulcastOffer.html
@@ -81,18 +81,18 @@
         },
         function PC_REMOTE_CHECK_SIZE_1() {
           var vlocal = test.pcLocal.localMediaElements[0];
           var vremote = test.pcRemote.remoteMediaElements[0];
           ok(vlocal, "Should have local video element for pcLocal");
           ok(vremote, "Should have remote video element for pcRemote");
           ok(vlocal.videoWidth > 0, "source width is positive");
           ok(vlocal.videoHeight > 0, "source height is positive");
-          is(vremote.videoWidth, vlocal.videoWidth, "sink is same width as source");
-          is(vremote.videoHeight, vlocal.videoHeight, "sink is same height as source");
+          is(vremote.videoWidth, vlocal.videoWidth / 2, "sink is 1/2 width of source");
+          is(vremote.videoHeight, vlocal.videoHeight / 2, "sink is 1/2 height of source");
         },
         function PC_REMOTE_SET_RTP_SECOND_RID(test) {
           // Now, cause pcRemote to filter out everything but the second SSRC.
           // This lets only the other simulcast stream through.
           selectRecvSsrc(test.pcRemote, 1);
         },
         function PC_REMOTE_WAIT_FOR_SECOND_MEDIA_FLOW(test) {
           return test.pcRemote.waitForMediaFlow();
@@ -111,28 +111,18 @@
         },
         function PC_REMOTE_CHECK_SIZE_2() {
           var vlocal = test.pcLocal.localMediaElements[0];
           var vremote = test.pcRemote.remoteMediaElements[0];
           ok(vlocal, "Should have local video element for pcLocal");
           ok(vremote, "Should have remote video element for pcRemote");
           ok(vlocal.videoWidth > 0, "source width is positive");
           ok(vlocal.videoHeight > 0, "source height is positive");
-          is(vremote.videoWidth, vlocal.videoWidth / 2, "sink is 1/2 width of source");
-          is(vremote.videoHeight, vlocal.videoHeight / 2,  "sink is 1/2 height of source");
-        },
-        function PC_REMOTE_SET_RTP_NONEXISTENT_RID(test) {
-          // Now, cause pcRemote to filter out everything, just to make sure
-          // selectRecvSsrc is working.
-          selectRecvSsrc(test.pcRemote, 2);
-        },
-        function PC_REMOTE_ENSURE_NO_FRAMES() {
-          var vremote = test.pcRemote.remoteMediaElements[0];
-          ok(vremote, "Should have remote video element for pcRemote");
-          return helper.verifyNoFrames(vremote);
+          is(vremote.videoWidth, vlocal.videoWidth, "sink is same width as source");
+          is(vremote.videoHeight, vlocal.videoHeight,  "sink is same height as source");
         },
       ]);
 
       return test.run();
   })
   .catch(e => ok(false, "unexpected failure: " + e)));
 </script>
 </pre>
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h
@@ -191,16 +191,20 @@ public:
   webrtc::VoiceEngine* GetVoiceEngine() { return mVoiceEngine; }
 
   /* Set Local SSRC list.
    * Note: Until the refactor of the VoE into the call API is complete
    *   this list should contain only a single ssrc.
    */
   bool SetLocalSSRCs(const std::vector<unsigned int>& aSSRCs) override;
   std::vector<unsigned int> GetLocalSSRCs() const override;
+  bool SetRemoteSSRC(unsigned int ssrc) override
+  {
+    return false;
+  }
   bool GetRemoteSSRC(unsigned int* ssrc) override;
   bool SetLocalCNAME(const char* cname) override;
   bool GetVideoEncoderStats(double* framerateMean,
                             double* framerateStdDev,
                             double* bitrateMean,
                             double* bitrateStdDev,
                             uint32_t* droppedFrames) override
   {
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
+++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
@@ -240,16 +240,17 @@ public:
   /* Sets the local SSRCs
    * @return true iff the local ssrcs == aSSRCs upon return
    * Note: this is an ordered list and {a,b,c} != {b,a,c}
    */
   virtual bool SetLocalSSRCs(const std::vector<unsigned int>& aSSRCs) = 0;
   virtual std::vector<unsigned int> GetLocalSSRCs() const = 0;
 
   virtual bool GetRemoteSSRC(unsigned int* ssrc) = 0;
+  virtual bool SetRemoteSSRC(unsigned int ssrc) = 0;
   virtual bool SetLocalCNAME(const char* cname) = 0;
 
   /**
    * Functions returning stats needed by w3c stats model.
    */
   virtual bool GetVideoEncoderStats(double* framerateMean,
                                     double* framerateStdDev,
                                     double* bitrateMean,
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -403,16 +403,17 @@ WebrtcVideoConduit::DeleteRecvStream()
 
 MediaConduitErrorCode
 WebrtcVideoConduit::CreateRecvStream()
 {
   webrtc::VideoReceiveStream::Decoder decoder_desc;
   std::unique_ptr<webrtc::VideoDecoder> decoder;
   webrtc::VideoDecoder::DecoderType decoder_type;
 
+  mRecvStreamConfig.decoders.clear();
   for (auto& config : mRecvCodecList) {
     decoder_type = PayloadNameToDecoderType(config->mName);
     if (decoder_type == webrtc::VideoDecoder::DecoderType::kUnsupportedCodec) {
       CSFLogError(logTag, "%s Unknown decoder type: %s", __FUNCTION__,
                   config->mName.c_str());
       continue;
     }
 
@@ -687,16 +688,22 @@ WebrtcVideoConduit::SetRemoteSSRC(unsign
     return true;
   }
 
   if (StopReceiving() != kMediaConduitNoError) {
     return false;
   }
 
   DeleteRecvStream();
+  MediaConduitErrorCode rval = CreateRecvStream();
+  if (rval != kMediaConduitNoError) {
+    CSFLogError(logTag, "%s Start Receive Error %d ", __FUNCTION__, rval);
+    return false;
+  }
+
   return (StartReceiving() == kMediaConduitNoError);
 }
 
 bool
 WebrtcVideoConduit::GetRemoteSSRC(unsigned int* ssrc)
 {
   {
     MutexAutoLock lock(mCodecMutex);
@@ -1143,20 +1150,25 @@ WebrtcVideoConduit::ConfigureRecvMediaCo
     } while (ssrc == mRecvStreamConfig.rtp.remote_ssrc);
 
     //DEBUG(pkerr)  mRecvStreamConfig.rtp.local_ssrc = ssrc;
     mRecvStreamConfig.rtp.local_ssrc = 1;
 
     // XXX Copy over those that are the same and don't rebuild them
     mRecvCodecList.SwapElements(recv_codecs);
     recv_codecs.Clear();
-    mRecvStreamConfig.decoders.clear();
     mRecvStreamConfig.rtp.rtx.clear();
     // Rebuilds mRecvStream from mRecvStreamConfig
     DeleteRecvStream();
+    MediaConduitErrorCode rval = CreateRecvStream();
+    if (rval != kMediaConduitNoError) {
+      CSFLogError(logTag, "%s Start Receive Error %d ", __FUNCTION__, rval);
+      return rval;
+    }
+
     return StartReceiving();
   }
   return kMediaConduitNoError;
 }
 
 webrtc::VideoDecoder*
 WebrtcVideoConduit::CreateDecoder(webrtc::VideoDecoder::DecoderType aType)
 {
@@ -1807,24 +1819,17 @@ WebrtcVideoConduit::StartReceiving()
   if (mEngineReceiving) {
     return kMediaConduitNoError;
   }
 
   CSFLogDebug(logTag, "%s Attemping to start... ", __FUNCTION__);
   {
     // Start Receive on the video engine
     MutexAutoLock lock(mCodecMutex);
-
-    if (!mRecvStream) {
-      MediaConduitErrorCode rval = CreateRecvStream();
-      if (rval != kMediaConduitNoError) {
-        CSFLogError(logTag, "%s Start Receive Error %d ", __FUNCTION__, rval);
-        return rval;
-      }
-    }
+    MOZ_ASSERT(mRecvStream);
 
     mRecvStream->Start();
     mEngineReceiving = true;
   }
 
   return kMediaConduitNoError;
 }
 
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -745,35 +745,34 @@ MediaPipeline::UpdateTransport_s(int lev
   } else {
     filter_ = filter;
   }
 }
 
 void
 MediaPipeline::SelectSsrc_m(size_t ssrc_index)
 {
-  RUN_ON_THREAD(sts_thread_,
-                WrapRunnable(
-                    this,
-                    &MediaPipeline::SelectSsrc_s,
-                    ssrc_index),
-                NS_DISPATCH_NORMAL);
+  if (ssrc_index < ssrcs_received_.size()) {
+    uint32_t ssrc = ssrcs_received_[ssrc_index];
+    RUN_ON_THREAD(sts_thread_,
+                  WrapRunnable(
+                               this,
+                               &MediaPipeline::SelectSsrc_s,
+                               ssrc),
+                  NS_DISPATCH_NORMAL);
+
+    conduit_->SetRemoteSSRC(ssrc);
+  }
 }
 
 void
-MediaPipeline::SelectSsrc_s(size_t ssrc_index)
+MediaPipeline::SelectSsrc_s(uint32_t ssrc)
 {
   filter_ = new MediaPipelineFilter;
-  if (ssrc_index < ssrcs_received_.size()) {
-    filter_->AddRemoteSSRC(ssrcs_received_[ssrc_index]);
-  } else {
-    MOZ_MTLOG(ML_WARNING, "SelectSsrc called with " << ssrc_index << " but we "
-                          << "have only seen " << ssrcs_received_.size()
-                          << " ssrcs");
-  }
+  filter_->AddRemoteSSRC(ssrc);
 }
 
 void MediaPipeline::StateChange(TransportFlow *flow, TransportLayer::State state) {
   TransportInfo* info = GetTransportInfo_s(flow);
   MOZ_ASSERT(info);
 
   if (state == TransportLayer::TS_OPEN) {
     MOZ_MTLOG(ML_INFO, "Flow is ready");
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
@@ -119,17 +119,17 @@ class MediaPipeline : public sigslot::ha
   void UpdateTransport_s(int level,
                          RefPtr<TransportFlow> rtp_transport,
                          RefPtr<TransportFlow> rtcp_transport,
                          nsAutoPtr<MediaPipelineFilter> filter);
 
   // Used only for testing; installs a MediaPipelineFilter that filters
   // everything but the nth ssrc
   void SelectSsrc_m(size_t ssrc_index);
-  void SelectSsrc_s(size_t ssrc_index);
+  void SelectSsrc_s(uint32_t ssrc);
 
   virtual Direction direction() const { return direction_; }
   virtual const std::string& trackid() const { return track_id_; }
   virtual int level() const { return level_; }
   virtual bool IsVideo() const = 0;
 
   bool IsDoingRtcpMux() const {
     return (rtp_.type_ == MUX);