[Java] Make default sdpSemantics NOT_SPECIFIED.
The default value of sdpSemantics is about to change from PLAN_B to
UNIFIED_PLAN. In order not to cause subtle bugs by applications that
depend on the default value being PLAN_B, we are temporarily making the
default NOT_SPECIFIED. Constructing with NOT_SPECIFIED causes the C++
layer to crash (https://webrtc-review.googlesource.com/c/src/+/242968).
This is in accordance to the publically announced plans:
https://groups.google.com/u/1/g/discuss-webrtc/c/SdoVP02eUIk
While we're at it, we're upgrading almost all unit tests to use Unified
Plan. However there are still two tests using Plan B for which I added
TODO comments to be dealt with later; not having an Android setup makes
it impossible to debug these efficiently.
Bug: webrtc:11121
Change-Id: Ib086186bee947d18d31b413e3aeba0cb247b377d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/246000
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Xavier Lepaul <xalep@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35700}
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java
index 468413b..56d584e 100644
--- a/sdk/android/api/org/webrtc/PeerConnection.java
+++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -432,9 +432,10 @@
/**
* Java version of webrtc::SdpSemantics.
*
- * Configure the SDP semantics used by this PeerConnection. Note that the
- * WebRTC 1.0 specification requires UNIFIED_PLAN semantics. The
- * RtpTransceiver API is only available with UNIFIED_PLAN semantics.
+ * Configure the SDP semantics used by this PeerConnection. That the WebRTC
+ * 1.0 specification requires UNIFIED_PLAN semantics and the RtpTransceiver
+ * API is only available with UNIFIED_PLAN semantics. PLAN_B is being
+ * deprecated and will be removed at a future date.
*
* <p>PLAN_B will cause PeerConnection to create offers and answers with at
* most one audio and one video m= section with multiple RtpSenders and
@@ -448,13 +449,27 @@
* will also cause PeerConnection to ignore all but the first a=ssrc lines
* that form a Plan B stream.
*
- * <p>For users who wish to send multiple audio/video streams and need to stay
- * interoperable with legacy WebRTC implementations, specify PLAN_B.
+ * <p>For users who have to interwork with legacy WebRTC implementations, it
+ * is possible to specify PLAN_B until the code is finally removed
+ * (https://crbug.com/webrtc/13528).
*
- * <p>For users who wish to send multiple audio/video streams and/or wish to
- * use the new RtpTransceiver API, specify UNIFIED_PLAN.
+ * <p>The default SdpSemantics value is about to change to UNIFIED_PLAN.
+ * During a short transition period, NOT_SPECIFIED is used to ensure clients
+ * that don't set SdpSemantics are aware of the change by CHECK-crashing.
+ * TODO(https://crbug.com/webrtc/11121): When the default has changed to
+ * UNIFIED_PLAN, delete NOT_SPECIFIED.
*/
- public enum SdpSemantics { PLAN_B, UNIFIED_PLAN }
+ public enum SdpSemantics {
+ // TODO(https://crbug.com/webrtc/13528): Remove support for PLAN_B.
+ @Deprecated PLAN_B,
+ UNIFIED_PLAN,
+ // The default SdpSemantics value is about to change to UNIFIED_PLAN. During
+ // a short transition period, NOT_SPECIFIED is used to ensure clients that
+ // don't set SdpSemantics are aware of the change by CHECK-crashing.
+ // TODO(https://crbug.com/webrtc/11121): When the default has changed to
+ // kUnifiedPlan, delete kNotSpecified.
+ NOT_SPECIFIED
+ }
/** Java version of PeerConnectionInterface.RTCConfiguration */
// TODO(qingsi): Resolve the naming inconsistency of fields with/without units.
@@ -611,7 +626,7 @@
screencastMinBitrate = null;
combinedAudioVideoBwe = null;
networkPreference = AdapterType.UNKNOWN;
- sdpSemantics = SdpSemantics.PLAN_B;
+ sdpSemantics = SdpSemantics.NOT_SPECIFIED;
activeResetSrtpParams = false;
cryptoOptions = null;
turnLoggingId = null;
diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
index 2b33c6c..e9cf6d3 100644
--- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java
+++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
@@ -404,6 +404,7 @@
public PeerConnection createPeerConnection(List<PeerConnection.IceServer> iceServers,
MediaConstraints constraints, PeerConnection.Observer observer) {
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
+ rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
return createPeerConnection(rtcConfig, constraints, observer);
}
@@ -411,6 +412,7 @@
public PeerConnection createPeerConnection(
List<PeerConnection.IceServer> iceServers, PeerConnection.Observer observer) {
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
+ rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
return createPeerConnection(rtcConfig, observer);
}
diff --git a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java
index d9799ab..588e647 100644
--- a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java
+++ b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java
@@ -27,6 +27,7 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
@@ -642,6 +643,12 @@
private static WeakReference<MediaStream> addTracksToPC(PeerConnectionFactory factory,
PeerConnection pc, VideoSource videoSource, String streamLabel, String videoTrackId,
String audioTrackId, VideoSink videoSink) {
+ return addTracksToPC(factory, pc, videoSource, streamLabel, videoTrackId, audioTrackId,
+ videoSink, /*useAddStream=*/false);
+ }
+ private static WeakReference<MediaStream> addTracksToPC(PeerConnectionFactory factory,
+ PeerConnection pc, VideoSource videoSource, String streamLabel, String videoTrackId,
+ String audioTrackId, VideoSink videoSink, boolean useAddStream) {
MediaStream lMS = factory.createLocalMediaStream(streamLabel);
VideoTrack videoTrack = factory.createVideoTrack(videoTrackId, videoSource);
assertNotNull(videoTrack);
@@ -653,7 +660,20 @@
lMS.addTrack(videoTrack);
lMS.addTrack(
factory.createAudioTrack(audioTrackId, factory.createAudioSource(new MediaConstraints())));
- pc.addStream(lMS);
+ if (!useAddStream) {
+ // In Unified Plan, addTrack() is the preferred way of adding tracks.
+ for (AudioTrack track : lMS.audioTracks) {
+ pc.addTrack(track, Collections.singletonList(lMS.getId()));
+ }
+ for (VideoTrack track : lMS.videoTracks) {
+ pc.addTrack(track, Collections.singletonList(lMS.getId()));
+ }
+ } else {
+ // Only in Plan B is addStream() supported. Used by a legacy test not yet
+ // updated to Unified Plan.
+ // TODO(https://crbug.com/webrtc/13528): Remove use of addStream().
+ pc.addStream(lMS);
+ }
return new WeakReference<MediaStream>(lMS);
}
@@ -680,6 +700,7 @@
.createIceServer());
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
+ rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
ObserverExpectations offeringExpectations = new ObserverExpectations("PCTest:offerer");
PeerConnection offeringPC = factory.createPeerConnection(rtcConfig, offeringExpectations);
@@ -946,6 +967,7 @@
.createIceServer());
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
+ rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
ObserverExpectations offeringExpectations = new ObserverExpectations("PCTest:offerer");
PeerConnection offeringPC = factory.createPeerConnection(rtcConfig, offeringExpectations);
@@ -1107,7 +1129,8 @@
PeerConnectionFactory.builder().setOptions(options).createPeerConnectionFactory();
PeerConnection.RTCConfiguration rtcConfig =
- new PeerConnection.RTCConfiguration(Arrays.asList());
+ new PeerConnection.RTCConfiguration(Collections.emptyList());
+ rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
// NONE would prevent any candidate being signaled to the PC.
rtcConfig.iceTransportsType = PeerConnection.IceTransportsType.NONE;
// We must have the continual gathering enabled to allow the surfacing of candidates on the ICE
@@ -1173,6 +1196,8 @@
PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer());
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
+ // TODO(https://crbug.com/webrtc/13528): Update test not to use Plan B.
+ rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.PLAN_B;
ObserverExpectations offeringExpectations = new ObserverExpectations("PCTest:offerer");
PeerConnection offeringPC = factory.createPeerConnection(rtcConfig, offeringExpectations);
@@ -1198,7 +1223,8 @@
offeringExpectations.expectRenegotiationNeeded();
WeakReference<MediaStream> oLMS =
addTracksToPC(factory, offeringPC, videoSource, "offeredMediaStream", "offeredVideoTrack",
- "offeredAudioTrack", new ExpectedResolutionSetter(answeringExpectations));
+ "offeredAudioTrack", new ExpectedResolutionSetter(answeringExpectations),
+ /*useAddStream=*/true);
offeringExpectations.expectAddTrack(2);
answeringExpectations.expectAddTrack(2);
@@ -1232,7 +1258,8 @@
answeringExpectations.expectRenegotiationNeeded();
WeakReference<MediaStream> aLMS = addTracksToPC(factory, answeringPC, videoSource,
"answeredMediaStream", "answeredVideoTrack", "answeredAudioTrack",
- new ExpectedResolutionSetter(offeringExpectations));
+ new ExpectedResolutionSetter(offeringExpectations),
+ /*useAddStream=*/true);
// Create answer.
sdpLatch = new SdpObserverLatch();
@@ -1376,8 +1403,10 @@
.setVideoDecoderFactory(new SoftwareVideoDecoderFactory())
.createPeerConnectionFactory();
- // This test is fine with no ICE servers.
- List<PeerConnection.IceServer> iceServers = new ArrayList<>();
+ // TODO(https://crbug.com/webrtc/13528): Update test not to use Plan B.
+ PeerConnection.RTCConfiguration planBConfig =
+ new PeerConnection.RTCConfiguration(Collections.emptyList());
+ planBConfig.sdpSemantics = PeerConnection.SdpSemantics.PLAN_B;
// Use OfferToReceiveAudio/Video to ensure every offer has an audio and
// video m= section. Simplifies the test because it means we don't have to
@@ -1391,11 +1420,11 @@
// This PeerConnection will only be used to generate offers.
ObserverExpectations offeringExpectations = new ObserverExpectations("offerer");
- PeerConnection offeringPC = factory.createPeerConnection(iceServers, offeringExpectations);
+ PeerConnection offeringPC = factory.createPeerConnection(planBConfig, offeringExpectations);
assertNotNull(offeringPC);
ObserverExpectations expectations = new ObserverExpectations("PC under test");
- PeerConnection pcUnderTest = factory.createPeerConnection(iceServers, expectations);
+ PeerConnection pcUnderTest = factory.createPeerConnection(planBConfig, expectations);
assertNotNull(pcUnderTest);
// Add offerer media stream with just an audio track.
@@ -1403,9 +1432,9 @@
AudioTrack localAudioTrack =
factory.createAudioTrack("audio", factory.createAudioSource(new MediaConstraints()));
localStream.addTrack(localAudioTrack);
- // TODO(deadbeef): Use addTrack once that's available.
offeringExpectations.expectRenegotiationNeeded();
- offeringPC.addStream(localStream);
+ RtpSender audioSender =
+ offeringPC.addTrack(localAudioTrack, Collections.singletonList(localStream.getId()));
// Create offer.
SdpObserverLatch sdpLatch = new SdpObserverLatch();
offeringPC.createOffer(sdpLatch, offerConstraints);
@@ -1435,6 +1464,7 @@
VideoTrack videoTrack = factory.createVideoTrack("video", videoSource);
offeringExpectations.expectRenegotiationNeeded();
localStream.addTrack(videoTrack);
+ offeringPC.addTrack(videoTrack, Collections.singletonList(localStream.getId()));
// ... and create an updated offer.
sdpLatch = new SdpObserverLatch();
offeringPC.createOffer(sdpLatch, offerConstraints);
@@ -1453,6 +1483,7 @@
offeringExpectations.expectRenegotiationNeeded();
localStream.removeTrack(localAudioTrack);
localAudioTrack.dispose();
+ offeringPC.removeTrack(audioSender);
sdpLatch = new SdpObserverLatch();
offeringPC.createOffer(sdpLatch, offerConstraints);
assertTrue(sdpLatch.await());
@@ -1492,7 +1523,8 @@
@SmallTest
public void testRollback() throws Exception {
PeerConnectionFactory factory = PeerConnectionFactory.builder().createPeerConnectionFactory();
- PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(Arrays.asList());
+ PeerConnection.RTCConfiguration config =
+ new PeerConnection.RTCConfiguration(Collections.emptyList());
config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
ObserverExpectations offeringExpectations = new ObserverExpectations("PCTest:offerer");
diff --git a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
index 8478fe5..7d19143 100644
--- a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
+++ b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
@@ -165,6 +165,7 @@
.setPassword("fakePassword")
.createIceServer());
PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(iceServers);
+ config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
// Test configuration options.
config.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY;
@@ -179,6 +180,7 @@
public void testCreationWithCertificate() throws Exception {
PeerConnectionFactory factory = PeerConnectionFactory.builder().createPeerConnectionFactory();
PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(Arrays.asList());
+ config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
// Test certificate.
RtcCertificatePem originalCert = RtcCertificatePem.generateCertificate();
@@ -197,6 +199,7 @@
public void testCreationWithCryptoOptions() throws Exception {
PeerConnectionFactory factory = PeerConnectionFactory.builder().createPeerConnectionFactory();
PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(Arrays.asList());
+ config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
assertNull(config.cryptoOptions);
diff --git a/sdk/android/src/jni/pc/peer_connection.cc b/sdk/android/src/jni/pc/peer_connection.cc
index ee3c35c..6bcaef4 100644
--- a/sdk/android/src/jni/pc/peer_connection.cc
+++ b/sdk/android/src/jni/pc/peer_connection.cc
@@ -118,6 +118,9 @@
if (enum_name == "UNIFIED_PLAN")
return SdpSemantics::kUnifiedPlan;
+ if (enum_name == "NOT_SPECIFIED")
+ return SdpSemantics::kNotSpecified;
+
RTC_DCHECK_NOTREACHED();
return SdpSemantics::kPlanB_DEPRECATED;
}