diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index 8aa39e228c..00ce2f0f94 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -423,6 +423,7 @@ generate_jni("generated_peerconnection_jni") {
"api/org/webrtc/RtpParameters.java",
"api/org/webrtc/RtpReceiver.java",
"api/org/webrtc/RtpSender.java",
+ "api/org/webrtc/RtpTransceiver.java",
"api/org/webrtc/SdpObserver.java",
"api/org/webrtc/SessionDescription.java",
"api/org/webrtc/StatsObserver.java",
@@ -471,6 +472,8 @@ rtc_static_library("peerconnection_jni") {
"src/jni/pc/rtpreceiver.h",
"src/jni/pc/rtpsender.cc",
"src/jni/pc/rtpsender.h",
+ "src/jni/pc/rtptransceiver.cc",
+ "src/jni/pc/rtptransceiver.h",
"src/jni/pc/sdpobserver.cc",
"src/jni/pc/sdpobserver.h",
"src/jni/pc/sessiondescription.cc",
@@ -669,6 +672,7 @@ rtc_android_library("libjingle_peerconnection_java") {
"api/org/webrtc/RtpParameters.java",
"api/org/webrtc/RtpReceiver.java",
"api/org/webrtc/RtpSender.java",
+ "api/org/webrtc/RtpTransceiver.java",
"api/org/webrtc/ScreenCapturerAndroid.java",
"api/org/webrtc/SdpObserver.java",
"api/org/webrtc/SessionDescription.java",
diff --git a/sdk/android/api/org/webrtc/MediaStream.java b/sdk/android/api/org/webrtc/MediaStream.java
index d66d844936..e04fabdd85 100644
--- a/sdk/android/api/org/webrtc/MediaStream.java
+++ b/sdk/android/api/org/webrtc/MediaStream.java
@@ -88,13 +88,19 @@ public class MediaStream {
JniCommon.nativeReleaseRef(nativeStream);
}
+ // TODO(shampson): Remove this when downstreams have moved to using id() instead.
+ @Deprecated
public String label() {
- return nativeGetLabel(nativeStream);
+ return nativeGetId(nativeStream);
+ }
+
+ public String getId() {
+ return nativeGetId(nativeStream);
}
@Override
public String toString() {
- return "[" + label() + ":A=" + audioTracks.size() + ":V=" + videoTracks.size() + "]";
+ return "[" + getId() + ":A=" + audioTracks.size() + ":V=" + videoTracks.size() + "]";
}
@CalledByNative
@@ -137,5 +143,5 @@ public class MediaStream {
long stream, long nativeVideoTrack);
private static native boolean nativeRemoveAudioTrack(long stream, long nativeAudioTrack);
private static native boolean nativeRemoveVideoTrack(long stream, long nativeVideoTrack);
- private static native String nativeGetLabel(long stream);
+ private static native String nativeGetId(long stream);
}
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java
index de1e57d787..603b36e371 100644
--- a/sdk/android/api/org/webrtc/PeerConnection.java
+++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -341,6 +341,33 @@ public class PeerConnection {
}
}
+ /**
+ * 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.
+ *
+ *
PLAN_B will cause PeerConnection to create offers and answers with at
+ * most one audio and one video m= section with multiple RtpSenders and
+ * RtpReceivers specified as multiple a=ssrc lines within the section. This
+ * will also cause PeerConnection to ignore all but the first m= section of
+ * the same media type.
+ *
+ *
UNIFIED_PLAN will cause PeerConnection to create offers and answers with
+ * multiple m= sections where each m= section maps to one RtpSender and one
+ * RtpReceiver (an RtpTransceiver), either both audio or both video. This
+ * will also cause PeerConnection to ignore all but the first a=ssrc lines
+ * that form a Plan B stream.
+ *
+ *
For users who wish to send multiple audio/video streams and need to stay
+ * interoperable with legacy WebRTC implementations, specify PLAN_B.
+ *
+ *
For users who wish to send multiple audio/video streams and/or wish to
+ * use the new RtpTransceiver API, specify UNIFIED_PLAN.
+ */
+ public enum SdpSemantics { PLAN_B, UNIFIED_PLAN }
+
/** Java version of PeerConnectionInterface.RTCConfiguration */
// TODO(qingsi): Resolve the naming inconsistency of fields with/without units.
public static class RTCConfiguration {
@@ -386,6 +413,7 @@ public class PeerConnection {
// Use "Unknown" to represent no preference of adapter types, not the
// preference of adapters of unknown types.
public AdapterType networkPreference;
+ public SdpSemantics sdpSemantics;
// This is an optional wrapper for the C++ webrtc::TurnCustomizer.
public TurnCustomizer turnCustomizer;
@@ -423,6 +451,7 @@ public class PeerConnection {
combinedAudioVideoBwe = null;
enableDtlsSrtp = null;
networkPreference = AdapterType.UNKNOWN;
+ sdpSemantics = SdpSemantics.PLAN_B;
}
@CalledByNative("RTCConfiguration")
@@ -574,12 +603,18 @@ public class PeerConnection {
AdapterType getNetworkPreference() {
return networkPreference;
}
+
+ @CalledByNative("RTCConfiguration")
+ SdpSemantics getSdpSemantics() {
+ return sdpSemantics;
+ }
};
private final List localStreams = new ArrayList<>();
private final long nativePeerConnection;
private List senders = new ArrayList<>();
private List receivers = new ArrayList<>();
+ private List transceivers = new ArrayList<>();
/**
* Wraps a PeerConnection created by the factory. Can be used by clients that want to implement
@@ -622,18 +657,24 @@ public class PeerConnection {
nativeSetRemoteDescription(observer, sdp);
}
- // True if remote audio should be played out. Defaults to true.
- // Note that even if playout is enabled, streams will only be played out if
- // the appropriate SDP is also applied. The main purpose of this API is to
- // be able to control the exact time when audio playout starts.
+ /**
+ * Enables/disables playout of received audio streams. Enabled by default.
+ *
+ * Note that even if playout is enabled, streams will only be played out if
+ * the appropriate SDP is also applied. The main purpose of this API is to
+ * be able to control the exact time when audio playout starts.
+ */
public void setAudioPlayout(boolean playout) {
nativeSetAudioPlayout(playout);
}
- // True if local audio shall be recorded. Defaults to true.
- // Note that even if recording is enabled, streams will only be recorded if
- // the appropriate SDP is also applied. The main purpose of this API is to
- // be able to control the exact time when audio recording starts.
+ /**
+ * Enables/disables recording of transmitted audio streams. Enabled by default.
+ *
+ * Note that even if recording is enabled, streams will only be recorded if
+ * the appropriate SDP is also applied. The main purpose of this API is to
+ * be able to control the exact time when audio recording starts.
+ */
public void setAudioRecording(boolean recording) {
nativeSetAudioRecording(recording);
}
@@ -650,6 +691,11 @@ public class PeerConnection {
return nativeRemoveIceCandidates(candidates);
}
+ /**
+ * Adds a new MediaStream to be sent on this peer connection.
+ * Note: This method is not supported with SdpSemantics.UNIFIED_PLAN. Please
+ * use addTrack instead.
+ */
public boolean addStream(MediaStream stream) {
boolean ret = nativeAddLocalStream(stream.nativeStream);
if (!ret) {
@@ -659,6 +705,11 @@ public class PeerConnection {
return true;
}
+ /**
+ * Removes the given media stream from this peer connection.
+ * This method is not supported with SdpSemantics.UNIFIED_PLAN. Please use
+ * removeTrack instead.
+ */
public void removeStream(MediaStream stream) {
nativeRemoveLocalStream(stream.nativeStream);
localStreams.remove(stream);
@@ -666,15 +717,15 @@ public class PeerConnection {
/**
* Creates an RtpSender without a track.
- *
- * This method allows an application to cause the PeerConnection to negotiate
+ *
+ *
This method allows an application to cause the PeerConnection to negotiate
* sending/receiving a specific media type, but without having a track to
* send yet.
- *
- * When the application does want to begin sending a track, it can call
+ *
+ *
When the application does want to begin sending a track, it can call
* RtpSender.setTrack, which doesn't require any additional SDP negotiation.
- *
- * Example use:
+ *
+ *
Example use:
*
* {@code
* audioSender = pc.createSender("audio", "stream1");
@@ -686,12 +737,15 @@ public class PeerConnection {
* videoSender.setTrack(videoTrack, false);
* }
*
- * Note: This corresponds most closely to "addTransceiver" in the official
+ * Note: This corresponds most closely to "addTransceiver" in the official
* WebRTC API, in that it creates a sender without a track. It was
* implemented before addTransceiver because it provides useful
* functionality, and properly implementing transceivers would have required
* a great deal more work.
*
+ *
Note: This is only available with SdpSemantics.PLAN_B specified. Please use
+ * addTransceiver instead.
+ *
* @param kind Corresponds to MediaStreamTrack kinds (must be "audio" or
* "video").
* @param stream_id The ID of the MediaStream that this sender's track will
@@ -702,15 +756,18 @@ public class PeerConnection {
* @return A new RtpSender object if successful, or null otherwise.
*/
public RtpSender createSender(String kind, String stream_id) {
- RtpSender new_sender = nativeCreateSender(kind, stream_id);
- if (new_sender != null) {
- senders.add(new_sender);
+ RtpSender newSender = nativeCreateSender(kind, stream_id);
+ if (newSender != null) {
+ senders.add(newSender);
}
- return new_sender;
+ return newSender;
}
- // Note that calling getSenders will dispose of the senders previously
- // returned (and same goes for getReceivers).
+ /**
+ * Gets all RtpSenders associated with this peer connection.
+ * Note that calling getSenders will dispose of the senders previously
+ * returned.
+ */
public List getSenders() {
for (RtpSender sender : senders) {
sender.dispose();
@@ -719,6 +776,11 @@ public class PeerConnection {
return Collections.unmodifiableList(senders);
}
+ /**
+ * Gets all RtpReceivers associated with this peer connection.
+ * Note that calling getReceivers will dispose of the receivers previously
+ * returned.
+ */
public List getReceivers() {
for (RtpReceiver receiver : receivers) {
receiver.dispose();
@@ -727,35 +789,162 @@ public class PeerConnection {
return Collections.unmodifiableList(receivers);
}
+ /**
+ * Gets all RtpTransceivers associated with this peer connection.
+ * Note that calling getTransceivers will dispose of the transceivers previously
+ * returned.
+ * Note: This is only available with SdpSemantics.UNIFIED_PLAN specified.
+ */
+ public List getTransceivers() {
+ for (RtpTransceiver transceiver : transceivers) {
+ transceiver.dispose();
+ }
+ transceivers = nativeGetTransceivers();
+ return Collections.unmodifiableList(transceivers);
+ }
+
+ /**
+ * Adds a new media stream track to be sent on this peer connection, and returns
+ * the newly created RtpSender. If streamIds are specified, the RtpSender will
+ * be associated with the streams specified in the streamIds list.
+ *
+ * @throws IllegalStateException if an error accors in C++ addTrack.
+ * An error can occur if:
+ * - A sender already exists for the track.
+ * - The peer connection is closed.
+ */
+ public RtpSender addTrack(MediaStreamTrack track) {
+ return addTrack(track, Collections.emptyList());
+ }
+
+ public RtpSender addTrack(MediaStreamTrack track, List streamIds) {
+ if (track == null || streamIds == null) {
+ throw new NullPointerException("No MediaStreamTrack specified in addTrack.");
+ }
+ RtpSender newSender = nativeAddTrack(track.nativeTrack, streamIds);
+ if (newSender == null) {
+ throw new IllegalStateException("C++ addTrack failed.");
+ }
+ senders.add(newSender);
+ return newSender;
+ }
+
+ /**
+ * Stops sending media from sender. The sender will still appear in getSenders. Future
+ * calls to createOffer will mark the m section for the corresponding transceiver as
+ * receive only or inactive, as defined in JSEP. Returns true on success.
+ */
+ public boolean removeTrack(RtpSender sender) {
+ if (sender == null) {
+ throw new NullPointerException("No RtpSender specified for removeTrack.");
+ }
+ return nativeRemoveTrack(sender.nativeRtpSender);
+ }
+
+ /**
+ * Creates a new RtpTransceiver and adds it to the set of transceivers. Adding a
+ * transceiver will cause future calls to CreateOffer to add a media description
+ * for the corresponding transceiver.
+ *
+ * The initial value of |mid| in the returned transceiver is null. Setting a
+ * new session description may change it to a non-null value.
+ *
+ *
https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
+ *
+ *
If a MediaStreamTrack is specified then a transceiver will be added with a
+ * sender set to transmit the given track. The kind
+ * of the transceiver (and sender/receiver) will be derived from the kind of
+ * the track.
+ *
+ *
If MediaType is specified then a transceiver will be added based upon that type.
+ * This can be either MEDIA_TYPE_AUDIO or MEDIA_TYPE_VIDEO.
+ *
+ *
Optionally, an RtpTransceiverInit structure can be specified to configure
+ * the transceiver from construction. If not specified, the transceiver will
+ * default to having a direction of kSendRecv and not be part of any streams.
+ *
+ *
Note: These methods are only available with SdpSemantics.UNIFIED_PLAN specified.
+ * @throws IllegalStateException if an error accors in C++ addTransceiver
+ */
+ public RtpTransceiver addTransceiver(MediaStreamTrack track) {
+ return addTransceiver(track, new RtpTransceiver.RtpTransceiverInit());
+ }
+
+ public RtpTransceiver addTransceiver(
+ MediaStreamTrack track, RtpTransceiver.RtpTransceiverInit init) {
+ if (track == null) {
+ throw new NullPointerException("No MediaStreamTrack specified for addTransceiver.");
+ }
+ if (init == null) {
+ init = new RtpTransceiver.RtpTransceiverInit();
+ }
+ RtpTransceiver newTransceiver = nativeAddTransceiverWithTrack(track.nativeTrack, init);
+ if (newTransceiver == null) {
+ throw new IllegalStateException("C++ addTransceiver failed.");
+ }
+ transceivers.add(newTransceiver);
+ return newTransceiver;
+ }
+
+ public RtpTransceiver addTransceiver(MediaStreamTrack.MediaType mediaType) {
+ return addTransceiver(mediaType, new RtpTransceiver.RtpTransceiverInit());
+ }
+
+ public RtpTransceiver addTransceiver(
+ MediaStreamTrack.MediaType mediaType, RtpTransceiver.RtpTransceiverInit init) {
+ if (mediaType == null) {
+ throw new NullPointerException("No MediaType specified for addTransceiver.");
+ }
+ if (init == null) {
+ init = new RtpTransceiver.RtpTransceiverInit();
+ }
+ RtpTransceiver newTransceiver = nativeAddTransceiverOfType(mediaType, init);
+ if (newTransceiver == null) {
+ throw new IllegalStateException("C++ addTransceiver failed.");
+ }
+ transceivers.add(newTransceiver);
+ return newTransceiver;
+ }
+
// Older, non-standard implementation of getStats.
@Deprecated
public boolean getStats(StatsObserver observer, MediaStreamTrack track) {
return nativeOldGetStats(observer, (track == null) ? 0 : track.nativeTrack);
}
- // Gets stats using the new stats collection API, see webrtc/api/stats/. These
- // will replace old stats collection API when the new API has matured enough.
+ /**
+ * Gets stats using the new stats collection API, see webrtc/api/stats/. These
+ * will replace old stats collection API when the new API has matured enough.
+ */
public void getStats(RTCStatsCollectorCallback callback) {
nativeNewGetStats(callback);
}
- // Limits the bandwidth allocated for all RTP streams sent by this
- // PeerConnection. Pass null to leave a value unchanged.
+ /**
+ * Limits the bandwidth allocated for all RTP streams sent by this
+ * PeerConnection. Pass null to leave a value unchanged.
+ */
public boolean setBitrate(Integer min, Integer current, Integer max) {
return nativeSetBitrate(min, current, max);
}
- // Starts recording an RTC event log. Ownership of the file is transfered to
- // the native code. If an RTC event log is already being recorded, it will be
- // stopped and a new one will start using the provided file. Logging will
- // continue until the stopRtcEventLog function is called. The max_size_bytes
- // argument is ignored, it is added for future use.
+ /**
+ * Starts recording an RTC event log.
+ *
+ * Ownership of the file is transfered to the native code. If an RTC event
+ * log is already being recorded, it will be stopped and a new one will start
+ * using the provided file. Logging will continue until the stopRtcEventLog
+ * function is called. The max_size_bytes argument is ignored, it is added
+ * for future use.
+ */
public boolean startRtcEventLog(int file_descriptor, int max_size_bytes) {
return nativeStartRtcEventLog(file_descriptor, max_size_bytes);
}
- // Stops recording an RTC event log. If no RTC event log is currently being
- // recorded, this call will have no effect.
+ /**
+ * Stops recording an RTC event log. If no RTC event log is currently being
+ * recorded, this call will have no effect.
+ */
public void stopRtcEventLog() {
nativeStopRtcEventLog();
}
@@ -780,14 +969,14 @@ public class PeerConnection {
/**
* Free native resources associated with this PeerConnection instance.
- *
+ *
* This method removes a reference count from the C++ PeerConnection object,
* which should result in it being destroyed. It also calls equivalent
* "dispose" methods on the Java objects attached to this PeerConnection
* (streams, senders, receivers), such that their associated C++ objects
* will also be destroyed.
- *
- * Note that this method cannot be safely called from an observer callback
+ *
+ *
Note that this method cannot be safely called from an observer callback
* (PeerConnection.Observer, DataChannel.Observer, etc.). If you want to, for
* example, destroy the PeerConnection after an "ICE failed" callback, you
* must do this asynchronously (in other words, unwind the stack first). See
@@ -808,6 +997,10 @@ public class PeerConnection {
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
+ for (RtpTransceiver transceiver : transceivers) {
+ transceiver.dispose();
+ }
+ transceivers.clear();
receivers.clear();
nativeFreeOwnedPeerConnection(nativePeerConnection);
}
@@ -854,6 +1047,13 @@ public class PeerConnection {
private native RtpSender nativeCreateSender(String kind, String stream_id);
private native List nativeGetSenders();
private native List nativeGetReceivers();
+ private native List nativeGetTransceivers();
+ private native RtpSender nativeAddTrack(long track, List streamIds);
+ private native boolean nativeRemoveTrack(long sender);
+ private native RtpTransceiver nativeAddTransceiverWithTrack(
+ long track, RtpTransceiver.RtpTransceiverInit init);
+ private native RtpTransceiver nativeAddTransceiverOfType(
+ MediaStreamTrack.MediaType mediaType, RtpTransceiver.RtpTransceiverInit init);
private native boolean nativeStartRtcEventLog(int file_descriptor, int max_size_bytes);
private native void nativeStopRtcEventLog();
}
diff --git a/sdk/android/api/org/webrtc/RtpTransceiver.java b/sdk/android/api/org/webrtc/RtpTransceiver.java
new file mode 100644
index 0000000000..d77ecb408e
--- /dev/null
+++ b/sdk/android/api/org/webrtc/RtpTransceiver.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.webrtc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.webrtc.RtpParameters.Encoding;
+
+/**
+ * Java wrapper for a C++ RtpTransceiverInterface.
+ *
+ * The RTCRtpTransceiver maps to the RTCRtpTransceiver defined by the WebRTC
+ * specification. A transceiver represents a combination of an RTCRtpSender
+ * and an RTCRtpReceiver that share a common mid. As defined in JSEP, an
+ * RTCRtpTransceiver is said to be associated with a media description if its
+ * mid property is non-nil; otherwise, it is said to be disassociated.
+ * JSEP: https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24
+ *
+ *
Note that RTCRtpTransceivers are only supported when using
+ * RTCPeerConnection with Unified Plan SDP.
+ *
+ *
WebRTC specification for RTCRtpTransceiver, the JavaScript analog:
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver
+ */
+@JNINamespace("webrtc::jni")
+public class RtpTransceiver {
+ /** Java version of webrtc::RtpTransceiverDirection - the ordering must be kept in sync. */
+ public enum RtpTransceiverDirection {
+ SEND_RECV(0),
+ SEND_ONLY(1),
+ RECV_ONLY(2),
+ INACTIVE(3);
+
+ private final int nativeIndex;
+
+ private RtpTransceiverDirection(int nativeIndex) {
+ this.nativeIndex = nativeIndex;
+ }
+
+ @CalledByNative("RtpTransceiverDirection")
+ int getNativeIndex() {
+ return nativeIndex;
+ }
+
+ @CalledByNative("RtpTransceiverDirection")
+ static RtpTransceiverDirection fromNativeIndex(int nativeIndex) {
+ for (RtpTransceiverDirection type : RtpTransceiverDirection.values()) {
+ if (type.getNativeIndex() == nativeIndex) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException(
+ "Uknown native RtpTransceiverDirection type" + nativeIndex);
+ }
+ }
+
+ /**
+ * Tracks webrtc::RtpTransceiverInit. https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
+ * A structure for initializing an RtpTransceiver in a call to addTransceiver.
+ * Note: This does not contain a list of encoding parameters, because they are currently
+ * not being used natively.
+ */
+ public static final class RtpTransceiverInit {
+ private final RtpTransceiverDirection direction;
+ private final List streamIds;
+
+ public RtpTransceiverInit() {
+ this(RtpTransceiverDirection.SEND_RECV);
+ }
+
+ public RtpTransceiverInit(RtpTransceiverDirection direction) {
+ this(direction, Collections.emptyList());
+ }
+
+ public RtpTransceiverInit(RtpTransceiverDirection direction, List streamIds) {
+ this.direction = direction;
+ this.streamIds = new ArrayList(streamIds);
+ }
+
+ @CalledByNative("RtpTransceiverInit")
+ int getDirectionNativeIndex() {
+ return direction.getNativeIndex();
+ }
+
+ @CalledByNative("RtpTransceiverInit")
+ List getStreamIds() {
+ return new ArrayList(this.streamIds);
+ }
+ }
+
+ private final long nativeRtpTransceiver;
+ private RtpSender cachedSender;
+ private RtpReceiver cachedReceiver;
+
+ @CalledByNative
+ protected RtpTransceiver(long nativeRtpTransceiver) {
+ this.nativeRtpTransceiver = nativeRtpTransceiver;
+ cachedSender = nativeGetSender(nativeRtpTransceiver);
+ cachedReceiver = nativeGetReceiver(nativeRtpTransceiver);
+ }
+
+ /**
+ * Media type of the transceiver. Any sender(s)/receiver(s) will have this
+ * type as well.
+ */
+ public MediaStreamTrack.MediaType getMediaType() {
+ return nativeGetMediaType(nativeRtpTransceiver);
+ }
+
+ /**
+ * The mid attribute is the mid negotiated and present in the local and
+ * remote descriptions. Before negotiation is complete, the mid value may be
+ * null. After rollbacks, the value may change from a non-null value to null.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-mid
+ */
+ public String getMid() {
+ return nativeGetMid(nativeRtpTransceiver);
+ }
+
+ /**
+ * The sender attribute exposes the RtpSender corresponding to the RTP media
+ * that may be sent with the transceiver's mid. The sender is always present,
+ * regardless of the direction of media.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-sender
+ */
+ public RtpSender getSender() {
+ return cachedSender;
+ }
+
+ /**
+ * The receiver attribute exposes the RtpReceiver corresponding to the RTP
+ * media that may be received with the transceiver's mid. The receiver is
+ * always present, regardless of the direction of media.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-receiver
+ */
+ public RtpReceiver getReceiver() {
+ return cachedReceiver;
+ }
+
+ /**
+ * The stopped attribute indicates that the sender of this transceiver will no
+ * longer send, and that the receiver will no longer receive. It is true if
+ * either stop has been called or if setting the local or remote description
+ * has caused the RtpTransceiver to be stopped.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stopped
+ */
+ public boolean isStopped() {
+ return nativeStopped(nativeRtpTransceiver);
+ }
+
+ /**
+ * The direction attribute indicates the preferred direction of this
+ * transceiver, which will be used in calls to CreateOffer and CreateAnswer.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
+ */
+ public RtpTransceiverDirection getDirection() {
+ return nativeDirection(nativeRtpTransceiver);
+ }
+
+ /**
+ * The current_direction attribute indicates the current direction negotiated
+ * for this transceiver. If this transceiver has never been represented in an
+ * offer/answer exchange, or if the transceiver is stopped, the value is null.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-currentdirection
+ */
+ public RtpTransceiverDirection getCurrentDirection() {
+ return nativeCurrentDirection(nativeRtpTransceiver);
+ }
+
+ /**
+ * Sets the preferred direction of this transceiver. An update of
+ * directionality does not take effect immediately. Instead, future calls to
+ * CreateOffer and CreateAnswer mark the corresponding media descriptions as
+ * sendrecv, sendonly, recvonly, or inactive.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
+ */
+ public void setDirection(RtpTransceiverDirection rtpTransceiverDirection) {
+ nativeSetDirection(nativeRtpTransceiver, rtpTransceiverDirection);
+ }
+
+ /**
+ * The Stop method irreversibly stops the RtpTransceiver. The sender of this
+ * transceiver will no longer send, the receiver will no longer receive.
+ * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop
+ */
+ public void stop() {
+ nativeStop(nativeRtpTransceiver);
+ }
+
+ public void dispose() {
+ cachedSender.dispose();
+ cachedReceiver.dispose();
+ JniCommon.nativeReleaseRef(nativeRtpTransceiver);
+ }
+
+ private static native MediaStreamTrack.MediaType nativeGetMediaType(long rtpTransceiver);
+ private static native String nativeGetMid(long rtpTransceiver);
+ private static native RtpSender nativeGetSender(long rtpTransceiver);
+ private static native RtpReceiver nativeGetReceiver(long rtpTransceiver);
+ private static native boolean nativeStopped(long rtpTransceiver);
+ private static native RtpTransceiverDirection nativeDirection(long rtpTransceiver);
+ private static native RtpTransceiverDirection nativeCurrentDirection(long rtpTransceiver);
+ private static native void nativeStop(long rtpTransceiver);
+ private static native void nativeSetDirection(
+ long rtpTransceiver, RtpTransceiverDirection rtpTransceiverDirection);
+}
diff --git a/sdk/android/native_api/jni/java_types.cc b/sdk/android/native_api/jni/java_types.cc
index 86ada91b1f..5f4ebba390 100644
--- a/sdk/android/native_api/jni/java_types.cc
+++ b/sdk/android/native_api/jni/java_types.cc
@@ -200,6 +200,12 @@ ScopedJavaLocalRef NativeToJavaInteger(
return optional_int ? NativeToJavaInteger(jni, *optional_int) : nullptr;
}
+ScopedJavaLocalRef NativeToJavaString(
+ JNIEnv* jni,
+ const rtc::Optional& str) {
+ return str ? NativeToJavaString(jni, *str) : nullptr;
+}
+
ScopedJavaLocalRef NativeToJavaBooleanArray(
JNIEnv* env,
const std::vector& container) {
diff --git a/sdk/android/native_api/jni/java_types.h b/sdk/android/native_api/jni/java_types.h
index d9d2b1a3e5..fb660635d6 100644
--- a/sdk/android/native_api/jni/java_types.h
+++ b/sdk/android/native_api/jni/java_types.h
@@ -150,6 +150,21 @@ std::vector JavaToNativeVector(JNIEnv* env,
return container;
}
+template
+std::vector JavaListToNativeVector(JNIEnv* env,
+ const JavaRef& j_list,
+ Convert convert) {
+ std::vector native_list;
+ if (!j_list.is_null()) {
+ for (ScopedJavaLocalRef& j_item : Iterable(env, j_list)) {
+ native_list.emplace_back(
+ convert(env, static_java_ref_cast(env, j_item)));
+ }
+ CHECK_EXCEPTION(env) << "Error during JavaListToNativeVector";
+ }
+ return native_list;
+}
+
template
std::map JavaToNativeMap(JNIEnv* env,
const JavaRef& j_map,
@@ -182,6 +197,9 @@ ScopedJavaLocalRef NativeToJavaString(JNIEnv* jni,
ScopedJavaLocalRef NativeToJavaInteger(
JNIEnv* jni,
const rtc::Optional& optional_int);
+ScopedJavaLocalRef NativeToJavaString(
+ JNIEnv* jni,
+ const rtc::Optional& str);
// Helper function for converting std::vector into a Java array.
template
@@ -282,7 +300,7 @@ inline std::string JavaToStdString(JNIEnv* jni, jstring j_string) {
return JavaToStdString(jni, JavaParamRef(j_string));
}
-// Deprecated. Use JavaToNativeVector instead.
+// Deprecated. Use JavaListToNativeVector instead.
// Given a List of (UTF-16) jstrings
// return a new vector of UTF-8 native strings.
std::vector JavaToStdVectorStrings(JNIEnv* jni,
diff --git a/sdk/android/src/jni/pc/mediastream.cc b/sdk/android/src/jni/pc/mediastream.cc
index e733c8c6fb..5f36414eed 100644
--- a/sdk/android/src/jni/pc/mediastream.cc
+++ b/sdk/android/src/jni/pc/mediastream.cc
@@ -135,9 +135,9 @@ static jboolean JNI_MediaStream_RemoveVideoTrack(JNIEnv* jni,
}
static ScopedJavaLocalRef
-JNI_MediaStream_GetLabel(JNIEnv* jni, const JavaParamRef&, jlong j_p) {
- return NativeToJavaString(
- jni, reinterpret_cast(j_p)->label());
+JNI_MediaStream_GetId(JNIEnv* jni, const JavaParamRef&, jlong j_p) {
+ return NativeToJavaString(jni,
+ reinterpret_cast(j_p)->id());
}
} // namespace jni
diff --git a/sdk/android/src/jni/pc/peerconnection.cc b/sdk/android/src/jni/pc/peerconnection.cc
index f954a4330c..048d22490c 100644
--- a/sdk/android/src/jni/pc/peerconnection.cc
+++ b/sdk/android/src/jni/pc/peerconnection.cc
@@ -36,6 +36,7 @@
#include "api/peerconnectioninterface.h"
#include "api/rtpreceiverinterface.h"
#include "api/rtpsenderinterface.h"
+#include "api/rtptransceiverinterface.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/ptr_util.h"
@@ -45,8 +46,10 @@
#include "sdk/android/src/jni/pc/datachannel.h"
#include "sdk/android/src/jni/pc/icecandidate.h"
#include "sdk/android/src/jni/pc/mediaconstraints.h"
+#include "sdk/android/src/jni/pc/mediastreamtrack.h"
#include "sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h"
#include "sdk/android/src/jni/pc/rtpsender.h"
+#include "sdk/android/src/jni/pc/rtptransceiver.h"
#include "sdk/android/src/jni/pc/sdpobserver.h"
#include "sdk/android/src/jni/pc/sessiondescription.h"
#include "sdk/android/src/jni/pc/statsobserver.h"
@@ -86,19 +89,35 @@ PeerConnectionInterface::IceServers JavaToNativeIceServers(
ScopedJavaLocalRef tls_elliptic_curves =
Java_IceServer_getTlsEllipticCurves(jni, j_ice_server);
PeerConnectionInterface::IceServer server;
- server.urls = JavaToStdVectorStrings(jni, urls);
- server.username = JavaToStdString(jni, username);
- server.password = JavaToStdString(jni, password);
+ server.urls = JavaListToNativeVector(
+ jni, urls, &JavaToNativeString);
+ server.username = JavaToNativeString(jni, username);
+ server.password = JavaToNativeString(jni, password);
server.tls_cert_policy = tls_cert_policy;
- server.hostname = JavaToStdString(jni, hostname);
- server.tls_alpn_protocols = JavaToStdVectorStrings(jni, tls_alpn_protocols);
- server.tls_elliptic_curves =
- JavaToStdVectorStrings(jni, tls_elliptic_curves);
+ server.hostname = JavaToNativeString(jni, hostname);
+ server.tls_alpn_protocols = JavaListToNativeVector(
+ jni, tls_alpn_protocols, &JavaToNativeString);
+ server.tls_elliptic_curves = JavaListToNativeVector(
+ jni, tls_elliptic_curves, &JavaToNativeString);
ice_servers.push_back(server);
}
return ice_servers;
}
+SdpSemantics JavaToNativeSdpSemantics(JNIEnv* jni,
+ const JavaRef& j_sdp_semantics) {
+ std::string enum_name = GetJavaEnumName(jni, j_sdp_semantics);
+
+ if (enum_name == "PLAN_B")
+ return SdpSemantics::kPlanB;
+
+ if (enum_name == "UNIFIED_PLAN")
+ return SdpSemantics::kUnifiedPlan;
+
+ RTC_NOTREACHED();
+ return SdpSemantics::kPlanB;
+}
+
} // namespace
void JavaToNativeRTCConfiguration(
@@ -123,6 +142,8 @@ void JavaToNativeRTCConfiguration(
Java_RTCConfiguration_getTurnCustomizer(jni, j_rtc_config);
ScopedJavaLocalRef j_network_preference =
Java_RTCConfiguration_getNetworkPreference(jni, j_rtc_config);
+ ScopedJavaLocalRef j_sdp_semantics =
+ Java_RTCConfiguration_getSdpSemantics(jni, j_rtc_config);
rtc_config->type = JavaToNativeIceTransportsType(jni, j_ice_transports_type);
rtc_config->bundle_policy = JavaToNativeBundlePolicy(jni, j_bundle_policy);
@@ -193,6 +214,7 @@ void JavaToNativeRTCConfiguration(
jni, Java_RTCConfiguration_getEnableDtlsSrtp(jni, j_rtc_config));
rtc_config->network_preference =
JavaToNativeNetworkPreference(jni, j_network_preference);
+ rtc_config->sdp_semantics = JavaToNativeSdpSemantics(jni, j_sdp_semantics);
}
rtc::KeyType GetRtcConfigKeyType(JNIEnv* env,
@@ -380,7 +402,7 @@ static ScopedJavaLocalRef JNI_PeerConnection_CreateDataChannel(
DataChannelInit init = JavaToNativeDataChannelInit(jni, j_init);
rtc::scoped_refptr channel(
ExtractNativePC(jni, j_pc)->CreateDataChannel(
- JavaToStdString(jni, j_label), &init));
+ JavaToNativeString(jni, j_label), &init));
return WrapNativeDataChannel(jni, channel);
}
@@ -469,8 +491,8 @@ static jboolean JNI_PeerConnection_AddIceCandidate(
const JavaParamRef& j_sdp_mid,
jint j_sdp_mline_index,
const JavaParamRef& j_candidate_sdp) {
- std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
- std::string sdp = JavaToStdString(jni, j_candidate_sdp);
+ std::string sdp_mid = JavaToNativeString(jni, j_sdp_mid);
+ std::string sdp = JavaToNativeString(jni, j_candidate_sdp);
std::unique_ptr candidate(
CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, nullptr));
return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
@@ -507,8 +529,8 @@ static ScopedJavaLocalRef JNI_PeerConnection_CreateSender(
const JavaParamRef& j_pc,
const JavaParamRef& j_kind,
const JavaParamRef& j_stream_id) {
- std::string kind = JavaToStdString(jni, j_kind);
- std::string stream_id = JavaToStdString(jni, j_stream_id);
+ std::string kind = JavaToNativeString(jni, j_kind);
+ std::string stream_id = JavaToNativeString(jni, j_stream_id);
rtc::scoped_refptr sender =
ExtractNativePC(jni, j_pc)->CreateSender(kind, stream_id);
return NativeToJavaRtpSender(jni, sender);
@@ -528,6 +550,75 @@ static ScopedJavaLocalRef JNI_PeerConnection_GetReceivers(
&NativeToJavaRtpReceiver);
}
+static ScopedJavaLocalRef JNI_PeerConnection_GetTransceivers(
+ JNIEnv* jni,
+ const JavaParamRef& j_pc) {
+ return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetTransceivers(),
+ &NativeToJavaRtpTransceiver);
+}
+
+static ScopedJavaLocalRef JNI_PeerConnection_AddTrack(
+ JNIEnv* jni,
+ const JavaParamRef& j_pc,
+ const jlong native_track,
+ const JavaParamRef& j_stream_labels) {
+ RTCErrorOr> result =
+ ExtractNativePC(jni, j_pc)->AddTrack(
+ reinterpret_cast(native_track),
+ JavaListToNativeVector(jni, j_stream_labels,
+ &JavaToNativeString));
+ if (!result.ok()) {
+ RTC_LOG(LS_ERROR) << "Failed to add track: " << result.error().message();
+ return nullptr;
+ } else {
+ return NativeToJavaRtpSender(jni, result.MoveValue());
+ }
+}
+
+static jboolean JNI_PeerConnection_RemoveTrack(
+ JNIEnv* jni,
+ const JavaParamRef& j_pc,
+ jlong native_sender) {
+ return ExtractNativePC(jni, j_pc)->RemoveTrack(
+ reinterpret_cast(native_sender));
+}
+
+static ScopedJavaLocalRef JNI_PeerConnection_AddTransceiverWithTrack(
+ JNIEnv* jni,
+ const JavaParamRef& j_pc,
+ jlong native_track,
+ const JavaParamRef& j_init) {
+ RTCErrorOr> result =
+ ExtractNativePC(jni, j_pc)->AddTransceiver(
+ reinterpret_cast(native_track),
+ JavaToNativeRtpTransceiverInit(jni, j_init));
+ if (!result.ok()) {
+ RTC_LOG(LS_ERROR) << "Failed to add transceiver: "
+ << result.error().message();
+ return nullptr;
+ } else {
+ return NativeToJavaRtpTransceiver(jni, result.MoveValue());
+ }
+}
+
+static ScopedJavaLocalRef JNI_PeerConnection_AddTransceiverOfType(
+ JNIEnv* jni,
+ const JavaParamRef& j_pc,
+ const JavaParamRef& j_media_type,
+ const JavaParamRef& j_init) {
+ RTCErrorOr> result =
+ ExtractNativePC(jni, j_pc)->AddTransceiver(
+ JavaToNativeMediaType(jni, j_media_type),
+ JavaToNativeRtpTransceiverInit(jni, j_init));
+ if (!result.ok()) {
+ RTC_LOG(LS_ERROR) << "Failed to add transceiver: "
+ << result.error().message();
+ return nullptr;
+ } else {
+ return NativeToJavaRtpTransceiver(jni, result.MoveValue());
+ }
+}
+
static jboolean JNI_PeerConnection_OldGetStats(
JNIEnv* jni,
const JavaParamRef& j_pc,
diff --git a/sdk/android/src/jni/pc/rtpparameters.cc b/sdk/android/src/jni/pc/rtpparameters.cc
index 9630e1d6aa..6a312b4865 100644
--- a/sdk/android/src/jni/pc/rtpparameters.cc
+++ b/sdk/android/src/jni/pc/rtpparameters.cc
@@ -40,6 +40,21 @@ ScopedJavaLocalRef NativeToJavaRtpCodecParameter(
} // namespace
+RtpEncodingParameters JavaToNativeRtpEncodingParameters(
+ JNIEnv* jni,
+ const JavaRef& j_encoding_parameters) {
+ RtpEncodingParameters encoding;
+ encoding.active = Java_Encoding_getActive(jni, j_encoding_parameters);
+ ScopedJavaLocalRef j_bitrate =
+ Java_Encoding_getMaxBitrateBps(jni, j_encoding_parameters);
+ encoding.max_bitrate_bps = JavaToNativeOptionalInt(jni, j_bitrate);
+ ScopedJavaLocalRef j_ssrc =
+ Java_Encoding_getSsrc(jni, j_encoding_parameters);
+ if (!IsNull(jni, j_ssrc))
+ encoding.ssrc = JavaToNativeLong(jni, j_ssrc);
+ return encoding;
+}
+
RtpParameters JavaToNativeRtpParameters(JNIEnv* jni,
const JavaRef& j_parameters) {
RtpParameters parameters;
@@ -49,15 +64,8 @@ RtpParameters JavaToNativeRtpParameters(JNIEnv* jni,
Java_RtpParameters_getEncodings(jni, j_parameters);
for (const JavaRef& j_encoding_parameters :
Iterable(jni, j_encodings)) {
- RtpEncodingParameters encoding;
- encoding.active = Java_Encoding_getActive(jni, j_encoding_parameters);
- ScopedJavaLocalRef j_bitrate =
- Java_Encoding_getMaxBitrateBps(jni, j_encoding_parameters);
- encoding.max_bitrate_bps = JavaToNativeOptionalInt(jni, j_bitrate);
- ScopedJavaLocalRef j_ssrc =
- Java_Encoding_getSsrc(jni, j_encoding_parameters);
- if (!IsNull(jni, j_ssrc))
- encoding.ssrc = JavaToNativeLong(jni, j_ssrc);
+ RtpEncodingParameters encoding =
+ JavaToNativeRtpEncodingParameters(jni, j_encoding_parameters);
parameters.encodings.push_back(encoding);
}
diff --git a/sdk/android/src/jni/pc/rtpparameters.h b/sdk/android/src/jni/pc/rtpparameters.h
index da7c995c03..ae79793b1a 100644
--- a/sdk/android/src/jni/pc/rtpparameters.h
+++ b/sdk/android/src/jni/pc/rtpparameters.h
@@ -19,6 +19,10 @@
namespace webrtc {
namespace jni {
+RtpEncodingParameters JavaToNativeRtpEncodingParameters(
+ JNIEnv* env,
+ const JavaRef& j_encoding_parameters);
+
RtpParameters JavaToNativeRtpParameters(JNIEnv* jni,
const JavaRef& j_parameters);
ScopedJavaLocalRef NativeToJavaRtpParameters(
diff --git a/sdk/android/src/jni/pc/rtptransceiver.cc b/sdk/android/src/jni/pc/rtptransceiver.cc
new file mode 100644
index 0000000000..f142d5868e
--- /dev/null
+++ b/sdk/android/src/jni/pc/rtptransceiver.cc
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "sdk/android/src/jni/pc/rtptransceiver.h"
+
+#include
+
+#include "sdk/android/generated_peerconnection_jni/jni/RtpTransceiver_jni.h"
+#include "sdk/android/native_api/jni/java_types.h"
+#include "sdk/android/src/jni/jni_helpers.h"
+#include "sdk/android/src/jni/pc/mediastreamtrack.h"
+#include "sdk/android/src/jni/pc/rtpparameters.h"
+#include "sdk/android/src/jni/pc/rtpreceiver.h"
+#include "sdk/android/src/jni/pc/rtpsender.h"
+
+namespace webrtc {
+namespace jni {
+
+namespace {
+
+ScopedJavaLocalRef NativeToJavaRtpTransceiverDirection(
+ JNIEnv* jni,
+ RtpTransceiverDirection rtp_transceiver_direction) {
+ return Java_RtpTransceiverDirection_fromNativeIndex(
+ jni, static_cast(rtp_transceiver_direction));
+}
+
+} // namespace
+
+RtpTransceiverInit JavaToNativeRtpTransceiverInit(
+ JNIEnv* jni,
+ const JavaRef& j_init) {
+ RtpTransceiverInit init;
+
+ // Convert the direction.
+ init.direction = static_cast(
+ Java_RtpTransceiverInit_getDirectionNativeIndex(jni, j_init));
+
+ // Convert the stream ids.
+ ScopedJavaLocalRef j_stream_ids =
+ Java_RtpTransceiverInit_getStreamIds(jni, j_init);
+ init.stream_ids = JavaListToNativeVector(
+ jni, j_stream_ids, &JavaToNativeString);
+ return init;
+}
+
+ScopedJavaLocalRef NativeToJavaRtpTransceiver(
+ JNIEnv* env,
+ rtc::scoped_refptr transceiver) {
+ if (!transceiver) {
+ return nullptr;
+ }
+ // Transceiver will now have shared ownership by the Java object.
+ return Java_RtpTransceiver_Constructor(
+ env, jlongFromPointer(transceiver.release()));
+}
+
+ScopedJavaLocalRef JNI_RtpTransceiver_GetMediaType(
+ JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ return NativeToJavaMediaType(
+ jni, reinterpret_cast(j_rtp_transceiver_pointer)
+ ->media_type());
+}
+
+ScopedJavaLocalRef JNI_RtpTransceiver_GetMid(
+ JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ rtc::Optional mid =
+ reinterpret_cast(j_rtp_transceiver_pointer)
+ ->mid();
+ return NativeToJavaString(jni, mid);
+}
+
+ScopedJavaLocalRef JNI_RtpTransceiver_GetSender(
+ JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ return NativeToJavaRtpSender(
+ jni, reinterpret_cast(j_rtp_transceiver_pointer)
+ ->sender());
+}
+
+ScopedJavaLocalRef JNI_RtpTransceiver_GetReceiver(
+ JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ return NativeToJavaRtpReceiver(
+ jni, reinterpret_cast(j_rtp_transceiver_pointer)
+ ->receiver());
+}
+
+jboolean JNI_RtpTransceiver_Stopped(JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ return reinterpret_cast(j_rtp_transceiver_pointer)
+ ->stopped();
+}
+
+ScopedJavaLocalRef JNI_RtpTransceiver_Direction(
+ JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ return NativeToJavaRtpTransceiverDirection(
+ jni, reinterpret_cast(j_rtp_transceiver_pointer)
+ ->direction());
+}
+
+ScopedJavaLocalRef JNI_RtpTransceiver_CurrentDirection(
+ JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ rtc::Optional direction =
+ reinterpret_cast(j_rtp_transceiver_pointer)
+ ->current_direction();
+ return direction ? NativeToJavaRtpTransceiverDirection(jni, *direction)
+ : nullptr;
+}
+
+void JNI_RtpTransceiver_Stop(JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer) {
+ reinterpret_cast(j_rtp_transceiver_pointer)->Stop();
+}
+
+void JNI_RtpTransceiver_SetDirection(
+ JNIEnv* jni,
+ const base::android::JavaParamRef&,
+ jlong j_rtp_transceiver_pointer,
+ const base::android::JavaParamRef& j_rtp_transceiver_direction) {
+ if (IsNull(jni, j_rtp_transceiver_direction)) {
+ return;
+ }
+ RtpTransceiverDirection direction = static_cast(
+ Java_RtpTransceiverDirection_getNativeIndex(jni,
+ j_rtp_transceiver_direction));
+ reinterpret_cast(j_rtp_transceiver_pointer)
+ ->SetDirection(direction);
+}
+
+} // namespace jni
+} // namespace webrtc
diff --git a/sdk/android/src/jni/pc/rtptransceiver.h b/sdk/android/src/jni/pc/rtptransceiver.h
new file mode 100644
index 0000000000..9017c2fcc2
--- /dev/null
+++ b/sdk/android/src/jni/pc/rtptransceiver.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef SDK_ANDROID_SRC_JNI_PC_RTPTRANSCEIVER_H_
+#define SDK_ANDROID_SRC_JNI_PC_RTPTRANSCEIVER_H_
+
+#include
+
+#include "api/rtptransceiverinterface.h"
+#include "sdk/android/native_api/jni/scoped_java_ref.h"
+
+namespace webrtc {
+namespace jni {
+
+RtpTransceiverInit JavaToNativeRtpTransceiverInit(
+ JNIEnv* jni,
+ const JavaRef& j_init);
+
+ScopedJavaLocalRef NativeToJavaRtpTransceiver(
+ JNIEnv* env,
+ rtc::scoped_refptr transceiver);
+
+} // namespace jni
+} // namespace webrtc
+
+#endif // SDK_ANDROID_SRC_JNI_PC_RTPTRANSCEIVER_H_