Add support for unified plan transceivers
authoryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Sep 2018 21:57:47 +0000 (21:57 +0000)
committeryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Sep 2018 21:57:47 +0000 (21:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=189390

Reviewed by Eric Carlson.

LayoutTests/imported/w3c:

* web-platform-tests/webrtc/RTCDTMFSender-insertDTMF.https-expected.txt:
* web-platform-tests/webrtc/RTCPeerConnection-addTrack.https-expected.txt:
Regression comes from the fact that the sender was never used but transceiver direction is sendrecv.
This might need further clarification in the spec or implementation of libwebrtc.
* web-platform-tests/webrtc/RTCPeerConnection-addTransceiver-expected.txt:
* web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https-expected.txt:
* web-platform-tests/webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt:
* web-platform-tests/webrtc/RTCRtpTransceiver-setDirection-expected.txt:

Source/ThirdParty/libwebrtc:

Expose more symbols.
* Configurations/libwebrtc.iOS.exp:
* Configurations/libwebrtc.iOSsim.exp:
* Configurations/libwebrtc.mac.exp:

Source/WebCore:

Keep previous transceiver behavior when unified plan flag is off.
Otherwise, use the libwebrtc transceiver API to create and use unified plan transceivers.
Fuel the implementation of transceivers through a dedicated backend.

Update transceiver IDL and make some smaller fixes at the same time:
- Make sure remote sources have a proper name as per https://w3c.github.io/webrtc-pc/#dfn-create-an-rtcrtpreceiver.
- Add support for transceiver.currentDirection.

Our mock peer connections are only supporting plan B APIs at the moment.
We therefore mandate plan B when using such mocks until we can upgrade mocks to support unified plan APIs.

Covered by modified and rebased tests.

* Modules/mediastream/PeerConnectionBackend.cpp:
(WebCore::PeerConnectionBackend::addTrack):
* Modules/mediastream/PeerConnectionBackend.h:
* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::addTrack):
(WebCore::RTCPeerConnection::addTransceiver):
* Modules/mediastream/RTCRtpSender.cpp:
(WebCore::RTCRtpSender::RTCRtpSender):
* Modules/mediastream/RTCRtpTransceiver.cpp:
(WebCore::RTCRtpTransceiver::mid const):
(WebCore::RTCRtpTransceiver::currentDirection const):
* Modules/mediastream/RTCRtpTransceiver.h:
(WebCore::RTCRtpTransceiver::backend):
* Modules/mediastream/RTCRtpTransceiver.idl:
* Modules/mediastream/RTCRtpTransceiverBackend.h:
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
(WebCore::LibWebRTCMediaEndpoint::addTrack):
(WebCore::LibWebRTCMediaEndpoint::newTransceiver):
(WebCore::LibWebRTCMediaEndpoint::addTransceiver):
(WebCore::LibWebRTCMediaEndpoint::transceiverBackendFromSender):
(WebCore::LibWebRTCMediaEndpoint::OnAddTrack):
(WebCore::LibWebRTCMediaEndpoint::OnTrack):
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
(WebCore::createReceiverForSource):
(WebCore::LibWebRTCPeerConnectionBackend::createReceiver):
(WebCore::LibWebRTCPeerConnectionBackend::videoReceiver):
(WebCore::LibWebRTCPeerConnectionBackend::audioReceiver):
(WebCore::LibWebRTCPeerConnectionBackend::addTrack):
(WebCore::LibWebRTCPeerConnectionBackend::addTransceiver):
(WebCore::backendFromRTPTransceiver):
(WebCore::LibWebRTCPeerConnectionBackend::existingTransceiver):
(WebCore::LibWebRTCPeerConnectionBackend::newTransceiver):
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
* Modules/mediastream/libwebrtc/LibWebRTCRtpSenderBackend.cpp:
(WebCore::LibWebRTCRtpSenderBackend::replaceTrack):
* Modules/mediastream/libwebrtc/LibWebRTCRtpSenderBackend.h:
* Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.cpp: Added.
(WebCore::LibWebRTCRtpTransceiverBackend::createReceiverBackend):
(WebCore::LibWebRTCRtpTransceiverBackend::createSenderBackend):
(WebCore::LibWebRTCRtpTransceiverBackend::direction const):
(WebCore::LibWebRTCRtpTransceiverBackend::currentDirection const):
(WebCore::LibWebRTCRtpTransceiverBackend::setDirection):
(WebCore::LibWebRTCRtpTransceiverBackend::mid):
(WebCore::LibWebRTCRtpTransceiverBackend::stop):
* Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.h: Added.
* Modules/mediastream/libwebrtc/LibWebRTCUtils.cpp:
(WebCore::toRTCRtpTransceiverDirection):
(WebCore::fromRTCRtpTransceiverDirection):
(WebCore::fromRtpTransceiverInit):
* Modules/mediastream/libwebrtc/LibWebRTCUtils.h:
* WebCore.xcodeproj/project.pbxproj:
* platform/mediastream/RealtimeIncomingAudioSource.cpp:
(WebCore::RealtimeIncomingAudioSource::RealtimeIncomingAudioSource):
* platform/mediastream/RealtimeIncomingVideoSource.cpp:
(WebCore::RealtimeIncomingVideoSource::RealtimeIncomingVideoSource):
* platform/mediastream/RealtimeMediaSource.h:
* testing/Internals.cpp:
(WebCore::Internals::useMockRTCPeerConnectionFactory):

LayoutTests:

Update tests using mock to enforce plan B for now until unified plan mocks are supported.

* fast/mediastream/RTCPeerConnection-addIceCandidate-expected.txt:
* fast/mediastream/RTCPeerConnection-icecandidate-event.html:
* fast/mediastream/RTCPeerConnection-iceconnectionstatechange-event.html:
* fast/mediastream/RTCPeerConnection-inspect-answer.html:
* fast/mediastream/RTCPeerConnection-inspect-offer.html:
* fast/mediastream/RTCPeerConnection-media-setup-single-dialog.html:
* fast/mediastream/RTCPeerConnection-media-setup-two-dialogs.html:
* fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html:
* fast/mediastream/RTCPeerConnection-setLocalDescription-offer.html:
* fast/mediastream/RTCPeerConnection-setRemoteDescription-offer.html:
* webrtc/calling-peerconnection-once-closed.html:
Once closed, addTransceiver is expected to throw.
* webrtc/libwebrtc/release-while-creating-offer.html:
* webrtc/libwebrtc/release-while-getting-stats.html:
* webrtc/libwebrtc/release-while-setting-local-description.html:
* webrtc/video-getParameters.html: sender and receiver parameters are no longer the same.
Testing them individually.
* webrtc/video-with-receiver.html:
Test is working only with legacy mode.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235809 268f45cc-cd09-0410-ab3c-d52691b4dbfc

55 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/mediastream/RTCPeerConnection-addIceCandidate-expected.txt
LayoutTests/fast/mediastream/RTCPeerConnection-icecandidate-event.html
LayoutTests/fast/mediastream/RTCPeerConnection-iceconnectionstatechange-event.html
LayoutTests/fast/mediastream/RTCPeerConnection-inspect-answer.html
LayoutTests/fast/mediastream/RTCPeerConnection-inspect-offer.html
LayoutTests/fast/mediastream/RTCPeerConnection-media-setup-single-dialog.html
LayoutTests/fast/mediastream/RTCPeerConnection-media-setup-two-dialogs.html
LayoutTests/fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html
LayoutTests/fast/mediastream/RTCPeerConnection-setLocalDescription-offer.html
LayoutTests/fast/mediastream/RTCPeerConnection-setRemoteDescription-offer.html
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDTMFSender-insertDTMF.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addTrack.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver-expected.txt
LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt
LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt
LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-setDirection-expected.txt
LayoutTests/webrtc/calling-peerconnection-once-closed.html
LayoutTests/webrtc/libwebrtc/release-while-creating-offer.html
LayoutTests/webrtc/libwebrtc/release-while-getting-stats.html
LayoutTests/webrtc/libwebrtc/release-while-setting-local-description.html
LayoutTests/webrtc/video-getParameters.html
LayoutTests/webrtc/video-with-receiver.html
Source/ThirdParty/libwebrtc/ChangeLog
Source/ThirdParty/libwebrtc/Configurations/libwebrtc.iOS.exp
Source/ThirdParty/libwebrtc/Configurations/libwebrtc.iOSsim.exp
Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp
Source/WebCore/Modules/mediastream/PeerConnectionBackend.h
Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
Source/WebCore/Modules/mediastream/RTCRtpReceiver.h
Source/WebCore/Modules/mediastream/RTCRtpSender.cpp
Source/WebCore/Modules/mediastream/RTCRtpTransceiver.cpp
Source/WebCore/Modules/mediastream/RTCRtpTransceiver.h
Source/WebCore/Modules/mediastream/RTCRtpTransceiver.idl
Source/WebCore/Modules/mediastream/RTCRtpTransceiverBackend.h
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpSenderBackend.cpp
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpSenderBackend.h
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.cpp [new file with mode: 0644]
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.h [new file with mode: 0644]
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCUtils.cpp
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCUtils.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/mediastream/RealtimeIncomingAudioSource.cpp
Source/WebCore/platform/mediastream/RealtimeIncomingVideoSource.cpp
Source/WebCore/platform/mediastream/RealtimeMediaSource.h
Source/WebCore/testing/Internals.cpp

index e77b3bf..6abea17 100644 (file)
@@ -1,3 +1,32 @@
+2018-09-07  Youenn Fablet  <youenn@apple.com>
+
+        Add support for unified plan transceivers
+        https://bugs.webkit.org/show_bug.cgi?id=189390
+
+        Reviewed by Eric Carlson.
+
+        Update tests using mock to enforce plan B for now until unified plan mocks are supported.
+
+        * fast/mediastream/RTCPeerConnection-addIceCandidate-expected.txt:
+        * fast/mediastream/RTCPeerConnection-icecandidate-event.html:
+        * fast/mediastream/RTCPeerConnection-iceconnectionstatechange-event.html:
+        * fast/mediastream/RTCPeerConnection-inspect-answer.html:
+        * fast/mediastream/RTCPeerConnection-inspect-offer.html:
+        * fast/mediastream/RTCPeerConnection-media-setup-single-dialog.html:
+        * fast/mediastream/RTCPeerConnection-media-setup-two-dialogs.html:
+        * fast/mediastream/RTCPeerConnection-remotely-assigned-transceiver-mid.html:
+        * fast/mediastream/RTCPeerConnection-setLocalDescription-offer.html:
+        * fast/mediastream/RTCPeerConnection-setRemoteDescription-offer.html:
+        * webrtc/calling-peerconnection-once-closed.html:
+        Once closed, addTransceiver is expected to throw.
+        * webrtc/libwebrtc/release-while-creating-offer.html:
+        * webrtc/libwebrtc/release-while-getting-stats.html:
+        * webrtc/libwebrtc/release-while-setting-local-description.html:
+        * webrtc/video-getParameters.html: sender and receiver parameters are no longer the same.
+        Testing them individually.
+        * webrtc/video-with-receiver.html:
+        Test is working only with legacy mode.
+
 2018-09-07  Frederic Wang  <fwang@igalia.com>
 
         [CSSOM View] Handle the scrollingElement in Element::scroll(Left/Top/Width/Height/To)
index 7ddfc1c..80195ba 100644 (file)
@@ -11,7 +11,7 @@ PASS Remote description set
 
 *** Define sdpMid, badSdpMid, sdpMLineIndex and badSdpMLineIndex for testing
 PASS sdpMLineIndex is not badSdpMLineIndex
-FAIL sdpMid should not be null.
+PASS sdpMid is not null
 PASS sdpMid is not badSdpMid
 FAIL promise pc.addIceCandidate(new RTCIceCandidate({candidate: validCandidate, sdpMid: badSdpMid})) fulfilled unexpectedly.
 FAIL promise pc.addIceCandidate(new RTCIceCandidate({candidate: validCandidate, sdpMLineIndex: badSdpMLineIndex})) fulfilled unexpectedly.
index 48488d5..44e2d3c 100644 (file)
@@ -8,6 +8,9 @@
         <script>
             description("Test RTCPeerConnection 'icecandidate' event and gathering done");
 
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
+
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("ICECandidates");
 
index 4db0564..ccc2b92 100644 (file)
@@ -7,6 +7,8 @@
     <body>
         <script>
             description("Test RTCPeerConnection 'iceconnectionstatechange' event");
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
 
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("ICEConnectionState");
index 04dd6e3..ae13428 100644 (file)
@@ -6,6 +6,9 @@
     </head>
     <body>
         <script>
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
+
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("");
 
index 9c3c20c..8e63638 100644 (file)
@@ -6,6 +6,9 @@
     </head>
     <body>
         <script>
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
+
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("");
 
index 4821e46..e829328 100644 (file)
@@ -6,6 +6,9 @@
     </head>
     <body>
         <script>
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
+
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("");
 
index 6887f3b..79e6865 100644 (file)
 
             description("Test setting up media between two RTCPeerConnection instances with a single SDP dialog.");
 
-            if (window.testRunner)
+            if (window.testRunner) {
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
                 testRunner.setUserMediaPermission(true);
-            else {
+            else {
                 debug("This test can not be run without the testRunner");
                 finishJSTest();
             }
index 973e139..0e3b5fd 100644 (file)
@@ -6,6 +6,9 @@
     </head>
     <body>
         <script>
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
+
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("");
 
index 229e4b5..cbd516f 100644 (file)
@@ -6,6 +6,9 @@
     </head>
     <body>
         <script>
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
+
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("");
 
index cac37f0..8118301 100644 (file)
@@ -6,6 +6,9 @@
     </head>
     <body>
         <script>
+            if (window.testRunner)
+                testRunner.setWebRTCUnifiedPlanEnabled(false);
+
             if (window.internals)
                 internals.useMockRTCPeerConnectionFactory("");
 
index 81dc0ef..c0bc2d6 100644 (file)
@@ -1,3 +1,19 @@
+2018-09-07  Youenn Fablet  <youenn@apple.com>
+
+        Add support for unified plan transceivers
+        https://bugs.webkit.org/show_bug.cgi?id=189390
+
+        Reviewed by Eric Carlson.
+
+        * web-platform-tests/webrtc/RTCDTMFSender-insertDTMF.https-expected.txt:
+        * web-platform-tests/webrtc/RTCPeerConnection-addTrack.https-expected.txt:
+        Regression comes from the fact that the sender was never used but transceiver direction is sendrecv.
+        This might need further clarification in the spec or implementation of libwebrtc.
+        * web-platform-tests/webrtc/RTCPeerConnection-addTransceiver-expected.txt:
+        * web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https-expected.txt:
+        * web-platform-tests/webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt:
+        * web-platform-tests/webrtc/RTCRtpTransceiver-setDirection-expected.txt:
+
 2018-09-07  Rob Buis  <rbuis@igalia.com>
 
         XMLHttpRequest: open() does not throw a SYNTAX_ERR exception if method is empty or url cannot be resolved
index 03dcca2..35dc84d 100644 (file)
@@ -2,8 +2,8 @@
 FAIL insertDTMF() should succeed if tones contains valid DTMF characters promise_test: Unhandled rejection with value: object "ReferenceError: Can't find variable: RTCDTMFSender"
 FAIL insertDTMF() should throw InvalidCharacterError if tones contains invalid DTMF characters promise_test: Unhandled rejection with value: object "ReferenceError: Can't find variable: RTCDTMFSender"
 FAIL insertDTMF() should throw InvalidStateError if transceiver is stopped assert_throws: function "() => dtmfSender.insertDTMF('')" threw object "TypeError: undefined is not an object (evaluating 'dtmfSender.insertDTMF')" that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
-FAIL insertDTMF() should throw InvalidStateError if transceiver.currentDirection is recvonly assert_equals: expected (string) "inactive" but got (undefined) undefined
-FAIL insertDTMF() should throw InvalidStateError if transceiver.currentDirection is inactive assert_equals: expected (string) "inactive" but got (undefined) undefined
+FAIL insertDTMF() should throw InvalidStateError if transceiver.currentDirection is recvonly assert_equals: expected (string) "inactive" but got (object) null
+FAIL insertDTMF() should throw InvalidStateError if transceiver.currentDirection is inactive assert_equals: expected (string) "inactive" but got (object) null
 FAIL insertDTMF() should set toneBuffer to provided tones normalized, with old tones overridden promise_test: Unhandled rejection with value: object "ReferenceError: Can't find variable: RTCDTMFSender"
 FAIL insertDTMF() after remove and close should reject assert_throws: function "() =>
                       dtmfSender.insertDTMF('123')" threw object "TypeError: undefined is not an object (evaluating 'dtmfSender.insertDTMF')" that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
index 7856527..067d643 100644 (file)
@@ -5,6 +5,6 @@ PASS addTrack with single track argument and single mediaStream should succeed
 PASS addTrack with single track argument and multiple mediaStreams should succeed 
 PASS Adding the same track multiple times should throw InvalidAccessError 
 PASS addTrack with existing sender with null track, same kind, and recvonly direction should reuse sender 
-PASS addTrack with existing sender with null track, same kind, and sendrecv direction should create new sender 
+FAIL addTrack with existing sender with null track, same kind, and sendrecv direction should create new sender assert_not_equals: got disallowed value object "[object RTCRtpSender]"
 PASS addTrack with existing sender with null track, different kind, and recvonly direction should create new sender 
 
index ff61059..81ff9f8 100644 (file)
@@ -1,11 +1,11 @@
 
 PASS addTransceiver() with string argument as invalid kind should throw TypeError 
-FAIL addTransceiver('audio') should return an audio transceiver assert_equals: expected (object) null but got (undefined) undefined
-FAIL addTransceiver('video') should return a video transceiver assert_equals: expected "remote video" but got ""
+PASS addTransceiver('audio') should return an audio transceiver 
+PASS addTransceiver('video') should return a video transceiver 
 PASS addTransceiver() with direction sendonly should have result transceiver.direction be the same 
 PASS addTransceiver() with direction inactive should have result transceiver.direction be the same 
 PASS addTransceiver() with invalid direction should throw TypeError 
-FAIL addTransceiver(track) should have result with sender.track be given track assert_equals: expected "remote audio" but got ""
+PASS addTransceiver(track) should have result with sender.track be given track 
 PASS addTransceiver(track) multiple times should create multiple transceivers 
 FAIL addTransceiver() with rid containing invalid non-alphanumeric characters should throw TypeError assert_throws: function "() =>
       pc.addTransceiver('audio', {
index f83abb2..a812574 100644 (file)
@@ -3,9 +3,9 @@ Harness Error (TIMEOUT), message = null
 
 PASS Creating first data channel should fire negotiationneeded event 
 PASS calling createDataChannel twice should fire negotiationneeded event once 
-TIMEOUT addTransceiver() should fire negotiationneeded event Test timed out
-PASS Calling addTransceiver() twice should fire negotiationneeded event once 
-PASS Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once 
+PASS addTransceiver() should fire negotiationneeded event 
+FAIL Calling addTransceiver() twice should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code
+FAIL Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code
 PASS negotiationneeded event should not fire if signaling state is not stable 
-NOTRUN negotiationneeded event should fire only after signaling state go back to stable 
+TIMEOUT negotiationneeded event should fire only after signaling state go back to stable Test timed out
 
index aae4e59..b0943dd 100644 (file)
@@ -5,10 +5,10 @@ PASS addTransceiver - Calling removeTrack on different connection that is closed
 PASS addTrack - Calling removeTrack on different connection that is closed should throw InvalidStateError 
 FAIL addTransceiver - Calling removeTrack on different connection should throw InvalidAccessError assert_throws: function "() => pc2.removeTrack(sender)" did not throw
 FAIL addTrack - Calling removeTrack on different connection should throw InvalidAccessError assert_throws: function "() => pc2.removeTrack(sender)" did not throw
-FAIL addTransceiver - Calling removeTrack with valid sender should set sender.track to null assert_equals: expected (object) null but got (undefined) undefined
+FAIL addTransceiver - Calling removeTrack with valid sender should set sender.track to null assert_equals: direction should not be altered expected "sendrecv" but got "recvonly"
 PASS addTrack - Calling removeTrack with valid sender should set sender.track to null 
-FAIL Calling removeTrack with currentDirection sendrecv should set direction to recvonly assert_equals: expected (object) null but got (undefined) undefined
-FAIL Calling removeTrack with currentDirection sendonly should set direction to inactive assert_equals: expected (object) null but got (undefined) undefined
-FAIL Calling removeTrack with currentDirection recvonly should not change direction assert_equals: expected (object) null but got (undefined) undefined
-FAIL Calling removeTrack with currentDirection inactive should not change direction assert_equals: expected (object) null but got (undefined) undefined
+FAIL Calling removeTrack with currentDirection sendrecv should set direction to recvonly assert_equals: expected "sendrecv" but got "sendonly"
+PASS Calling removeTrack with currentDirection sendonly should set direction to inactive 
+FAIL Calling removeTrack with currentDirection recvonly should not change direction assert_equals: expected "recvonly" but got "inactive"
+PASS Calling removeTrack with currentDirection inactive should not change direction 
 
index 897129a..7b0d13d 100644 (file)
@@ -1,7 +1,7 @@
 
-FAIL setLocalDescription(offer) with m= section should assign mid to corresponding transceiver assert_equals: Expect transceiver.mid to set to valid string value expected "string" but got "object"
+PASS setLocalDescription(offer) with m= section should assign mid to corresponding transceiver 
 FAIL setRemoteDescription(offer) with m= section and no existing transceiver should create corresponding transceiver promise_test: Unhandled rejection with value: object "TypeError: pc2.setRemoteDescrption is not a function. (In 'pc2.setRemoteDescrption(offer)', 'pc2.setRemoteDescrption' is undefined)"
-FAIL setLocalDescription(rollback) should unset transceiver.mid assert_not_equals: got disallowed value null
-FAIL setLocalDescription(rollback) should only unset transceiver mids associated with current round assert_not_equals: got disallowed value null
-FAIL setRemoteDescription(rollback) should remove newly created transceiver from transceiver list assert_equals: expected 1 but got 0
+FAIL setLocalDescription(rollback) should unset transceiver.mid promise_test: Unhandled rejection with value: object "InvalidStateError: Description type incompatible with current signaling state"
+FAIL setLocalDescription(rollback) should only unset transceiver mids associated with current round promise_test: Unhandled rejection with value: object "InvalidStateError: Description type incompatible with current signaling state"
+FAIL setRemoteDescription(rollback) should remove newly created transceiver from transceiver list promise_test: Unhandled rejection with value: object "InvalidStateError: Description type incompatible with current signaling state"
 
index f95f5c6..ba722a0 100644 (file)
@@ -1,5 +1,5 @@
 
-FAIL setDirection should change transceiver.direction assert_equals: expected (object) null but got (undefined) undefined
+PASS setDirection should change transceiver.direction 
 PASS setDirection with same direction should have no effect 
-FAIL setDirection should change transceiver.direction independent of transceiver.currentDirection assert_equals: expected (object) null but got (undefined) undefined
+FAIL setDirection should change transceiver.direction independent of transceiver.currentDirection assert_equals: expected "recvonly" but got "inactive"
 
index c72d938..c6a41bd 100644 (file)
@@ -42,7 +42,7 @@ promise_test(() => {
 
 promise_test(() => {
     return closedConnection().then((connection) => {
-        connection.addTransceiver("video");
+        assert_throws("InvalidStateError", () => { connection.addTransceiver("video"); });
     });
 }, "Ensuring closed connection addTransceiver does not crash");
 
index cc7bed9..518aef7 100644 (file)
@@ -7,6 +7,9 @@
 <script>
 self.jsTestIsAsync = true;
 
+if (window.testRunner)
+    testRunner.setWebRTCUnifiedPlanEnabled(false);
+
 if (window.internals)
     internals.useMockRTCPeerConnectionFactory("LibWebRTCReleasingWhileCreatingOffer");
 
index a94449e..3f120da 100644 (file)
@@ -7,6 +7,9 @@
 <script>
 self.jsTestIsAsync = true;
 
+if (window.testRunner)
+    testRunner.setWebRTCUnifiedPlanEnabled(false);
+
 if (window.internals)
     internals.useMockRTCPeerConnectionFactory("LibWebRTCReleasingWhileGettingStats");
 
index 62e899e..fa9c653 100644 (file)
@@ -10,6 +10,9 @@ self.jsTestIsAsync = true;
 // Silence unhandled rejection messages.
 window.onunhandledrejection = () => false;
 
+if (window.testRunner)
+    testRunner.setWebRTCUnifiedPlanEnabled(false);
+
 if (window.internals)
     internals.useMockRTCPeerConnectionFactory("LibWebRTCReleasingWhileSettingDescription");
 
index e3a2931..9e43930 100644 (file)
@@ -42,16 +42,13 @@ promise_test((test) => {
 
         senderParameters.encodings[0].fec.ssrc = 1;
         senderParameters.encodings[0].rtx.ssrc = 1;
-        receiverParameters.encodings[0].fec.ssrc = 1;
-        receiverParameters.encodings[0].rtx.ssrc = 1;
 
         senderParameters.transactionId = "";
         receiverParameters.transactionId = "";
 
-        assert_equals(JSON.stringify(senderParameters), JSON.stringify(receiverParameters), "testing sender vs. receiver parameters");
-
         senderParameters.encodings[0].ssrc = 1;
-        assert_equals(JSON.stringify(senderParameters), '{"codecs":[],"degradationPreference":"balanced","encodings":[{"active":true,"fec":{"ssrc":1},"maxBitrate":0,"maxFramerate":0,"priority":"medium","rid":"","rtx":{"ssrc":1},"scaleResolutionDownBy":1,"ssrc":1}],"headerExtensions":[],"transactionId":""}', "Testing sanitized parameters");
+        assert_equals(JSON.stringify(senderParameters), '{"codecs":[],"degradationPreference":"balanced","encodings":[{"active":true,"fec":{"ssrc":1},"maxBitrate":0,"maxFramerate":0,"priority":"medium","rid":"","rtx":{"ssrc":1},"scaleResolutionDownBy":1,"ssrc":1}],"headerExtensions":[],"transactionId":""}', "Testing sanitized sender parameters");
+        assert_equals(JSON.stringify(receiverParameters), '{"codecs":[],"degradationPreference":"balanced","encodings":[],"headerExtensions":[],"transactionId":""}', "Testing sanitized receiver parameters");
     });
 }, "Basic video stats");
         </script>
index c0cf821..63bceef 100644 (file)
@@ -14,6 +14,9 @@
 video = document.getElementById("video");
 canvas = document.getElementById("canvas");
 
+if (window.testRunner)
+    testRunner.setWebRTCUnifiedPlanEnabled(false);
+
 function testImage()
 {
     canvas.width = video.videoWidth;
index ddec699..6274d2b 100644 (file)
@@ -1,3 +1,15 @@
+2018-09-07  Youenn Fablet  <youenn@apple.com>
+
+        Add support for unified plan transceivers
+        https://bugs.webkit.org/show_bug.cgi?id=189390
+
+        Reviewed by Eric Carlson.
+
+        Expose more symbols.
+        * Configurations/libwebrtc.iOS.exp:
+        * Configurations/libwebrtc.iOSsim.exp:
+        * Configurations/libwebrtc.mac.exp:
+
 2018-09-05  Youenn Fablet  <youenn@apple.com>
 
         Expose RTCRtpSender.setParameters
index d64cdf0..76497e3 100644 (file)
@@ -212,3 +212,5 @@ __ZN6webrtc12RtpExtensionD1Ev
 __ZN6webrtc21RtpEncodingParametersC1ERKS0_
 __ZN6webrtc21RtpEncodingParametersC1Ev
 __ZN6webrtc21RtpEncodingParametersD1Ev
+__ZN6webrtc18RtpTransceiverInitC1Ev
+__ZN6webrtc18RtpTransceiverInitD1Ev
index 4fc1c4a..1e713ce 100644 (file)
@@ -213,3 +213,6 @@ __ZN6webrtc12RtpExtensionD1Ev
 __ZN6webrtc21RtpEncodingParametersC1ERKS0_
 __ZN6webrtc21RtpEncodingParametersC1Ev
 __ZN6webrtc21RtpEncodingParametersD1Ev
+
+__ZN6webrtc18RtpTransceiverInitC1Ev
+__ZN6webrtc18RtpTransceiverInitD1Ev
index 4fc1c4a..c2e741b 100644 (file)
@@ -213,3 +213,5 @@ __ZN6webrtc12RtpExtensionD1Ev
 __ZN6webrtc21RtpEncodingParametersC1ERKS0_
 __ZN6webrtc21RtpEncodingParametersC1Ev
 __ZN6webrtc21RtpEncodingParametersD1Ev
+__ZN6webrtc18RtpTransceiverInitC1Ev
+__ZN6webrtc18RtpTransceiverInitD1Ev
index ec77463..e2fa2d9 100644 (file)
@@ -1572,6 +1572,7 @@ if (USE_LIBWEBRTC)
       Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp
       Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.cpp
       Modules/mediastream/libwebrtc/LibWebRTCRtpSenderBackend.cpp
+      Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.cpp
       Modules/mediastream/libwebrtc/LibWebRTCUtils.cpp
       )
 endif ()
index ccee452..96a1739 100644 (file)
@@ -1,3 +1,83 @@
+2018-09-07  Youenn Fablet  <youenn@apple.com>
+
+        Add support for unified plan transceivers
+        https://bugs.webkit.org/show_bug.cgi?id=189390
+
+        Reviewed by Eric Carlson.
+
+        Keep previous transceiver behavior when unified plan flag is off.
+        Otherwise, use the libwebrtc transceiver API to create and use unified plan transceivers.
+        Fuel the implementation of transceivers through a dedicated backend.
+
+        Update transceiver IDL and make some smaller fixes at the same time:
+        - Make sure remote sources have a proper name as per https://w3c.github.io/webrtc-pc/#dfn-create-an-rtcrtpreceiver.
+        - Add support for transceiver.currentDirection.
+
+        Our mock peer connections are only supporting plan B APIs at the moment.
+        We therefore mandate plan B when using such mocks until we can upgrade mocks to support unified plan APIs.
+
+        Covered by modified and rebased tests.
+
+        * Modules/mediastream/PeerConnectionBackend.cpp:
+        (WebCore::PeerConnectionBackend::addTrack):
+        * Modules/mediastream/PeerConnectionBackend.h:
+        * Modules/mediastream/RTCPeerConnection.cpp:
+        (WebCore::RTCPeerConnection::addTrack):
+        (WebCore::RTCPeerConnection::addTransceiver):
+        * Modules/mediastream/RTCRtpSender.cpp:
+        (WebCore::RTCRtpSender::RTCRtpSender):
+        * Modules/mediastream/RTCRtpTransceiver.cpp:
+        (WebCore::RTCRtpTransceiver::mid const):
+        (WebCore::RTCRtpTransceiver::currentDirection const):
+        * Modules/mediastream/RTCRtpTransceiver.h:
+        (WebCore::RTCRtpTransceiver::backend):
+        * Modules/mediastream/RTCRtpTransceiver.idl:
+        * Modules/mediastream/RTCRtpTransceiverBackend.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
+        (WebCore::LibWebRTCMediaEndpoint::addTrack):
+        (WebCore::LibWebRTCMediaEndpoint::newTransceiver):
+        (WebCore::LibWebRTCMediaEndpoint::addTransceiver):
+        (WebCore::LibWebRTCMediaEndpoint::transceiverBackendFromSender):
+        (WebCore::LibWebRTCMediaEndpoint::OnAddTrack):
+        (WebCore::LibWebRTCMediaEndpoint::OnTrack):
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
+        (WebCore::createReceiverForSource):
+        (WebCore::LibWebRTCPeerConnectionBackend::createReceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::videoReceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::audioReceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::addTrack):
+        (WebCore::LibWebRTCPeerConnectionBackend::addTransceiver):
+        (WebCore::backendFromRTPTransceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::existingTransceiver):
+        (WebCore::LibWebRTCPeerConnectionBackend::newTransceiver):
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCRtpSenderBackend.cpp:
+        (WebCore::LibWebRTCRtpSenderBackend::replaceTrack):
+        * Modules/mediastream/libwebrtc/LibWebRTCRtpSenderBackend.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.cpp: Added.
+        (WebCore::LibWebRTCRtpTransceiverBackend::createReceiverBackend):
+        (WebCore::LibWebRTCRtpTransceiverBackend::createSenderBackend):
+        (WebCore::LibWebRTCRtpTransceiverBackend::direction const):
+        (WebCore::LibWebRTCRtpTransceiverBackend::currentDirection const):
+        (WebCore::LibWebRTCRtpTransceiverBackend::setDirection):
+        (WebCore::LibWebRTCRtpTransceiverBackend::mid):
+        (WebCore::LibWebRTCRtpTransceiverBackend::stop):
+        * Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.h: Added.
+        * Modules/mediastream/libwebrtc/LibWebRTCUtils.cpp:
+        (WebCore::toRTCRtpTransceiverDirection):
+        (WebCore::fromRTCRtpTransceiverDirection):
+        (WebCore::fromRtpTransceiverInit):
+        * Modules/mediastream/libwebrtc/LibWebRTCUtils.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/mediastream/RealtimeIncomingAudioSource.cpp:
+        (WebCore::RealtimeIncomingAudioSource::RealtimeIncomingAudioSource):
+        * platform/mediastream/RealtimeIncomingVideoSource.cpp:
+        (WebCore::RealtimeIncomingVideoSource::RealtimeIncomingVideoSource):
+        * platform/mediastream/RealtimeMediaSource.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::useMockRTCPeerConnectionFactory):
+
 2018-09-07  Rob Buis  <rbuis@igalia.com>
 
         XMLHttpRequest: open() does not throw a SYNTAX_ERR exception if method is empty or url cannot be resolved
index 333113f..2f17418 100644 (file)
@@ -530,7 +530,7 @@ void PeerConnectionBackend::markAsNeedingNegotiation()
         m_peerConnection.scheduleNegotiationNeededEvent();
 }
 
-ExceptionOr<Ref<RTCRtpSender>> PeerConnectionBackend::addTrack(RTCRtpSender*, MediaStreamTrack&, const Vector<String>&)
+ExceptionOr<Ref<RTCRtpSender>> PeerConnectionBackend::addTrack(MediaStreamTrack&, Vector<String>&&)
 {
     return Exception { NotSupportedError, "Not implemented"_s };
 }
index bc6d2f6..284a64a 100644 (file)
@@ -100,7 +100,7 @@ public:
 
     virtual void getStats(MediaStreamTrack*, Ref<DeferredPromise>&&) = 0;
 
-    virtual ExceptionOr<Ref<RTCRtpSender>> addTrack(RTCRtpSender*, MediaStreamTrack&, const Vector<String>&);
+    virtual ExceptionOr<Ref<RTCRtpSender>> addTrack(MediaStreamTrack&, Vector<String>&&);
     virtual void removeTrack(RTCRtpSender&) { }
 
     virtual ExceptionOr<Ref<RTCRtpTransceiver>> addTransceiver(const String&, const RTCRtpTransceiverInit&);
index 4ad4f7c..ba2ee56 100644 (file)
@@ -122,22 +122,7 @@ ExceptionOr<Ref<RTCRtpSender>> RTCPeerConnection::addTrack(Ref<MediaStreamTrack>
     for (auto stream : streams)
         mediaStreamIds.append(stream.get().id());
 
-    RTCRtpSender* sender = nullptr;
-
-    // Reuse an existing sender with the same track kind if it has never been used to send before.
-    for (auto& transceiver : m_transceiverSet->list()) {
-        auto& existingSender = transceiver->sender();
-        if (existingSender.trackKind() == track->kind() && existingSender.trackId().isNull() && !transceiver->hasSendingDirection()) {
-            existingSender.setTrack(track.copyRef());
-            existingSender.setMediaStreamIds(WTFMove(mediaStreamIds));
-            transceiver->enableSendingDirection();
-            sender = &existingSender;
-            
-            break;
-        }
-    }
-
-    return m_backend->addTrack(sender, track.get(), mediaStreamIds);
+    return m_backend->addTrack(track.get(), WTFMove(mediaStreamIds));
 }
 
 ExceptionOr<void> RTCPeerConnection::removeTrack(RTCRtpSender& sender)
@@ -168,12 +153,18 @@ ExceptionOr<Ref<RTCRtpTransceiver>> RTCPeerConnection::addTransceiver(AddTransce
 
     if (WTF::holds_alternative<String>(withTrack)) {
         const String& kind = WTF::get<String>(withTrack);
-        if (kind != "audio" && kind != "video")
+        if (kind != "audio"_s && kind != "video"_s)
             return Exception { TypeError };
 
+        if (isClosed())
+            return Exception { InvalidStateError };
+
         return m_backend->addTransceiver(kind, init);
     }
 
+    if (isClosed())
+        return Exception { InvalidStateError };
+
     auto track = WTF::get<RefPtr<MediaStreamTrack>>(withTrack).releaseNonNull();
     return m_backend->addTransceiver(WTFMove(track), init);
 }
index db6b749..ac3da10 100644 (file)
@@ -41,7 +41,7 @@ namespace WebCore {
 
 class RTCRtpReceiver : public RTCRtpSenderReceiverBase {
 public:
-    static Ref<RTCRtpReceiver> create(Ref<MediaStreamTrack>&& track, std::unique_ptr<RTCRtpReceiverBackend>&& backend = nullptr)
+    static Ref<RTCRtpReceiver> create(Ref<MediaStreamTrack>&& track, std::unique_ptr<RTCRtpReceiverBackend>&& backend)
     {
         return adoptRef(*new RTCRtpReceiver(WTFMove(track), WTFMove(backend)));
     }
index 75839e1..3a321f6 100644 (file)
@@ -33,6 +33,8 @@
 
 #if ENABLE(WEB_RTC)
 
+#include "RuntimeEnabledFeatures.h"
+
 namespace WebCore {
 
 Ref<RTCRtpSender> RTCRtpSender::create(Ref<MediaStreamTrack>&& track, Vector<String>&& mediaStreamIds, std::unique_ptr<RTCRtpSenderBackend>&& backend)
@@ -53,6 +55,7 @@ RTCRtpSender::RTCRtpSender(String&& trackKind, Vector<String>&& mediaStreamIds,
     , m_mediaStreamIds(WTFMove(mediaStreamIds))
     , m_backend(WTFMove(backend))
 {
+    ASSERT(!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled() || m_backend);
 }
 
 void RTCRtpSender::setTrackToNull()
index 674b321..601246e 100644 (file)
@@ -47,11 +47,9 @@ RTCRtpTransceiver::RTCRtpTransceiver(Ref<RTCRtpSender>&& sender, Ref<RTCRtpRecei
 {
 }
 
-const String& RTCRtpTransceiver::mid() const
+String RTCRtpTransceiver::mid() const
 {
-    if (!m_backend)
-        return m_mid;
-    return m_backend->mid();
+    return m_backend ? m_backend->mid() : String { };
 }
 
 bool RTCRtpTransceiver::hasSendingDirection() const
@@ -66,6 +64,13 @@ RTCRtpTransceiverDirection RTCRtpTransceiver::direction() const
     return m_backend->direction();
 }
 
+std::optional<RTCRtpTransceiverDirection> RTCRtpTransceiver::currentDirection() const
+{
+    if (!m_backend)
+        return std::nullopt;
+    return m_backend->currentDirection();
+}
+
 void RTCRtpTransceiver::setDirection(RTCRtpTransceiverDirection direction)
 {
     m_direction = direction;
index 802672b..b991d72 100644 (file)
@@ -55,8 +55,9 @@ public:
     void disableSendingDirection();
 
     RTCRtpTransceiverDirection direction() const;
+    std::optional<RTCRtpTransceiverDirection> currentDirection() const;
     void setDirection(RTCRtpTransceiverDirection);
-    const String& mid() const;
+    String mid() const;
 
     RTCRtpSender& sender() { return m_sender.get(); }
     RTCRtpReceiver& receiver() { return m_receiver.get(); }
@@ -69,10 +70,11 @@ public:
     // transport each.
     RTCIceTransport& iceTransport() { return m_iceTransport.get(); }
 
+    RTCRtpTransceiverBackend* backend() { return m_backend.get(); }
+
 private:
     RTCRtpTransceiver(Ref<RTCRtpSender>&&, Ref<RTCRtpReceiver>&&, std::unique_ptr<RTCRtpTransceiverBackend>&&);
 
-    String m_mid;
     RTCRtpTransceiverDirection m_direction;
 
     Ref<RTCRtpSender> m_sender;
index 407871e..aa16602 100644 (file)
@@ -36,13 +36,11 @@ typedef RTCRtpTransceiverDirection RtpTransceiverDirection;
     EnabledAtRuntime=PeerConnection
 ] interface RTCRtpTransceiver {
     readonly attribute DOMString? mid;
-    // FIXME 169662: missing [SameObject]
-    readonly attribute RTCRtpSender sender;
-    // FIXME 169662: missing [SameObject]
-    readonly attribute RTCRtpReceiver receiver;
+    [SameObject] readonly attribute RTCRtpSender sender;
+    [SameObject] readonly attribute RTCRtpReceiver receiver;
     readonly attribute boolean stopped;
     readonly attribute RtpTransceiverDirection direction;
-    // FIXME 169662: missing currentDirection
+    readonly attribute RTCRtpTransceiverDirection? currentDirection;
     void setDirection(RtpTransceiverDirection direction);
     void stop();
     // FIXME 169662: missing setCodecPreferences
index 8dfdf96..f280ea4 100644 (file)
@@ -35,9 +35,10 @@ public:
     virtual ~RTCRtpTransceiverBackend() = default;
 
     virtual RTCRtpTransceiverDirection direction() const = 0;
+    virtual std::optional<RTCRtpTransceiverDirection> currentDirection() const = 0;
     virtual void setDirection(RTCRtpTransceiverDirection) = 0;
 
-    virtual const String& mid() = 0;
+    virtual String mid() = 0;
     virtual void stop() = 0;
 };
 
index efa19ad..89efce1 100644 (file)
@@ -34,6 +34,7 @@
 #include "LibWebRTCProvider.h"
 #include "LibWebRTCRtpReceiverBackend.h"
 #include "LibWebRTCRtpSenderBackend.h"
+#include "LibWebRTCRtpTransceiverBackend.h"
 #include "LibWebRTCStatsCollector.h"
 #include "LibWebRTCUtils.h"
 #include "Logging.h"
@@ -197,7 +198,6 @@ void LibWebRTCMediaEndpoint::doSetRemoteDescription(RTCSessionDescription& descr
 bool LibWebRTCMediaEndpoint::addTrack(LibWebRTCRtpSenderBackend& sender, MediaStreamTrack& track, const Vector<String>& mediaStreamIds)
 {
     ASSERT(m_backend);
-    ASSERT(!sender.rtcSender());
 
     if (!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled()) {
         String mediaStreamId = mediaStreamIds.isEmpty() ? createCanonicalUUIDString() : mediaStreamIds[0];
@@ -208,35 +208,41 @@ bool LibWebRTCMediaEndpoint::addTrack(LibWebRTCRtpSenderBackend& sender, MediaSt
         });
     }
 
-    std::vector<std::string> ids;
-    for (auto& id : mediaStreamIds)
-        ids.push_back(id.utf8().data());
-
+    LibWebRTCRtpSenderBackend::Source source;
+    rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> rtcTrack;
     switch (track.privateTrack().type()) {
     case RealtimeMediaSource::Type::Audio: {
         auto audioSource = RealtimeOutgoingAudioSource::create(track.privateTrack());
-        auto audioTrack = m_peerConnectionFactory.CreateAudioTrack(track.id().utf8().data(), audioSource.ptr());
-        sender.setSource(WTFMove(audioSource));
-        auto rtpSender = m_backend->AddTrack(audioTrack.get(), WTFMove(ids));
-        if (!rtpSender.ok())
-            return false;
-        sender.setRTCSender(rtpSender.MoveValue());
-        return true;
+        rtcTrack = m_peerConnectionFactory.CreateAudioTrack(track.id().utf8().data(), audioSource.ptr());
+        source = WTFMove(audioSource);
+        break;
     }
     case RealtimeMediaSource::Type::Video: {
         auto videoSource = RealtimeOutgoingVideoSource::create(track.privateTrack());
-        auto videoTrack = m_peerConnectionFactory.CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
-        sender.setSource(WTFMove(videoSource));
-        auto rtpSender = m_backend->AddTrack(videoTrack.get(), WTFMove(ids));
-        if (!rtpSender.ok())
-            return false;
-        sender.setRTCSender(rtpSender.MoveValue());
-        return true;
+        rtcTrack = m_peerConnectionFactory.CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
+        source = WTFMove(videoSource);
+        break;
     }
     case RealtimeMediaSource::Type::None:
         ASSERT_NOT_REACHED();
+        return false;
     }
-    return false;
+
+    sender.setSource(WTFMove(source));
+    if (auto rtpSender = sender.rtcSender()) {
+        rtpSender->SetTrack(rtcTrack.get());
+        return true;
+    }
+
+    std::vector<std::string> ids;
+    for (auto& id : mediaStreamIds)
+        ids.push_back(id.utf8().data());
+
+    auto newRTPSender = m_backend->AddTrack(rtcTrack.get(), WTFMove(ids));
+    if (!newRTPSender.ok())
+        return false;
+    sender.setRTCSender(newRTPSender.MoveValue());
+    return true;
 }
 
 void LibWebRTCMediaEndpoint::removeTrack(LibWebRTCRtpSenderBackend& sender)
@@ -361,20 +367,131 @@ void LibWebRTCMediaEndpoint::addRemoteTrack(rtc::scoped_refptr<webrtc::RtpReceiv
     }
 
     receiver->setBackend(std::make_unique<LibWebRTCRtpReceiverBackend>(WTFMove(rtcReceiver)));
-    
-    auto* track = receiver->track();
-    ASSERT(track);
+    auto& track = *receiver->track();
+    fireTrackEvent(receiver.releaseNonNull(), track, rtcStreams, nullptr);
+}
 
+void LibWebRTCMediaEndpoint::fireTrackEvent(Ref<RTCRtpReceiver>&& receiver, Ref<MediaStreamTrack>&& track, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& rtcStreams, RefPtr<RTCRtpTransceiver>&& transceiver)
+{
     Vector<RefPtr<MediaStream>> streams;
     for (auto& rtcStream : rtcStreams) {
         auto& mediaStream = mediaStreamFromRTCStream(*rtcStream.get());
         streams.append(&mediaStream);
-        mediaStream.addTrackFromPlatform(*track);
+        mediaStream.addTrackFromPlatform(track.get());
     }
     m_peerConnectionBackend.connection().fireEvent(RTCTrackEvent::create(eventNames().trackEvent,
-        Event::CanBubble::No, Event::IsCancelable::No, WTFMove(receiver), track, WTFMove(streams), nullptr));
+        Event::CanBubble::No, Event::IsCancelable::No, WTFMove(receiver), WTFMove(track), WTFMove(streams), WTFMove(transceiver)));
+}
+
+static inline void setExistingReceiverSourceTrack(RealtimeMediaSource& existingSource, webrtc::RtpReceiverInterface& rtcReceiver)
+{
+    switch (rtcReceiver.media_type()) {
+    case cricket::MEDIA_TYPE_AUDIO: {
+        ASSERT(existingSource.type() == RealtimeMediaSource::Type::Audio);
+        rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcReceiver.track().get());
+        static_cast<RealtimeIncomingAudioSource&>(existingSource).setSourceTrack(WTFMove(audioTrack));
+        return;
+    }
+    case cricket::MEDIA_TYPE_VIDEO: {
+        ASSERT(existingSource.type() == RealtimeMediaSource::Type::Video);
+        rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcReceiver.track().get());
+        static_cast<RealtimeIncomingVideoSource&>(existingSource).setSourceTrack(WTFMove(videoTrack));
+        return;
+    }
+    case cricket::MEDIA_TYPE_DATA:
+        ASSERT_NOT_REACHED();
+        return;
+    }
+}
+
+static inline RefPtr<RealtimeMediaSource> sourceFromNewReceiver(webrtc::RtpReceiverInterface& rtcReceiver)
+{
+    auto rtcTrack = rtcReceiver.track();
+    switch (rtcReceiver.media_type()) {
+    case cricket::MEDIA_TYPE_DATA:
+        return nullptr;
+    case cricket::MEDIA_TYPE_AUDIO: {
+        rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcTrack.get());
+        return RealtimeIncomingAudioSource::create(WTFMove(audioTrack), fromStdString(rtcTrack->id()));
+    }
+    case cricket::MEDIA_TYPE_VIDEO: {
+        rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcTrack.get());
+        return RealtimeIncomingVideoSource::create(WTFMove(videoTrack), fromStdString(rtcTrack->id()));
+    }
+    }
+}
+
+void LibWebRTCMediaEndpoint::newTransceiver(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>&& rtcTransceiver)
+{
+    auto* transceiver = m_peerConnectionBackend.existingTransceiver([&](auto& transceiverBackend) {
+        return rtcTransceiver.get() == transceiverBackend.rtcTransceiver();
+    });
+    if (transceiver) {
+        setExistingReceiverSourceTrack(transceiver->receiver().track()->source(), *rtcTransceiver->receiver());
+        return;
+    }
+
+    auto rtcReceiver = rtcTransceiver->receiver();
+    auto source = sourceFromNewReceiver(*rtcReceiver);
+    if (!source)
+        return;
+
+    auto& newTransceiver = m_peerConnectionBackend.newRemoteTransceiver(std::make_unique<LibWebRTCRtpTransceiverBackend>(WTFMove(rtcTransceiver)), source.releaseNonNull());
+
+    fireTrackEvent(makeRef(newTransceiver.receiver()), *newTransceiver.receiver().track(), rtcReceiver->streams(), makeRef(newTransceiver));
+}
+
+template<typename T>
+std::optional<LibWebRTCMediaEndpoint::Backends> LibWebRTCMediaEndpoint::createTransceiverBackends(T&& trackOrKind, const RTCRtpTransceiverInit& init, LibWebRTCRtpSenderBackend::Source&& source)
+{
+    auto result = m_backend->AddTransceiver(WTFMove(trackOrKind), fromRtpTransceiverInit(init));
+    if (!result.ok())
+        return std::nullopt;
+
+    auto transceiver = std::make_unique<LibWebRTCRtpTransceiverBackend>(result.MoveValue());
+    return LibWebRTCMediaEndpoint::Backends { transceiver->createSenderBackend(m_peerConnectionBackend, WTFMove(source)), transceiver->createReceiverBackend(), WTFMove(transceiver) };
+}
+
+std::optional<LibWebRTCMediaEndpoint::Backends> LibWebRTCMediaEndpoint::addTransceiver(const String& trackKind, const RTCRtpTransceiverInit& init)
+{
+    auto type = trackKind == "audio" ? cricket::MediaType::MEDIA_TYPE_AUDIO : cricket::MediaType::MEDIA_TYPE_VIDEO;
+    return createTransceiverBackends(type, init, nullptr);
+}
+
+std::optional<LibWebRTCMediaEndpoint::Backends> LibWebRTCMediaEndpoint::addTransceiver(MediaStreamTrack& track, const RTCRtpTransceiverInit& init)
+{
+    LibWebRTCRtpSenderBackend::Source source;
+    rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> rtcTrack;
+    switch (track.privateTrack().type()) {
+    case RealtimeMediaSource::Type::None:
+        return std::nullopt;
+    case RealtimeMediaSource::Type::Audio: {
+        auto audioSource = RealtimeOutgoingAudioSource::create(track.privateTrack());
+        rtcTrack = m_peerConnectionFactory.CreateAudioTrack(track.id().utf8().data(), audioSource.ptr());
+        source = WTFMove(audioSource);
+        break;
+    }
+    case RealtimeMediaSource::Type::Video: {
+        auto videoSource = RealtimeOutgoingVideoSource::create(track.privateTrack());
+        rtcTrack = m_peerConnectionFactory.CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());
+        source = WTFMove(videoSource);
+        break;
+    }
+    }
+
+    return createTransceiverBackends(WTFMove(rtcTrack), init, WTFMove(source));
 }
 
+std::unique_ptr<LibWebRTCRtpTransceiverBackend> LibWebRTCMediaEndpoint::transceiverBackendFromSender(LibWebRTCRtpSenderBackend& backend)
+{
+    for (auto& transceiver : m_backend->GetTransceivers()) {
+        if (transceiver->sender().get() == backend.rtcSender())
+            return std::make_unique<LibWebRTCRtpTransceiverBackend>(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>(transceiver));
+    }
+    return nullptr;
+}
+
+
 void LibWebRTCMediaEndpoint::removeRemoteStream(webrtc::MediaStreamInterface& rtcStream)
 {
     bool removed = m_streams.remove(&rtcStream);
@@ -403,6 +520,9 @@ void LibWebRTCMediaEndpoint::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStre
 
 void LibWebRTCMediaEndpoint::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& streams)
 {
+    if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
+        return;
+
     callOnMainThread([protectedThis = makeRef(*this), receiver = WTFMove(receiver), streams]() mutable {
         if (protectedThis->isStopped())
             return;
@@ -410,6 +530,19 @@ void LibWebRTCMediaEndpoint::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverIn
     });
 }
 
+void LibWebRTCMediaEndpoint::OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver)
+{
+    if (!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
+        return;
+
+    callOnMainThread([protectedThis = makeRef(*this), transceiver = WTFMove(transceiver)]() mutable {
+        if (protectedThis->isStopped())
+            return;
+        protectedThis->newTransceiver(WTFMove(transceiver));
+    });
+}
+
+
 std::unique_ptr<RTCDataChannelHandler> LibWebRTCMediaEndpoint::createDataChannel(const String& label, const RTCDataChannelInit& options)
 {
     auto init = LibWebRTCDataChannelHandler::fromRTCDataChannelInit(options);
index f2ba6bc..3fd5096 100644 (file)
 
 #include "LibWebRTCObservers.h"
 #include "LibWebRTCProvider.h"
-#include "PeerConnectionBackend.h"
+#include "LibWebRTCRtpSenderBackend.h"
 #include "RTCRtpReceiver.h"
-#include "RealtimeOutgoingAudioSource.h"
-#include "RealtimeOutgoingVideoSource.h"
 #include <Timer.h>
 
 #pragma GCC diagnostic push
@@ -61,7 +59,8 @@ namespace WebCore {
 
 class LibWebRTCProvider;
 class LibWebRTCPeerConnectionBackend;
-class LibWebRTCRtpSenderBackend;
+class LibWebRTCRtpReceiverBackend;
+class LibWebRTCRtpTransceiverBackend;
 class MediaStreamTrack;
 class RTCSessionDescription;
 
@@ -101,6 +100,15 @@ public:
     bool addTrack(LibWebRTCRtpSenderBackend&, MediaStreamTrack&, const Vector<String>&);
     void removeTrack(LibWebRTCRtpSenderBackend&);
 
+    struct Backends {
+        std::unique_ptr<LibWebRTCRtpSenderBackend> senderBackend;
+        std::unique_ptr<LibWebRTCRtpReceiverBackend> receiverBackend;
+        std::unique_ptr<LibWebRTCRtpTransceiverBackend> transceiverBackend;
+    };
+    std::optional<Backends> addTransceiver(const String& trackKind, const RTCRtpTransceiverInit&);
+    std::optional<Backends> addTransceiver(MediaStreamTrack&, const RTCRtpTransceiverInit&);
+    std::unique_ptr<LibWebRTCRtpTransceiverBackend> transceiverBackendFromSender(LibWebRTCRtpSenderBackend&);
+
 private:
     LibWebRTCMediaEndpoint(LibWebRTCPeerConnectionBackend&, LibWebRTCProvider&);
 
@@ -110,6 +118,8 @@ private:
     void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface>) final;
     void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>) final;
     void OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface>, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>&) final;
+    void OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>) final;
+
     void OnRenegotiationNeeded() final;
     void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState) final;
     void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState) final;
@@ -125,6 +135,12 @@ private:
     void addRemoteStream(webrtc::MediaStreamInterface&);
     void addRemoteTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface>&&, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>&);
     void removeRemoteStream(webrtc::MediaStreamInterface&);
+    void newTransceiver(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>&&);
+
+    void fireTrackEvent(Ref<RTCRtpReceiver>&&, Ref<MediaStreamTrack>&&, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>&, RefPtr<RTCRtpTransceiver>&&);
+
+    template<typename T>
+    std::optional<Backends> createTransceiverBackends(T&&, const RTCRtpTransceiverInit&, LibWebRTCRtpSenderBackend::Source&&);
 
     void OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>&) final;
     void gatherStatsForLogging();
index 5082459..1da68d4 100644 (file)
@@ -33,6 +33,7 @@
 #include "LibWebRTCMediaEndpoint.h"
 #include "LibWebRTCRtpReceiverBackend.h"
 #include "LibWebRTCRtpSenderBackend.h"
+#include "LibWebRTCRtpTransceiverBackend.h"
 #include "MediaEndpointConfiguration.h"
 #include "Page.h"
 #include "RTCIceCandidate.h"
@@ -200,12 +201,12 @@ void LibWebRTCPeerConnectionBackend::doAddIceCandidate(RTCIceCandidate& candidat
     addIceCandidateSucceeded();
 }
 
-static inline Ref<RTCRtpReceiver> createReceiverForSource(ScriptExecutionContext& context, Ref<RealtimeMediaSource>&& source)
+static inline Ref<RTCRtpReceiver> createReceiverForSource(ScriptExecutionContext& context, Ref<RealtimeMediaSource>&& source, std::unique_ptr<RTCRtpReceiverBackend>&& backend)
 {
     auto remoteTrackPrivate = MediaStreamTrackPrivate::create(WTFMove(source), String { source->id() });
     auto remoteTrack = MediaStreamTrack::create(context, WTFMove(remoteTrackPrivate));
 
-    return RTCRtpReceiver::create(WTFMove(remoteTrack));
+    return RTCRtpReceiver::create(WTFMove(remoteTrack), WTFMove(backend));
 }
 
 static inline Ref<RealtimeMediaSource> createEmptySource(const String& trackKind, String&& trackId)
@@ -219,7 +220,7 @@ static inline Ref<RealtimeMediaSource> createEmptySource(const String& trackKind
 
 Ref<RTCRtpReceiver> LibWebRTCPeerConnectionBackend::createReceiver(const String& trackKind, const String& trackId)
 {
-    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), createEmptySource(trackKind, String(trackId)));
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), createEmptySource(trackKind, String(trackId)), nullptr);
     m_pendingReceivers.append(receiver.copyRef());
     return receiver;
 }
@@ -237,7 +238,7 @@ LibWebRTCPeerConnectionBackend::VideoReceiver LibWebRTCPeerConnectionBackend::vi
         }
     }
     auto source = RealtimeIncomingVideoSource::create(nullptr, WTFMove(trackId));
-    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), source.copyRef());
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), source.copyRef(), nullptr);
 
     auto senderBackend = std::make_unique<LibWebRTCRtpSenderBackend>(*this, nullptr);
     auto transceiver = RTCRtpTransceiver::create(RTCRtpSender::create("video", { }, WTFMove(senderBackend)), receiver.copyRef(), nullptr);
@@ -260,7 +261,7 @@ LibWebRTCPeerConnectionBackend::AudioReceiver LibWebRTCPeerConnectionBackend::au
         }
     }
     auto source = RealtimeIncomingAudioSource::create(nullptr, WTFMove(trackId));
-    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), source.copyRef());
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), source.copyRef(), nullptr);
 
     auto senderBackend = std::make_unique<LibWebRTCRtpSenderBackend>(*this, nullptr);
     auto transceiver = RTCRtpTransceiver::create(RTCRtpSender::create("audio", { }, WTFMove(senderBackend)), receiver.copyRef(), nullptr);
@@ -316,11 +317,57 @@ RefPtr<RTCSessionDescription> LibWebRTCPeerConnectionBackend::remoteDescription(
 
 static inline LibWebRTCRtpSenderBackend& backendFromRTPSender(RTCRtpSender& sender)
 {
+    ASSERT(!sender.isStopped());
     return static_cast<LibWebRTCRtpSenderBackend&>(*sender.backend());
 }
 
-ExceptionOr<Ref<RTCRtpSender>> LibWebRTCPeerConnectionBackend::addTrack(RTCRtpSender* sender, MediaStreamTrack& track, const Vector<String>& mediaStreamIds)
+
+static inline RefPtr<RTCRtpSender> findExistingSender(const Vector<std::reference_wrapper<RTCRtpSender>>& senders, LibWebRTCRtpSenderBackend& senderBackend)
+{
+    ASSERT(senderBackend.rtcSender());
+    for (RTCRtpSender& sender : senders) {
+        if (!sender.isStopped() && senderBackend.rtcSender() == backendFromRTPSender(sender).rtcSender())
+            return makeRef(sender);
+    }
+    return nullptr;
+}
+
+ExceptionOr<Ref<RTCRtpSender>> LibWebRTCPeerConnectionBackend::addTrack(MediaStreamTrack& track, Vector<String>&& mediaStreamIds)
 {
+    if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled()) {
+        auto senderBackend = std::make_unique<LibWebRTCRtpSenderBackend>(*this, nullptr);
+        if (!m_endpoint->addTrack(*senderBackend, track, mediaStreamIds))
+            return Exception { TypeError, "Unable to add track"_s };
+
+        if (auto sender = findExistingSender(m_peerConnection.getSenders(), *senderBackend)) {
+            sender->setTrack(makeRef(track));
+            sender->setMediaStreamIds(WTFMove(mediaStreamIds));
+            return sender.releaseNonNull();
+        }
+
+        auto transceiverBackend = m_endpoint->transceiverBackendFromSender(*senderBackend);
+
+        auto sender = RTCRtpSender::create(makeRef(track), WTFMove(mediaStreamIds), WTFMove(senderBackend));
+        auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), createEmptySource(track.kind(), createCanonicalUUIDString()), transceiverBackend->createReceiverBackend());
+        auto transceiver = RTCRtpTransceiver::create(sender.copyRef(), WTFMove(receiver), WTFMove(transceiverBackend));
+        m_peerConnection.addInternalTransceiver(WTFMove(transceiver));
+        return WTFMove(sender);
+    }
+
+    RTCRtpSender* sender = nullptr;
+    // Reuse an existing sender with the same track kind if it has never been used to send before.
+    for (auto& transceiver : m_peerConnection.getTransceivers()) {
+        auto& existingSender = transceiver->sender();
+        if (!existingSender.isStopped() && existingSender.trackKind() == track.kind() && existingSender.trackId().isNull() && !transceiver->hasSendingDirection()) {
+            existingSender.setTrack(makeRef(track));
+            existingSender.setMediaStreamIds(WTFMove(mediaStreamIds));
+            transceiver->enableSendingDirection();
+            sender = &existingSender;
+
+            break;
+        }
+    }
+
     if (!sender) {
         const String& trackKind = track.kind();
         String trackId = createCanonicalUUIDString();
@@ -340,8 +387,25 @@ ExceptionOr<Ref<RTCRtpSender>> LibWebRTCPeerConnectionBackend::addTrack(RTCRtpSe
     return makeRef(*sender);
 }
 
+template<typename T>
+ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addUnifiedPlanTransceiver(T&& trackOrKind, const RTCRtpTransceiverInit& init)
+{
+    auto backends = m_endpoint->addTransceiver(trackOrKind, init);
+    if (!backends)
+        return Exception { InvalidAccessError, "Unable to add transceiver"_s };
+
+    auto sender = RTCRtpSender::create(WTFMove(trackOrKind), Vector<String> { }, WTFMove(backends->senderBackend));
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), createEmptySource(sender->trackKind(), createCanonicalUUIDString()), WTFMove(backends->receiverBackend));
+    auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver), WTFMove(backends->transceiverBackend));
+    m_peerConnection.addInternalTransceiver(transceiver.copyRef());
+    return WTFMove(transceiver);
+}
+
 ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addTransceiver(const String& trackKind, const RTCRtpTransceiverInit& init)
 {
+    if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
+        return addUnifiedPlanTransceiver(String { trackKind }, init);
+
     auto senderBackend = std::make_unique<LibWebRTCRtpSenderBackend>(*this, nullptr);
     auto newSender = RTCRtpSender::create(String(trackKind), Vector<String>(), WTFMove(senderBackend));
     return completeAddTransceiver(WTFMove(newSender), init, createCanonicalUUIDString(), trackKind);
@@ -349,6 +413,9 @@ ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addTransceiv
 
 ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addTransceiver(Ref<MediaStreamTrack>&& track, const RTCRtpTransceiverInit& init)
 {
+    if (RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled())
+        return addUnifiedPlanTransceiver(WTFMove(track), init);
+
     auto senderBackend = std::make_unique<LibWebRTCRtpSenderBackend>(*this, nullptr);
     auto& backend = *senderBackend;
     auto sender = RTCRtpSender::create(track.copyRef(), Vector<String>(), WTFMove(senderBackend));
@@ -358,6 +425,29 @@ ExceptionOr<Ref<RTCRtpTransceiver>> LibWebRTCPeerConnectionBackend::addTransceiv
     return completeAddTransceiver(WTFMove(sender), init, track->id(), track->kind());
 }
 
+static inline LibWebRTCRtpTransceiverBackend& backendFromRTPTransceiver(RTCRtpTransceiver& transceiver)
+{
+    return static_cast<LibWebRTCRtpTransceiverBackend&>(*transceiver.backend());
+}
+
+RTCRtpTransceiver* LibWebRTCPeerConnectionBackend::existingTransceiver(WTF::Function<bool(LibWebRTCRtpTransceiverBackend&)>&& matchingFunction)
+{
+    for (auto& transceiver : m_peerConnection.getTransceivers()) {
+        if (matchingFunction(backendFromRTPTransceiver(*transceiver)))
+            return transceiver.get();
+    }
+    return nullptr;
+}
+
+RTCRtpTransceiver& LibWebRTCPeerConnectionBackend::newRemoteTransceiver(std::unique_ptr<LibWebRTCRtpTransceiverBackend>&& transceiverBackend, Ref<RealtimeMediaSource>&& receiverSource)
+{
+    auto sender = RTCRtpSender::create(receiverSource->type() == RealtimeMediaSource::Type::Audio ? "audio"_s : "video"_s, Vector<String> { }, transceiverBackend->createSenderBackend(*this, nullptr));
+    auto receiver = createReceiverForSource(*m_peerConnection.scriptExecutionContext(), WTFMove(receiverSource), transceiverBackend->createReceiverBackend());
+    auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver), WTFMove(transceiverBackend));
+    m_peerConnection.addInternalTransceiver(transceiver.copyRef());
+    return transceiver.get();
+}
+
 Ref<RTCRtpTransceiver> LibWebRTCPeerConnectionBackend::completeAddTransceiver(Ref<RTCRtpSender>&& sender, const RTCRtpTransceiverInit& init, const String& trackId, const String& trackKind)
 {
     auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), createReceiver(trackKind, trackId), nullptr);
@@ -373,21 +463,13 @@ void LibWebRTCPeerConnectionBackend::removeTrack(RTCRtpSender& sender)
     m_endpoint->removeTrack(backendFromRTPSender(sender));
 }
 
-template<typename Source>
-static inline bool updateTrackSource(Source& source, MediaStreamTrack* track)
-{
-    if (!track) {
-        source.stop();
-        return true;
-    }
-    return source.setSource(track->privateTrack());
-}
-
 void LibWebRTCPeerConnectionBackend::applyRotationForOutgoingVideoSources()
 {
     for (auto& transceiver : m_peerConnection.getTransceivers()) {
-        if (auto* videoSource = backendFromRTPSender(transceiver->sender()).videoSource())
-            videoSource->setApplyRotation(true);
+        if (!transceiver->sender().isStopped()) {
+            if (auto* videoSource = backendFromRTPSender(transceiver->sender()).videoSource())
+                videoSource->setApplyRotation(true);
+        }
     }
 }
 
index d376f0e..1f6850d 100644 (file)
@@ -38,11 +38,13 @@ namespace WebCore {
 
 class LibWebRTCMediaEndpoint;
 class LibWebRTCProvider;
+class LibWebRTCRtpTransceiverBackend;
 class RTCRtpReceiver;
 class RTCSessionDescription;
 class RTCStatsReport;
 class RealtimeIncomingAudioSource;
 class RealtimeIncomingVideoSource;
+class RealtimeMediaSource;
 class RealtimeOutgoingAudioSource;
 class RealtimeOutgoingVideoSource;
 
@@ -84,12 +86,15 @@ private:
 
     void getStatsSucceeded(const DeferredPromise&, Ref<RTCStatsReport>&&);
 
-    ExceptionOr<Ref<RTCRtpSender>> addTrack(RTCRtpSender*, MediaStreamTrack&, const Vector<String>&) final;
+    ExceptionOr<Ref<RTCRtpSender>> addTrack(MediaStreamTrack&, Vector<String>&&) final;
     void removeTrack(RTCRtpSender&) final;
 
     ExceptionOr<Ref<RTCRtpTransceiver>> addTransceiver(const String&, const RTCRtpTransceiverInit&) final;
     ExceptionOr<Ref<RTCRtpTransceiver>> addTransceiver(Ref<MediaStreamTrack>&&, const RTCRtpTransceiverInit&) final;
 
+    RTCRtpTransceiver* existingTransceiver(WTF::Function<bool(LibWebRTCRtpTransceiverBackend&)>&&);
+    RTCRtpTransceiver& newRemoteTransceiver(std::unique_ptr<LibWebRTCRtpTransceiverBackend>&&, Ref<RealtimeMediaSource>&&);
+
     struct VideoReceiver {
         Ref<RTCRtpReceiver> receiver;
         Ref<RealtimeIncomingVideoSource> source;
@@ -108,6 +113,9 @@ private:
 
     Ref<RTCRtpReceiver> createReceiver(const String& trackKind, const String& trackId);
 
+    template<typename T>
+    ExceptionOr<Ref<RTCRtpTransceiver>> addUnifiedPlanTransceiver(T&& trackOrKind, const RTCRtpTransceiverInit&);
+
     Ref<LibWebRTCMediaEndpoint> m_endpoint;
     bool m_isLocalDescriptionSet { false };
     bool m_isRemoteDescriptionSet { false };
index ad96b1f..a0e1488 100644 (file)
@@ -90,7 +90,7 @@ void LibWebRTCRtpSenderBackend::replaceTrack(ScriptExecutionContext& context, RT
         protectedSender->setTrack(track.releaseNonNull());
         if (!hasTrack) {
             // FIXME: In case of unified plan, we should use m_rtcSender->SetTrack and no longer need m_peerConnectionBackend.
-            auto result = m_peerConnectionBackend->addTrack(protectedSender.ptr(), *protectedSender->track(), { });
+            auto result = m_peerConnectionBackend->addTrack(*protectedSender->track(), { });
             if (result.hasException()) {
                 promise.reject(result.releaseException());
                 return;
index 9dff4aa..c734404 100644 (file)
@@ -27,6 +27,7 @@
 #if ENABLE(WEB_RTC)
 
 #include "LibWebRTCMacros.h"
+#include "LibWebRTCPeerConnectionBackend.h"
 #include "RTCRtpSenderBackend.h"
 #include "RealtimeOutgoingAudioSource.h"
 #include "RealtimeOutgoingVideoSource.h"
@@ -46,12 +47,20 @@ class LibWebRTCPeerConnectionBackend;
 
 class LibWebRTCRtpSenderBackend final : public RTCRtpSenderBackend {
 public:
-    explicit LibWebRTCRtpSenderBackend(LibWebRTCPeerConnectionBackend& backend, rtc::scoped_refptr<webrtc::RtpSenderInterface>&& rtcSender)
+    LibWebRTCRtpSenderBackend(LibWebRTCPeerConnectionBackend& backend, rtc::scoped_refptr<webrtc::RtpSenderInterface>&& rtcSender)
         : m_peerConnectionBackend(makeWeakPtr(&backend))
         , m_rtcSender(WTFMove(rtcSender))
     {
     }
 
+    using Source = Variant<std::nullptr_t, Ref<RealtimeOutgoingAudioSource>, Ref<RealtimeOutgoingVideoSource>>;
+    LibWebRTCRtpSenderBackend(LibWebRTCPeerConnectionBackend& backend, rtc::scoped_refptr<webrtc::RtpSenderInterface>&& rtcSender, Source&& source)
+        : m_peerConnectionBackend(makeWeakPtr(&backend))
+        , m_rtcSender(WTFMove(rtcSender))
+        , m_source(WTFMove(source))
+    {
+    }
+
     void setRTCSender(rtc::scoped_refptr<webrtc::RtpSenderInterface>&& rtcSender) { m_rtcSender = WTFMove(rtcSender); }
     webrtc::RtpSenderInterface* rtcSender() { return m_rtcSender.get(); }
 
@@ -71,24 +80,19 @@ public:
         );
     }
 
-    bool hasNoSource() const
+    bool hasSource() const
     {
         return WTF::switchOn(m_source,
-            [] (const std::nullptr_t&) { return true; },
-            [] (const auto&) { return false; }
+            [] (const std::nullptr_t&) { return false; },
+            [] (const auto&) { return true; }
         );
     }
 
-    void setSource(Ref<RealtimeOutgoingAudioSource>&& source)
-    {
-        ASSERT(hasNoSource());
-        m_source = WTFMove(source);
-    }
-
-    void setSource(Ref<RealtimeOutgoingVideoSource>&& source)
+    void setSource(Source&& source)
     {
-        ASSERT(hasNoSource());
+        ASSERT(!hasSource());
         m_source = WTFMove(source);
+        ASSERT(hasSource());
     }
 
 private:
@@ -98,7 +102,7 @@ private:
 
     WeakPtr<LibWebRTCPeerConnectionBackend> m_peerConnectionBackend;
     rtc::scoped_refptr<webrtc::RtpSenderInterface> m_rtcSender;
-    Variant<std::nullptr_t, Ref<RealtimeOutgoingAudioSource>, Ref<RealtimeOutgoingVideoSource>> m_source;
+    Source m_source;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.cpp b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.cpp
new file mode 100644 (file)
index 0000000..850cfe9
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LibWebRTCRtpTransceiverBackend.h"
+
+#if ENABLE(WEB_RTC) && USE(LIBWEBRTC)
+
+#include "LibWebRTCRtpReceiverBackend.h"
+#include "LibWebRTCRtpSenderBackend.h"
+#include "LibWebRTCUtils.h"
+
+namespace WebCore {
+
+std::unique_ptr<LibWebRTCRtpReceiverBackend> LibWebRTCRtpTransceiverBackend::createReceiverBackend()
+{
+    return std::make_unique<LibWebRTCRtpReceiverBackend>(m_rtcTransceiver->receiver());
+}
+
+std::unique_ptr<LibWebRTCRtpSenderBackend> LibWebRTCRtpTransceiverBackend::createSenderBackend(LibWebRTCPeerConnectionBackend& backend, LibWebRTCRtpSenderBackend::Source&& source)
+{
+    return std::make_unique<LibWebRTCRtpSenderBackend>(backend, m_rtcTransceiver->sender(), WTFMove(source));
+}
+
+RTCRtpTransceiverDirection LibWebRTCRtpTransceiverBackend::direction() const
+{
+    return toRTCRtpTransceiverDirection(m_rtcTransceiver->direction());
+}
+
+std::optional<RTCRtpTransceiverDirection> LibWebRTCRtpTransceiverBackend::currentDirection() const
+{
+    auto value = m_rtcTransceiver->current_direction();
+    if (!value)
+        return std::nullopt;
+    return toRTCRtpTransceiverDirection(*value);
+}
+
+void LibWebRTCRtpTransceiverBackend::setDirection(RTCRtpTransceiverDirection direction)
+{
+    m_rtcTransceiver->SetDirection(fromRTCRtpTransceiverDirection(direction));
+}
+
+String LibWebRTCRtpTransceiverBackend::mid()
+{
+    if (auto mid = m_rtcTransceiver->mid())
+        return fromStdString(*mid);
+    return String { };
+}
+
+void LibWebRTCRtpTransceiverBackend::stop()
+{
+    m_rtcTransceiver->Stop();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC) && USE(LIBWEBRTC)
diff --git a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.h b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpTransceiverBackend.h
new file mode 100644 (file)
index 0000000..c47ff20
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEB_RTC) && USE(LIBWEBRTC)
+
+#include "LibWebRTCMacros.h"
+#include "LibWebRTCRtpSenderBackend.h"
+#include "RTCRtpTransceiverBackend.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
+#include <webrtc/api/rtptransceiverinterface.h>
+#include <webrtc/rtc_base/scoped_ref_ptr.h>
+
+#pragma GCC diagnostic pop
+
+namespace WebCore {
+
+class LibWebRTCRtpReceiverBackend;
+
+class LibWebRTCRtpTransceiverBackend final : public RTCRtpTransceiverBackend {
+public:
+    explicit LibWebRTCRtpTransceiverBackend(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>&& rtcTransceiver)
+        : m_rtcTransceiver(WTFMove(rtcTransceiver))
+    {
+    }
+
+    std::unique_ptr<LibWebRTCRtpReceiverBackend> createReceiverBackend();
+    std::unique_ptr<LibWebRTCRtpSenderBackend> createSenderBackend(LibWebRTCPeerConnectionBackend&, LibWebRTCRtpSenderBackend::Source&&);
+
+    webrtc::RtpTransceiverInterface* rtcTransceiver() { return m_rtcTransceiver.get(); }
+
+private:
+    RTCRtpTransceiverDirection direction() const final;
+    std::optional<RTCRtpTransceiverDirection> currentDirection() const final;
+    void setDirection(RTCRtpTransceiverDirection) final;
+    String mid() final;
+    void stop() final;
+
+    rtc::scoped_refptr<webrtc::RtpTransceiverInterface> m_rtcTransceiver;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC) && USE(LIBWEBRTC)
index 2f3c10c..64509d0 100644 (file)
 #if USE(LIBWEBRTC)
 
 #include "LibWebRTCMacros.h"
+#include "RTCPeerConnection.h"
 #include "RTCRtpParameters.h"
-#include <webrtc/api/rtpparameters.h>
 #include <wtf/text/WTFString.h>
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
+#include <webrtc/api/rtpparameters.h>
+#include <webrtc/api/rtptransceiverinterface.h>
+
+#pragma GCC diagnostic pop
+
 namespace WebCore {
 
 static inline RTCRtpParameters::EncodingParameters toRTCEncodingParameters(const webrtc::RtpEncodingParameters& rtcParameters)
@@ -177,6 +185,41 @@ webrtc::RtpParameters fromRTCRtpParameters(const RTCRtpParameters& parameters)
     return rtcParameters;
 }
 
+RTCRtpTransceiverDirection toRTCRtpTransceiverDirection(webrtc::RtpTransceiverDirection rtcDirection)
+{
+    switch (rtcDirection) {
+    case webrtc::RtpTransceiverDirection::kSendRecv:
+        return RTCRtpTransceiverDirection::Sendrecv;
+    case webrtc::RtpTransceiverDirection::kSendOnly:
+        return RTCRtpTransceiverDirection::Sendonly;
+    case webrtc::RtpTransceiverDirection::kRecvOnly:
+        return RTCRtpTransceiverDirection::Recvonly;
+    case webrtc::RtpTransceiverDirection::kInactive:
+        return RTCRtpTransceiverDirection::Inactive;
+    };
+}
+
+webrtc::RtpTransceiverDirection fromRTCRtpTransceiverDirection(RTCRtpTransceiverDirection direction)
+{
+    switch (direction) {
+    case RTCRtpTransceiverDirection::Sendrecv:
+        return webrtc::RtpTransceiverDirection::kSendRecv;
+    case RTCRtpTransceiverDirection::Sendonly:
+        return webrtc::RtpTransceiverDirection::kSendOnly;
+    case RTCRtpTransceiverDirection::Recvonly:
+        return webrtc::RtpTransceiverDirection::kRecvOnly;
+    case RTCRtpTransceiverDirection::Inactive:
+        return webrtc::RtpTransceiverDirection::kInactive;
+    };
+}
+
+webrtc::RtpTransceiverInit fromRtpTransceiverInit(const RTCRtpTransceiverInit& init)
+{
+    webrtc::RtpTransceiverInit rtcInit;
+    rtcInit.direction = fromRTCRtpTransceiverDirection(init.direction);
+    return rtcInit;
+}
+
 }; // namespace WebCore
 
 #endif // USE(LIBWEBRTC)
index ba63751..c1b307c 100644 (file)
 
 namespace webrtc {
 struct RtpParameters;
+struct RtpTransceiverInit;
+
+enum class RtpTransceiverDirection;
 }
 
 namespace WebCore {
 
 struct RTCRtpParameters;
+struct RTCRtpTransceiverInit;
+
+enum class RTCRtpTransceiverDirection;
 
 RTCRtpParameters toRTCRtpParameters(const webrtc::RtpParameters&);
 webrtc::RtpParameters fromRTCRtpParameters(const RTCRtpParameters&);
 
+RTCRtpTransceiverDirection toRTCRtpTransceiverDirection(webrtc::RtpTransceiverDirection);
+webrtc::RtpTransceiverDirection fromRTCRtpTransceiverDirection(RTCRtpTransceiverDirection);
+webrtc::RtpTransceiverInit fromRtpTransceiverInit(const RTCRtpTransceiverInit&);
+
 inline String fromStdString(const std::string& value)
 {
     return String::fromUTF8(value.data(), value.length());
index 4a8ac36..7929ff6 100644 (file)
                4186BD3E213EE3400001826F /* LibWebRTCUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D1A049213EDDFD0063FB6B /* LibWebRTCUtils.cpp */; };
                4186BD3F213EE3430001826F /* LibWebRTCRtpSenderBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D1A04B213EDDFE0063FB6B /* LibWebRTCRtpSenderBackend.cpp */; };
                4186BD40213EE3450001826F /* LibWebRTCRtpReceiverBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D1A04A213EDDFE0063FB6B /* LibWebRTCRtpReceiverBackend.cpp */; };
+               4186BD4E2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4186BD4D2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp */; };
                41885B9311B6FDA6003383BB /* FormSubmission.h in Headers */ = {isa = PBXBuildFile; fileRef = 41885B9111B6FDA6003383BB /* FormSubmission.h */; settings = {ATTRIBUTES = (Private, ); }; };
                418A06D0133C04D500CD379C /* EventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 418A06CE133C04D500CD379C /* EventDispatcher.h */; };
                418F88050FF957AF0080F045 /* JSAbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 418F88030FF957AE0080F045 /* JSAbstractWorker.h */; };
                4186BD3B213EDE380001826F /* LibWebRTCRtpReceiverBackend.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibWebRTCRtpReceiverBackend.h; path = libwebrtc/LibWebRTCRtpReceiverBackend.h; sourceTree = "<group>"; };
                4186BD3D213EDE390001826F /* LibWebRTCRtpSenderBackend.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibWebRTCRtpSenderBackend.h; path = libwebrtc/LibWebRTCRtpSenderBackend.h; sourceTree = "<group>"; };
                4186BD46214072B60001826F /* RTCRtpTransceiverBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCRtpTransceiverBackend.h; sourceTree = "<group>"; };
+               4186BD4B2140A8050001826F /* LibWebRTCRtpTransceiverBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCRtpTransceiverBackend.h; path = libwebrtc/LibWebRTCRtpTransceiverBackend.h; sourceTree = "<group>"; };
+               4186BD4D2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCRtpTransceiverBackend.cpp; path = libwebrtc/LibWebRTCRtpTransceiverBackend.cpp; sourceTree = "<group>"; };
                41885B9111B6FDA6003383BB /* FormSubmission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormSubmission.h; sourceTree = "<group>"; };
                41885B9211B6FDA6003383BB /* FormSubmission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormSubmission.cpp; sourceTree = "<group>"; };
                418A06CE133C04D500CD379C /* EventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventDispatcher.h; sourceTree = "<group>"; };
                                4186BD3B213EDE380001826F /* LibWebRTCRtpReceiverBackend.h */,
                                41D1A04B213EDDFE0063FB6B /* LibWebRTCRtpSenderBackend.cpp */,
                                4186BD3D213EDE390001826F /* LibWebRTCRtpSenderBackend.h */,
+                               4186BD4D2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp */,
+                               4186BD4B2140A8050001826F /* LibWebRTCRtpTransceiverBackend.h */,
                                41D28D0B2139E01D00F4206F /* LibWebRTCStatsCollector.cpp */,
                                41D28D0C2139E01E00F4206F /* LibWebRTCStatsCollector.h */,
                                41D1A049213EDDFD0063FB6B /* LibWebRTCUtils.cpp */,
                                D6489D26166FFCF1007C031B /* JSHTMLTemplateElement.h in Headers */,
                                A80E7E9D0A1A83E3007FB8C5 /* JSHTMLTextAreaElement.h in Headers */,
                                83E359A21BB1031D002CEB98 /* JSHTMLTimeElement.h in Headers */,
-                               E42050172141901B0066EF3B /* ProcessWarming.h in Headers */,
                                A80E7B0C0A19D606007FB8C5 /* JSHTMLTitleElement.h in Headers */,
                                070756D414239A4F00414161 /* JSHTMLTrackElement.h in Headers */,
                                1A85B2110A1B258700D8C87C /* JSHTMLUListElement.h in Headers */,
                                B71FE6DF11091CB300DAEF77 /* PrintContext.h in Headers */,
                                51F645D51FECDBCE00B54DED /* Process.h in Headers */,
                                A8EA7EBC0A1945D000A8EF5F /* ProcessingInstruction.h in Headers */,
+                               E42050172141901B0066EF3B /* ProcessWarming.h in Headers */,
                                E44613EC0CD681B500FADA75 /* ProgressEvent.h in Headers */,
                                A715E653134BBBEC00D8E713 /* ProgressShadowElement.h in Headers */,
                                1A2A68240B5BEDE70002A480 /* ProgressTracker.h in Headers */,
                                417612B11E3A994000C3D81D /* LibWebRTCPeerConnectionBackend.cpp in Sources */,
                                4186BD40213EE3450001826F /* LibWebRTCRtpReceiverBackend.cpp in Sources */,
                                4186BD3F213EE3430001826F /* LibWebRTCRtpSenderBackend.cpp in Sources */,
+                               4186BD4E2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp in Sources */,
                                41D28D0D2139E05800F4206F /* LibWebRTCStatsCollector.cpp in Sources */,
                                4186BD3E213EE3400001826F /* LibWebRTCUtils.cpp in Sources */,
                                9759E93E14EF1CF80026A2DD /* LoadableTextTrack.cpp in Sources */,
index 471ab3d..5233138 100644 (file)
@@ -41,6 +41,7 @@ RealtimeIncomingAudioSource::RealtimeIncomingAudioSource(rtc::scoped_refptr<webr
     : RealtimeMediaSource(WTFMove(audioTrackId), RealtimeMediaSource::Type::Audio, String())
     , m_audioTrack(WTFMove(audioTrack))
 {
+    setName("remote audio");
     notifyMutedChange(!m_audioTrack);
 }
 
index 259b46b..f760d40 100644 (file)
@@ -41,6 +41,7 @@ RealtimeIncomingVideoSource::RealtimeIncomingVideoSource(rtc::scoped_refptr<webr
     : RealtimeMediaSource(WTFMove(videoTrackId), RealtimeMediaSource::Type::Video, String())
     , m_videoTrack(WTFMove(videoTrack))
 {
+    setName("remote video");
     m_currentSettings.setWidth(640);
     m_currentSettings.setHeight(480);
     notifyMutedChange(!m_videoTrack);
index 1e1bb82..057240f 100644 (file)
@@ -158,7 +158,7 @@ public:
     virtual void setInterrupted(bool, bool);
 
     const String& name() const { return m_name; }
-    void setName(const String& name) { m_name = name; }
+    void setName(String&& name) { m_name = WTFMove(name); }
 
     unsigned fitnessScore() const { return m_fitnessScore; }
 
index ef1ea4e..f75ab24 100644 (file)
@@ -1386,6 +1386,9 @@ void Internals::emulateRTCPeerConnectionPlatformEvent(RTCPeerConnection& connect
 
 void Internals::useMockRTCPeerConnectionFactory(const String& testCase)
 {
+    // FIXME: We should upgrade mocks to support unified plan APIs, until then use plan B in tests using mock.
+
+    ASSERT(!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled());
     if (!LibWebRTCProvider::webRTCAvailable())
         return;