1 /*
2  *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 package org.webrtc;
12 
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import org.webrtc.MediaStreamTrack;
17 import org.webrtc.RtpParameters;
18 
19 /**
20  * Java wrapper for a C++ RtpTransceiverInterface.
21  *
22  * <p>The RTCRtpTransceiver maps to the RTCRtpTransceiver defined by the WebRTC
23  * specification. A transceiver represents a combination of an RTCRtpSender
24  * and an RTCRtpReceiver that share a common mid. As defined in JSEP, an
25  * RTCRtpTransceiver is said to be associated with a media description if its
26  * mid property is non-nil; otherwise, it is said to be disassociated.
27  * JSEP: https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24
28  *
29  * <p>Note that RTCRtpTransceivers are only supported when using
30  * RTCPeerConnection with Unified Plan SDP.
31  *
32  * <p>WebRTC specification for RTCRtpTransceiver, the JavaScript analog:
33  * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver
34  */
35 public class RtpTransceiver {
36   /** Java version of webrtc::RtpTransceiverDirection - the ordering must be kept in sync. */
37   public enum RtpTransceiverDirection {
38     SEND_RECV(0),
39     SEND_ONLY(1),
40     RECV_ONLY(2),
41     INACTIVE(3);
42 
43     private final int nativeIndex;
44 
RtpTransceiverDirection(int nativeIndex)45     private RtpTransceiverDirection(int nativeIndex) {
46       this.nativeIndex = nativeIndex;
47     }
48 
49     @CalledByNative("RtpTransceiverDirection")
getNativeIndex()50     int getNativeIndex() {
51       return nativeIndex;
52     }
53 
54     @CalledByNative("RtpTransceiverDirection")
fromNativeIndex(int nativeIndex)55     static RtpTransceiverDirection fromNativeIndex(int nativeIndex) {
56       for (RtpTransceiverDirection type : RtpTransceiverDirection.values()) {
57         if (type.getNativeIndex() == nativeIndex) {
58           return type;
59         }
60       }
61       throw new IllegalArgumentException(
62           "Uknown native RtpTransceiverDirection type" + nativeIndex);
63     }
64   }
65 
66   /**
67    * Tracks webrtc::RtpTransceiverInit. https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
68    * A structure for initializing an RtpTransceiver in a call to addTransceiver.
69    * Note: This does not contain a list of encoding parameters, because they are currently
70    * not being used natively.
71    */
72   public static final class RtpTransceiverInit {
73     private final RtpTransceiverDirection direction;
74     private final List<String> streamIds;
75     private final List<RtpParameters.Encoding> sendEncodings;
76 
RtpTransceiverInit()77     public RtpTransceiverInit() {
78       this(RtpTransceiverDirection.SEND_RECV);
79     }
80 
RtpTransceiverInit(RtpTransceiverDirection direction)81     public RtpTransceiverInit(RtpTransceiverDirection direction) {
82       this(direction, Collections.emptyList(), Collections.emptyList());
83     }
84 
RtpTransceiverInit(RtpTransceiverDirection direction, List<String> streamIds)85     public RtpTransceiverInit(RtpTransceiverDirection direction, List<String> streamIds) {
86       this(direction, streamIds, Collections.emptyList());
87     }
88 
RtpTransceiverInit(RtpTransceiverDirection direction, List<String> streamIds, List<RtpParameters.Encoding> sendEncodings)89     public RtpTransceiverInit(RtpTransceiverDirection direction, List<String> streamIds,
90         List<RtpParameters.Encoding> sendEncodings) {
91       this.direction = direction;
92       this.streamIds = new ArrayList<String>(streamIds);
93       this.sendEncodings = new ArrayList<RtpParameters.Encoding>(sendEncodings);
94     }
95 
96     @CalledByNative("RtpTransceiverInit")
getDirectionNativeIndex()97     int getDirectionNativeIndex() {
98       return direction.getNativeIndex();
99     }
100 
101     @CalledByNative("RtpTransceiverInit")
getStreamIds()102     List<String> getStreamIds() {
103       return new ArrayList<String>(this.streamIds);
104     }
105 
106     @CalledByNative("RtpTransceiverInit")
getSendEncodings()107     List<RtpParameters.Encoding> getSendEncodings() {
108       return new ArrayList<RtpParameters.Encoding>(this.sendEncodings);
109     }
110   }
111 
112   private long nativeRtpTransceiver;
113   private RtpSender cachedSender;
114   private RtpReceiver cachedReceiver;
115 
116   @CalledByNative
RtpTransceiver(long nativeRtpTransceiver)117   protected RtpTransceiver(long nativeRtpTransceiver) {
118     this.nativeRtpTransceiver = nativeRtpTransceiver;
119     cachedSender = nativeGetSender(nativeRtpTransceiver);
120     cachedReceiver = nativeGetReceiver(nativeRtpTransceiver);
121   }
122 
123   /**
124    * Media type of the transceiver. Any sender(s)/receiver(s) will have this
125    * type as well.
126    */
getMediaType()127   public MediaStreamTrack.MediaType getMediaType() {
128     checkRtpTransceiverExists();
129     return nativeGetMediaType(nativeRtpTransceiver);
130   }
131 
132   /**
133    * The mid attribute is the mid negotiated and present in the local and
134    * remote descriptions. Before negotiation is complete, the mid value may be
135    * null. After rollbacks, the value may change from a non-null value to null.
136    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-mid
137    */
getMid()138   public String getMid() {
139     checkRtpTransceiverExists();
140     return nativeGetMid(nativeRtpTransceiver);
141   }
142 
143   /**
144    * The sender attribute exposes the RtpSender corresponding to the RTP media
145    * that may be sent with the transceiver's mid. The sender is always present,
146    * regardless of the direction of media.
147    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-sender
148    */
getSender()149   public RtpSender getSender() {
150     return cachedSender;
151   }
152 
153   /**
154    * The receiver attribute exposes the RtpReceiver corresponding to the RTP
155    * media that may be received with the transceiver's mid. The receiver is
156    * always present, regardless of the direction of media.
157    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-receiver
158    */
getReceiver()159   public RtpReceiver getReceiver() {
160     return cachedReceiver;
161   }
162 
163   /**
164    * The stopped attribute indicates that the sender of this transceiver will no
165    * longer send, and that the receiver will no longer receive. It is true if
166    * either stop has been called or if setting the local or remote description
167    * has caused the RtpTransceiver to be stopped.
168    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stopped
169    */
isStopped()170   public boolean isStopped() {
171     checkRtpTransceiverExists();
172     return nativeStopped(nativeRtpTransceiver);
173   }
174 
175   /**
176    * The direction attribute indicates the preferred direction of this
177    * transceiver, which will be used in calls to CreateOffer and CreateAnswer.
178    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
179    */
getDirection()180   public RtpTransceiverDirection getDirection() {
181     checkRtpTransceiverExists();
182     return nativeDirection(nativeRtpTransceiver);
183   }
184 
185   /**
186    * The current_direction attribute indicates the current direction negotiated
187    * for this transceiver. If this transceiver has never been represented in an
188    * offer/answer exchange, or if the transceiver is stopped, the value is null.
189    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-currentdirection
190    */
getCurrentDirection()191   public RtpTransceiverDirection getCurrentDirection() {
192     checkRtpTransceiverExists();
193     return nativeCurrentDirection(nativeRtpTransceiver);
194   }
195 
196   /**
197    * Sets the preferred direction of this transceiver. An update of
198    * directionality does not take effect immediately. Instead, future calls to
199    * CreateOffer and CreateAnswer mark the corresponding media descriptions as
200    * sendrecv, sendonly, recvonly, or inactive.
201    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
202    */
setDirection(RtpTransceiverDirection rtpTransceiverDirection)203   public boolean setDirection(RtpTransceiverDirection rtpTransceiverDirection) {
204     checkRtpTransceiverExists();
205     return nativeSetDirection(nativeRtpTransceiver, rtpTransceiverDirection);
206   }
207 
208   /**
209    * The Stop method will for the time being call the StopInternal method.
210    * After a migration procedure, stop() will be equivalent to StopStandard.
211    */
stop()212   public void stop() {
213     checkRtpTransceiverExists();
214     nativeStopInternal(nativeRtpTransceiver);
215   }
216 
217   /**
218    * The StopInternal method stops the RtpTransceiver, like Stop, but goes
219    * immediately to Stopped state.
220    */
stopInternal()221   public void stopInternal() {
222     checkRtpTransceiverExists();
223     nativeStopInternal(nativeRtpTransceiver);
224   }
225 
226   /**
227    * The StopStandard method irreversibly stops the RtpTransceiver. The sender
228    * of this transceiver will no longer send, the receiver will no longer
229    * receive.
230    *
231    * <p>The transceiver will enter Stopping state and signal NegotiationNeeded.
232    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop
233    */
stopStandard()234   public void stopStandard() {
235     checkRtpTransceiverExists();
236     nativeStopStandard(nativeRtpTransceiver);
237   }
238 
239   @CalledByNative
dispose()240   public void dispose() {
241     checkRtpTransceiverExists();
242     cachedSender.dispose();
243     cachedReceiver.dispose();
244     JniCommon.nativeReleaseRef(nativeRtpTransceiver);
245     nativeRtpTransceiver = 0;
246   }
247 
checkRtpTransceiverExists()248   private void checkRtpTransceiverExists() {
249     if (nativeRtpTransceiver == 0) {
250       throw new IllegalStateException("RtpTransceiver has been disposed.");
251     }
252   }
253 
nativeGetMediaType(long rtpTransceiver)254   private static native MediaStreamTrack.MediaType nativeGetMediaType(long rtpTransceiver);
nativeGetMid(long rtpTransceiver)255   private static native String nativeGetMid(long rtpTransceiver);
nativeGetSender(long rtpTransceiver)256   private static native RtpSender nativeGetSender(long rtpTransceiver);
nativeGetReceiver(long rtpTransceiver)257   private static native RtpReceiver nativeGetReceiver(long rtpTransceiver);
nativeStopped(long rtpTransceiver)258   private static native boolean nativeStopped(long rtpTransceiver);
nativeDirection(long rtpTransceiver)259   private static native RtpTransceiverDirection nativeDirection(long rtpTransceiver);
nativeCurrentDirection(long rtpTransceiver)260   private static native RtpTransceiverDirection nativeCurrentDirection(long rtpTransceiver);
nativeStopInternal(long rtpTransceiver)261   private static native void nativeStopInternal(long rtpTransceiver);
nativeStopStandard(long rtpTransceiver)262   private static native void nativeStopStandard(long rtpTransceiver);
nativeSetDirection( long rtpTransceiver, RtpTransceiverDirection rtpTransceiverDirection)263   private static native boolean nativeSetDirection(
264       long rtpTransceiver, RtpTransceiverDirection rtpTransceiverDirection);
265 }
266