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 void setDirection(RtpTransceiverDirection rtpTransceiverDirection) {
204     checkRtpTransceiverExists();
205     nativeSetDirection(nativeRtpTransceiver, rtpTransceiverDirection);
206   }
207 
208   /**
209    * The Stop method irreversibly stops the RtpTransceiver. The sender of this
210    * transceiver will no longer send, the receiver will no longer receive.
211    * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop
212    */
stop()213   public void stop() {
214     checkRtpTransceiverExists();
215     nativeStop(nativeRtpTransceiver);
216   }
217 
218   @CalledByNative
dispose()219   public void dispose() {
220     checkRtpTransceiverExists();
221     cachedSender.dispose();
222     cachedReceiver.dispose();
223     JniCommon.nativeReleaseRef(nativeRtpTransceiver);
224     nativeRtpTransceiver = 0;
225   }
226 
checkRtpTransceiverExists()227   private void checkRtpTransceiverExists() {
228     if (nativeRtpTransceiver == 0) {
229       throw new IllegalStateException("RtpTransceiver has been disposed.");
230     }
231   }
232 
nativeGetMediaType(long rtpTransceiver)233   private static native MediaStreamTrack.MediaType nativeGetMediaType(long rtpTransceiver);
nativeGetMid(long rtpTransceiver)234   private static native String nativeGetMid(long rtpTransceiver);
nativeGetSender(long rtpTransceiver)235   private static native RtpSender nativeGetSender(long rtpTransceiver);
nativeGetReceiver(long rtpTransceiver)236   private static native RtpReceiver nativeGetReceiver(long rtpTransceiver);
nativeStopped(long rtpTransceiver)237   private static native boolean nativeStopped(long rtpTransceiver);
nativeDirection(long rtpTransceiver)238   private static native RtpTransceiverDirection nativeDirection(long rtpTransceiver);
nativeCurrentDirection(long rtpTransceiver)239   private static native RtpTransceiverDirection nativeCurrentDirection(long rtpTransceiver);
nativeStop(long rtpTransceiver)240   private static native void nativeStop(long rtpTransceiver);
nativeSetDirection( long rtpTransceiver, RtpTransceiverDirection rtpTransceiverDirection)241   private static native void nativeSetDirection(
242       long rtpTransceiver, RtpTransceiverDirection rtpTransceiverDirection);
243 }
244