<!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>[214132] 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/214132">214132</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-17 19:36:24 -0700 (Fri, 17 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement incoming webrtc data based on tracksCurr
https://bugs.webkit.org/show_bug.cgi?id=169836

Patch by Youenn Fablet &lt;youenn@apple.com&gt; on 2017-03-17
Reviewed by Eric Carlson.

Source/WebCore:

Test: webrtc/video-with-receiver.html

Constructing incoming tracks based on libwebrtc OnAddTrack.
Constructing incoming media streams based on libwebrtc OnAddStream.
Firing only addstream if legacy API flag is on.

Ensuring that media stream and media stream tracks relationship is still correctly implemented.
For that, we keep a map that relates libwebrtc media streams with WebCore media streams.
Adding the ability to get a receiver related to the track on the track event.

Implementing the possibility to create a transceiver ahead of track arrival time.
Created transceivers that are not related to any real source are kept in the peer connection back end.
When a libwebrtc track is appearing, it is associated with the track source of the corresponding transceiver based on track type.

Added the ability to create empty real time sources and set their data libwebrtc track when being available.

* Modules/mediastream/MediaStream.cpp:
(WebCore::MediaStream::addTrackFromPlatform):
* Modules/mediastream/MediaStream.h:
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
(WebCore::LibWebRTCMediaEndpoint::mediaStreamFromRTCStream):
(WebCore::LibWebRTCMediaEndpoint::addRemoteStream):
(WebCore::LibWebRTCMediaEndpoint::addRemoteTrack):
(WebCore::LibWebRTCMediaEndpoint::removeRemoteStream):
(WebCore::LibWebRTCMediaEndpoint::OnAddStream):
(WebCore::LibWebRTCMediaEndpoint::OnRemoveStream):
(WebCore::LibWebRTCMediaEndpoint::OnAddTrack):
(WebCore::LibWebRTCMediaEndpoint::stop):
(WebCore::createMediaStreamTrack): Deleted.
(WebCore::LibWebRTCMediaEndpoint::addStream): Deleted.
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
(WebCore::LibWebRTCPeerConnectionBackend::doStop):
(WebCore::createReceiverForSource):
(WebCore::createEmptySource):
(WebCore::LibWebRTCPeerConnectionBackend::createReceiver):
(WebCore::LibWebRTCPeerConnectionBackend::videoReceiver):
(WebCore::LibWebRTCPeerConnectionBackend::audioReceiver):
(WebCore::LibWebRTCPeerConnectionBackend::removeRemoteStream):
(WebCore::LibWebRTCPeerConnectionBackend::addRemoteStream):
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
* platform/mediastream/mac/RealtimeIncomingAudioSource.cpp:
(WebCore::RealtimeIncomingAudioSource::setSourceTrack):
* platform/mediastream/mac/RealtimeIncomingAudioSource.h:
* platform/mediastream/mac/RealtimeIncomingVideoSource.cpp:
(WebCore::RealtimeIncomingVideoSource::setSourceTrack):
* platform/mediastream/mac/RealtimeIncomingVideoSource.h:

LayoutTests:

* webrtc/video-with-receiver-expected.txt: Added.
* webrtc/video-with-receiver.html: Copied from LayoutTests/webrtc/video.html.
* webrtc/video.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestswebrtcvideohtml">trunk/LayoutTests/webrtc/video.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaStreamcpp">trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaStreamh">trunk/Source/WebCore/Modules/mediastream/MediaStream.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="#trunkSourceWebCoreplatformmediastreammacRealtimeIncomingAudioSourcecpp">trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacRealtimeIncomingAudioSourceh">trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacRealtimeIncomingVideoSourcecpp">trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacRealtimeIncomingVideoSourceh">trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestswebrtcvideowithreceiverexpectedtxt">trunk/LayoutTests/webrtc/video-with-receiver-expected.txt</a></li>
<li><a href="#trunkLayoutTestswebrtcvideowithreceiverhtml">trunk/LayoutTests/webrtc/video-with-receiver.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/LayoutTests/ChangeLog        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2017-03-17  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        Implement incoming webrtc data based on tracksCurr
+        https://bugs.webkit.org/show_bug.cgi?id=169836
+
+        Reviewed by Eric Carlson.
+
+        * webrtc/video-with-receiver-expected.txt: Added.
+        * webrtc/video-with-receiver.html: Copied from LayoutTests/webrtc/video.html.
+        * webrtc/video.html:
+
</ins><span class="cx"> 2017-03-17  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove TestExpectation for a test that is no longer in the tree.
</span></span></pre></div>
<a id="trunkLayoutTestswebrtcvideowithreceiverexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/webrtc/video-with-receiver-expected.txt (0 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webrtc/video-with-receiver-expected.txt                                (rev 0)
+++ trunk/LayoutTests/webrtc/video-with-receiver-expected.txt        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+
+
+PASS Basic video exchange 
+
</ins></span></pre></div>
<a id="trunkLayoutTestswebrtcvideowithreceiverhtmlfromrev214131trunkLayoutTestswebrtcvideohtml"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/webrtc/video-with-receiver.html (from rev 214131, trunk/LayoutTests/webrtc/video.html) (0 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webrtc/video-with-receiver.html                                (rev 0)
+++ trunk/LayoutTests/webrtc/video-with-receiver.html        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -0,0 +1,69 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+    &lt;head&gt;
+        &lt;meta charset=&quot;utf-8&quot;&gt;
+        &lt;title&gt;Testing basic video exchange from offerer to receiver&lt;/title&gt;
+        &lt;script src=&quot;../resources/testharness.js&quot;&gt;&lt;/script&gt;
+        &lt;script src=&quot;../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+    &lt;/head&gt;
+    &lt;body&gt;
+        &lt;video id=&quot;video&quot; autoplay=&quot;&quot;&gt;&lt;/video&gt;
+        &lt;canvas id=&quot;canvas&quot; width=&quot;640&quot; height=&quot;480&quot;&gt;&lt;/canvas&gt;
+        &lt;script src =&quot;routines.js&quot;&gt;&lt;/script&gt;
+        &lt;script&gt;
+video = document.getElementById(&quot;video&quot;);
+canvas = document.getElementById(&quot;canvas&quot;);
+
+function testImage()
+{
+    canvas.width = video.videoWidth;
+    canvas.height = video.videoHeight;
+    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
+
+    imageData = canvas.getContext('2d').getImageData(10, 325, 250, 1);
+    data = imageData.data;
+
+    var index = 20;
+    assert_true(data[index] &lt; 100);
+    assert_true(data[index + 1] &lt; 100);
+    assert_true(data[index + 2] &lt; 100);
+
+    index = 80;
+    assert_true(data[index] &gt; 200);
+    assert_true(data[index + 1] &gt; 200);
+    assert_true(data[index + 2] &gt; 200);
+
+    index += 80;
+    assert_true(data[index] &gt; 200);
+    assert_true(data[index + 1] &gt; 200);
+    assert_true(data[index + 2] &lt; 100);
+}
+
+promise_test((test) =&gt; {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    return navigator.mediaDevices.getUserMedia({ video: true}).then((stream) =&gt; {
+        return new Promise((resolve, reject) =&gt; {
+            if (window.internals)
+                internals.useMockRTCPeerConnectionFactory(&quot;TwoRealPeerConnections&quot;);
+
+            createConnections((firstConnection) =&gt; {
+                firstConnection.addStream(stream);
+            }, (secondConnection) =&gt; {
+                resolve(secondConnection.addTransceiver(&quot;video&quot;).receiver.track);
+            });
+            setTimeout(() =&gt; reject(&quot;Test timed out&quot;), 5000);
+        });
+    }).then((track) =&gt; {
+        video.srcObject = new MediaStream([track]);
+        return waitFor(500);
+    }).then(() =&gt; {
+        return video.play();
+    }).then(() =&gt; {
+        testImage();
+    });
+}, &quot;Basic video exchange&quot;);
+        &lt;/script&gt;
+    &lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestswebrtcvideohtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webrtc/video.html (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webrtc/video.html        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/LayoutTests/webrtc/video.html        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -13,7 +13,6 @@
</span><span class="cx">         &lt;script&gt;
</span><span class="cx"> video = document.getElementById(&quot;video&quot;);
</span><span class="cx"> canvas = document.getElementById(&quot;canvas&quot;);
</span><del>-// FIXME: We should use tracks
</del><span class="cx"> 
</span><span class="cx"> function testImage()
</span><span class="cx"> {
</span><span class="lines">@@ -52,7 +51,13 @@
</span><span class="cx">             createConnections((firstConnection) =&gt; {
</span><span class="cx">                 firstConnection.addStream(stream);
</span><span class="cx">             }, (secondConnection) =&gt; {
</span><del>-                secondConnection.onaddstream = (streamEvent) =&gt; { resolve(streamEvent.stream); };
</del><ins>+                secondConnection.ontrack = (trackEvent) =&gt; {
+                    assert_true(trackEvent.track instanceof MediaStreamTrack);
+                    assert_true(trackEvent.receiver instanceof RTCRtpReceiver);
+                    assert_true(Array.isArray(trackEvent.streams), &quot;Array.isArray() should return true&quot;)
+                    assert_true(Object.isFrozen(trackEvent.streams), &quot;Object.isFrozen() should return true&quot;)
+                    resolve(trackEvent.streams[0]);
+                };
</ins><span class="cx">             });
</span><span class="cx">             setTimeout(() =&gt; reject(&quot;Test timed out&quot;), 5000);
</span><span class="cx">         });
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/ChangeLog        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -1,3 +1,58 @@
</span><ins>+2017-03-17  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        Implement incoming webrtc data based on tracksCurr
+        https://bugs.webkit.org/show_bug.cgi?id=169836
+
+        Reviewed by Eric Carlson.
+
+        Test: webrtc/video-with-receiver.html
+
+        Constructing incoming tracks based on libwebrtc OnAddTrack.
+        Constructing incoming media streams based on libwebrtc OnAddStream.
+        Firing only addstream if legacy API flag is on.
+
+        Ensuring that media stream and media stream tracks relationship is still correctly implemented.
+        For that, we keep a map that relates libwebrtc media streams with WebCore media streams.
+        Adding the ability to get a receiver related to the track on the track event.
+
+        Implementing the possibility to create a transceiver ahead of track arrival time.
+        Created transceivers that are not related to any real source are kept in the peer connection back end.
+        When a libwebrtc track is appearing, it is associated with the track source of the corresponding transceiver based on track type.
+
+        Added the ability to create empty real time sources and set their data libwebrtc track when being available.
+
+        * Modules/mediastream/MediaStream.cpp:
+        (WebCore::MediaStream::addTrackFromPlatform):
+        * Modules/mediastream/MediaStream.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
+        (WebCore::LibWebRTCMediaEndpoint::mediaStreamFromRTCStream):
+        (WebCore::LibWebRTCMediaEndpoint::addRemoteStream):
+        (WebCore::LibWebRTCMediaEndpoint::addRemoteTrack):
+        (WebCore::LibWebRTCMediaEndpoint::removeRemoteStream):
+        (WebCore::LibWebRTCMediaEndpoint::OnAddStream):
+        (WebCore::LibWebRTCMediaEndpoint::OnRemoveStream):
+        (WebCore::LibWebRTCMediaEndpoint::OnAddTrack):
+        (WebCore::LibWebRTCMediaEndpoint::stop):
+        (WebCore::createMediaStreamTrack): Deleted.
+        (WebCore::LibWebRTCMediaEndpoint::addStream): Deleted.
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
+        (WebCore::LibWebRTCPeerConnectionBackend::doStop):
+        (WebCore::createReceiverForSource):
+        (WebCore::createEmptySource):
+        (WebCore::LibWebRTCPeerConnectionBackend::createReceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::videoReceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::audioReceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::removeRemoteStream):
+        (WebCore::LibWebRTCPeerConnectionBackend::addRemoteStream):
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
+        * platform/mediastream/mac/RealtimeIncomingAudioSource.cpp:
+        (WebCore::RealtimeIncomingAudioSource::setSourceTrack):
+        * platform/mediastream/mac/RealtimeIncomingAudioSource.h:
+        * platform/mediastream/mac/RealtimeIncomingVideoSource.cpp:
+        (WebCore::RealtimeIncomingVideoSource::setSourceTrack):
+        * platform/mediastream/mac/RealtimeIncomingVideoSource.h:
+
</ins><span class="cx"> 2017-03-17  Eric Carlson  &lt;eric.carlson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [MediaStream] Compensate for video capture orientation
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -207,6 +207,12 @@
</span><span class="cx">     internalRemoveTrack(trackPrivate.id(), StreamModifier::Platform);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaStream::addTrackFromPlatform(Ref&lt;MediaStreamTrack&gt;&amp;&amp; track)
+{
+    m_private-&gt;addTrack(&amp;track-&gt;privateTrack(), MediaStreamPrivate::NotifyClientOption::Notify);
+    internalAddTrack(WTFMove(track), StreamModifier::Platform);
+}
+
</ins><span class="cx"> bool MediaStream::internalAddTrack(Ref&lt;MediaStreamTrack&gt;&amp;&amp; trackToAdd, StreamModifier streamModifier)
</span><span class="cx"> {
</span><span class="cx">     auto result = m_trackSet.add(trackToAdd-&gt;id(), WTFMove(trackToAdd));
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.h (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaStream.h        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.h        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -102,6 +102,8 @@
</span><span class="cx">     void addObserver(Observer*);
</span><span class="cx">     void removeObserver(Observer*);
</span><span class="cx"> 
</span><ins>+    void addTrackFromPlatform(Ref&lt;MediaStreamTrack&gt;&amp;&amp;);
+
</ins><span class="cx"> protected:
</span><span class="cx">     MediaStream(ScriptExecutionContext&amp;, const MediaStreamTrackVector&amp;);
</span><span class="cx">     MediaStream(ScriptExecutionContext&amp;, RefPtr&lt;MediaStreamPrivate&gt;&amp;&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCMediaEndpointcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;RTCTrackEvent.h&quot;
</span><span class="cx"> #include &quot;RealtimeIncomingAudioSource.h&quot;
</span><span class="cx"> #include &quot;RealtimeIncomingVideoSource.h&quot;
</span><ins>+#include &quot;RuntimeEnabledFeatures.h&quot;
</ins><span class="cx"> #include &lt;webrtc/base/physicalsocketserver.h&gt;
</span><span class="cx"> #include &lt;webrtc/p2p/base/basicpacketsocketfactory.h&gt;
</span><span class="cx"> #include &lt;webrtc/p2p/client/basicportallocator.h&gt;
</span><span class="lines">@@ -382,37 +383,73 @@
</span><span class="cx">     return String(videoTrack.id().data(), videoTrack.id().size());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline Ref&lt;MediaStreamTrack&gt; createMediaStreamTrack(ScriptExecutionContext&amp; context, Ref&lt;RealtimeMediaSource&gt;&amp;&amp; remoteSource)
</del><ins>+MediaStream&amp; LibWebRTCMediaEndpoint::mediaStreamFromRTCStream(webrtc::MediaStreamInterface* rtcStream)
</ins><span class="cx"> {
</span><del>-    String trackId = remoteSource-&gt;id();
-    return MediaStreamTrack::create(context, MediaStreamTrackPrivate::create(WTFMove(remoteSource), WTFMove(trackId)));
</del><ins>+    auto mediaStream = m_streams.ensure(rtcStream, [this] {
+        auto stream = MediaStream::create(*m_peerConnectionBackend.connection().scriptExecutionContext());
+        auto streamPointer = stream.ptr();
+        m_peerConnectionBackend.addRemoteStream(WTFMove(stream));
+        return streamPointer;
+    });
+    return *mediaStream.iterator-&gt;value;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void LibWebRTCMediaEndpoint::addStream(webrtc::MediaStreamInterface&amp; stream)
</del><ins>+void LibWebRTCMediaEndpoint::addRemoteStream(webrtc::MediaStreamInterface&amp; rtcStream)
</ins><span class="cx"> {
</span><del>-    MediaStreamTrackVector tracks;
-    for (auto&amp; videoTrack : stream.GetVideoTracks()) {
-        ASSERT(videoTrack);
-        String id = trackId(*videoTrack);
-        auto remoteSource = RealtimeIncomingVideoSource::create(WTFMove(videoTrack), WTFMove(id));
-        tracks.append(createMediaStreamTrack(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(remoteSource)));
</del><ins>+    if (!RuntimeEnabledFeatures::sharedFeatures().webRTCLegacyAPIEnabled())
+        return;
+
+    auto&amp; mediaStream = mediaStreamFromRTCStream(&amp;rtcStream);
+    m_peerConnectionBackend.connection().fireEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, &amp;mediaStream));
+}
+
+void LibWebRTCMediaEndpoint::addRemoteTrack(const webrtc::RtpReceiverInterface&amp; rtcReceiver, const std::vector&lt;rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt;&gt;&amp; rtcStreams)
+{
+    RefPtr&lt;RTCRtpReceiver&gt; receiver;
+    RefPtr&lt;RealtimeMediaSource&gt; remoteSource;
+
+    auto* rtcTrack = rtcReceiver.track().get();
+
+    switch (rtcReceiver.media_type()) {
+    case cricket::MEDIA_TYPE_DATA:
+        return;
+    case cricket::MEDIA_TYPE_AUDIO: {
+        rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt; audioTrack = static_cast&lt;webrtc::AudioTrackInterface*&gt;(rtcTrack);
+        auto audioReceiver = m_peerConnectionBackend.audioReceiver(trackId(*rtcTrack));
+
+        receiver = WTFMove(audioReceiver.receiver);
+        audioReceiver.source-&gt;setSourceTrack(WTFMove(audioTrack));
+        break;
</ins><span class="cx">     }
</span><del>-    for (auto&amp; audioTrack : stream.GetAudioTracks()) {
-        ASSERT(audioTrack);
-        String id = trackId(*audioTrack);
-        auto remoteSource = RealtimeIncomingAudioSource::create(WTFMove(audioTrack), WTFMove(id));
-        tracks.append(createMediaStreamTrack(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(remoteSource)));
</del><ins>+    case cricket::MEDIA_TYPE_VIDEO: {
+        rtc::scoped_refptr&lt;webrtc::VideoTrackInterface&gt; videoTrack = static_cast&lt;webrtc::VideoTrackInterface*&gt;(rtcTrack);
+        auto videoReceiver = m_peerConnectionBackend.videoReceiver(trackId(*rtcTrack));
+
+        receiver = WTFMove(videoReceiver.receiver);
+        videoReceiver.source-&gt;setSourceTrack(WTFMove(videoTrack));
+        break;
</ins><span class="cx">     }
</span><ins>+    }
</ins><span class="cx"> 
</span><del>-    auto newStream = MediaStream::create(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(tracks));
-    m_peerConnectionBackend.connection().fireEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, newStream.copyRef()));
</del><ins>+    auto* track = receiver-&gt;track();
+    ASSERT(track);
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;RefPtr&lt;MediaStream&gt;&gt; streams;
</span><del>-    streams.append(newStream.copyRef());
-    for (auto&amp; track : newStream-&gt;getTracks())
-        m_peerConnectionBackend.connection().fireEvent(RTCTrackEvent::create(eventNames().trackEvent, false, false, nullptr, track.get(), Vector&lt;RefPtr&lt;MediaStream&gt;&gt;(streams), nullptr));
</del><ins>+    for (auto&amp; rtcStream : rtcStreams) {
+        auto&amp; mediaStream = mediaStreamFromRTCStream(rtcStream.get());
+        streams.append(&amp;mediaStream);
+        mediaStream.addTrackFromPlatform(*track);
+    }
+    m_peerConnectionBackend.connection().fireEvent(RTCTrackEvent::create(eventNames().trackEvent, false, false, WTFMove(receiver), track, WTFMove(streams), nullptr));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void LibWebRTCMediaEndpoint::removeRemoteStream(webrtc::MediaStreamInterface&amp; rtcStream)
+{
+    auto* mediaStream = m_streams.take(&amp;rtcStream);
+    if (mediaStream)
+        m_peerConnectionBackend.removeRemoteStream(mediaStream);
+}
+
</ins><span class="cx"> void LibWebRTCMediaEndpoint::OnAddStream(rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt; stream)
</span><span class="cx"> {
</span><span class="cx">     callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
</span><span class="lines">@@ -419,15 +456,30 @@
</span><span class="cx">         if (protectedThis-&gt;isStopped())
</span><span class="cx">             return;
</span><span class="cx">         ASSERT(stream);
</span><del>-        protectedThis-&gt;addStream(*stream.get());
</del><ins>+        protectedThis-&gt;addRemoteStream(*stream.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void LibWebRTCMediaEndpoint::OnRemoveStream(rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt;)
</del><ins>+void LibWebRTCMediaEndpoint::OnRemoveStream(rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt; stream)
</ins><span class="cx"> {
</span><del>-    notImplemented();
</del><ins>+    callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
+        if (protectedThis-&gt;isStopped())
+            return;
+        ASSERT(stream);
+        protectedThis-&gt;removeRemoteStream(*stream.get());
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void LibWebRTCMediaEndpoint::OnAddTrack(rtc::scoped_refptr&lt;webrtc::RtpReceiverInterface&gt; receiver, const std::vector&lt;rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt;&gt;&amp; streams)
+{
+    callOnMainThread([protectedThis = makeRef(*this), receiver = WTFMove(receiver), streams] {
+        if (protectedThis-&gt;isStopped())
+            return;
+        ASSERT(receiver);
+        protectedThis-&gt;addRemoteTrack(*receiver, streams);
+    });
+}
+
</ins><span class="cx"> std::unique_ptr&lt;RTCDataChannelHandler&gt; LibWebRTCMediaEndpoint::createDataChannel(const String&amp; label, const RTCDataChannelInit&amp; options)
</span><span class="cx"> {
</span><span class="cx">     webrtc::DataChannelInit init;
</span><span class="lines">@@ -485,6 +537,7 @@
</span><span class="cx">     ASSERT(m_backend);
</span><span class="cx">     m_backend-&gt;Close();
</span><span class="cx">     m_backend = nullptr;
</span><ins>+    m_streams.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void LibWebRTCMediaEndpoint::OnRenegotiationNeeded()
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamlibwebrtcLibWebRTCMediaEndpointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -89,6 +89,7 @@
</span><span class="cx">     void OnAddStream(rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt;) final;
</span><span class="cx">     void OnRemoveStream(rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt;) final;
</span><span class="cx">     void OnDataChannel(rtc::scoped_refptr&lt;webrtc::DataChannelInterface&gt;) final;
</span><ins>+    void OnAddTrack(rtc::scoped_refptr&lt;webrtc::RtpReceiverInterface&gt;, const std::vector&lt;rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt;&gt;&amp;) final;
</ins><span class="cx">     void OnRenegotiationNeeded() final;
</span><span class="cx">     void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState) final;
</span><span class="cx">     void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState) final;
</span><span class="lines">@@ -101,9 +102,13 @@
</span><span class="cx">     void setLocalSessionDescriptionFailed(const std::string&amp;);
</span><span class="cx">     void setRemoteSessionDescriptionSucceeded();
</span><span class="cx">     void setRemoteSessionDescriptionFailed(const std::string&amp;);
</span><del>-    void addStream(webrtc::MediaStreamInterface&amp;);
</del><ins>+    void addRemoteStream(webrtc::MediaStreamInterface&amp;);
+    void addRemoteTrack(const webrtc::RtpReceiverInterface&amp;, const std::vector&lt;rtc::scoped_refptr&lt;webrtc::MediaStreamInterface&gt;&gt;&amp;);
+    void removeRemoteStream(webrtc::MediaStreamInterface&amp;);
</ins><span class="cx">     void addDataChannel(rtc::scoped_refptr&lt;webrtc::DataChannelInterface&gt;&amp;&amp;);
</span><span class="cx"> 
</span><ins>+    MediaStream&amp; mediaStreamFromRTCStream(webrtc::MediaStreamInterface*);
+
</ins><span class="cx">     int AddRef() const { ref(); return static_cast&lt;int&gt;(refCount()); }
</span><span class="cx">     int Release() const { deref(); return static_cast&lt;int&gt;(refCount()); }
</span><span class="cx"> 
</span><span class="lines">@@ -169,6 +174,7 @@
</span><span class="cx">     CreateSessionDescriptionObserver m_createSessionDescriptionObserver;
</span><span class="cx">     SetLocalSessionDescriptionObserver m_setLocalSessionDescriptionObserver;
</span><span class="cx">     SetRemoteSessionDescriptionObserver m_setRemoteSessionDescriptionObserver;
</span><ins>+    HashMap&lt;webrtc::MediaStreamInterface*, MediaStream*&gt; m_streams;
</ins><span class="cx"> 
</span><span class="cx">     bool m_isInitiator { false };
</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 (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -165,6 +165,9 @@
</span><span class="cx"> void LibWebRTCPeerConnectionBackend::doStop()
</span><span class="cx"> {
</span><span class="cx">     m_endpoint-&gt;stop();
</span><ins>+
+    m_remoteStreams.clear();
+    m_pendingReceivers.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void LibWebRTCPeerConnectionBackend::doAddIceCandidate(RTCIceCandidate&amp; candidate)
</span><span class="lines">@@ -200,16 +203,64 @@
</span><span class="cx">     m_videoSources.append(WTFMove(source));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref&lt;RTCRtpReceiver&gt; LibWebRTCPeerConnectionBackend::createReceiver(const String&amp;, const String&amp; trackKind, const String&amp; trackId)
</del><ins>+static inline Ref&lt;RTCRtpReceiver&gt; createReceiverForSource(ScriptExecutionContext&amp; context, Ref&lt;RealtimeMediaSource&gt;&amp;&amp; source)
</ins><span class="cx"> {
</span><del>-    // FIXME: We need to create a source that will get fueled once we will receive OnAddStream.
-    // For the moment, we create an empty one.
-    auto remoteTrackPrivate = (trackKind == &quot;audio&quot;) ? MediaStreamTrackPrivate::create(RealtimeIncomingAudioSource::create(nullptr, String(trackId))) : MediaStreamTrackPrivate::create(RealtimeIncomingVideoSource::create(nullptr, String(trackId)));
-    auto remoteTrack = MediaStreamTrack::create(*m_peerConnection.scriptExecutionContext(), WTFMove(remoteTrackPrivate));
</del><ins>+    auto remoteTrackPrivate = MediaStreamTrackPrivate::create(WTFMove(source));
+    auto remoteTrack = MediaStreamTrack::create(context, WTFMove(remoteTrackPrivate));
</ins><span class="cx"> 
</span><span class="cx">     return RTCRtpReceiver::create(WTFMove(remoteTrack));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline Ref&lt;RealtimeMediaSource&gt; createEmptySource(const String&amp; trackKind, String&amp;&amp; trackId)
+{
+    // FIXME: trackKind should be an enumeration
+    if (trackKind == &quot;audio&quot;)
+        return RealtimeIncomingAudioSource::create(nullptr, WTFMove(trackId));
+    ASSERT(trackKind == &quot;video&quot;);
+    return RealtimeIncomingVideoSource::create(nullptr, WTFMove(trackId));
+}
+
+Ref&lt;RTCRtpReceiver&gt; LibWebRTCPeerConnectionBackend::createReceiver(const String&amp;, const String&amp; trackKind, const String&amp; trackId)
+{
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), createEmptySource(trackKind, String(trackId)));
+    m_pendingReceivers.append(receiver.copyRef());
+    return receiver;
+}
+
+LibWebRTCPeerConnectionBackend::VideoReceiver LibWebRTCPeerConnectionBackend::videoReceiver(String&amp;&amp; trackId)
+{
+    // FIXME: Add to Vector a utility routine for that take-or-create pattern.
+    // FIXME: We should be selecting the receiver based on track id.
+    for (size_t cptr = 0; cptr &lt; m_pendingReceivers.size(); ++cptr) {
+        if (m_pendingReceivers[cptr]-&gt;track()-&gt;source().type() == RealtimeMediaSource::Type::Video) {
+            Ref&lt;RTCRtpReceiver&gt; receiver = m_pendingReceivers[cptr].copyRef();
+            m_pendingReceivers.remove(cptr);
+            Ref&lt;RealtimeIncomingVideoSource&gt; source = static_cast&lt;RealtimeIncomingVideoSource&amp;&gt;(receiver-&gt;track()-&gt;source());
+            return { WTFMove(receiver), WTFMove(source) };
+        }
+    }
+    auto source = RealtimeIncomingVideoSource::create(nullptr, WTFMove(trackId));
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), source.copyRef());
+    return { WTFMove(receiver), WTFMove(source) };
+}
+
+LibWebRTCPeerConnectionBackend::AudioReceiver LibWebRTCPeerConnectionBackend::audioReceiver(String&amp;&amp; trackId)
+{
+    // FIXME: Add to Vector a utility routine for that take-or-create pattern.
+    // FIXME: We should be selecting the receiver based on track id.
+    for (size_t cptr = 0; cptr &lt; m_pendingReceivers.size(); ++cptr) {
+        if (m_pendingReceivers[cptr]-&gt;track()-&gt;source().type() == RealtimeMediaSource::Type::Audio) {
+            Ref&lt;RTCRtpReceiver&gt; receiver = m_pendingReceivers[cptr].copyRef();
+            m_pendingReceivers.remove(cptr);
+            Ref&lt;RealtimeIncomingAudioSource&gt; source = static_cast&lt;RealtimeIncomingAudioSource&amp;&gt;(receiver-&gt;track()-&gt;source());
+            return { WTFMove(receiver), WTFMove(source) };
+        }
+    }
+    auto source = RealtimeIncomingAudioSource::create(nullptr, WTFMove(trackId));
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), source.copyRef());
+    return { WTFMove(receiver), WTFMove(source) };
+}
+
</ins><span class="cx"> std::unique_ptr&lt;RTCDataChannelHandler&gt; LibWebRTCPeerConnectionBackend::createDataChannelHandler(const String&amp; label, const RTCDataChannelInit&amp; options)
</span><span class="cx"> {
</span><span class="cx">     return m_endpoint-&gt;createDataChannel(label, options);
</span><span class="lines">@@ -251,6 +302,18 @@
</span><span class="cx">     m_endpoint-&gt;addTrack(*sender.track(), sender.mediaStreamIds());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void LibWebRTCPeerConnectionBackend::removeRemoteStream(MediaStream* mediaStream)
+{
+    m_remoteStreams.removeFirstMatching([mediaStream](const auto&amp; item) {
+        return item.get() == mediaStream;
+    });
+}
+
+void LibWebRTCPeerConnectionBackend::addRemoteStream(Ref&lt;MediaStream&gt;&amp;&amp; mediaStream)
+{
+    m_remoteStreams.append(WTFMove(mediaStream));
+}
+
</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 (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -39,6 +39,8 @@
</span><span class="cx"> class RTCRtpReceiver;
</span><span class="cx"> class RTCSessionDescription;
</span><span class="cx"> class RTCStatsReport;
</span><ins>+class RealtimeIncomingAudioSource;
+class RealtimeIncomingVideoSource;
</ins><span class="cx"> class RealtimeOutgoingAudioSource;
</span><span class="cx"> class RealtimeOutgoingVideoSource;
</span><span class="cx"> 
</span><span class="lines">@@ -67,9 +69,7 @@
</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><del>-    void notifyAddedTrack(RTCRtpSender&amp;) final;
</del><span class="cx">     // FIXME: API to implement for real
</span><del>-    Vector&lt;RefPtr&lt;MediaStream&gt;&gt; getRemoteStreams() const final { return { }; }
</del><span class="cx">     void replaceTrack(RTCRtpSender&amp;, Ref&lt;MediaStreamTrack&gt;&amp;&amp;, DOMPromise&lt;void&gt;&amp;&amp;) final { }
</span><span class="cx"> 
</span><span class="cx">     void emulatePlatformEvent(const String&amp;) final { }
</span><span class="lines">@@ -82,15 +82,35 @@
</span><span class="cx">     void getStatsSucceeded(const DeferredPromise&amp;, Ref&lt;RTCStatsReport&gt;&amp;&amp;);
</span><span class="cx">     void getStatsFailed(const DeferredPromise&amp;, Exception&amp;&amp;);
</span><span class="cx"> 
</span><ins>+    Vector&lt;RefPtr&lt;MediaStream&gt;&gt; getRemoteStreams() const final { return m_remoteStreams; }
+    void removeRemoteStream(MediaStream*);
+    void addRemoteStream(Ref&lt;MediaStream&gt;&amp;&amp;);
+
+    void notifyAddedTrack(RTCRtpSender&amp;) final;
+
+    struct VideoReceiver {
+        Ref&lt;RTCRtpReceiver&gt; receiver;
+        Ref&lt;RealtimeIncomingVideoSource&gt; source;
+    };
+    struct AudioReceiver {
+        Ref&lt;RTCRtpReceiver&gt; receiver;
+        Ref&lt;RealtimeIncomingAudioSource&gt; source;
+    };
+    VideoReceiver videoReceiver(String&amp;&amp; trackId);
+    AudioReceiver audioReceiver(String&amp;&amp; trackId);
+
</ins><span class="cx"> private:
</span><span class="cx">     Ref&lt;LibWebRTCMediaEndpoint&gt; m_endpoint;
</span><span class="cx">     bool m_isLocalDescriptionSet { false };
</span><span class="cx">     bool m_isRemoteDescriptionSet { false };
</span><span class="cx"> 
</span><ins>+    // FIXME: Make m_remoteStreams a Vector of Ref.
+    Vector&lt;RefPtr&lt;MediaStream&gt;&gt; m_remoteStreams;
</ins><span class="cx">     Vector&lt;std::unique_ptr&lt;webrtc::IceCandidateInterface&gt;&gt; m_pendingCandidates;
</span><span class="cx">     Vector&lt;Ref&lt;RealtimeOutgoingAudioSource&gt;&gt; m_audioSources;
</span><span class="cx">     Vector&lt;Ref&lt;RealtimeOutgoingVideoSource&gt;&gt; m_videoSources;
</span><span class="cx">     HashMap&lt;const DeferredPromise*, Ref&lt;DeferredPromise&gt;&gt; m_statsPromises;
</span><ins>+    Vector&lt;Ref&lt;RTCRtpReceiver&gt;&gt; m_pendingReceivers;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacRealtimeIncomingAudioSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.cpp (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.cpp        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.cpp        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -130,7 +130,16 @@
</span><span class="cx">         m_audioTrack-&gt;RemoveSink(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RealtimeIncomingAudioSource::setSourceTrack(rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt;&amp;&amp; track)
+{
+    ASSERT(!m_audioTrack);
+    ASSERT(track);
</ins><span class="cx"> 
</span><ins>+    m_audioTrack = WTFMove(track);
+    if (m_isProducingData)
+        m_audioTrack-&gt;AddSink(this);
+}
+
</ins><span class="cx"> RefPtr&lt;RealtimeMediaSourceCapabilities&gt; RealtimeIncomingAudioSource::capabilities() const
</span><span class="cx"> {
</span><span class="cx">     return m_capabilities;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacRealtimeIncomingAudioSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.h (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.h        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSource.h        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -48,6 +48,8 @@
</span><span class="cx"> public:
</span><span class="cx">     static Ref&lt;RealtimeIncomingAudioSource&gt; create(rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt;&amp;&amp;, String&amp;&amp;);
</span><span class="cx"> 
</span><ins>+    void setSourceTrack(rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt;&amp;&amp;);
+
</ins><span class="cx"> private:
</span><span class="cx">     RealtimeIncomingAudioSource(rtc::scoped_refptr&lt;webrtc::AudioTrackInterface&gt;&amp;&amp;, String&amp;&amp;);
</span><span class="cx">     ~RealtimeIncomingAudioSource();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacRealtimeIncomingVideoSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.cpp (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.cpp        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.cpp        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -82,6 +82,17 @@
</span><span class="cx">         m_videoTrack-&gt;AddOrUpdateSink(this, rtc::VideoSinkWants());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RealtimeIncomingVideoSource::setSourceTrack(rtc::scoped_refptr&lt;webrtc::VideoTrackInterface&gt;&amp;&amp; track)
+{
+    ASSERT(!m_videoTrack);
+    ASSERT(track);
+
+    m_muted = false;
+    m_videoTrack = track;
+    if (m_isProducingData)
+        m_videoTrack-&gt;AddOrUpdateSink(this, rtc::VideoSinkWants());
+}
+
</ins><span class="cx"> void RealtimeIncomingVideoSource::stopProducingData()
</span><span class="cx"> {
</span><span class="cx">     if (!m_isProducingData)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacRealtimeIncomingVideoSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.h (214131 => 214132)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.h        2017-03-18 00:39:23 UTC (rev 214131)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSource.h        2017-03-18 02:36:24 UTC (rev 214132)
</span><span class="lines">@@ -49,6 +49,8 @@
</span><span class="cx">     static Ref&lt;RealtimeIncomingVideoSource&gt; create(rtc::scoped_refptr&lt;webrtc::VideoTrackInterface&gt;&amp;&amp;, String&amp;&amp;);
</span><span class="cx">     ~RealtimeIncomingVideoSource() { stopProducingData(); }
</span><span class="cx"> 
</span><ins>+    void setSourceTrack(rtc::scoped_refptr&lt;webrtc::VideoTrackInterface&gt;&amp;&amp;);
+
</ins><span class="cx"> private:
</span><span class="cx">     RealtimeIncomingVideoSource(rtc::scoped_refptr&lt;webrtc::VideoTrackInterface&gt;&amp;&amp;, String&amp;&amp;, CFMutableDictionaryRef);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>