<!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>[213736] 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/213736">213736</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-10 16:46:44 -0800 (Fri, 10 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Move libwebrtc backend to using tracks
https://bugs.webkit.org/show_bug.cgi?id=169472

Patch by Youenn Fablet &lt;youenn@apple.com&gt; on 2017-03-10
Reviewed by Alex Christensen.

Source/ThirdParty/libwebrtc:

* Source/webrtc/pc/rtcstatscollector.cc: Moving from using media stream to tracks.

Source/WebCore:

Covered by current test sets.

This change allows to move away from streams and use more tracks.
This allows future better alignment with the spec and better implementation of sender/receover/transceiver.

Small refactoring to use more Ref&lt;&gt; in WebRTC track-based code.
Added a notifyAddedTrack to notify the backend that a track was added.
For libwebrtc, this allows calling AddTrack before making the offer.
Updated mock libwebrtc backend accordingly.

* Modules/mediastream/MediaEndpointPeerConnection.cpp:
(WebCore::MediaEndpointPeerConnection::replaceTrack):
(WebCore::MediaEndpointPeerConnection::replaceTrackTask):
* Modules/mediastream/MediaEndpointPeerConnection.h:
* Modules/mediastream/PeerConnectionBackend.h:
(WebCore::PeerConnectionBackend::notifyAddedTrack):
* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::addTrack):
(WebCore::RTCPeerConnection::replaceTrack):
* Modules/mediastream/RTCPeerConnection.h:
* Modules/mediastream/RTCRtpSender.cpp:
(WebCore::RTCRtpSender::create):
(WebCore::RTCRtpSender::RTCRtpSender):
(WebCore::RTCRtpSender::setTrack):
* Modules/mediastream/RTCRtpSender.h:
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
(WebCore::LibWebRTCMediaEndpoint::addTrack):
(WebCore::LibWebRTCMediaEndpoint::doCreateOffer):
(WebCore::LibWebRTCMediaEndpoint::doCreateAnswer):
(WebCore::LibWebRTCMediaEndpoint::getStats):
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
(WebCore::LibWebRTCPeerConnectionBackend::doAddIceCandidate):
(WebCore::LibWebRTCPeerConnectionBackend::notifyAddedTrack):
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
* testing/MockLibWebRTCPeerConnection.cpp:
(WebCore::MockLibWebRTCPeerConnection::AddTrack):
(WebCore::MockLibWebRTCPeerConnection::RemoveTrack):
(WebCore::MockLibWebRTCPeerConnection::CreateOffer):
(WebCore::MockLibWebRTCPeerConnection::CreateAnswer):
* testing/MockLibWebRTCPeerConnection.h:
(WebCore::MockRtpSender::MockRtpSender):
(WebCore::MockRtpSender::ssrc):
(WebCore::MockRtpSender::media_type):
(WebCore::MockRtpSender::id):
(WebCore::MockRtpSender::stream_ids):
(WebCore::MockRtpSender::GetParameters):
(WebCore::MockRtpSender::SetParameters):
(WebCore::MockRtpSender::GetDtmfSender):

LayoutTests:

* TestExpectations:</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="#trunkSourceThirdPartylibwebrtcChangeLog">trunk/Source/ThirdParty/libwebrtc/ChangeLog</a></li>
<li><a href="#trunkSourceThirdPartylibwebrtcSourcewebrtcpcrtcstatscollectorcc">trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtcstatscollector.cc</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="#trunkSourceWebCoreModulesmediastreamMediaEndpointPeerConnectionh">trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamPeerConnectionBackendh">trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCPeerConnectioncpp">trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCPeerConnectionh">trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCRtpSendercpp">trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCRtpSenderh">trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCMediaEndpointcpp">trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCMediaEndpointh">trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCPeerConnectionBackendcpp">trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCPeerConnectionBackendh">trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h</a></li>
<li><a href="#trunkSourceWebCoretestingMockLibWebRTCPeerConnectioncpp">trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingMockLibWebRTCPeerConnectionh">trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/LayoutTests/ChangeLog        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2017-03-10  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        Move libwebrtc backend to using tracks
+        https://bugs.webkit.org/show_bug.cgi?id=169472
+
+        Reviewed by Alex Christensen.
+
+        * TestExpectations:
+
</ins><span class="cx"> 2017-03-10  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Mark compositing/regions/transformed-layer-inside-transformed-layer.html as failing on ios-simulator.
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/LayoutTests/TestExpectations        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -715,8 +715,6 @@
</span><span class="cx"> 
</span><span class="cx"> # See webkit.org/b/168736
</span><span class="cx"> fast/mediastream/RTCPeerConnection-addIceCandidate.html [ Failure  ]
</span><del>-fast/mediastream/RTCPeerConnection-addTrack-reuse-sender.html [ Failure  ]
-fast/mediastream/RTCPeerConnection-legacy-stream-based-api.html [ Failure  ]
</del><span class="cx"> imported/w3c/web-platform-tests/webrtc/datachannel-emptystring.html [ Failure  ]
</span><span class="cx"> imported/w3c/web-platform-tests/webrtc/no-media-call.html [ Failure  ]
</span><span class="cx"> imported/w3c/web-platform-tests/webrtc/promises-call.html [ Failure  ]
</span></span></pre></div>
<a id="trunkSourceThirdPartylibwebrtcChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/ThirdParty/libwebrtc/ChangeLog (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/libwebrtc/ChangeLog        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/ThirdParty/libwebrtc/ChangeLog        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2017-03-10  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        Move libwebrtc backend to using tracks
+        https://bugs.webkit.org/show_bug.cgi?id=169472
+
+        Reviewed by Alex Christensen.
+
+        * Source/webrtc/pc/rtcstatscollector.cc: Moving from using media stream to tracks.
+
</ins><span class="cx"> 2017-03-08  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use H264 hardware encoder for Mac libwebrtc
</span></span></pre></div>
<a id="trunkSourceThirdPartylibwebrtcSourcewebrtcpcrtcstatscollectorcc"></a>
<div class="modfile"><h4>Modified: trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtcstatscollector.cc (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtcstatscollector.cc        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/rtcstatscollector.cc        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -1198,6 +1198,20 @@
</span><span class="cx"> RTCStatsCollector::PrepareTrackToID_s() const {
</span><span class="cx">   RTC_DCHECK(signaling_thread_-&gt;IsCurrent());
</span><span class="cx">   std::map&lt;MediaStreamTrackInterface*, std::string&gt; track_to_id;
</span><ins>+#if defined(WEBRTC_WEBKIT_BUILD)
+  for (auto&amp; sender : pc_-&gt;GetSenders()) {
+    auto track = sender-&gt;track();
+    if (!track)
+      continue;
+    track_to_id[track.get()] = track-&gt;id();
+  }
+  for (auto&amp; receiver : pc_-&gt;GetReceivers()) {
+    auto track = receiver-&gt;track();
+    if (!track)
+      continue;
+    track_to_id[track.get()] = track-&gt;id();
+  }
+#else
</ins><span class="cx">   StreamCollectionInterface* local_and_remote_streams[] =
</span><span class="cx">       { pc_-&gt;local_streams().get(), pc_-&gt;remote_streams().get() };
</span><span class="cx">   for (auto&amp; streams : local_and_remote_streams) {
</span><span class="lines">@@ -1215,6 +1229,7 @@
</span><span class="cx">       }
</span><span class="cx">     }
</span><span class="cx">   }
</span><ins>+#endif
</ins><span class="cx">   return track_to_id;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/ChangeLog        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2017-03-10  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        Move libwebrtc backend to using tracks
+        https://bugs.webkit.org/show_bug.cgi?id=169472
+
+        Reviewed by Alex Christensen.
+
+        Covered by current test sets.
+
+        This change allows to move away from streams and use more tracks.
+        This allows future better alignment with the spec and better implementation of sender/receover/transceiver.
+
+        Small refactoring to use more Ref&lt;&gt; in WebRTC track-based code.
+        Added a notifyAddedTrack to notify the backend that a track was added.
+        For libwebrtc, this allows calling AddTrack before making the offer.
+        Updated mock libwebrtc backend accordingly.
+
+        * Modules/mediastream/MediaEndpointPeerConnection.cpp:
+        (WebCore::MediaEndpointPeerConnection::replaceTrack):
+        (WebCore::MediaEndpointPeerConnection::replaceTrackTask):
+        * Modules/mediastream/MediaEndpointPeerConnection.h:
+        * Modules/mediastream/PeerConnectionBackend.h:
+        (WebCore::PeerConnectionBackend::notifyAddedTrack):
+        * Modules/mediastream/RTCPeerConnection.cpp:
+        (WebCore::RTCPeerConnection::addTrack):
+        (WebCore::RTCPeerConnection::replaceTrack):
+        * Modules/mediastream/RTCPeerConnection.h:
+        * Modules/mediastream/RTCRtpSender.cpp:
+        (WebCore::RTCRtpSender::create):
+        (WebCore::RTCRtpSender::RTCRtpSender):
+        (WebCore::RTCRtpSender::setTrack):
+        * Modules/mediastream/RTCRtpSender.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
+        (WebCore::LibWebRTCMediaEndpoint::addTrack):
+        (WebCore::LibWebRTCMediaEndpoint::doCreateOffer):
+        (WebCore::LibWebRTCMediaEndpoint::doCreateAnswer):
+        (WebCore::LibWebRTCMediaEndpoint::getStats):
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
+        (WebCore::LibWebRTCPeerConnectionBackend::doAddIceCandidate):
+        (WebCore::LibWebRTCPeerConnectionBackend::notifyAddedTrack):
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
+        * testing/MockLibWebRTCPeerConnection.cpp:
+        (WebCore::MockLibWebRTCPeerConnection::AddTrack):
+        (WebCore::MockLibWebRTCPeerConnection::RemoveTrack):
+        (WebCore::MockLibWebRTCPeerConnection::CreateOffer):
+        (WebCore::MockLibWebRTCPeerConnection::CreateAnswer):
+        * testing/MockLibWebRTCPeerConnection.h:
+        (WebCore::MockRtpSender::MockRtpSender):
+        (WebCore::MockRtpSender::ssrc):
+        (WebCore::MockRtpSender::media_type):
+        (WebCore::MockRtpSender::id):
+        (WebCore::MockRtpSender::stream_ids):
+        (WebCore::MockRtpSender::GetParameters):
+        (WebCore::MockRtpSender::SetParameters):
+        (WebCore::MockRtpSender::GetDtmfSender):
+
</ins><span class="cx"> 2017-03-10  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Simple line layout: Check how many orphans needed on the current page before breaking.
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaEndpointPeerConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -693,7 +693,7 @@
</span><span class="cx">     return m_mediaEndpoint-&gt;createDataChannelHandler(label, options);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaEndpointPeerConnection::replaceTrack(RTCRtpSender&amp; sender, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp; withTrack, DOMPromise&lt;void&gt;&amp;&amp; promise)
</del><ins>+void MediaEndpointPeerConnection::replaceTrack(RTCRtpSender&amp; sender, Ref&lt;MediaStreamTrack&gt;&amp;&amp; withTrack, DOMPromise&lt;void&gt;&amp;&amp; promise)
</ins><span class="cx"> {
</span><span class="cx">     RTCRtpTransceiver* transceiver = matchTransceiver(m_peerConnection.getTransceivers(), [&amp;sender] (RTCRtpTransceiver&amp; current) {
</span><span class="cx">         return &amp;current.sender() == &amp;sender;
</span><span class="lines">@@ -713,7 +713,7 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaEndpointPeerConnection::replaceTrackTask(RTCRtpSender&amp; sender, const String&amp; mid, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp; withTrack, DOMPromise&lt;void&gt;&amp; promise)
</del><ins>+void MediaEndpointPeerConnection::replaceTrackTask(RTCRtpSender&amp; sender, const String&amp; mid, Ref&lt;MediaStreamTrack&gt;&amp;&amp; withTrack, DOMPromise&lt;void&gt;&amp; promise)
</ins><span class="cx"> {
</span><span class="cx">     if (m_peerConnection.internalSignalingState() == SignalingState::Closed)
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaEndpointPeerConnectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.h (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.h        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.h        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;MediaStream&gt;&gt; getRemoteStreams() const final;
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;RTCRtpReceiver&gt; createReceiver(const String&amp; transceiverMid, const String&amp; trackKind, const String&amp; trackId) final;
</span><del>-    void replaceTrack(RTCRtpSender&amp;, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) final;
</del><ins>+    void replaceTrack(RTCRtpSender&amp;, Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) final;
</ins><span class="cx"> 
</span><span class="cx">     void emulatePlatformEvent(const String&amp; action) final;
</span><span class="cx"> 
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx"> 
</span><span class="cx">     void addIceCandidateTask(RTCIceCandidate&amp;);
</span><span class="cx"> 
</span><del>-    void replaceTrackTask(RTCRtpSender&amp;, const String&amp; mid, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;);
</del><ins>+    void replaceTrackTask(RTCRtpSender&amp;, const String&amp; mid, Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool localDescriptionTypeValidForState(RTCSessionDescription::SdpType) const;
</span><span class="cx">     bool remoteDescriptionTypeValidForState(RTCSessionDescription::SdpType) const;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamPeerConnectionBackendh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -93,7 +93,8 @@
</span><span class="cx">     virtual Vector&lt;RefPtr&lt;MediaStream&gt;&gt; getRemoteStreams() const = 0;
</span><span class="cx"> 
</span><span class="cx">     virtual Ref&lt;RTCRtpReceiver&gt; createReceiver(const String&amp; transceiverMid, const String&amp; trackKind, const String&amp; trackId) = 0;
</span><del>-    virtual void replaceTrack(RTCRtpSender&amp;, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) = 0;
</del><ins>+    virtual void replaceTrack(RTCRtpSender&amp;, Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) = 0;
+    virtual void notifyAddedTrack(RTCRtpSender&amp;) { }
</ins><span class="cx"> 
</span><span class="cx">     void markAsNeedingNegotiation();
</span><span class="cx">     bool isNegotiationNeeded() const { return m_negotiationNeeded; };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCPeerConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -123,6 +123,7 @@
</span><span class="cx">             existingSender.setMediaStreamIds(WTFMove(mediaStreamIds));
</span><span class="cx">             transceiver-&gt;enableSendingDirection();
</span><span class="cx">             sender = &amp;existingSender;
</span><ins>+            
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -146,6 +147,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_backend-&gt;markAsNeedingNegotiation();
</span><span class="cx"> 
</span><ins>+    m_backend-&gt;notifyAddedTrack(*sender);
</ins><span class="cx">     return Ref&lt;RTCRtpSender&gt; { *sender };
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -510,7 +512,7 @@
</span><span class="cx">     dispatchEvent(event);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RTCPeerConnection::replaceTrack(RTCRtpSender&amp; sender, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp; withTrack, DOMPromise&lt;void&gt;&amp;&amp; promise)
</del><ins>+void RTCPeerConnection::replaceTrack(RTCRtpSender&amp; sender, Ref&lt;MediaStreamTrack&gt;&amp;&amp; withTrack, DOMPromise&lt;void&gt;&amp;&amp; promise)
</ins><span class="cx"> {
</span><span class="cx">     m_backend-&gt;replaceTrack(sender, WTFMove(withTrack), WTFMove(promise));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCPeerConnectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -159,7 +159,7 @@
</span><span class="cx">     bool canSuspendForDocumentSuspension() const final;
</span><span class="cx"> 
</span><span class="cx">     // RTCRtpSenderClient
</span><del>-    void replaceTrack(RTCRtpSender&amp;, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) final;
</del><ins>+    void replaceTrack(RTCRtpSender&amp;, Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) final;
</ins><span class="cx"> 
</span><span class="cx">     PeerConnectionStates::SignalingState m_signalingState { PeerConnectionStates::SignalingState::Stable };
</span><span class="cx">     PeerConnectionStates::IceGatheringState m_iceGatheringState { PeerConnectionStates::IceGatheringState::New };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCRtpSendercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.cpp (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.cpp        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.cpp        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -39,31 +39,29 @@
</span><span class="cx"> 
</span><span class="cx"> Ref&lt;RTCRtpSender&gt; RTCRtpSender::create(Ref&lt;MediaStreamTrack&gt;&amp;&amp; track, Vector&lt;String&gt;&amp;&amp; mediaStreamIds, RTCRtpSenderClient&amp; client)
</span><span class="cx"> {
</span><del>-    const String&amp; trackKind = track-&gt;kind();
-    return adoptRef(*new RTCRtpSender(WTFMove(track), trackKind, WTFMove(mediaStreamIds), client));
</del><ins>+    auto sender = adoptRef(*new RTCRtpSender(track-&gt;kind(), WTFMove(mediaStreamIds), client));
+    sender-&gt;setTrack(WTFMove(track));
+    return sender;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Ref&lt;RTCRtpSender&gt; RTCRtpSender::create(const String&amp; trackKind, Vector&lt;String&gt;&amp;&amp; mediaStreamIds, RTCRtpSenderClient&amp; client)
</span><span class="cx"> {
</span><del>-    return adoptRef(*new RTCRtpSender(nullptr, trackKind, WTFMove(mediaStreamIds), client));
</del><ins>+    return adoptRef(*new RTCRtpSender(trackKind, WTFMove(mediaStreamIds), client));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RTCRtpSender::RTCRtpSender(RefPtr&lt;MediaStreamTrack&gt;&amp;&amp; track, const String&amp; trackKind, Vector&lt;String&gt;&amp;&amp; mediaStreamIds, RTCRtpSenderClient&amp; client)
</del><ins>+RTCRtpSender::RTCRtpSender(const String&amp; trackKind, Vector&lt;String&gt;&amp;&amp; mediaStreamIds, RTCRtpSenderClient&amp; client)
</ins><span class="cx">     : RTCRtpSenderReceiverBase()
</span><span class="cx">     , m_trackKind(trackKind)
</span><span class="cx">     , m_mediaStreamIds(WTFMove(mediaStreamIds))
</span><span class="cx">     , m_client(&amp;client)
</span><span class="cx"> {
</span><del>-    setTrack(WTFMove(track));
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RTCRtpSender::setTrack(RefPtr&lt;MediaStreamTrack&gt;&amp;&amp; track)
</del><ins>+void RTCRtpSender::setTrack(Ref&lt;MediaStreamTrack&gt;&amp;&amp; track)
</ins><span class="cx"> {
</span><del>-    // Save the id from the first non-null track set. That id will be used to negotiate the sender
-    // even if the track is replaced.
-    if (!m_track &amp;&amp; track)
-        m_trackId = track-&gt;id();
-
</del><ins>+    ASSERT(!isStopped());
+    ASSERT(!m_track);
+    m_trackId = track-&gt;id();
</ins><span class="cx">     m_track = WTFMove(track);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCRtpSenderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.h (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.h        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.h        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> class RTCRtpSenderClient {
</span><span class="cx"> public:
</span><del>-    virtual void replaceTrack(RTCRtpSender&amp;, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) = 0;
</del><ins>+    virtual void replaceTrack(RTCRtpSender&amp;, Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual ~RTCRtpSenderClient() { }
</span><span class="cx"> };
</span><span class="lines">@@ -57,12 +57,12 @@
</span><span class="cx"> 
</span><span class="cx">     bool isStopped() const { return !m_client; }
</span><span class="cx">     void stop() { m_client = nullptr; }
</span><del>-    void setTrack(RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;);
</del><ins>+    void setTrack(Ref&lt;MediaStreamTrack&gt;&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     ExceptionOr&lt;void&gt; replaceTrack(Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    RTCRtpSender(RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;, const String&amp; trackKind, Vector&lt;String&gt;&amp;&amp; mediaStreamIds, RTCRtpSenderClient&amp;);
</del><ins>+    RTCRtpSender(const String&amp; trackKind, Vector&lt;String&gt;&amp;&amp; mediaStreamIds, RTCRtpSenderClient&amp;);
</ins><span class="cx"> 
</span><span class="cx">     String m_trackId;
</span><span class="cx">     String m_trackKind;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCMediaEndpointcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -158,19 +158,34 @@
</span><span class="cx">     m_backend-&gt;SetRemoteDescription(&amp;m_setRemoteSessionDescriptionObserver, sessionDescription.release());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline std::string streamId(RTCPeerConnection&amp; connection)
</del><ins>+void LibWebRTCMediaEndpoint::addTrack(MediaStreamTrack&amp; track, const Vector&lt;String&gt;&amp; mediaStreamIds)
</ins><span class="cx"> {
</span><del>-    auto&amp; senders = connection.getSenders();
-    if (senders.size()) {
-        for (RTCRtpSender&amp; sender : senders) {
-            auto* track = sender.track();
-            if (track) {
-                ASSERT(sender.mediaStreamIds().size() == 1);
-                return std::string(sender.mediaStreamIds().first().utf8().data());
-            }
-        }
</del><ins>+    if (!LibWebRTCProvider::factory())
+        return;
+
+    std::vector&lt;webrtc::MediaStreamInterface*&gt; mediaStreams;
+    rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt; mediaStream = nullptr;
+    if (mediaStreamIds.size()) {
+        // libwebrtc is only using the first one if any.
+        mediaStream = LibWebRTCProvider::factory()-&gt;CreateLocalMediaStream(mediaStreamIds[0].utf8().data());
+        mediaStreams.push_back(mediaStream.get());
</ins><span class="cx">     }
</span><del>-    return &quot;av_label&quot;;
</del><ins>+    
+    auto&amp; source = track.source();
+    ASSERT(source.type() != RealtimeMediaSource::None);
+
+    if (source.type() == RealtimeMediaSource::Audio) {
+        auto trackSource = RealtimeOutgoingAudioSource::create(source);
+        auto audioTrack = LibWebRTCProvider::factory()-&gt;CreateAudioTrack(track.id().utf8().data(), trackSource.ptr());
+        trackSource-&gt;setTrack(rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt;(audioTrack));
+        m_peerConnectionBackend.addAudioSource(WTFMove(trackSource));
+        m_backend-&gt;AddTrack(audioTrack.get(), WTFMove(mediaStreams));
+    } else {
+        auto videoSource = RealtimeOutgoingVideoSource::create(source);
+        auto videoTrack = LibWebRTCProvider::factory()-&gt;CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
+        m_peerConnectionBackend.addVideoSource(WTFMove(videoSource));
+        m_backend-&gt;AddTrack(videoTrack.get(), WTFMove(mediaStreams));
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void LibWebRTCMediaEndpoint::doCreateOffer()
</span><span class="lines">@@ -181,31 +196,6 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     m_isInitiator = true;
</span><del>-    auto&amp; senders = m_peerConnectionBackend.connection().getSenders();
-    if (senders.size()) {
-        // FIXME: We only support one stream for the moment.
-        auto stream = LibWebRTCProvider::factory()-&gt;CreateLocalMediaStream(streamId(m_peerConnectionBackend.connection()));
-        for (RTCRtpSender&amp; sender : senders) {
-            auto* track = sender.track();
-            if (track) {
-                ASSERT(sender.mediaStreamIds().size() == 1);
-                auto&amp; source = track-&gt;source();
-                if (source.type() == RealtimeMediaSource::Audio) {
-                    auto trackSource = RealtimeOutgoingAudioSource::create(source);
-                    auto rtcTrack = LibWebRTCProvider::factory()-&gt;CreateAudioTrack(track-&gt;id().utf8().data(), trackSource.ptr());
-                    trackSource-&gt;setTrack(rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt;(rtcTrack));
-                    m_peerConnectionBackend.addAudioSource(WTFMove(trackSource));
-                    stream-&gt;AddTrack(WTFMove(rtcTrack));
-                } else {
-                    auto videoSource = RealtimeOutgoingVideoSource::create(source);
-                    auto videoTrack = LibWebRTCProvider::factory()-&gt;CreateVideoTrack(track-&gt;id().utf8().data(), videoSource.ptr());
-                    m_peerConnectionBackend.addVideoSource(WTFMove(videoSource));
-                    stream-&gt;AddTrack(WTFMove(videoTrack));
-                }
-            }
-        }
-        m_backend-&gt;AddStream(stream);
-    }
</del><span class="cx">     m_backend-&gt;CreateOffer(&amp;m_createSessionDescriptionObserver, nullptr);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -217,37 +207,13 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_isInitiator = false;
</span><del>-
-    auto&amp; senders = m_peerConnectionBackend.connection().getSenders();
-    if (senders.size()) {
-        // FIXME: We only support one stream for the moment.
-        auto stream = LibWebRTCProvider::factory()-&gt;CreateLocalMediaStream(streamId(m_peerConnectionBackend.connection()));
-        for (RTCRtpSender&amp; sender : senders) {
-            auto* track = sender.track();
-            if (track) {
-                ASSERT(sender.mediaStreamIds().size() == 1);
-                auto&amp; source = track-&gt;source();
-                if (source.type() == RealtimeMediaSource::Audio) {
-                    auto trackSource = RealtimeOutgoingAudioSource::create(source);
-                    auto rtcTrack = LibWebRTCProvider::factory()-&gt;CreateAudioTrack(track-&gt;id().utf8().data(), trackSource.ptr());
-                    trackSource-&gt;setTrack(rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt;(rtcTrack));
-                    m_peerConnectionBackend.addAudioSource(WTFMove(trackSource));
-                    stream-&gt;AddTrack(WTFMove(rtcTrack));
-                } else {
-                    auto videoSource = RealtimeOutgoingVideoSource::create(source);
-                    auto videoTrack = LibWebRTCProvider::factory()-&gt;CreateVideoTrack(track-&gt;id().utf8().data(), videoSource.ptr());
-                    m_peerConnectionBackend.addVideoSource(WTFMove(videoSource));
-                    stream-&gt;AddTrack(WTFMove(videoTrack));
-                }
-            }
-        }
-        m_backend-&gt;AddStream(stream);
-    }
</del><span class="cx">     m_backend-&gt;CreateAnswer(&amp;m_createSessionDescriptionObserver, nullptr);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void LibWebRTCMediaEndpoint::getStats(MediaStreamTrack* track, const DeferredPromise&amp; promise)
</span><span class="cx"> {
</span><ins>+    UNUSED_PARAM(track);
+    UNUSED_PARAM(promise);
</ins><span class="cx">     m_backend-&gt;GetStats(StatsCollector::create(*this, promise, track).get());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCMediaEndpointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -79,6 +79,8 @@
</span><span class="cx">     RefPtr&lt;RTCSessionDescription&gt; pendingLocalDescription() const;
</span><span class="cx">     RefPtr&lt;RTCSessionDescription&gt; pendingRemoteDescription() const;
</span><span class="cx"> 
</span><ins>+    void addTrack(MediaStreamTrack&amp;, const Vector&lt;String&gt;&amp;);
+
</ins><span class="cx"> private:
</span><span class="cx">     LibWebRTCMediaEndpoint(LibWebRTCPeerConnectionBackend&amp;, LibWebRTCProvider&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCPeerConnectionBackendcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -169,11 +169,6 @@
</span><span class="cx"> 
</span><span class="cx"> void LibWebRTCPeerConnectionBackend::doAddIceCandidate(RTCIceCandidate&amp; candidate)
</span><span class="cx"> {
</span><del>-    if (!m_isRemoteDescriptionSet) {
-        addIceCandidateFailed(Exception { INVALID_STATE_ERR, &quot;No remote description set&quot; });
-        return;
-    }
-
</del><span class="cx">     webrtc::SdpParseError error;
</span><span class="cx">     int sdpMLineIndex = candidate.sdpMLineIndex() ? candidate.sdpMLineIndex().value() : 0;
</span><span class="cx">     std::unique_ptr&lt;webrtc::IceCandidateInterface&gt; rtcCandidate(webrtc::CreateIceCandidate(candidate.sdpMid().utf8().data(), sdpMLineIndex, candidate.candidate().utf8().data(), &amp;error));
</span><span class="lines">@@ -250,6 +245,12 @@
</span><span class="cx">     return m_endpoint-&gt;remoteDescription();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void LibWebRTCPeerConnectionBackend::notifyAddedTrack(RTCRtpSender&amp; sender)
+{
+    ASSERT(sender.track());
+    m_endpoint-&gt;addTrack(*sender.track(), sender.mediaStreamIds());
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // USE(LIBWEBRTC)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCPeerConnectionBackendh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -67,9 +67,10 @@
</span><span class="cx">     RefPtr&lt;RTCSessionDescription&gt; currentRemoteDescription() const final;
</span><span class="cx">     RefPtr&lt;RTCSessionDescription&gt; pendingRemoteDescription() const final;
</span><span class="cx"> 
</span><ins>+    void notifyAddedTrack(RTCRtpSender&amp;) final;
</ins><span class="cx">     // FIXME: API to implement for real
</span><span class="cx">     Vector&lt;RefPtr&lt;MediaStream&gt;&gt; getRemoteStreams() const final { return { }; }
</span><del>-    void replaceTrack(RTCRtpSender&amp;, RefPtr&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) final { }
</del><ins>+    void replaceTrack(RTCRtpSender&amp;, Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) final { }
</ins><span class="cx"> 
</span><span class="cx">     void emulatePlatformEvent(const String&amp;) final { }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockLibWebRTCPeerConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.cpp (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.cpp        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.cpp        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -226,21 +226,31 @@
</span><span class="cx">     return new rtc::RefCountedObject&lt;MockLibWebRTCDataChannel&gt;(std::string(label), parameters.ordered, parameters.reliable, parameters.id);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool MockLibWebRTCPeerConnection::AddStream(webrtc::MediaStreamInterface* stream)
</del><ins>+rtc::scoped_refptr&lt;webrtc::RtpSenderInterface&gt; MockLibWebRTCPeerConnection::AddTrack(webrtc::MediaStreamTrackInterface* track, std::vector&lt;webrtc::MediaStreamInterface*&gt; streams)
</ins><span class="cx"> {
</span><del>-    m_stream = stream;
</del><span class="cx">     LibWebRTCProvider::callOnWebRTCSignalingThread([observer = &amp;m_observer] {
</span><span class="cx">         observer-&gt;OnRenegotiationNeeded();
</span><span class="cx">     });
</span><del>-    return true;
</del><ins>+
+    if (streams.size())
+        m_streamLabel = streams.front()-&gt;label();
+
+    m_senders.append(new rtc::RefCountedObject&lt;MockRtpSender&gt;(rtc::scoped_refptr&lt;webrtc::MediaStreamTrackInterface&gt;(track)));
+    return m_senders.last().get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MockLibWebRTCPeerConnection::RemoveStream(webrtc::MediaStreamInterface*)
</del><ins>+bool MockLibWebRTCPeerConnection::RemoveTrack(webrtc::RtpSenderInterface* sender)
</ins><span class="cx"> {
</span><span class="cx">     LibWebRTCProvider::callOnWebRTCSignalingThread([observer = &amp;m_observer] {
</span><span class="cx">         observer-&gt;OnRenegotiationNeeded();
</span><span class="cx">     });
</span><del>-    m_stream = nullptr;
</del><ins>+    bool isRemoved = false;
+    return m_senders.removeFirstMatching([&amp;](auto&amp; item) {
+        if (item.get() != sender)
+            return false;
+        isRemoved = true;
+        return true;
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockLibWebRTCPeerConnection::CreateOffer(webrtc::CreateSessionDescriptionObserver* observer, const webrtc::MediaConstraintsInterface*)
</span><span class="lines">@@ -252,10 +262,13 @@
</span><span class="cx">             &quot;o=- 5667094644266930845 &quot; &lt;&lt; m_counter++ &lt;&lt; &quot; IN IP4 127.0.0.1\r\n&quot;
</span><span class="cx">             &quot;s=-\r\n&quot;
</span><span class="cx">             &quot;t=0 0\r\n&quot;;
</span><del>-        if (m_stream) {
</del><ins>+        if (m_senders.size()) {
</ins><span class="cx">             unsigned partCounter = 1;
</span><del>-            sdp &lt;&lt; &quot;a=msid-semantic:WMS &quot; &lt;&lt; m_stream-&gt;label() &lt;&lt; &quot;\r\n&quot;;
-            for (auto&amp; audioTrack : m_stream-&gt;GetAudioTracks()) {
</del><ins>+            sdp &lt;&lt; &quot;a=msid-semantic:WMS &quot; &lt;&lt; m_streamLabel &lt;&lt; &quot;\r\n&quot;;
+            for (auto&amp; sender : m_senders) {
+                auto track = sender-&gt;track();
+                if (track-&gt;kind() != &quot;audio&quot;)
+                    continue;
</ins><span class="cx">                 sdp &lt;&lt;
</span><span class="cx">                     &quot;m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0\r\n&quot;
</span><span class="cx">                     &quot;c=IN IP4 0.0.0.0\r\n&quot;
</span><span class="lines">@@ -266,13 +279,16 @@
</span><span class="cx">                     &quot;a=rtpmap:8 PCMA/8000\r\n&quot;
</span><span class="cx">                     &quot;a=rtpmap:0 PCMU/8000\r\n&quot;
</span><span class="cx">                     &quot;a=ssrc:3409173717 cname:/chKzCS9K6KOgL0n\r\n&quot;
</span><del>-                    &quot;a=msid:&quot; &lt;&lt; m_stream-&gt;label() &lt;&lt; &quot; &quot; &lt;&lt; audioTrack-&gt;id() &lt;&lt; &quot;\r\n&quot;
</del><ins>+                    &quot;a=msid:&quot; &lt;&lt; m_streamLabel &lt;&lt; &quot; &quot; &lt;&lt; track-&gt;id() &lt;&lt; &quot;\r\n&quot;
</ins><span class="cx">                     &quot;a=ice-ufrag:e/B1\r\n&quot;
</span><span class="cx">                     &quot;a=ice-pwd:Yotk3Im3mnyi+1Q38p51MDub\r\n&quot;
</span><span class="cx">                     &quot;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\r\n&quot;
</span><span class="cx">                     &quot;a=setup:actpass\r\n&quot;;
</span><span class="cx">             }
</span><del>-            for (auto&amp; videoTrack : m_stream-&gt;GetVideoTracks()) {
</del><ins>+            for (auto&amp; sender : m_senders) {
+                auto track = sender-&gt;track();
+                if (track-&gt;kind() != &quot;video&quot;)
+                    continue;
</ins><span class="cx">                 sdp &lt;&lt;
</span><span class="cx">                     &quot;m=video 9 UDP/TLS/RTP/SAVPF 103 100 120\r\n&quot;
</span><span class="cx">                     &quot;c=IN IP4 0.0.0.0\r\n&quot;
</span><span class="lines">@@ -290,7 +306,7 @@
</span><span class="cx">                     &quot;a=rtcp-fb:103 ccm fir\r\n&quot;
</span><span class="cx">                     &quot;a=rtcp-fb:100 ccm fir\r\n&quot;
</span><span class="cx">                     &quot;a=ssrc:3409173718 cname:/chKzCS9K6KOgL0n\r\n&quot;
</span><del>-                    &quot;a=msid:&quot; &lt;&lt; m_stream-&gt;label() &lt;&lt; &quot; &quot; &lt;&lt; videoTrack-&gt;id() &lt;&lt; &quot;\r\n&quot;
</del><ins>+                    &quot;a=msid:&quot; &lt;&lt; m_streamLabel &lt;&lt; &quot; &quot; &lt;&lt; track-&gt;id() &lt;&lt; &quot;\r\n&quot;
</ins><span class="cx">                     &quot;a=ice-ufrag:e/B1\r\n&quot;
</span><span class="cx">                     &quot;a=ice-pwd:Yotk3Im3mnyi+1Q38p51MDub\r\n&quot;
</span><span class="cx">                     &quot;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\r\n&quot;
</span><span class="lines">@@ -311,9 +327,11 @@
</span><span class="cx">             &quot;o=- 5667094644266930846 &quot; &lt;&lt; m_counter++ &lt;&lt; &quot; IN IP4 127.0.0.1\r\n&quot;
</span><span class="cx">             &quot;s=-\r\n&quot;
</span><span class="cx">             &quot;t=0 0\r\n&quot;;
</span><del>-        if (m_stream) {
-            for (auto&amp; audioTrack : m_stream-&gt;GetAudioTracks()) {
-                ASSERT_UNUSED(audioTrack, !!audioTrack);
</del><ins>+        if (m_senders.size()) {
+            for (auto&amp; sender : m_senders) {
+                auto track = sender-&gt;track();
+                if (track-&gt;kind() != &quot;audio&quot;)
+                    continue;
</ins><span class="cx">                 sdp &lt;&lt;
</span><span class="cx">                     &quot;m=audio 9 UDP/TLS/RTP/SAVPF 111 8 0\r\n&quot;
</span><span class="cx">                     &quot;c=IN IP4 0.0.0.0\r\n&quot;
</span><span class="lines">@@ -329,8 +347,10 @@
</span><span class="cx">                     &quot;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\r\n&quot;
</span><span class="cx">                     &quot;a=setup:active\r\n&quot;;
</span><span class="cx">             }
</span><del>-            for (auto&amp; videoTrack : m_stream-&gt;GetVideoTracks()) {
-                ASSERT_UNUSED(videoTrack, !!videoTrack);
</del><ins>+            for (auto&amp; sender : m_senders) {
+                auto track = sender-&gt;track();
+                if (track-&gt;kind() != &quot;video&quot;)
+                    continue;
</ins><span class="cx">                 sdp &lt;&lt;
</span><span class="cx">                     &quot;m=video 9 UDP/TLS/RTP/SAVPF 103 100 120\r\n&quot;
</span><span class="cx">                     &quot;c=IN IP4 0.0.0.0\r\n&quot;
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockLibWebRTCPeerConnectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.h (213735 => 213736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.h        2017-03-11 00:46:00 UTC (rev 213735)
+++ trunk/Source/WebCore/testing/MockLibWebRTCPeerConnection.h        2017-03-11 00:46:44 UTC (rev 213736)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class LibWebRTCProvider;
</span><ins>+class MockRtpSender;
</ins><span class="cx"> 
</span><span class="cx"> void useMockRTCPeerConnectionFactory(LibWebRTCProvider*, const String&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -58,12 +59,15 @@
</span><span class="cx">     void StopRtcEventLog() override { }
</span><span class="cx">     void Close() override { }
</span><span class="cx"> 
</span><ins>+    bool AddStream(webrtc::MediaStreamInterface*) final { return false; }
+    void RemoveStream(webrtc::MediaStreamInterface*) final { }
+
</ins><span class="cx"> protected:
</span><span class="cx">     void SetRemoteDescription(webrtc::SetSessionDescriptionObserver*, webrtc::SessionDescriptionInterface*) final;
</span><span class="cx">     void CreateAnswer(webrtc::CreateSessionDescriptionObserver*, const webrtc::MediaConstraintsInterface*) final;
</span><span class="cx">     rtc::scoped_refptr&lt;webrtc::DataChannelInterface&gt; CreateDataChannel(const std::string&amp;, const webrtc::DataChannelInit*) final;
</span><del>-    bool AddStream(webrtc::MediaStreamInterface*) final;
-    void RemoveStream(webrtc::MediaStreamInterface*) final;
</del><ins>+    rtc::scoped_refptr&lt;webrtc::RtpSenderInterface&gt; AddTrack(webrtc::MediaStreamTrackInterface*, std::vector&lt;webrtc::MediaStreamInterface*&gt; streams) final;
+    bool RemoveTrack(webrtc::RtpSenderInterface*) final;
</ins><span class="cx"> 
</span><span class="cx">     void SetLocalDescription(webrtc::SetSessionDescriptionObserver*, webrtc::SessionDescriptionInterface*) override;
</span><span class="cx">     bool GetStats(webrtc::StatsObserver*, webrtc::MediaStreamTrackInterface*, StatsOutputLevel) override { return false; }
</span><span class="lines">@@ -73,10 +77,11 @@
</span><span class="cx"> 
</span><span class="cx">     webrtc::PeerConnectionObserver&amp; m_observer;
</span><span class="cx">     unsigned m_counter { 0 };
</span><del>-    rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt; m_stream;
</del><ins>+    Vector&lt;rtc::scoped_refptr&lt;MockRtpSender&gt;&gt; m_senders;
</ins><span class="cx">     bool m_isInitiator { true };
</span><span class="cx">     bool m_isReceivingAudio { false };
</span><span class="cx">     bool m_isReceivingVideo { false };
</span><ins>+    std::string m_streamLabel;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class MockLibWebRTCSessionDescription: public webrtc::SessionDescriptionInterface {
</span><span class="lines">@@ -199,6 +204,25 @@
</span><span class="cx">     int m_id { -1 };
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class MockRtpSender : public webrtc::RtpSenderInterface {
+public:
+    MockRtpSender(rtc::scoped_refptr&lt;webrtc::MediaStreamTrackInterface&gt;&amp;&amp; track) : m_track(WTFMove(track)) { }
+
+    bool SetTrack(webrtc::MediaStreamTrackInterface*) final { return false; }
+    rtc::scoped_refptr&lt;webrtc::MediaStreamTrackInterface&gt; track() const final { return m_track; }
+    
+    uint32_t ssrc() const { return 0; }
+    cricket::MediaType media_type() const { return cricket::MEDIA_TYPE_VIDEO; }
+    std::string id() const { return &quot;&quot;; }
+    std::vector&lt;std::string&gt; stream_ids() const { return { }; }
+    webrtc::RtpParameters GetParameters() const { return { }; }
+    bool SetParameters(const webrtc::RtpParameters&amp;) { return false; }
+    rtc::scoped_refptr&lt;webrtc::DtmfSenderInterface&gt; GetDtmfSender() const { return nullptr; }
+
+private:
+    rtc::scoped_refptr&lt;webrtc::MediaStreamTrackInterface&gt; m_track;
+};
+    
</ins><span class="cx"> class MockLibWebRTCPeerConnectionFactory : public webrtc::PeerConnectionFactoryInterface {
</span><span class="cx"> public:
</span><span class="cx">     static rtc::scoped_refptr&lt;webrtc::PeerConnectionFactoryInterface&gt; create(String&amp;&amp; testCase) { return new rtc::RefCountedObject&lt;MockLibWebRTCPeerConnectionFactory&gt;(WTFMove(testCase)); }
</span></span></pre>
</div>
</div>

</body>
</html>