<!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 <adam.bergkvist@ericsson.com> and Alejandro G. Castro <alex@igalia.com> 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 "unmute-remote-sources-by-mid" 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 <adam.bergkvist@ericsson.com> and Alejandro G. Castro <alex@igalia.com>
+
+ 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 <gyuyoung.kim@navercorp.com>
</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 "PASS" messages, followed by "TEST COMPLETE".
+
+
+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>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <script src="../../resources/js-test-pre.js"></script>
+ <script src="resources/promise-utils.js"></script>
+ </head>
+ <body>
+ <script>
+ let stream;
+ let midAssignedByA;
+ let event;
+
+ description("Test the case where an RTCRtpTransceiver gets a remotely assigned mid and also unmute the associated source");
+
+ if (window.testRunner)
+ testRunner.setUserMediaPermission(true);
+ else {
+ debug("This test can not be run without the testRunner");
+ finishJSTest();
+ }
+
+ const pcA = new webkitRTCPeerConnection({iceServers:[{urls:'stun:foo.com'}]});
+ const pcB = new webkitRTCPeerConnection({iceServers:[{urls:'stun:foo.com'}]});
+
+ pcA.ontrack = function (evt) {
+ testPassed("A: got remote track event");
+ };
+
+ pcB.ontrack = function (e) {
+ event = e;
+
+ testPassed("B: got remote track event");
+ shouldBeType("event.track", "MediaStreamTrack");
+
+ event.track.onunmute = function () {
+ testPassed("B: remote track unmute event");
+ finishJSTest();
+ };
+ };
+
+ navigator.mediaDevices.getUserMedia({ "audio": true })
+ .then(function (s) {
+ stream = s;
+
+ evalAndLog("pcA.addTrack(stream.getAudioTracks()[0], stream)");
+ debug("A's transceiver is not yet associated with a media description and should have a null mid");
+ shouldBeNull("pcA.getTransceivers()[0].mid");
+
+ return pcA.createOffer();
+ })
+ .then(function (offer) {
+ return pcA.setLocalDescription(offer);
+ })
+ .then(function () {
+ debug("A: local offer set (mid gets defined)");
+
+ evalAndLog("midAssignedByA = pcA.getTransceivers()[0].mid");
+ shouldBeTrue("midAssignedByA !== null");
+
+ evalAndLog("pcB.addTrack(stream.getAudioTracks()[0], stream)");
+ debug("B's transceiver is not yet associated with a media description and should have a null mid");
+ shouldBeNull("pcB.getTransceivers()[0].mid");
+
+ return pcB.setRemoteDescription(pcA.localDescription);
+ })
+ .then(function () {
+ debug("B: remote offer set (mid gets defined)");
+
+ debug("B's transceiver should get its mid from the remote side (A)");
+ shouldBe("pcB.getTransceivers()[0].mid", "midAssignedByA");
+
+ return pcB.createAnswer();
+ })
+ .then(function (answer) {
+ return pcB.setLocalDescription(answer);
+ })
+ .then(function () {
+ return pcA.setRemoteDescription(pcB.localDescription);
+ })
+ .then(function () {
+ testPassed("Offer/answer dialog completed")
+
+ window.internals.emulateRTCPeerConnectionPlatformEvent(pcB, "unmute-remote-sources-by-mid");
+ })
+ .catch(function (error) {
+ testFailed("Error in promise chain: " + error);
+ finishJSTest();
+ });
+
+ window.jsTestIsAsync = true;
+ window.successfullyParsed = true;
+
+ </script>
+ <script src="../../resources/js-test-post.js"></script>
+ </body>
+</html>
</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 <adam.bergkvist@ericsson.com> and Alejandro G. Castro <alex@igalia.com>
+
+ 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 "unmute-remote-sources-by-mid" 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 <darin@apple.com>
</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->hasSendingDirection() && transceiver->sender()->track())
</span><span class="cx"> sourceMap.set(transceiver->mid(), &transceiver->sender()->track()->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() && current.mid().isNull() && current.sender()->trackKind() == mediaDescription->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->setMid(mediaDescription->mid());
</span><del>- else
</del><ins>+ m_mediaEndpoint->replaceMutedRemoteSourceMid(transceiver->provisionalMid(), mediaDescription->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<RealtimeMediaSource> createMutedRemoteSource(const String&, RealtimeMediaSource::Type) override { return EmptyRealtimeMediaSource::create(); }
</span><span class="cx"> void replaceSendSource(RealtimeMediaSource&, const String&) override { }
</span><ins>+ void replaceMutedRemoteSourceMid(const String&, const String&) 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<RealtimeMediaSource> createMutedRemoteSource(const String& mid, RealtimeMediaSource::Type) = 0;
</span><span class="cx"> virtual void replaceSendSource(RealtimeMediaSource&, const String& mid) = 0;
</span><ins>+ virtual void replaceMutedRemoteSourceMid(const String& oldMid, const String& 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 "MediaPayload.h"
</span><span class="cx"> #include "MockRealtimeAudioSource.h"
</span><span class="cx"> #include "MockRealtimeVideoSource.h"
</span><ins>+#include "RealtimeMediaSource.h"
</ins><span class="cx"> #include <wtf/MainThread.h>
</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, &MockMediaEndpoint::iceCandidateTimerFired)
</span><span class="cx"> , m_iceTransportTimer(*this, &MockMediaEndpoint::iceTransportTimerFired)
</span><ins>+ , m_unmuteTimer(*this, &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<String> mids;
- for (const RefPtr<PeerMediaDescription>& mediaDescription : configuration->mediaDescriptions())
- mids.append(mediaDescription->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& 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<RealtimeMediaSource> MockMediaEndpoint::createMutedRemoteSource(const String&, RealtimeMediaSource::Type type)
</del><ins>+Ref<RealtimeMediaSource> MockMediaEndpoint::createMutedRemoteSource(const String& mid, RealtimeMediaSource::Type type)
</ins><span class="cx"> {
</span><del>- if (type == RealtimeMediaSource::Audio)
- return MockRealtimeAudioSource::createMuted("remote audio");
</del><ins>+ RefPtr<RealtimeMediaSource> source;
</ins><span class="cx">
</span><del>- ASSERT(type == RealtimeMediaSource::Video);
- return MockRealtimeVideoSource::createMuted("remote video");
</del><ins>+ switch (type) {
+ case RealtimeMediaSource::Audio: source = MockRealtimeAudioSource::createMuted("remote audio"); break;
+ case RealtimeMediaSource::Video: source = MockRealtimeVideoSource::createMuted("remote video"); 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& newSource, const String& 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& oldMid, const String& newMid)
+{
+ RefPtr<RealtimeMediaSource> 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 == "step-ice-transport-states")
</span><span class="cx"> stepIceTransportStates();
</span><ins>+ else if (action == "unmute-remote-sources-by-mid")
+ unmuteRemoteSourcesByMid();
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void MockMediaEndpoint::updateConfigurationMids(const MediaEndpointSessionConfiguration& configuration)
+{
+ Vector<String> mids;
+ for (const RefPtr<PeerMediaDescription>& mediaDescription : configuration.mediaDescriptions())
+ mids.append(mediaDescription->mid());
+ m_mids.swap(mids);
+}
+
</ins><span class="cx"> void MockMediaEndpoint::dispatchFakeIceCandidates()
</span><span class="cx"> {
</span><span class="cx"> RefPtr<IceCandidate> 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 >= 0; --i)
+ m_midsOfSourcesToUnmute.append(m_mids[i]);
+
+ m_unmuteTimer.startOneShot(0);
+}
+
+void MockMediaEndpoint::unmuteTimerFired()
+{
+ RefPtr<RealtimeMediaSource> source = m_mutedRemoteSources.get(m_midsOfSourcesToUnmute.takeLast());
+ if (source)
+ source->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<RealtimeMediaSource> createMutedRemoteSource(const String& mid, RealtimeMediaSource::Type) override;
</span><span class="cx"> void replaceSendSource(RealtimeMediaSource&, const String& mid) override;
</span><ins>+ void replaceMutedRemoteSourceMid(const String& oldMid, const String& 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& action) override;
</span><span class="cx">
</span><span class="cx"> private:
</span><ins>+ void updateConfigurationMids(const MediaEndpointSessionConfiguration&);
+
</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& m_client;
</span><span class="cx"> Vector<String> m_mids;
</span><ins>+ HashMap<String, RefPtr<RealtimeMediaSource>> m_mutedRemoteSources;
</ins><span class="cx">
</span><span class="cx"> Vector<RefPtr<IceCandidate>> 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<std::pair<String, MediaEndpoint::IceTransportState>> m_iceTransportStateChanges;
</span><span class="cx"> Timer m_iceTransportTimer;
</span><ins>+
+ Vector<String> 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>