1 /* 2 * libjingle 3 * Copyright 2013, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 29 package org.webrtc; 30 31 import java.util.LinkedList; 32 import java.util.List; 33 34 /** 35 * Java-land version of the PeerConnection APIs; wraps the C++ API 36 * http://www.webrtc.org/reference/native-apis, which in turn is inspired by the 37 * JS APIs: http://dev.w3.org/2011/webrtc/editor/webrtc.html and 38 * http://www.w3.org/TR/mediacapture-streams/ 39 */ 40 public class PeerConnection { 41 static { 42 System.loadLibrary("jingle_peerconnection_so"); 43 } 44 45 /** Tracks PeerConnectionInterface::IceGatheringState */ 46 public enum IceGatheringState { NEW, GATHERING, COMPLETE }; 47 48 49 /** Tracks PeerConnectionInterface::IceConnectionState */ 50 public enum IceConnectionState { 51 NEW, CHECKING, CONNECTED, COMPLETED, FAILED, DISCONNECTED, CLOSED 52 }; 53 54 /** Tracks PeerConnectionInterface::SignalingState */ 55 public enum SignalingState { 56 STABLE, HAVE_LOCAL_OFFER, HAVE_LOCAL_PRANSWER, HAVE_REMOTE_OFFER, 57 HAVE_REMOTE_PRANSWER, CLOSED 58 }; 59 60 /** Java version of PeerConnectionObserver. */ 61 public static interface Observer { 62 /** Triggered when the SignalingState changes. */ 63 public void onSignalingChange(SignalingState newState); 64 65 /** Triggered when the IceConnectionState changes. */ 66 public void onIceConnectionChange(IceConnectionState newState); 67 68 /** Triggered when the IceGatheringState changes. */ 69 public void onIceGatheringChange(IceGatheringState newState); 70 71 /** Triggered when a new ICE candidate has been found. */ 72 public void onIceCandidate(IceCandidate candidate); 73 74 /** Triggered on any error. */ 75 public void onError(); 76 77 /** Triggered when media is received on a new stream from remote peer. */ 78 public void onAddStream(MediaStream stream); 79 80 /** Triggered when a remote peer close a stream. */ 81 public void onRemoveStream(MediaStream stream); 82 83 /** Triggered when a remote peer opens a DataChannel. */ 84 public void onDataChannel(DataChannel dataChannel); 85 86 /** Triggered when renegotiation is necessary. */ 87 public void onRenegotiationNeeded(); 88 } 89 90 /** Java version of PeerConnectionInterface.IceServer. */ 91 public static class IceServer { 92 public final String uri; 93 public final String username; 94 public final String password; 95 96 /** Convenience constructor for STUN servers. */ 97 public IceServer(String uri) { 98 this(uri, "", ""); 99 } 100 101 public IceServer(String uri, String username, String password) { 102 this.uri = uri; 103 this.username = username; 104 this.password = password; 105 } 106 107 public String toString() { 108 return uri + "[" + username + ":" + password + "]"; 109 } 110 } 111 112 private final List<MediaStream> localStreams; 113 private final long nativePeerConnection; 114 private final long nativeObserver; 115 116 PeerConnection(long nativePeerConnection, long nativeObserver) { 117 this.nativePeerConnection = nativePeerConnection; 118 this.nativeObserver = nativeObserver; 119 localStreams = new LinkedList<MediaStream>(); 120 } 121 122 // JsepInterface. 123 public native SessionDescription getLocalDescription(); 124 125 public native SessionDescription getRemoteDescription(); 126 127 public native DataChannel createDataChannel( 128 String label, DataChannel.Init init); 129 130 public native void createOffer( 131 SdpObserver observer, MediaConstraints constraints); 132 133 public native void createAnswer( 134 SdpObserver observer, MediaConstraints constraints); 135 136 public native void setLocalDescription( 137 SdpObserver observer, SessionDescription sdp); 138 139 public native void setRemoteDescription( 140 SdpObserver observer, SessionDescription sdp); 141 142 public native boolean updateIce( 143 List<IceServer> iceServers, MediaConstraints constraints); 144 145 public boolean addIceCandidate(IceCandidate candidate) { 146 return nativeAddIceCandidate( 147 candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp); 148 } 149 150 public boolean addStream( 151 MediaStream stream, MediaConstraints constraints) { 152 boolean ret = nativeAddLocalStream(stream.nativeStream, constraints); 153 if (!ret) { 154 return false; 155 } 156 localStreams.add(stream); 157 return true; 158 } 159 160 public void removeStream(MediaStream stream) { 161 nativeRemoveLocalStream(stream.nativeStream); 162 localStreams.remove(stream); 163 } 164 165 public boolean getStats(StatsObserver observer, MediaStreamTrack track) { 166 return nativeGetStats(observer, (track == null) ? 0 : track.nativeTrack); 167 } 168 169 // TODO(fischman): add support for DTMF-related methods once that API 170 // stabilizes. 171 public native SignalingState signalingState(); 172 173 public native IceConnectionState iceConnectionState(); 174 175 public native IceGatheringState iceGatheringState(); 176 177 public native void close(); 178 179 public void dispose() { 180 close(); 181 for (MediaStream stream : localStreams) { 182 nativeRemoveLocalStream(stream.nativeStream); 183 stream.dispose(); 184 } 185 localStreams.clear(); 186 freePeerConnection(nativePeerConnection); 187 freeObserver(nativeObserver); 188 } 189 190 private static native void freePeerConnection(long nativePeerConnection); 191 192 private static native void freeObserver(long nativeObserver); 193 194 private native boolean nativeAddIceCandidate( 195 String sdpMid, int sdpMLineIndex, String iceCandidateSdp); 196 197 private native boolean nativeAddLocalStream( 198 long nativeStream, MediaConstraints constraints); 199 200 private native void nativeRemoveLocalStream(long nativeStream); 201 202 private native boolean nativeGetStats( 203 StatsObserver observer, long nativeTrack); 204 } 205