Bug 1344556 - Part 1: Test cases for simulcast answerer. r=drno draft
authorByron Campen [:bwc] <docfaraday@gmail.com>
Wed, 08 Mar 2017 11:22:32 -0600
changeset 551892 9319082052b02d731d7a3016906bde128e72414a
parent 551789 9577ddeaafd85554c2a855f385a87472a089d5c0
child 551893 8c4df8561e0758ba132dfe6cc6a85dc91a606a21
push id51186
push userbcampen@mozilla.com
push dateMon, 27 Mar 2017 16:29:37 +0000
reviewersdrno
bugs1344556
milestone55.0a1
Bug 1344556 - Part 1: Test cases for simulcast answerer. r=drno MozReview-Commit-ID: DiHjaPlmmDx
dom/media/tests/mochitest/mochitest.ini
dom/media/tests/mochitest/sdpUtils.js
dom/media/tests/mochitest/test_peerConnection_simulcastAnswer.html
dom/media/tests/mochitest/test_peerConnection_simulcastOffer.html
media/webrtc/signaling/gtest/jsep_track_unittest.cpp
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -186,16 +186,18 @@ skip-if = android_version
 [test_peerConnection_restartIceLocalRollback.html]
 skip-if = android_version
 [test_peerConnection_restartIceLocalAndRemoteRollback.html]
 skip-if = android_version
 [test_peerConnection_scaleResolution.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_simulcastOffer.html]
 skip-if = android_version # no simulcast support on android
+[test_peerConnection_simulcastAnswer.html]
+skip-if = android_version # no simulcast support on android
 #[test_peerConnection_relayOnly.html]
 [test_peerConnection_callbacks.html]
 skip-if = (android_version == '18' && debug) # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_replaceTrack.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_syncSetDescription.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_setLocalAnswerInHaveLocalOffer.html]
--- a/dom/media/tests/mochitest/sdpUtils.js
+++ b/dom/media/tests/mochitest/sdpUtils.js
@@ -65,16 +65,22 @@ setAllMsectionsInactive: function(sdp) {
 removeAllRtpMaps: function(sdp) {
   return sdp.replace(/a=rtpmap:.*\r\n/g, "");
 },
 
 reduceAudioMLineToDynamicPtAndOpus: function(sdp) {
   return sdp.replace(/m=audio .*\r\n/g, "m=audio 9 UDP/TLS/RTP/SAVPF 101 109\r\n");
 },
 
+removeSimulcastProperties: function(sdp) {
+  return sdp.replace(/a=simulcast:.*\r\n/g, "")
+            .replace(/a=rid:.*\r\n/g, "")
+            .replace(/a=extmap:[^\s]* urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id.*\r\n/g, "");
+},
+
 transferSimulcastProperties: function(offer_sdp, answer_sdp) {
   if (!offer_sdp.includes("a=simulcast:")) {
     return answer_sdp;
   }
   ok(offer_sdp.includes("a=simulcast: send rid"), "Offer contains simulcast attribute");
   var o_simul = offer_sdp.match(/simulcast: send rid=(.*)([\n$])*/i);
   var new_answer_sdp = answer_sdp + "a=simulcast: recv rid=" + o_simul[1] + "\r\n";
   ok(offer_sdp.includes("a=rid:"), "Offer contains RID attribute");
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_simulcastAnswer.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="pc.js"></script>
+  <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1231507",
+    title: "Basic video-only peer connection with Simulcast answer",
+    visible: true
+  });
+
+  var test;
+  var pushPrefs = (...p) => SpecialPowers.pushPrefEnv({set: p});
+
+  function selectRecvSsrc(pc, index) {
+    var receivers = pc._pc.getReceivers();
+    is(receivers.length, 1, "We have exactly one RTP receiver");
+    var receiver = receivers[0];
+
+    SpecialPowers.wrap(pc._pc).mozSelectSsrc(receiver, index);
+  }
+
+  runNetworkTest(() =>
+    pushPrefs(['media.peerconnection.simulcast', true],
+              // 180Kbps was determined empirically, set well-higher than
+              // the 80Kbps+overhead needed for the two simulcast streams.
+              // 100Kbps was apparently too low.
+              ['media.peerconnection.video.min_bitrate_estimate', 180*1000]).then(() => {
+      var helper;
+
+      test = new PeerConnectionTest({bundle: false});
+      test.setMediaConstraints([{video: true}], [{video: true}]);
+
+      test.chain.replace("PC_REMOTE_GUM", [
+        function PC_REMOTE_CANVAS_CAPTURESTREAM(test) {
+          helper = new VideoStreamHelper();
+          test.pcRemote.attachLocalStream(helper.stream());
+        }
+      ]);
+
+      test.chain.insertAfter('PC_REMOTE_GET_OFFER', [
+        function PC_REMOTE_SET_RIDS(test) {
+          var senders = test.pcRemote._pc.getSenders();
+          is(senders.length, 1, "We have exactly one RTP sender");
+          var sender = senders[0];
+          ok(sender.track, "Sender has a track");
+
+          return sender.setParameters({
+            encodings: [{ rid: "foo", maxBitrate: 40000 },
+                        { rid: "bar", maxBitrate: 40000, scaleResolutionDownBy: 2 }]
+          });
+        },
+        function PC_LOCAL_ADD_RIDS_TO_OFFER(test) {
+          // Create a dummy offer, and use it to set simulcast stuff on the
+          // offer we will actually be using.
+          return test.createOffer(test.pcRemote).then(offer => {
+            test._local_offer.sdp = sdputils.transferSimulcastProperties(
+                offer.sdp, test._local_offer.sdp);
+            info("Offer with RIDs: " + JSON.stringify(test._local_offer));
+            ok(test._local_offer.sdp.match(/a=simulcast:/), "Modified offer has simulcast");
+            ok(test._local_offer.sdp.match(/a=rid:foo/), "Modified offer has rid foo");
+            ok(test._local_offer.sdp.match(/a=rid:bar/), "Modified offer has rid bar");
+            ok(test._local_offer.sdp.match(/urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id/), "Modified offer has RID");
+          });
+        }
+      ]);
+
+      test.chain.insertAfter('PC_LOCAL_GET_ANSWER',[
+        function PC_LOCAL_REMOVE_SIMULCAST_ATTRS_FROM_ANSWER(test) {
+          test._remote_answer.sdp =
+            sdputils.removeSimulcastProperties(test._remote_answer.sdp);
+        }
+      ]);
+
+      test.chain.insertAfter('PC_REMOTE_WAIT_FOR_MEDIA_FLOW',[
+        function PC_REMOTE_SET_RTP_FIRST_RID(test) {
+          // Cause pcLocal to filter out everything but the first SSRC. This
+          // lets only one of the simulcast streams through.
+          selectRecvSsrc(test.pcLocal, 0);
+        }
+      ]);
+
+      test.chain.append([
+        function PC_LOCAL_WAIT_FOR_FRAMES() {
+          var vremote = test.pcLocal.remoteMediaElements[0];
+          ok(vremote, "Should have remote video element for pcLocal");
+          return helper.waitForFrames(vremote);
+        },
+        function PC_LOCAL_CHECK_SIZE_1() {
+          var vlocal = test.pcRemote.localMediaElements[0];
+          var vremote = test.pcLocal.remoteMediaElements[0];
+          ok(vlocal, "Should have local video element for pcRemote");
+          ok(vremote, "Should have remote video element for pcLocal");
+          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_LOCAL_SET_RTP_SECOND_RID(test) {
+          // Now, cause pcLocal to filter out everything but the second SSRC.
+          // This lets only the other simulcast stream through.
+          selectRecvSsrc(test.pcLocal, 1);
+        },
+        function PC_LOCAL_WAIT_FOR_SECOND_MEDIA_FLOW(test) {
+          return test.pcLocal.waitForMediaFlow();
+        },
+        function PC_LOCAL_WAIT_FOR_FRAMES_2() {
+          var vremote = test.pcLocal.remoteMediaElements[0];
+          ok(vremote, "Should have remote video element for pcLocal");
+          return helper.waitForFrames(vremote);
+        },
+        // For some reason, even though we're getting a 25x25 stream, sometimes
+        // the resolution isn't updated on the video element on the first frame.
+        function PC_LOCAL_WAIT_FOR_FRAMES_3() {
+          var vremote = test.pcLocal.remoteMediaElements[0];
+          ok(vremote, "Should have remote video element for pcLocal");
+          return helper.waitForFrames(vremote);
+        },
+        function PC_LOCAL_CHECK_SIZE_2() {
+          var vlocal = test.pcRemote.localMediaElements[0];
+          var vremote = test.pcLocal.remoteMediaElements[0];
+          ok(vlocal, "Should have local video element for pcRemote");
+          ok(vremote, "Should have remote video element for pcLocal");
+          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");
+        },
+      ]);
+
+      return test.run();
+  })
+  .catch(e => ok(false, "unexpected failure: " + e)));
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/tests/mochitest/test_peerConnection_simulcastOffer.html
+++ b/dom/media/tests/mochitest/test_peerConnection_simulcastOffer.html
@@ -25,17 +25,16 @@
   }
 
   runNetworkTest(() =>
     pushPrefs(['media.peerconnection.simulcast', true],
               // 180Kbps was determined empirically, set well-higher than
               // the 80Kbps+overhead needed for the two simulcast streams.
               // 100Kbps was apparently too low.
               ['media.peerconnection.video.min_bitrate_estimate', 180*1000]).then(() => {
-      SimpleTest.requestCompleteLog();
       var helper;
 
       test = new PeerConnectionTest({bundle: false});
       test.setMediaConstraints([{video: true}], []);
 
       test.chain.replace("PC_LOCAL_GUM", [
         function PC_LOCAL_CANVAS_CAPTURESTREAM(test) {
           helper = new VideoStreamHelper();
--- a/media/webrtc/signaling/gtest/jsep_track_unittest.cpp
+++ b/media/webrtc/signaling/gtest/jsep_track_unittest.cpp
@@ -1221,16 +1221,24 @@ TEST_F(JsepTrackTest, SimulcastOfferer)
   ASSERT_TRUE(mSendOff->GetNegotiatedDetails());
   ASSERT_EQ(2U, mSendOff->GetNegotiatedDetails()->GetEncodingCount());
   ASSERT_EQ("foo", mSendOff->GetNegotiatedDetails()->GetEncoding(0).mRid);
   ASSERT_EQ(40000U,
       mSendOff->GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
   ASSERT_EQ("bar", mSendOff->GetNegotiatedDetails()->GetEncoding(1).mRid);
   ASSERT_EQ(10000U,
       mSendOff->GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
+  ASSERT_NE(std::string::npos,
+            mOffer->ToString().find("a=simulcast: send rid=foo;bar"));
+  ASSERT_NE(std::string::npos,
+            mAnswer->ToString().find("a=simulcast: recv rid=foo;bar"));
+  ASSERT_NE(std::string::npos, mOffer->ToString().find("a=rid:foo send"));
+  ASSERT_NE(std::string::npos, mOffer->ToString().find("a=rid:bar send"));
+  ASSERT_NE(std::string::npos, mAnswer->ToString().find("a=rid:foo recv"));
+  ASSERT_NE(std::string::npos, mAnswer->ToString().find("a=rid:bar recv"));
 }
 
 TEST_F(JsepTrackTest, SimulcastAnswerer)
 {
   Init(SdpMediaSection::kVideo);
   std::vector<JsepTrack::JsConstraints> constraints;
   constraints.push_back(MakeConstraints("foo", 40000));
   constraints.push_back(MakeConstraints("bar", 10000));
@@ -1243,16 +1251,24 @@ TEST_F(JsepTrackTest, SimulcastAnswerer)
   ASSERT_TRUE(mSendAns->GetNegotiatedDetails());
   ASSERT_EQ(2U, mSendAns->GetNegotiatedDetails()->GetEncodingCount());
   ASSERT_EQ("foo", mSendAns->GetNegotiatedDetails()->GetEncoding(0).mRid);
   ASSERT_EQ(40000U,
       mSendAns->GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
   ASSERT_EQ("bar", mSendAns->GetNegotiatedDetails()->GetEncoding(1).mRid);
   ASSERT_EQ(10000U,
       mSendAns->GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
+  ASSERT_NE(std::string::npos,
+            mOffer->ToString().find("a=simulcast: recv rid=foo;bar"));
+  ASSERT_NE(std::string::npos,
+            mAnswer->ToString().find("a=simulcast: send rid=foo;bar"));
+  ASSERT_NE(std::string::npos, mOffer->ToString().find("a=rid:foo recv"));
+  ASSERT_NE(std::string::npos, mOffer->ToString().find("a=rid:bar recv"));
+  ASSERT_NE(std::string::npos, mAnswer->ToString().find("a=rid:foo send"));
+  ASSERT_NE(std::string::npos, mAnswer->ToString().find("a=rid:bar send"));
 }
 
 #define VERIFY_OPUS_MAX_PLAYBACK_RATE(track, expectedRate)  \
 {  \
   JsepTrack& copy(track); \
   ASSERT_TRUE(copy.GetNegotiatedDetails());  \
   ASSERT_TRUE(copy.GetNegotiatedDetails()->GetEncodingCount());  \
   for (auto codec : copy.GetNegotiatedDetails()->GetEncoding(0).GetCodecs()) {\