<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214960] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214960">214960</a></dd>
<dt>Author</dt> <dd>clopez@igalia.com</dd>
<dt>Date</dt> <dd>2017-04-05 12:14:36 -0700 (Wed, 05 Apr 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>[WebRTC][OpenWebRTC] Add support for SDP BUNDLE ("a:group:BUNDLE" and "a=bundle-only" lines)
https://bugs.webkit.org/show_bug.cgi?id=170157
Reviewed by Alejandro G. Castro.
Source/WebCore:
This implements support on the SDPProcessor for generating an "a=group:BUNDLE"
attribute with the MID identifiers specified in the bundle group in the most
recent answer.
It also implements support for generating "a=bundle-only" attributes on the
"m=" sections of the SDP according to the bundlePolicy defined.
Test: fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html
* Modules/mediastream/MediaEndpointPeerConnection.cpp:
(WebCore::MediaEndpointPeerConnection::createOfferTask):
(WebCore::MediaEndpointPeerConnection::createAnswerTask):
* Modules/mediastream/SDPProcessor.cpp:
(WebCore::getBundlePolicyName):
(WebCore::configurationToJSON):
* Modules/mediastream/sdp.js:
(SDP.generate):
* platform/mediastream/MediaEndpointSessionConfiguration.h:
(WebCore::MediaEndpointSessionConfiguration::bundlePolicy):
(WebCore::MediaEndpointSessionConfiguration::setBundlePolicy):
(WebCore::MediaEndpointSessionConfiguration::clone):
LayoutTests:
The test fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html
is used to check that we generate the "a=bundle-only" lines on the "m=" sections
according to the bundlePolicy. The 3 possible values of bundlePolicy are tested.
To properly test bundlePolicy:"balanced" we generate 5 extra tracks (6 in total)
for each one of the audio media type and video media type.
* TestExpectations: Set RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html
as failing in the general TestExpectations, because the libwebrtc backend currently
doesn't generate the expected a=bundle-only lines.
On the GTK+ port TestExpectations file this is overriden, and the test is marked to pass.
The whole fast/mediastream directory is already overriden to pass.
* fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only-expected.txt: Added.
* fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html: Added.
* fast/mediastream/resources/sdp-utils.js:
(printComparableSessionDescription): Validate the a=group:BUNDLE line to contain the required MID identifiers.
* platform/gtk/fast/mediastream/RTCPeerConnection-inspect-answer-expected.txt: Added. Rebaseline with the expected a=group:BUNDLE line.
* platform/gtk/fast/mediastream/RTCPeerConnection-inspect-offer-expected.txt: Added. Rebaseline with the expected a=group:BUNDLE line.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsTestExpectations">trunk/LayoutTests/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamresourcessdputilsjs">trunk/LayoutTests/fast/mediastream/resources/sdp-utils.js</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaEndpointPeerConnectioncpp">trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamSDPProcessorcpp">trunk/Source/WebCore/Modules/mediastream/SDPProcessor.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamsdpjs">trunk/Source/WebCore/Modules/mediastream/sdp.js</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaEndpointSessionConfigurationh">trunk/Source/WebCore/platform/mediastream/MediaEndpointSessionConfiguration.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastmediastreamRTCPeerConnectioninspectofferbundlePolicybundleonlyexpectedtxt">trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamRTCPeerConnectioninspectofferbundlePolicybundleonlyhtml">trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html</a></li>
<li><a href="#trunkLayoutTestsplatformgtkfastmediastreamRTCPeerConnectioninspectanswerexpectedtxt">trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-answer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformgtkfastmediastreamRTCPeerConnectioninspectofferexpectedtxt">trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-offer-expected.txt</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/LayoutTests/ChangeLog        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2017-04-05 Carlos Alberto Lopez Perez <clopez@igalia.com>
+
+ [WebRTC][OpenWebRTC] Add support for SDP BUNDLE ("a:group:BUNDLE" and "a=bundle-only" lines)
+ https://bugs.webkit.org/show_bug.cgi?id=170157
+
+ Reviewed by Alejandro G. Castro.
+
+ The test fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html
+ is used to check that we generate the "a=bundle-only" lines on the "m=" sections
+ according to the bundlePolicy. The 3 possible values of bundlePolicy are tested.
+ To properly test bundlePolicy:"balanced" we generate 5 extra tracks (6 in total)
+ for each one of the audio media type and video media type.
+
+ * TestExpectations: Set RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html
+ as failing in the general TestExpectations, because the libwebrtc backend currently
+ doesn't generate the expected a=bundle-only lines.
+ On the GTK+ port TestExpectations file this is overriden, and the test is marked to pass.
+ The whole fast/mediastream directory is already overriden to pass.
+ * fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only-expected.txt: Added.
+ * fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html: Added.
+ * fast/mediastream/resources/sdp-utils.js:
+ (printComparableSessionDescription): Validate the a=group:BUNDLE line to contain the required MID identifiers.
+ * platform/gtk/fast/mediastream/RTCPeerConnection-inspect-answer-expected.txt: Added. Rebaseline with the expected a=group:BUNDLE line.
+ * platform/gtk/fast/mediastream/RTCPeerConnection-inspect-offer-expected.txt: Added. Rebaseline with the expected a=group:BUNDLE line.
+
</ins><span class="cx"> 2017-04-05 Jer Noble <jer.noble@apple.com>
</span><span class="cx">
</span><span class="cx"> [MSE] Seeks to currentTime=0 will fail if currentTime is already 0.
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/LayoutTests/TestExpectations        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -724,6 +724,8 @@
</span><span class="cx"> fast/mediastream/RTCRtpSender-replaceTrack.html [ Skip ]
</span><span class="cx"> fast/mediastream/RTCPeerConnection-icecandidate-event.html [ Pass Failure ]
</span><span class="cx"> fast/mediastream/RTCPeerConnection-dtmf.html [ Failure ]
</span><ins>+# libwebrtc backend doesn't generate a=bundle-only lines
+fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html [ Failure ]
</ins><span class="cx">
</span><span class="cx"> # Need updating wptserve
</span><span class="cx"> imported/w3c/web-platform-tests/XMLHttpRequest/setrequestheader-content-type.htm [ Skip ]
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamRTCPeerConnectioninspectofferbundlePolicybundleonlyexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only-expected.txt (0 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only-expected.txt         (rev 0)
+++ trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only-expected.txt        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -0,0 +1,700 @@
</span><ins>+Inspect that the SDP offer contains the correct number of a=bundle-only lines according to the bundlePolicy value.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Start promise chain for bundlePolicy: max-compat
+PASS Generated SDP offer for bundlePolicy: max-compat
+=== RTCSessionDescription ===
+type: offer, sdp:
+v=0
+o=- {session-id:OK} 0 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE {bundle:OK}
+a=msid-semantic:WMS {media-stream-id:OK}
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+===
+
+PASS Generated SDP offer for bundlePolicy: max-compat. Got the expected number of a=bundle-only lines: 0
+PASS Start promise chain for bundlePolicy: balanced
+PASS Generated SDP offer for bundlePolicy: balanced
+=== RTCSessionDescription ===
+type: offer, sdp:
+v=0
+o=- {session-id:OK} 0 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE {bundle:OK}
+a=msid-semantic:WMS {media-stream-id:OK}
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+===
+
+PASS Generated SDP offer for bundlePolicy: balanced. Got the expected number of a=bundle-only lines: 10
+PASS Start promise chain for bundlePolicy: max-bundle
+PASS Generated SDP offer for bundlePolicy: max-bundle
+=== RTCSessionDescription ===
+type: offer, sdp:
+v=0
+o=- {session-id:OK} 0 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE {bundle:OK}
+a=msid-semantic:WMS {media-stream-id:OK}
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=bundle-only
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+===
+
+PASS Generated SDP offer for bundlePolicy: max-bundle. Got the expected number of a=bundle-only lines: 11
+PASS Tested the following bundlePolicy values: max-compat balanced max-bundle
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamRTCPeerConnectioninspectofferbundlePolicybundleonlyhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html (0 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html         (rev 0)
+++ trunk/LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <script src="../../resources/js-test-pre.js"></script>
+ <script src="./resources/sdp-utils.js"></script>
+ </head>
+ <body>
+ <script>
+
+ description("Inspect that the SDP offer contains the correct number of a=bundle-only lines according to the bundlePolicy value.");
+
+ if (window.testRunner)
+ testRunner.setUserMediaPermission(true);
+ else {
+ debug("This test can not be run without the testRunner");
+ finishJSTest();
+ }
+
+ function testBundlePolicySDP(bundlePolicy) {
+ var mediaDescriptionVariables = [];
+ var numberOfExtraTracksPerType = 5;
+ var stream;
+ var numberOfGeneratedBundleOnlyLines = 0;
+ var numberOfExpectedBundleOnlyLines = 0;
+ var numberOfDifferentTypeTracks = 2; // audio and video
+
+ switch (bundlePolicy) {
+ case "max-compat":
+ // None of the m= sections should have a=bundle-only.
+ numberOfExpectedBundleOnlyLines = 0;
+ break;
+ case "max-bundle":
+ // All the m= sections (except the first one) should have a=bundle-only.
+ numberOfExpectedBundleOnlyLines = numberOfDifferentTypeTracks * (numberOfExtraTracksPerType + 1 ) - 1;
+ break;
+ default: // balanced
+ // All the m= sections (except the first one of each type) should have a=bundle-only.
+ numberOfExpectedBundleOnlyLines = numberOfDifferentTypeTracks * numberOfExtraTracksPerType;
+ break;
+ }
+ if (numberOfExpectedBundleOnlyLines < 0)
+ numberOfExpectedBundleOnlyLines = 0;
+
+ var connectionConfig = { iceServers:[{urls:'stun:foo.com'}],
+ bundlePolicy: bundlePolicy };
+ var pc = new RTCPeerConnection(connectionConfig);
+
+ navigator.mediaDevices.getUserMedia({ "audio": true, "video": true})
+ .then(function (stream) {
+ testPassed("Start promise chain for bundlePolicy: " + bundlePolicy);
+ var audioTrack = stream.getAudioTracks()[0];
+ var videoTrack = stream.getVideoTracks()[0];
+ pc.addTrack(audioTrack, stream);
+ pc.addTrack(videoTrack, stream);
+ mediaDescriptionVariables.push({ "trackId": audioTrack.id, "streamId": stream.id });
+ mediaDescriptionVariables.push({ "trackId": videoTrack.id, "streamId": stream.id });
+ for(var i=0; i < numberOfExtraTracksPerType; i++){
+ var audioTrackCloned = audioTrack.clone();
+ var videoTrackCloned = videoTrack.clone();
+ pc.addTrack(audioTrackCloned, stream);
+ pc.addTrack(videoTrackCloned, stream);
+ mediaDescriptionVariables.push({ "trackId": audioTrackCloned.id, "streamId": stream.id });
+ mediaDescriptionVariables.push({ "trackId": videoTrackCloned.id, "streamId": stream.id });
+ }
+ return pc.createOffer();
+ })
+ .then(function (offer) {
+ testPassed("Generated SDP offer for bundlePolicy: " + bundlePolicy);
+ printComparableSessionDescription(offer, mediaDescriptionVariables);
+ offer.sdp.split("\r\n").forEach(function (line) {
+ if (line == "a=bundle-only") {
+ numberOfGeneratedBundleOnlyLines++;
+ };
+ });
+ if (numberOfExpectedBundleOnlyLines == numberOfGeneratedBundleOnlyLines) {
+ testPassed("Generated SDP offer for bundlePolicy: " + bundlePolicy + ". Got the expected number of a=bundle-only lines: " + numberOfGeneratedBundleOnlyLines);
+ } else {
+ testFailed("Generated SDP offer for bundlePolicy: " + bundlePolicy + ". Expected " + numberOfExpectedBundleOnlyLines + " a=bundle-only lines, but got " + numberOfGeneratedBundleOnlyLines + " lines instead.");
+ }
+ runNextSubTestIfNotFinished();
+
+ })
+ .catch(function (error) {
+ testFailed("Error caught in promise chain: " + error);
+ finishJSTest();
+ });
+
+ };
+
+
+ function runNextSubTestIfNotFinished() {
+ if (subTestsCompleted == bundlePolicies.length) {
+ testPassed("Tested the following bundlePolicy values: " + bundlePolicies.join(" "));
+ finishJSTest();
+ } else {
+ testBundlePolicySDP(bundlePolicies[subTestsCompleted]);
+ subTestsCompleted++;
+ };
+ };
+
+
+ var subTestsCompleted = 0;
+ var bundlePolicies = ["max-compat", "balanced", "max-bundle"];
+
+ runNextSubTestIfNotFinished();
+
+ window.jsTestIsAsync = true;
+ window.successfullyParsed = true;
+
+ </script>
+ <script src="../../resources/js-test-post.js"></script>
+ </body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamresourcessdputilsjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/resources/sdp-utils.js (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/resources/sdp-utils.js        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/LayoutTests/fast/mediastream/resources/sdp-utils.js        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -16,10 +16,19 @@
</span><span class="cx"> "msid": "^a=(ssrc:\\d+ )?msid:([\\w+/\\-=]+) +([\\w+/\\-=]+).*$",
</span><span class="cx"> "iceufrag": "^a=ice-ufrag:([\\w+/]*).*$",
</span><span class="cx"> "icepwd": "^a=ice-pwd:([\\w+/]*).*$",
</span><ins>+ "bundle": "^a=group:BUNDLE .*$",
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> var mdescIndex = -1;
</span><ins>+
+ var mid;
+ var mids = [];
</ins><span class="cx"> sdp.split("\r\n").forEach(function (line) {
</span><ins>+ if (mid = match(line, regexp.mid))
+ mids.push(mid[1]);
+ });
+
+ sdp.split("\r\n").forEach(function (line) {
</ins><span class="cx"> if (match(line, regexp.mline)) {
</span><span class="cx"> // Media block ("header" line)
</span><span class="cx"> mdescIndex++;
</span><span class="lines">@@ -32,6 +41,9 @@
</span><span class="cx"> // The session-id should be a number between 0 and LLONG_MAX (2^63-1).
</span><span class="cx"> if (sessid >= 0 && sessid <= 9223372036854775807)
</span><span class="cx"> line = line.replace(oline[2], verified("session-id"));
</span><ins>+ } else if (match(line, regexp.bundle)) {
+ if (mids.length > 0)
+ line = line.replace("a=group:BUNDLE " + mids.join(" "), "a=group:BUNDLE " + verified("bundle"));
</ins><span class="cx"> } else if (match(line, regexp.msidsemantic)) {
</span><span class="cx"> mdescVariables.forEach(function (variables) {
</span><span class="cx"> line = line.replace(variables.streamId, verified("media-stream-id"));
</span><span class="lines">@@ -40,7 +52,6 @@
</span><span class="cx"> } else {
</span><span class="cx"> // Media block (content lines)
</span><span class="cx"> var cname;
</span><del>- var mid;
</del><span class="cx"> var msid;
</span><span class="cx"> var iceufrag;
</span><span class="cx"> var icepwd;
</span><span class="lines">@@ -49,7 +60,7 @@
</span><span class="cx"> line = line.replace(cname[1], verified("ssrc"));
</span><span class="cx"> line = line.replace(cname[2], verified("cname"));
</span><span class="cx"> } else if (mid = match(line, regexp.mid))
</span><del>- line = line.replace(mid[1], verified("mid"))
</del><ins>+ line = line.replace(mid[1], verified("mid"));
</ins><span class="cx"> else if (msid = match(line, regexp.msid)) {
</span><span class="cx"> if (msid[1])
</span><span class="cx"> line = line.replace(msid[1], verified("ssrc"));
</span></span></pre></div>
<a id="trunkLayoutTestsplatformgtkfastmediastreamRTCPeerConnectioninspectanswerexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-answer-expected.txt (0 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-answer-expected.txt         (rev 0)
+++ trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-answer-expected.txt        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -0,0 +1,75 @@
</span><ins>+Test RTCPeerConnection.setRemoteDescription called with an RTCSessionDescription of type 'offer'
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Answer with audio created
+=== RTCSessionDescription ===
+type: answer, sdp:
+v=0
+o=- {session-id:OK} 0 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE {bundle:OK}
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=recvonly
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:active
+===
+
+PASS Answer with audio and video created
+=== RTCSessionDescription ===
+type: answer, sdp:
+v=0
+o=- {session-id:OK} 1 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE {bundle:OK}
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=recvonly
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:active
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=recvonly
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:active
+===
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformgtkfastmediastreamRTCPeerConnectioninspectofferexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-offer-expected.txt (0 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-offer-expected.txt         (rev 0)
+++ trunk/LayoutTests/platform/gtk/fast/mediastream/RTCPeerConnection-inspect-offer-expected.txt        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+Inspect the result of RTCPeerConnection.createOffer()
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Got offer
+=== RTCSessionDescription ===
+type: offer, sdp:
+v=0
+o=- {session-id:OK} 0 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE {bundle:OK}
+a=msid-semantic:WMS {media-stream-id:OK}
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+===
+
+PASS Got offer
+=== RTCSessionDescription ===
+type: offer, sdp:
+v=0
+o=- {session-id:OK} 1 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE {bundle:OK}
+a=msid-semantic:WMS {media-stream-id:OK}
+m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:111 OPUS/48000/2
+a=rtpmap:8 PCMA/8000
+a=rtpmap:0 PCMU/8000
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+m=video 9 UDP/TLS/RTP/SAVPF 103 100 120
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendrecv
+a=mid:{mid:OK}
+a=rtpmap:103 H264/90000
+a=rtpmap:100 VP8/90000
+a=rtpmap:120 RTX/90000
+a=fmtp:103 packetization-mode=1
+a=fmtp:120 apt=100;rtx-time=200
+a=rtcp-fb:100 nack
+a=rtcp-fb:103 nack pli
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:103 ccm fir
+a=rtcp-fb:100 ccm fir
+a=ssrc:{ssrc:OK} cname:{cname:OK}
+a=msid:{media-stream-id:OK} {media-stream-track-id:OK}
+a=ice-ufrag:{ice-ufrag:OK}
+a=ice-pwd:{ice-password:OK}
+a=fingerprint:sha-256 8B:87:09:8A:5D:C2:F3:33:EF:C5:B1:F6:84:3A:3D:D6:A3:E2:9C:17:4C:E7:46:3B:1B:CE:84:98:DD:8E:AF:7B
+a=setup:actpass
+===
+
+PASS End of promise chain
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/Source/WebCore/ChangeLog        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2017-04-05 Carlos Alberto Lopez Perez <clopez@igalia.com>
+
+ [WebRTC][OpenWebRTC] Add support for SDP BUNDLE ("a:group:BUNDLE" and "a=bundle-only" lines)
+ https://bugs.webkit.org/show_bug.cgi?id=170157
+
+ Reviewed by Alejandro G. Castro.
+
+ This implements support on the SDPProcessor for generating an "a=group:BUNDLE"
+ attribute with the MID identifiers specified in the bundle group in the most
+ recent answer.
+ It also implements support for generating "a=bundle-only" attributes on the
+ "m=" sections of the SDP according to the bundlePolicy defined.
+
+ Test: fast/mediastream/RTCPeerConnection-inspect-offer-bundlePolicy-bundle-only.html
+
+ * Modules/mediastream/MediaEndpointPeerConnection.cpp:
+ (WebCore::MediaEndpointPeerConnection::createOfferTask):
+ (WebCore::MediaEndpointPeerConnection::createAnswerTask):
+ * Modules/mediastream/SDPProcessor.cpp:
+ (WebCore::getBundlePolicyName):
+ (WebCore::configurationToJSON):
+ * Modules/mediastream/sdp.js:
+ (SDP.generate):
+ * platform/mediastream/MediaEndpointSessionConfiguration.h:
+ (WebCore::MediaEndpointSessionConfiguration::bundlePolicy):
+ (WebCore::MediaEndpointSessionConfiguration::setBundlePolicy):
+ (WebCore::MediaEndpointSessionConfiguration::clone):
+
</ins><span class="cx"> 2017-04-05 Jer Noble <jer.noble@apple.com>
</span><span class="cx">
</span><span class="cx"> [MSE] Seeks to currentTime=0 will fail if currentTime is already 0.
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaEndpointPeerConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -159,6 +159,7 @@
</span><span class="cx"> RefPtr<MediaEndpointSessionConfiguration> configurationSnapshot = localDescription ?
</span><span class="cx"> localDescription->configuration()->clone() : MediaEndpointSessionConfiguration::create();
</span><span class="cx">
</span><ins>+ configurationSnapshot->setBundlePolicy(m_peerConnection.getConfiguration().bundlePolicy);
</ins><span class="cx"> configurationSnapshot->setSessionVersion(m_sdpOfferSessionVersion++);
</span><span class="cx">
</span><span class="cx"> auto transceivers = RtpTransceiverVector(m_peerConnection.getTransceivers());
</span><span class="lines">@@ -237,6 +238,7 @@
</span><span class="cx"> RefPtr<MediaEndpointSessionConfiguration> configurationSnapshot = localDescription ?
</span><span class="cx"> localDescription->configuration()->clone() : MediaEndpointSessionConfiguration::create();
</span><span class="cx">
</span><ins>+ configurationSnapshot->setBundlePolicy(m_peerConnection.getConfiguration().bundlePolicy);
</ins><span class="cx"> configurationSnapshot->setSessionVersion(m_sdpAnswerSessionVersion++);
</span><span class="cx">
</span><span class="cx"> auto transceivers = RtpTransceiverVector(m_peerConnection.getTransceivers());
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamSDPProcessorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/SDPProcessor.cpp (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/SDPProcessor.cpp        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/Source/WebCore/Modules/mediastream/SDPProcessor.cpp        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx">
</span><span class="cx"> STRING_FUNCTION(address)
</span><span class="cx"> STRING_FUNCTION(apt)
</span><ins>+STRING_FUNCTION(bundlePolicy)
</ins><span class="cx"> STRING_FUNCTION(candidates)
</span><span class="cx"> STRING_FUNCTION(ccmfir)
</span><span class="cx"> STRING_FUNCTION(channels)
</span><span class="lines">@@ -340,9 +341,23 @@
</span><span class="cx"> return createCandidate(*candidateObject);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static String getBundlePolicyName(const PeerConnectionStates::BundlePolicy bundlePolicy)
+{
+ switch (bundlePolicy) {
+ case PeerConnectionStates::BundlePolicy::MaxCompat:
+ return "max-compat";
+ case PeerConnectionStates::BundlePolicy::MaxBundle:
+ return "max-bundle";
+ case PeerConnectionStates::BundlePolicy::Balanced:
+ default:
+ return "balanced";
+ };
+}
+
</ins><span class="cx"> static String configurationToJSON(const MediaEndpointSessionConfiguration& configuration)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<InspectorObject> object = InspectorObject::create();
</span><ins>+ object->setString(bundlePolicyString(), getBundlePolicyName(configuration.bundlePolicy()));
</ins><span class="cx">
</span><span class="cx"> RefPtr<InspectorObject> originatorObject = InspectorObject::create();
</span><span class="cx"> originatorObject->setString(sessionIdString(), String::number(configuration.sessionId()));
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamsdpjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/sdp.js (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/sdp.js        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/Source/WebCore/Modules/mediastream/sdp.js        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -68,6 +68,7 @@
</span><span class="cx"> "o=${username} ${sessionId} ${sessionVersion} ${netType} ${addressType} ${address}\r\n" +
</span><span class="cx"> "s=${sessionName}\r\n" +
</span><span class="cx"> "t=${startTime} ${stopTime}\r\n" +
</span><ins>+ "${bundleLine}" +
</ins><span class="cx"> "${msidsemanticLine}",
</span><span class="cx">
</span><span class="cx"> "msidsemantic": "a=msid-semantic:WMS ${mediaStreamIds}\r\n",
</span><span class="lines">@@ -77,6 +78,7 @@
</span><span class="cx"> "c=${netType} ${addressType} ${address}\r\n" +
</span><span class="cx"> "${rtcpLine}" +
</span><span class="cx"> "${rtcpMuxLine}" +
</span><ins>+ "${bundleOnlyLine}" +
</ins><span class="cx"> "a=${mode}\r\n" +
</span><span class="cx"> "${midLine}" +
</span><span class="cx"> "${rtpMapLines}" +
</span><span class="lines">@@ -96,6 +98,7 @@
</span><span class="cx"> "rtcp": "a=rtcp:${port}${[ ]netType}${[ ]addressType}${[ ]address}\r\n",
</span><span class="cx"> "rtcpMux": "a=rtcp-mux\r\n",
</span><span class="cx"> "mid": "a=mid:${mid}\r\n",
</span><ins>+ "bundle": "a=group:BUNDLE ${midsBundle}\r\n",
</ins><span class="cx">
</span><span class="cx"> "rtpMap": "a=rtpmap:${type} ${encodingName}/${clockRate}${[/]channels}\r\n",
</span><span class="cx"> "fmtp": "a=fmtp:${type} ${parameters}\r\n",
</span><span class="lines">@@ -373,6 +376,7 @@
</span><span class="cx"> "sessionName": "-",
</span><span class="cx"> "startTime": 0,
</span><span class="cx"> "stopTime": 0,
</span><ins>+ "bundlePolicy": "balanced",
</ins><span class="cx"> "mediaDescriptions": []
</span><span class="cx"> });
</span><span class="cx"> addDefaults(sdpObj.originator, {
</span><span class="lines">@@ -386,6 +390,8 @@
</span><span class="cx"> var sdpText = fillTemplate(templates.sdp, sdpObj);
</span><span class="cx"> sdpText = fillTemplate(sdpText, sdpObj.originator);
</span><span class="cx">
</span><ins>+ var midsBundle = [];
+ var mediatypesBundle = [];
</ins><span class="cx"> var msidsemanticLine = "";
</span><span class="cx"> var mediaStreamIds = [];
</span><span class="cx"> sdpObj.mediaDescriptions.forEach(function (mdesc) {
</span><span class="lines">@@ -412,10 +418,16 @@
</span><span class="cx"> });
</span><span class="cx"> var mblock = fillTemplate(templates.mblock, mediaDescription);
</span><span class="cx">
</span><del>- var midInfo = {"midLine": ""};
- if (mediaDescription.mid)
- midInfo.midLine = fillTemplate(templates.mid, mediaDescription);
- mblock = fillTemplate(mblock, midInfo);
</del><ins>+ var midBundleInfo = {"midLine": "", "bundleOnlyLine": ""};
+ if (mediaDescription.mid) {
+ midBundleInfo.midLine = fillTemplate(templates.mid, mediaDescription);
+ if ((sdpObj.bundlePolicy == "balanced" && mediatypesBundle.includes(mediaDescription.type)) ||
+ (sdpObj.bundlePolicy == "max-bundle" && mediatypesBundle.length > 0))
+ midBundleInfo.bundleOnlyLine = "a=bundle-only\r\n";
+ mediatypesBundle.push(mediaDescription.type)
+ midsBundle.push(mediaDescription.mid);
+ }
+ mblock = fillTemplate(mblock, midBundleInfo);
</ins><span class="cx">
</span><span class="cx"> var payloadInfo = {"rtpMapLines": "", "fmtpLines": "", "nackLines": "",
</span><span class="cx"> "nackpliLines": "", "ccmfirLines": "", "ericScreamLines": ""};
</span><span class="lines">@@ -523,6 +535,11 @@
</span><span class="cx"> sdpText += mblock;
</span><span class="cx"> });
</span><span class="cx">
</span><ins>+ var bundleLine = "";
+ if (midsBundle.length > 0)
+ bundleLine = fillTemplate(templates.bundle, { "midsBundle": midsBundle.join(" ") });
+ sdpText = fillTemplate(sdpText, { "bundleLine": bundleLine });
+
</ins><span class="cx"> return sdpText;
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaEndpointSessionConfigurationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaEndpointSessionConfiguration.h (214959 => 214960)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaEndpointSessionConfiguration.h        2017-04-05 19:09:28 UTC (rev 214959)
+++ trunk/Source/WebCore/platform/mediastream/MediaEndpointSessionConfiguration.h        2017-04-05 19:14:36 UTC (rev 214960)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(WEB_RTC)
</span><span class="cx">
</span><ins>+#include "PeerConnectionStates.h"
</ins><span class="cx"> #include "PeerMediaDescription.h"
</span><span class="cx"> #include <wtf/CryptographicallyRandomNumber.h>
</span><span class="cx">
</span><span class="lines">@@ -56,6 +57,9 @@
</span><span class="cx"> const Vector<PeerMediaDescription>& mediaDescriptions() const { return m_mediaDescriptions; }
</span><span class="cx"> void addMediaDescription(PeerMediaDescription&& description) { m_mediaDescriptions.append(WTFMove(description)); }
</span><span class="cx">
</span><ins>+ PeerConnectionStates::BundlePolicy bundlePolicy() const { return m_bundlePolicy; }
+ void setBundlePolicy(PeerConnectionStates::BundlePolicy bundlePolicy) { m_bundlePolicy = bundlePolicy; }
+
</ins><span class="cx"> RefPtr<MediaEndpointSessionConfiguration> clone() const
</span><span class="cx"> {
</span><span class="cx"> RefPtr<MediaEndpointSessionConfiguration> copy = create();
</span><span class="lines">@@ -62,6 +66,7 @@
</span><span class="cx"> copy->m_sessionId = m_sessionId;
</span><span class="cx"> copy->m_sessionVersion = m_sessionVersion;
</span><span class="cx"> copy->m_mediaDescriptions = m_mediaDescriptions;
</span><ins>+ copy->m_bundlePolicy = m_bundlePolicy;
</ins><span class="cx">
</span><span class="cx"> return copy;
</span><span class="cx"> }
</span><span class="lines">@@ -77,6 +82,8 @@
</span><span class="cx"> unsigned m_sessionVersion { 0 };
</span><span class="cx">
</span><span class="cx"> Vector<PeerMediaDescription> m_mediaDescriptions;
</span><ins>+
+ PeerConnectionStates::BundlePolicy m_bundlePolicy { PeerConnectionStates::BundlePolicy::Balanced };
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre>
</div>
</div>
</body>
</html>