<!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>[207052] 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/207052">207052</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-10-10 23:39:15 -0700 (Mon, 10 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebRTC: Make MediaEndpointPeerConnection handle remotely assigned mids correctly
https://bugs.webkit.org/show_bug.cgi?id=163202

Patch by Adam Bergkvist  &lt;adam.bergkvist@ericsson.com&gt; and Alejandro G. Castro &lt;alex@igalia.com&gt; on 2016-10-10
Reviewed by Eric Carlson.

Source/WebCore:

An RTCRtpTransceiver has a null mid until it's been associated with a
media description (with a mid) [1]. During that time, it's identified by
a provisional mid that might become its real mid, but the transceiver
can also get its mid assigned by a remote media description. In the
second case, the mid value is initially unknown. A transceiver's
RTCRtpSender must directly (synchronously in the script) provide a muted
remote source that is playable by, for example, a media element. This
source is initially registered in the MediaEndpoint (WebRTC backend)
with the transceiver's provisional mid. So, if the real mid is set by a
remote description, the registered mid must be updated to preserve the
association between the registered source and the transceiver.

[1] https://w3c.github.io/webrtc-pc/archives/20160913/webrtc.html#dom-rtcrtptransceiver-mid

Test: fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html

* Modules/mediastream/MediaEndpointPeerConnection.cpp:
Don't break after finding the first transceiver in the loop that builds the send source map.
Update the mid used to register the muted remote source if the a transceiver's mid gets
assigned by a remote media description.
(WebCore::createSourceMap):
(WebCore::MediaEndpointPeerConnection::setRemoteDescriptionTask):
* platform/mediastream/MediaEndpoint.cpp:
* platform/mediastream/MediaEndpoint.h:
* platform/mock/MockMediaEndpoint.cpp:
(WebCore::MockMediaEndpoint::MockMediaEndpoint):
(WebCore::MockMediaEndpoint::updateReceiveConfiguration):
(WebCore::MockMediaEndpoint::updateSendConfiguration):
(WebCore::MockMediaEndpoint::createMutedRemoteSource):
(WebCore::MockMediaEndpoint::replaceMutedRemoteSourceMid):
(WebCore::MockMediaEndpoint::emulatePlatformEvent):
Add &quot;unmute-remote-sources-by-mid&quot; action that emulates data arriving on media descriptions
which unmutes the remote sources.
(WebCore::MockMediaEndpoint::updateConfigurationMids):
(WebCore::MockMediaEndpoint::unmuteRemoteSourcesByMid):
(WebCore::MockMediaEndpoint::unmuteTimerFired):
* platform/mock/MockMediaEndpoint.h:

LayoutTests:

Test the case when an RTCRtpTransceiver gets its mid assigned from a remote session
description.

* fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid-expected.txt: Added.
* fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html: Added.
* platform/mac/TestExpectations:
Skip above test until the Mac port builds with WEB_RTC.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformmacTestExpectations">trunk/LayoutTests/platform/mac/TestExpectations</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="#trunkSourceWebCoreplatformmediastreamMediaEndpointcpp">trunk/Source/WebCore/platform/mediastream/MediaEndpoint.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaEndpointh">trunk/Source/WebCore/platform/mediastream/MediaEndpoint.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockMediaEndpointcpp">trunk/Source/WebCore/platform/mock/MockMediaEndpoint.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockMediaEndpointh">trunk/Source/WebCore/platform/mock/MockMediaEndpoint.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastmediastreamRTCPeerConnectionremotelyassignedtransceivermidexpectedtxt">trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamRTCPeerConnectionremotelyassignedtransceivermidhtml">trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/LayoutTests/ChangeLog        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2016-10-10  Adam Bergkvist  &lt;adam.bergkvist@ericsson.com&gt; and Alejandro G. Castro &lt;alex@igalia.com&gt;
+
+        WebRTC: Make MediaEndpointPeerConnection handle remotely assigned mids correctly
+        https://bugs.webkit.org/show_bug.cgi?id=163202
+
+        Reviewed by Eric Carlson.
+
+        Test the case when an RTCRtpTransceiver gets its mid assigned from a remote session
+        description.
+
+        * fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid-expected.txt: Added.
+        * fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html: Added.
+        * platform/mac/TestExpectations:
+        Skip above test until the Mac port builds with WEB_RTC.
+
</ins><span class="cx"> 2016-10-10  Gyuyoung Kim  &lt;gyuyoung.kim@navercorp.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] Skip imported/w3c/web-platform-tests for a while
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamRTCPeerConnectionremotelyassignedtransceivermidexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid-expected.txt (0 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid-expected.txt        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+Test the case where an RTCRtpTransceiver gets a remotely assigned mid and also unmute the associated source
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+pcA.addTrack(stream.getAudioTracks()[0], stream)
+A's transceiver is not yet associated with a media description and should have a null mid
+PASS pcA.getTransceivers()[0].mid is null
+A: local offer set (mid gets defined)
+midAssignedByA = pcA.getTransceivers()[0].mid
+PASS midAssignedByA !== null is true
+pcB.addTrack(stream.getAudioTracks()[0], stream)
+B's transceiver is not yet associated with a media description and should have a null mid
+PASS pcB.getTransceivers()[0].mid is null
+PASS B: got remote track event
+PASS event.track is an instance of MediaStreamTrack
+B: remote offer set (mid gets defined)
+B's transceiver should get its mid from the remote side (A)
+PASS pcB.getTransceivers()[0].mid is midAssignedByA
+PASS A: got remote track event
+PASS Offer/answer dialog completed
+PASS B: remote track unmute event
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamRTCPeerConnectionremotelyassignedtransceivermidhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html (0 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html                                (rev 0)
+++ trunk/LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+    &lt;head&gt;
+        &lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+        &lt;script src=&quot;resources/promise-utils.js&quot;&gt;&lt;/script&gt;
+    &lt;/head&gt;
+    &lt;body&gt;
+        &lt;script&gt;
+            let stream;
+            let midAssignedByA;
+            let event;
+
+            description(&quot;Test the case where an RTCRtpTransceiver gets a remotely assigned mid and also unmute the associated source&quot;);
+
+            if (window.testRunner)
+                testRunner.setUserMediaPermission(true);
+            else {
+                debug(&quot;This test can not be run without the testRunner&quot;);
+                finishJSTest();
+            }
+
+            const pcA = new webkitRTCPeerConnection({iceServers:[{urls:'stun:foo.com'}]});
+            const pcB = new webkitRTCPeerConnection({iceServers:[{urls:'stun:foo.com'}]});
+
+            pcA.ontrack = function (evt) {
+                testPassed(&quot;A: got remote track event&quot;);
+            };
+
+            pcB.ontrack = function (e) {
+                event = e;
+
+                testPassed(&quot;B: got remote track event&quot;);
+                shouldBeType(&quot;event.track&quot;, &quot;MediaStreamTrack&quot;);
+
+                event.track.onunmute = function () {
+                    testPassed(&quot;B: remote track unmute event&quot;);
+                    finishJSTest();
+                };
+            };
+
+            navigator.mediaDevices.getUserMedia({ &quot;audio&quot;: true })
+            .then(function (s) {
+                stream = s;
+
+                evalAndLog(&quot;pcA.addTrack(stream.getAudioTracks()[0], stream)&quot;);
+                debug(&quot;A's transceiver is not yet associated with a media description and should have a null mid&quot;);
+                shouldBeNull(&quot;pcA.getTransceivers()[0].mid&quot;);
+
+                return pcA.createOffer();
+            })
+            .then(function (offer) {
+                return pcA.setLocalDescription(offer);
+            })
+            .then(function () {
+                debug(&quot;A: local offer set (mid gets defined)&quot;);
+
+                evalAndLog(&quot;midAssignedByA = pcA.getTransceivers()[0].mid&quot;);
+                shouldBeTrue(&quot;midAssignedByA !== null&quot;);
+
+                evalAndLog(&quot;pcB.addTrack(stream.getAudioTracks()[0], stream)&quot;);
+                debug(&quot;B's transceiver is not yet associated with a media description and should have a null mid&quot;);
+                shouldBeNull(&quot;pcB.getTransceivers()[0].mid&quot;);
+
+                return pcB.setRemoteDescription(pcA.localDescription);
+            })
+            .then(function () {
+                debug(&quot;B: remote offer set (mid gets defined)&quot;);
+
+                debug(&quot;B's transceiver should get its mid from the remote side (A)&quot;);
+                shouldBe(&quot;pcB.getTransceivers()[0].mid&quot;, &quot;midAssignedByA&quot;);
+
+                return pcB.createAnswer();
+            })
+            .then(function (answer) {
+                return pcB.setLocalDescription(answer);
+            })
+            .then(function () {
+                return pcA.setRemoteDescription(pcB.localDescription);
+            })
+            .then(function () {
+                testPassed(&quot;Offer/answer dialog completed&quot;)
+
+                window.internals.emulateRTCPeerConnectionPlatformEvent(pcB, &quot;unmute-remote-sources-by-mid&quot;);
+            })
+            .catch(function (error) {
+                testFailed(&quot;Error in promise chain: &quot; + error);
+                finishJSTest();
+            });
+
+            window.jsTestIsAsync = true;
+            window.successfullyParsed = true;
+
+        &lt;/script&gt;
+        &lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+    &lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformmacTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/TestExpectations (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/TestExpectations        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/LayoutTests/platform/mac/TestExpectations        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -208,6 +208,7 @@
</span><span class="cx"> fast/mediastream/RTCPeerConnection-legacy-stream-based-api.html
</span><span class="cx"> fast/mediastream/RTCPeerConnection-icecandidate-event.html
</span><span class="cx"> fast/mediastream/RTCPeerConnection-iceconnectionstatechange-event.html
</span><ins>+fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html
</ins><span class="cx"> 
</span><span class="cx"> # Asserts in debug.
</span><span class="cx"> [ Debug ] fast/images/large-size-image-crash.html [ Skip ]
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/Source/WebCore/ChangeLog        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -1,3 +1,48 @@
</span><ins>+2016-10-10  Adam Bergkvist  &lt;adam.bergkvist@ericsson.com&gt; and Alejandro G. Castro &lt;alex@igalia.com&gt;
+
+        WebRTC: Make MediaEndpointPeerConnection handle remotely assigned mids correctly
+        https://bugs.webkit.org/show_bug.cgi?id=163202
+
+        Reviewed by Eric Carlson.
+
+        An RTCRtpTransceiver has a null mid until it's been associated with a
+        media description (with a mid) [1]. During that time, it's identified by
+        a provisional mid that might become its real mid, but the transceiver
+        can also get its mid assigned by a remote media description. In the
+        second case, the mid value is initially unknown. A transceiver's
+        RTCRtpSender must directly (synchronously in the script) provide a muted
+        remote source that is playable by, for example, a media element. This
+        source is initially registered in the MediaEndpoint (WebRTC backend)
+        with the transceiver's provisional mid. So, if the real mid is set by a
+        remote description, the registered mid must be updated to preserve the
+        association between the registered source and the transceiver.
+
+        [1] https://w3c.github.io/webrtc-pc/archives/20160913/webrtc.html#dom-rtcrtptransceiver-mid
+
+        Test: fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html
+
+        * Modules/mediastream/MediaEndpointPeerConnection.cpp:
+        Don't break after finding the first transceiver in the loop that builds the send source map.
+        Update the mid used to register the muted remote source if the a transceiver's mid gets
+        assigned by a remote media description.
+        (WebCore::createSourceMap):
+        (WebCore::MediaEndpointPeerConnection::setRemoteDescriptionTask):
+        * platform/mediastream/MediaEndpoint.cpp:
+        * platform/mediastream/MediaEndpoint.h:
+        * platform/mock/MockMediaEndpoint.cpp:
+        (WebCore::MockMediaEndpoint::MockMediaEndpoint):
+        (WebCore::MockMediaEndpoint::updateReceiveConfiguration):
+        (WebCore::MockMediaEndpoint::updateSendConfiguration):
+        (WebCore::MockMediaEndpoint::createMutedRemoteSource):
+        (WebCore::MockMediaEndpoint::replaceMutedRemoteSourceMid):
+        (WebCore::MockMediaEndpoint::emulatePlatformEvent):
+        Add &quot;unmute-remote-sources-by-mid&quot; action that emulates data arriving on media descriptions
+        which unmutes the remote sources.
+        (WebCore::MockMediaEndpoint::updateConfigurationMids):
+        (WebCore::MockMediaEndpoint::unmuteRemoteSourcesByMid):
+        (WebCore::MockMediaEndpoint::unmuteTimerFired):
+        * platform/mock/MockMediaEndpoint.h:
+
</ins><span class="cx"> 2016-10-10  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move audio module off of legacy exceptions
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaEndpointPeerConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -303,7 +303,6 @@
</span><span class="cx">         if (transceiver) {
</span><span class="cx">             if (transceiver-&gt;hasSendingDirection() &amp;&amp; transceiver-&gt;sender()-&gt;track())
</span><span class="cx">                 sourceMap.set(transceiver-&gt;mid(), &amp;transceiver-&gt;sender()-&gt;track()-&gt;source());
</span><del>-            break;
</del><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -500,9 +499,12 @@
</span><span class="cx">                     return !current.stopped() &amp;&amp; current.mid().isNull() &amp;&amp; current.sender()-&gt;trackKind() == mediaDescription-&gt;type();
</span><span class="cx">                 });
</span><span class="cx"> 
</span><del>-                if (transceiver)
</del><ins>+                if (transceiver) {
+                    // This transceiver was created locally with a provisional mid. Its real mid will now be set by the remote
+                    // description so we need to update the mid of the transceiver's muted source to preserve the association.
</ins><span class="cx">                     transceiver-&gt;setMid(mediaDescription-&gt;mid());
</span><del>-                else
</del><ins>+                    m_mediaEndpoint-&gt;replaceMutedRemoteSourceMid(transceiver-&gt;provisionalMid(), mediaDescription-&gt;mid());
+                } else
</ins><span class="cx">                     receiveOnlyFlag = true;
</span><span class="cx">             }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaEndpointcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaEndpoint.cpp (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaEndpoint.cpp        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/Source/WebCore/platform/mediastream/MediaEndpoint.cpp        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;RealtimeMediaSource&gt; createMutedRemoteSource(const String&amp;, RealtimeMediaSource::Type) override { return EmptyRealtimeMediaSource::create(); }
</span><span class="cx">     void replaceSendSource(RealtimeMediaSource&amp;, const String&amp;) override { }
</span><ins>+    void replaceMutedRemoteSourceMid(const String&amp;, const String&amp;) override { };
</ins><span class="cx"> 
</span><span class="cx">     void stop() override { }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaEndpointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaEndpoint.h (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaEndpoint.h        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/Source/WebCore/platform/mediastream/MediaEndpoint.h        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -77,6 +77,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual Ref&lt;RealtimeMediaSource&gt; createMutedRemoteSource(const String&amp; mid, RealtimeMediaSource::Type) = 0;
</span><span class="cx">     virtual void replaceSendSource(RealtimeMediaSource&amp;, const String&amp; mid) = 0;
</span><ins>+    virtual void replaceMutedRemoteSourceMid(const String&amp; oldMid, const String&amp; newMid) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual void stop() = 0;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockMediaEndpointcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockMediaEndpoint.cpp (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockMediaEndpoint.cpp        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/Source/WebCore/platform/mock/MockMediaEndpoint.cpp        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;MediaPayload.h&quot;
</span><span class="cx"> #include &quot;MockRealtimeAudioSource.h&quot;
</span><span class="cx"> #include &quot;MockRealtimeVideoSource.h&quot;
</span><ins>+#include &quot;RealtimeMediaSource.h&quot;
</ins><span class="cx"> #include &lt;wtf/MainThread.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -53,6 +54,7 @@
</span><span class="cx">     : m_client(client)
</span><span class="cx">     , m_iceCandidateTimer(*this, &amp;MockMediaEndpoint::iceCandidateTimerFired)
</span><span class="cx">     , m_iceTransportTimer(*this, &amp;MockMediaEndpoint::iceTransportTimerFired)
</span><ins>+    , m_unmuteTimer(*this, &amp;MockMediaEndpoint::unmuteTimerFired)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -163,20 +165,16 @@
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(isInitiator);
</span><span class="cx"> 
</span><del>-    Vector&lt;String&gt; mids;
-    for (const RefPtr&lt;PeerMediaDescription&gt;&amp; mediaDescription : configuration-&gt;mediaDescriptions())
-        mids.append(mediaDescription-&gt;mid());
-    m_mids.swap(mids);
-
</del><ins>+    updateConfigurationMids(*configuration);
</ins><span class="cx">     return UpdateResult::Success;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MediaEndpoint::UpdateResult MockMediaEndpoint::updateSendConfiguration(MediaEndpointSessionConfiguration* configuration, const RealtimeMediaSourceMap&amp; sendSourceMap, bool isInitiator)
</span><span class="cx"> {
</span><del>-    UNUSED_PARAM(configuration);
</del><span class="cx">     UNUSED_PARAM(sendSourceMap);
</span><span class="cx">     UNUSED_PARAM(isInitiator);
</span><span class="cx"> 
</span><ins>+    updateConfigurationMids(*configuration);
</ins><span class="cx">     return UpdateResult::Success;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -188,13 +186,19 @@
</span><span class="cx">     UNUSED_PARAM(password);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref&lt;RealtimeMediaSource&gt; MockMediaEndpoint::createMutedRemoteSource(const String&amp;, RealtimeMediaSource::Type type)
</del><ins>+Ref&lt;RealtimeMediaSource&gt; MockMediaEndpoint::createMutedRemoteSource(const String&amp; mid, RealtimeMediaSource::Type type)
</ins><span class="cx"> {
</span><del>-    if (type == RealtimeMediaSource::Audio)
-        return MockRealtimeAudioSource::createMuted(&quot;remote audio&quot;);
</del><ins>+    RefPtr&lt;RealtimeMediaSource&gt; source;
</ins><span class="cx"> 
</span><del>-    ASSERT(type == RealtimeMediaSource::Video);
-    return MockRealtimeVideoSource::createMuted(&quot;remote video&quot;);
</del><ins>+    switch (type) {
+    case RealtimeMediaSource::Audio: source = MockRealtimeAudioSource::createMuted(&quot;remote audio&quot;); break;
+    case RealtimeMediaSource::Video: source = MockRealtimeVideoSource::createMuted(&quot;remote video&quot;); break;
+    case RealtimeMediaSource::None:
+        ASSERT_NOT_REACHED();
+    }
+
+    m_mutedRemoteSources.set(mid, source);
+    return *source;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockMediaEndpoint::replaceSendSource(RealtimeMediaSource&amp; newSource, const String&amp; mid)
</span><span class="lines">@@ -203,6 +207,12 @@
</span><span class="cx">     UNUSED_PARAM(mid);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockMediaEndpoint::replaceMutedRemoteSourceMid(const String&amp; oldMid, const String&amp; newMid)
+{
+    RefPtr&lt;RealtimeMediaSource&gt; remoteSource = m_mutedRemoteSources.take(oldMid);
+    m_mutedRemoteSources.set(newMid, WTFMove(remoteSource));
+}
+
</ins><span class="cx"> void MockMediaEndpoint::stop()
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -213,8 +223,18 @@
</span><span class="cx">         dispatchFakeIceCandidates();
</span><span class="cx">     else if (action == &quot;step-ice-transport-states&quot;)
</span><span class="cx">         stepIceTransportStates();
</span><ins>+    else if (action == &quot;unmute-remote-sources-by-mid&quot;)
+        unmuteRemoteSourcesByMid();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockMediaEndpoint::updateConfigurationMids(const MediaEndpointSessionConfiguration&amp; configuration)
+{
+    Vector&lt;String&gt; mids;
+    for (const RefPtr&lt;PeerMediaDescription&gt;&amp; mediaDescription : configuration.mediaDescriptions())
+        mids.append(mediaDescription-&gt;mid());
+    m_mids.swap(mids);
+}
+
</ins><span class="cx"> void MockMediaEndpoint::dispatchFakeIceCandidates()
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;IceCandidate&gt; iceCandidate = IceCandidate::create();
</span><span class="lines">@@ -316,6 +336,31 @@
</span><span class="cx">     m_iceTransportTimer.startOneShot(0);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockMediaEndpoint::unmuteRemoteSourcesByMid()
+{
+    if (m_mids.isEmpty())
+        return;
+
+    // Looking up each source by its mid, instead of simply iterating over the list of muted sources,
+    // emulates remote media arriving on a media description with a specific mid (RTCRtpTransceiver).
+
+    // Copy values in reverse order to maintain the original order while using takeLast()
+    for (int i = m_mids.size() - 1; i &gt;= 0; --i)
+        m_midsOfSourcesToUnmute.append(m_mids[i]);
+
+    m_unmuteTimer.startOneShot(0);
+}
+
+void MockMediaEndpoint::unmuteTimerFired()
+{
+    RefPtr&lt;RealtimeMediaSource&gt; source = m_mutedRemoteSources.get(m_midsOfSourcesToUnmute.takeLast());
+    if (source)
+        source-&gt;setMuted(false);
+
+    if (!m_midsOfSourcesToUnmute.isEmpty())
+        m_unmuteTimer.startOneShot(0);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEB_RTC)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockMediaEndpointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockMediaEndpoint.h (207051 => 207052)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockMediaEndpoint.h        2016-10-11 06:36:49 UTC (rev 207051)
+++ trunk/Source/WebCore/platform/mock/MockMediaEndpoint.h        2016-10-11 06:39:15 UTC (rev 207052)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;RealtimeMediaSource&gt; createMutedRemoteSource(const String&amp; mid, RealtimeMediaSource::Type) override;
</span><span class="cx">     void replaceSendSource(RealtimeMediaSource&amp;, const String&amp; mid) override;
</span><ins>+    void replaceMutedRemoteSourceMid(const String&amp; oldMid, const String&amp; newMid) override;
</ins><span class="cx"> 
</span><span class="cx">     void stop() override;
</span><span class="cx"> 
</span><span class="lines">@@ -65,6 +66,8 @@
</span><span class="cx">     void emulatePlatformEvent(const String&amp; action) override;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    void updateConfigurationMids(const MediaEndpointSessionConfiguration&amp;);
+
</ins><span class="cx">     void dispatchFakeIceCandidates();
</span><span class="cx">     void iceCandidateTimerFired();
</span><span class="cx"> 
</span><span class="lines">@@ -71,8 +74,12 @@
</span><span class="cx">     void stepIceTransportStates();
</span><span class="cx">     void iceTransportTimerFired();
</span><span class="cx"> 
</span><ins>+    void unmuteRemoteSourcesByMid();
+    void unmuteTimerFired();
+
</ins><span class="cx">     MediaEndpointClient&amp; m_client;
</span><span class="cx">     Vector&lt;String&gt; m_mids;
</span><ins>+    HashMap&lt;String, RefPtr&lt;RealtimeMediaSource&gt;&gt; m_mutedRemoteSources;
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;RefPtr&lt;IceCandidate&gt;&gt; m_fakeIceCandidates;
</span><span class="cx">     Timer m_iceCandidateTimer;
</span><span class="lines">@@ -79,6 +86,9 @@
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;std::pair&lt;String, MediaEndpoint::IceTransportState&gt;&gt; m_iceTransportStateChanges;
</span><span class="cx">     Timer m_iceTransportTimer;
</span><ins>+
+    Vector&lt;String&gt; m_midsOfSourcesToUnmute;
+    Timer m_unmuteTimer;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre>
</div>
</div>

</body>
</html>