Title: [214357] trunk
Revision
214357
Author
[email protected]
Date
2017-03-24 11:01:18 -0700 (Fri, 24 Mar 2017)

Log Message

Add libwebrtc backend support for RTCRtpSender::replaceTrack
https://bugs.webkit.org/show_bug.cgi?id=169841

Patch by Youenn Fablet <[email protected]> on 2017-03-24
Reviewed by Alex Christensen.

Source/WebCore:

Tests: webrtc/audio-replace-track.html
       webrtc/video-replace-track.html

Adding support for replaceTrack for audio and video sources.
Replacing tracks will always succeed for audio sources.
For video tracks, it will only succeed if the video resolution is not greater.
LibWebRTCPeerConnectionBackend will delegate the track replacing by replacing the source of the outgoing sources with the source wrapped in the replacing track.

Video test is not fully passing as size constraints for mock video sources are not providing the right video stream resolution.

* Modules/mediastream/RTCRtpSender.cpp:
(WebCore::RTCRtpSender::replaceTrack):
* Modules/mediastream/RTCRtpSender.h:
* Modules/mediastream/RTCRtpSender.idl:
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
(WebCore::LibWebRTCPeerConnectionBackend::replaceTrack):
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
* platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp:
(WebCore::RealtimeOutgoingAudioSource::setSource):
* platform/mediastream/mac/RealtimeOutgoingAudioSource.h:
* platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp:
(WebCore::RealtimeOutgoingVideoSource::setSource):
* platform/mediastream/mac/RealtimeOutgoingVideoSource.h:
* platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSource::drawText):
(WebCore::MockRealtimeVideoSource::generateFrame):

LayoutTests:

* webrtc/audio-replace-track-expected.txt: Added.
* webrtc/audio-replace-track.html: Added.
* webrtc/video-replace-track-expected.txt: Added.
* webrtc/video-replace-track.html: Added.
* webrtc/video-replace-track-to-null-expected.txt: Added.
* webrtc/video-replace-track-to-null.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (214356 => 214357)


--- trunk/LayoutTests/ChangeLog	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/LayoutTests/ChangeLog	2017-03-24 18:01:18 UTC (rev 214357)
@@ -1,3 +1,17 @@
+2017-03-24  Youenn Fablet  <[email protected]>
+
+        Add libwebrtc backend support for RTCRtpSender::replaceTrack
+        https://bugs.webkit.org/show_bug.cgi?id=169841
+
+        Reviewed by Alex Christensen.
+
+        * webrtc/audio-replace-track-expected.txt: Added.
+        * webrtc/audio-replace-track.html: Added.
+        * webrtc/video-replace-track-expected.txt: Added.
+        * webrtc/video-replace-track.html: Added.
+        * webrtc/video-replace-track-to-null-expected.txt: Added.
+        * webrtc/video-replace-track-to-null.html: Added.
+
 2017-03-24  Ryan Haddad  <[email protected]>
 
         Update TestExpectations for media/restore-from-page-cache.html.

Added: trunk/LayoutTests/webrtc/audio-replace-track-expected.txt (0 => 214357)


--- trunk/LayoutTests/webrtc/audio-replace-track-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webrtc/audio-replace-track-expected.txt	2017-03-24 18:01:18 UTC (rev 214357)
@@ -0,0 +1,3 @@
+
+PASS Replacing audio track from a peer connection 
+

Added: trunk/LayoutTests/webrtc/audio-replace-track.html (0 => 214357)


--- trunk/LayoutTests/webrtc/audio-replace-track.html	                        (rev 0)
+++ trunk/LayoutTests/webrtc/audio-replace-track.html	2017-03-24 18:01:18 UTC (rev 214357)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Testing local audio capture playback causes "playing" event to fire</title>
+    <script src=""
+    <script src=""
+    <script src =""
+    <script>
+    promise_test((test) => {
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(true);
+
+        var sender;
+        var firsStream;
+        var secondStream;
+        var remoteStream;
+        return navigator.mediaDevices.getUserMedia({ audio: { sampleRate: { exact: 48000 } } }).then((stream) => {
+            firstStream = stream;
+            return navigator.mediaDevices.getUserMedia({ audio: { sampleRate: { exact: 48000 } } });
+        }).then((stream) => {
+            secondStream = stream;
+            if (window.internals)
+                internals.useMockRTCPeerConnectionFactory("TwoRealPeerConnections");
+            return new Promise((resolve, reject) => {
+                createConnections((firstConnection) => {
+                    sender = firstConnection.addTrack(firstStream.getAudioTracks()[0], firstStream);
+                }, (secondConnection) => {
+                    secondConnection._ontrack_ = (trackEvent) => { resolve(trackEvent.streams[0]); };
+                });
+                setTimeout(() => reject("Test timed out"), 5000);
+            });
+        }).then((stream) => {
+            remoteStream = stream;
+            return analyseAudio(remoteStream, 1000);
+        }).then((results) => {
+            assert_true(results.heardHum, "heard hum");
+            return sender.replaceTrack(secondStream.getAudioTracks()[0], secondStream);
+        }).then(() => {
+            assert_true(sender.track === secondStream.getAudioTracks()[0]);
+            return waitFor(500);
+        }).then((results) => {
+            return analyseAudio(remoteStream, 1000);
+        }).then((results) => {
+            assert_true(results.heardHum, "heard hum");
+        });
+    }, "Replacing audio track from a peer connection");
+    </script>
+</head>
+<body>
+</body>
+</html>

Added: trunk/LayoutTests/webrtc/video-replace-track-expected.txt (0 => 214357)


--- trunk/LayoutTests/webrtc/video-replace-track-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webrtc/video-replace-track-expected.txt	2017-03-24 18:01:18 UTC (rev 214357)
@@ -0,0 +1,5 @@
+
+PASS Switching from front to back camera 
+FAIL Switching from front to back camera, with lower resolution assert_true: backStream should be smaller expected true got false
+FAIL Switching from front to back camera, with higher resolution assert_true: front stream should be smaller expected true got false
+

Added: trunk/LayoutTests/webrtc/video-replace-track-to-null-expected.txt (0 => 214357)


--- trunk/LayoutTests/webrtc/video-replace-track-to-null-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webrtc/video-replace-track-to-null-expected.txt	2017-03-24 18:01:18 UTC (rev 214357)
@@ -0,0 +1,3 @@
+
+PASS Stopping sending video using replaceTrack 
+

Added: trunk/LayoutTests/webrtc/video-replace-track-to-null.html (0 => 214357)


--- trunk/LayoutTests/webrtc/video-replace-track-to-null.html	                        (rev 0)
+++ trunk/LayoutTests/webrtc/video-replace-track-to-null.html	2017-03-24 18:01:18 UTC (rev 214357)
@@ -0,0 +1,103 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Testing basic video exchange from offerer to receiver</title>
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+<div id="log"></div>
+        <video id="video" autoplay=""></video>
+        <canvas id="canvas" width="640" height="480"></canvas>
+        <script src =""
+        <script>
+video = document.getElementById("video");
+canvas = document.getElementById("canvas");
+
+function grabImagePixels()
+{
+    canvas.width = video.videoWidth;
+    canvas.height = video.videoHeight;
+    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
+
+    imageData = canvas.getContext('2d').getImageData(20, 20, 100, 100);
+    return imageData.data;
+ }
+
+var firstFrameData;
+
+function storeFrame()
+{
+    firstFrameData = grabImagePixels();
+}
+
+function testCameraImage()
+{
+    data = ""
+
+    assert_true(data[0] < 20);
+    assert_true(data[1] < 20);
+    assert_true(data[2] < 20);
+
+    var same = true;
+    for (var cptr = 0; cptr < data.length; ++cptr) {
+        if (data[cptr] != firstFrameData[cptr]) {
+            same = false;
+            break;
+        }
+    }
+    assert_false(same);
+}
+
+function testStoppedImage()
+{
+    assert_array_equals(grabImagePixels(), firstFrameData);
+}
+
+promise_test((test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    var sender;
+    var frontStream;
+    return navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
+        frontStream = stream;
+    }).then(() => {
+        return new Promise((resolve, reject) => {
+            if (window.internals)
+                internals.useMockRTCPeerConnectionFactory("TwoRealPeerConnections");
+
+            createConnections((firstConnection) => {
+                sender = firstConnection.addTrack(frontStream.getVideoTracks()[0], frontStream);
+            }, (secondConnection) => {
+                secondConnection._ontrack_ = (trackEvent) => {
+                    resolve(trackEvent.streams[0]);
+                };
+            });
+            setTimeout(() => reject("Test timed out"), 5000);
+        });
+    }).then((remoteStream) => {
+        video.srcObject = remoteStream;
+        return video.play();
+    }).then(() => {
+        storeFrame();
+        return waitFor(100);
+    }).then(() => {
+        testCameraImage();
+    }).then(() => {
+        promise = sender.replaceTrack(null);
+        assert_true(!!sender.track);
+        return promise;
+    }).then(() => {
+        return waitFor(100);
+    }).then(() => {
+        storeFrame();
+        return waitFor(100);
+    }).then(() => {
+        testStoppedImage();
+    });
+}, "Stopping sending video using replaceTrack");
+        </script>
+    </body>
+</html>

Added: trunk/LayoutTests/webrtc/video-replace-track.html (0 => 214357)


--- trunk/LayoutTests/webrtc/video-replace-track.html	                        (rev 0)
+++ trunk/LayoutTests/webrtc/video-replace-track.html	2017-03-24 18:01:18 UTC (rev 214357)
@@ -0,0 +1,181 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Testing basic video exchange from offerer to receiver</title>
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+<div id="log"></div>
+        <video id="video" autoplay=""></video>
+        <canvas id="canvas" width="640" height="480"></canvas>
+        <script src =""
+        <script>
+video = document.getElementById("video");
+canvas = document.getElementById("canvas");
+
+function grabImagePixels()
+{
+    canvas.width = video.videoWidth;
+    canvas.height = video.videoHeight;
+    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
+
+    imageData = canvas.getContext('2d').getImageData(20, 20, 2, 2);
+    return imageData.data;
+ }
+
+function testFrontCameraImage()
+{
+    data = ""
+
+    assert_true(data[0] < 20);
+    assert_true(data[1] < 20);
+    assert_true(data[2] < 20);
+}
+
+function testBackCameraImage()
+{
+    data = ""
+
+    assert_true(data[0] > 100);
+    assert_true(data[1] > 100);
+    assert_true(data[2] > 100);
+
+    assert_true(data[0] < 200);
+    assert_true(data[1] < 200);
+    assert_true(data[2] < 200);
+}
+
+promise_test((test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    var sender;
+    var frontStream;
+    var backStream;
+    return navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: ["user"] } } }).then((stream) => {
+        frontStream = stream;
+        return navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: ["environment"] } } });
+    }).then((stream) => {
+        backStream = stream;
+    }).then(() => {
+        return new Promise((resolve, reject) => {
+            if (window.internals)
+                internals.useMockRTCPeerConnectionFactory("TwoRealPeerConnections");
+
+            createConnections((firstConnection) => {
+                sender = firstConnection.addTrack(frontStream.getVideoTracks()[0], frontStream);
+            }, (secondConnection) => {
+                secondConnection._ontrack_ = (trackEvent) => {
+                    resolve(trackEvent.streams[0]);
+                };
+            });
+            setTimeout(() => reject("Test timed out"), 5000);
+        });
+    }).then((remoteStream) => {
+        video.srcObject = remoteStream;
+        return video.play();
+    }).then(() => {
+        testFrontCameraImage();
+    }).then(() => {
+        var currentTrack = sender.track;
+        promise = sender.replaceTrack(backStream.getVideoTracks()[0]);
+        assert_true(currentTrack === sender.track);
+        return promise;
+    }).then(() => {
+        assert_true(sender.track === backStream.getVideoTracks()[0]);
+        return waitFor(500);
+    }).then(() => {
+        testBackCameraImage();
+    });
+}, "Switching from front to back camera");
+
+promise_test((test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    var sender;
+    var frontStream;
+    var backStream;
+
+    return navigator.mediaDevices.getUserMedia({ video: { height: { min: 400 }, facingMode: { exact: ["user"] } } }).then((stream) => {
+        frontStream = stream;
+        return navigator.mediaDevices.getUserMedia({ video: { height: { max: 400 }, facingMode: { exact: ["environment"] } } });
+    }).then((stream) => {
+        backStream = stream;
+        assert_true(frontStream.getVideoTracks()[0].getSettings().height >= 400, "frontStream should be bigger");
+        assert_true(backStream.getVideoTracks()[0].getSettings().height < 400, "backStream should be smaller");
+    }).then(() => {
+        return new Promise((resolve, reject) => {
+            if (window.internals)
+                internals.useMockRTCPeerConnectionFactory("TwoRealPeerConnections");
+
+            createConnections((firstConnection) => {
+                sender = firstConnection.addTrack(frontStream.getVideoTracks()[0], frontStream);
+            }, (secondConnection) => {
+                secondConnection._ontrack_ = (trackEvent) => {
+                    resolve(trackEvent.streams[0]);
+                };
+            });
+            setTimeout(() => reject("Test timed out"), 5000);
+        });
+    }).then((remoteStream) => {
+        video.srcObject = remoteStream;
+        return video.play();
+    }).then(() => {
+        testFrontCameraImage();
+    }).then(() => {
+        return sender.replaceTrack(backStream.getVideoTracks()[0]);
+    }).then(() => {
+        return waitFor(500);
+    }).then(() => {
+        testBackCameraImage();
+    });
+}, "Switching from front to back camera, with lower resolution");
+
+promise_test((test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    var sender;
+    var frontStream;
+    var backStream;
+
+    return navigator.mediaDevices.getUserMedia({ video: { height: { max: 400 }, facingMode: { exact: ["user"] } } }).then((stream) => {
+        frontStream = stream;
+        return navigator.mediaDevices.getUserMedia({ video: { height: { min: 400 }, facingMode: { exact: ["environment"] } } });
+    }).then((stream) => {
+        backStream = stream;
+        assert_true(frontStream.getVideoTracks()[0].getSettings().height < 400, "front stream should be smaller");
+        assert_true(backStream.getVideoTracks()[0].getSettings().height >= 400, "back stream should be bigger");
+    }).then(() => {
+        return new Promise((resolve, reject) => {
+            if (window.internals)
+                internals.useMockRTCPeerConnectionFactory("TwoRealPeerConnections");
+
+            createConnections((firstConnection) => {
+                sender = firstConnection.addTrack(frontStream.getVideoTracks()[0], frontStream);
+            }, (secondConnection) => {
+                secondConnection._ontrack_ = (trackEvent) => {
+                    resolve(trackEvent.streams[0]);
+                };
+            });
+            setTimeout(() => reject("Test timed out"), 5000);
+        });
+    }).then((remoteStream) => {
+        video.srcObject = remoteStream;
+        return video.play();
+    }).then(() => {
+        testFrontCameraImage();
+    }).then(() => {
+        return promise_rejects(test, "InvalidModificationError", sender.replaceTrack(backStream.getVideoTracks()[0]));
+    }).then(() => {
+        return waitFor(500);
+    }).then(() => {
+        testBackCameraImage();
+    });
+}, "Switching from front to back camera, with higher resolution");
+        </script>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (214356 => 214357)


--- trunk/Source/WebCore/ChangeLog	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/ChangeLog	2017-03-24 18:01:18 UTC (rev 214357)
@@ -1,3 +1,37 @@
+2017-03-24  Youenn Fablet  <[email protected]>
+
+        Add libwebrtc backend support for RTCRtpSender::replaceTrack
+        https://bugs.webkit.org/show_bug.cgi?id=169841
+
+        Reviewed by Alex Christensen.
+
+        Tests: webrtc/audio-replace-track.html
+               webrtc/video-replace-track.html
+
+        Adding support for replaceTrack for audio and video sources.
+        Replacing tracks will always succeed for audio sources.
+        For video tracks, it will only succeed if the video resolution is not greater.
+        LibWebRTCPeerConnectionBackend will delegate the track replacing by replacing the source of the outgoing sources with the source wrapped in the replacing track.
+
+        Video test is not fully passing as size constraints for mock video sources are not providing the right video stream resolution.
+
+        * Modules/mediastream/RTCRtpSender.cpp:
+        (WebCore::RTCRtpSender::replaceTrack):
+        * Modules/mediastream/RTCRtpSender.h:
+        * Modules/mediastream/RTCRtpSender.idl:
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
+        (WebCore::LibWebRTCPeerConnectionBackend::replaceTrack):
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
+        * platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp:
+        (WebCore::RealtimeOutgoingAudioSource::setSource):
+        * platform/mediastream/mac/RealtimeOutgoingAudioSource.h:
+        * platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp:
+        (WebCore::RealtimeOutgoingVideoSource::setSource):
+        * platform/mediastream/mac/RealtimeOutgoingVideoSource.h:
+        * platform/mock/MockRealtimeVideoSource.cpp:
+        (WebCore::MockRealtimeVideoSource::drawText):
+        (WebCore::MockRealtimeVideoSource::generateFrame):
+
 2017-03-24  Jon Lee  <[email protected]>
 
         Remove comment from RTCStatsReport.idl to convert ssrc to DOMString.

Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp (214356 => 214357)


--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp	2017-03-24 18:01:18 UTC (rev 214357)
@@ -496,11 +496,32 @@
     dispatchEvent(event);
 }
 
-void RTCPeerConnection::replaceTrack(RTCRtpSender& sender, Ref<MediaStreamTrack>&& withTrack, DOMPromise<void>&& promise)
+void RTCPeerConnection::enqueueReplaceTrackTask(RTCRtpSender& sender, Ref<MediaStreamTrack>&& withTrack, DOMPromise<void>&& promise)
 {
-    m_backend->replaceTrack(sender, WTFMove(withTrack), WTFMove(promise));
+    scriptExecutionContext()->postTask([protectedSender = makeRef(sender), promise = WTFMove(promise), withTrack = WTFMove(withTrack)](ScriptExecutionContext&) mutable {
+        protectedSender->setTrack(WTFMove(withTrack));
+        promise.resolve();
+    });
 }
 
+void RTCPeerConnection::replaceTrack(RTCRtpSender& sender, RefPtr<MediaStreamTrack>&& withTrack, DOMPromise<void>&& promise)
+{
+    if (!withTrack) {
+        scriptExecutionContext()->postTask([protectedSender = makeRef(sender), promise = WTFMove(promise)](ScriptExecutionContext&) mutable {
+            protectedSender->setTrackToNull();
+            promise.resolve();
+        });
+        return;
+    }
+    
+    if (!sender.track()) {
+        enqueueReplaceTrackTask(sender, withTrack.releaseNonNull(), WTFMove(promise));
+        return;
+    }
+
+    m_backend->replaceTrack(sender, withTrack.releaseNonNull(), WTFMove(promise));
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEB_RTC)

Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h (214356 => 214357)


--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h	2017-03-24 18:01:18 UTC (rev 214357)
@@ -140,6 +140,8 @@
     void disableICECandidateFiltering() { m_backend->disableICECandidateFiltering(); }
     void enableICECandidateFiltering() { m_backend->enableICECandidateFiltering(); }
 
+    void enqueueReplaceTrackTask(RTCRtpSender&, Ref<MediaStreamTrack>&&, DOMPromise<void>&&);
+
 private:
     RTCPeerConnection(ScriptExecutionContext&);
 
@@ -159,7 +161,7 @@
     bool canSuspendForDocumentSuspension() const final;
 
     // RTCRtpSenderClient
-    void replaceTrack(RTCRtpSender&, Ref<MediaStreamTrack>&&, DOMPromise<void>&&) final;
+    void replaceTrack(RTCRtpSender&, RefPtr<MediaStreamTrack>&&, DOMPromise<void>&&) final;
 
     void updateConnectionState();
     bool doClose();

Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.cpp (214356 => 214357)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.cpp	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.cpp	2017-03-24 18:01:18 UTC (rev 214357)
@@ -57,27 +57,37 @@
 {
 }
 
+void RTCRtpSender::setTrackToNull()
+{
+    ASSERT(m_track);
+    m_trackId = { };
+    m_track = nullptr;
+}
+
 void RTCRtpSender::setTrack(Ref<MediaStreamTrack>&& track)
 {
     ASSERT(!isStopped());
-    ASSERT(!m_track);
-    m_trackId = track->id();
+    if (!m_track)
+        m_trackId = track->id();
     m_track = WTFMove(track);
 }
 
-ExceptionOr<void> RTCRtpSender::replaceTrack(Ref<MediaStreamTrack>&& withTrack, DOMPromise<void>&& promise)
+void RTCRtpSender::replaceTrack(RefPtr<MediaStreamTrack>&& withTrack, DOMPromise<void>&& promise)
 {
     if (isStopped()) {
         promise.reject(INVALID_STATE_ERR);
-        return { };
+        return;
     }
 
-    if (m_trackKind != withTrack->kind())
-        return Exception { TypeError };
+    if (withTrack && m_trackKind != withTrack->kind()) {
+        promise.reject(TypeError);
+        return;
+    }
 
+    if (!withTrack && m_track)
+        m_track->stopProducingData();
+
     m_client->replaceTrack(*this, WTFMove(withTrack), WTFMove(promise));
-
-    return { };
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.h (214356 => 214357)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.h	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.h	2017-03-24 18:01:18 UTC (rev 214357)
@@ -39,7 +39,7 @@
 
 class RTCRtpSenderClient {
 public:
-    virtual void replaceTrack(RTCRtpSender&, Ref<MediaStreamTrack>&&, DOMPromise<void>&&) = 0;
+    virtual void replaceTrack(RTCRtpSender&, RefPtr<MediaStreamTrack>&&, DOMPromise<void>&&) = 0;
 
     virtual ~RTCRtpSenderClient() { }
 };
@@ -58,8 +58,9 @@
     bool isStopped() const { return !m_client; }
     void stop() { m_client = nullptr; }
     void setTrack(Ref<MediaStreamTrack>&&);
+    void setTrackToNull();
 
-    ExceptionOr<void> replaceTrack(Ref<MediaStreamTrack>&&, DOMPromise<void>&&);
+    void replaceTrack(RefPtr<MediaStreamTrack>&&, DOMPromise<void>&&);
 
 private:
     RTCRtpSender(String&& trackKind, Vector<String>&& mediaStreamIds, RTCRtpSenderClient&);

Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.idl (214356 => 214357)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.idl	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSender.idl	2017-03-24 18:01:18 UTC (rev 214357)
@@ -39,5 +39,5 @@
     // FIXME 169662: missing getCapabilities
     // FIXME 169662: missing setParameters
     // FIXME 169662: missing getParameters
-    [MayThrowException] Promise<void> replaceTrack(MediaStreamTrack withTrack);
+    Promise<void> replaceTrack(MediaStreamTrack? withTrack);
 };

Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp (214356 => 214357)


--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp	2017-03-24 18:01:18 UTC (rev 214357)
@@ -28,6 +28,7 @@
 #if USE(LIBWEBRTC)
 
 #include "Document.h"
+#include "ExceptionCode.h"
 #include "IceCandidate.h"
 #include "JSRTCStatsReport.h"
 #include "LibWebRTCDataChannelHandler.h"
@@ -321,6 +322,48 @@
     m_remoteStreams.append(WTFMove(mediaStream));
 }
 
+void LibWebRTCPeerConnectionBackend::replaceTrack(RTCRtpSender& sender, Ref<MediaStreamTrack>&& track, DOMPromise<void>&& promise)
+{
+    ASSERT(sender.track());
+    auto* currentTrack = sender.track();
+
+    ASSERT(currentTrack->source().type() == track->source().type());
+    switch (currentTrack->source().type()) {
+    case RealtimeMediaSource::Type::None:
+        ASSERT_NOT_REACHED();
+        promise.reject(INVALID_MODIFICATION_ERR);
+        break;
+    case RealtimeMediaSource::Type::Audio: {
+        for (auto& audioSource : m_audioSources) {
+            if (&audioSource->source() == &currentTrack->source()) {
+                if (!audioSource->setSource(track->source())) {
+                    promise.reject(INVALID_MODIFICATION_ERR);
+                    return;
+                }
+                connection().enqueueReplaceTrackTask(sender, WTFMove(track), WTFMove(promise));
+                return;
+            }
+        }
+        promise.reject(INVALID_MODIFICATION_ERR);
+        break;
+    }
+    case RealtimeMediaSource::Type::Video: {
+        for (auto& videoSource : m_videoSources) {
+            if (&videoSource->source() == &currentTrack->source()) {
+                if (!videoSource->setSource(track->source())) {
+                    promise.reject(INVALID_MODIFICATION_ERR);
+                    return;
+                }
+                connection().enqueueReplaceTrackTask(sender, WTFMove(track), WTFMove(promise));
+                return;
+            }
+        }
+        promise.reject(INVALID_MODIFICATION_ERR);
+        break;
+    }
+    }
+}
+
 } // namespace WebCore
 
 #endif // USE(LIBWEBRTC)

Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h (214356 => 214357)


--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h	2017-03-24 18:01:18 UTC (rev 214357)
@@ -69,8 +69,7 @@
     RefPtr<RTCSessionDescription> currentRemoteDescription() const final;
     RefPtr<RTCSessionDescription> pendingRemoteDescription() const final;
 
-    // FIXME: API to implement for real
-    void replaceTrack(RTCRtpSender&, Ref<MediaStreamTrack>&&, DOMPromise<void>&&) final { }
+    void replaceTrack(RTCRtpSender&, Ref<MediaStreamTrack>&&, DOMPromise<void>&&) final;
 
     void emulatePlatformEvent(const String&) final { }
 

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp (214356 => 214357)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.cpp	2017-03-24 18:01:18 UTC (rev 214357)
@@ -51,6 +51,14 @@
     m_audioSource->addObserver(*this);
 }
 
+bool RealtimeOutgoingAudioSource::setSource(Ref<RealtimeMediaSource>&& newSource)
+{
+    m_audioSource->removeObserver(*this);
+    m_audioSource = WTFMove(newSource);
+    m_audioSource->addObserver(*this);
+    return true;
+}
+
 void RealtimeOutgoingAudioSource::stop()
 {
     m_audioSource->removeObserver(*this);

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.h (214356 => 214357)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.h	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingAudioSource.h	2017-03-24 18:01:18 UTC (rev 214357)
@@ -51,6 +51,9 @@
     void setTrack(rtc::scoped_refptr<webrtc::AudioTrackInterface>&& track) { m_track = WTFMove(track); }
     void stop();
 
+    bool setSource(Ref<RealtimeMediaSource>&&);
+    RealtimeMediaSource& source() const { return m_audioSource.get(); }
+
 private:
     explicit RealtimeOutgoingAudioSource(Ref<RealtimeMediaSource>&&);
 

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp (214356 => 214357)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.cpp	2017-03-24 18:01:18 UTC (rev 214357)
@@ -46,6 +46,22 @@
     m_videoSource->addObserver(*this);
 }
 
+bool RealtimeOutgoingVideoSource::setSource(Ref<RealtimeMediaSource>&& newSource)
+{
+    if (!m_initialSettings)
+        m_initialSettings = m_videoSource->settings();
+
+    auto newSettings = newSource->settings();
+
+    if (m_initialSettings->width() < newSettings.width() || m_initialSettings->height() < newSettings.height())
+        return false;
+
+    m_videoSource->removeObserver(*this);
+    m_videoSource = WTFMove(newSource);
+    m_videoSource->addObserver(*this);
+    return true;
+}
+
 void RealtimeOutgoingVideoSource::stop()
 {
     m_videoSource->removeObserver(*this);

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.h (214356 => 214357)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.h	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeOutgoingVideoSource.h	2017-03-24 18:01:18 UTC (rev 214357)
@@ -36,6 +36,7 @@
 #include <webrtc/base/optional.h>
 #include <webrtc/common_video/include/i420_buffer_pool.h>
 #include <webrtc/media/base/videosinkinterface.h>
+#include <wtf/Optional.h>
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace WebCore {
@@ -46,6 +47,8 @@
     ~RealtimeOutgoingVideoSource() { stop(); }
 
     void stop();
+    bool setSource(Ref<RealtimeMediaSource>&&);
+    RealtimeMediaSource& source() const { return m_videoSource.get(); }
 
     int AddRef() const final { ref(); return refCount(); }
     int Release() const final { deref(); return refCount(); }
@@ -82,6 +85,7 @@
     Ref<RealtimeMediaSource> m_videoSource;
     bool m_enabled { true };
     bool m_muted { false };
+    std::optional<RealtimeMediaSourceSettings> m_initialSettings;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (214356 => 214357)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2017-03-24 17:46:36 UTC (rev 214356)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2017-03-24 18:01:18 UTC (rev 214357)
@@ -327,11 +327,11 @@
     FloatPoint bipBopLocation(size.width() * .6, size.height() * .6);
     unsigned frameMod = m_frameNumber % 60;
     if (frameMod <= 15) {
-        context.setFillColor(Color::gray);
+        context.setFillColor(Color::cyan);
         String bip(ASCIILiteral("Bip"));
         context.drawText(m_bipBopFont, TextRun(StringView(bip)), bipBopLocation);
     } else if (frameMod > 30 && frameMod <= 45) {
-        context.setFillColor(Color::white);
+        context.setFillColor(Color::yellow);
         String bop(ASCIILiteral("Bop"));
         context.drawText(m_bipBopFont, TextRun(StringView(bop)), bipBopLocation);
     }
@@ -348,7 +348,7 @@
 
     IntSize size = this->size();
     FloatRect frameRect(FloatPoint(), size);
-    context.fillRect(FloatRect(FloatPoint(), size), Color::black);
+    context.fillRect(FloatRect(FloatPoint(), size), facingMode() ==  RealtimeMediaSourceSettings::User ? Color::black : Color::gray);
 
     if (!m_muted && m_enabled) {
         drawText(context);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to