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.List;
32 
33 /**
34  * Java wrapper for a C++ PeerConnectionFactoryInterface.  Main entry point to
35  * the PeerConnection API for clients.
36  */
37 public class PeerConnectionFactory {
38   static {
39     System.loadLibrary("jingle_peerconnection_so");
40   }
41 
42   private static final String TAG = "PeerConnectionFactory";
43   private final long nativeFactory;
44   private static Thread workerThread;
45   private static Thread signalingThread;
46 
47   public static class Options {
48     // Keep in sync with webrtc/base/network.h!
49     static final int ADAPTER_TYPE_UNKNOWN = 0;
50     static final int ADAPTER_TYPE_ETHERNET = 1 << 0;
51     static final int ADAPTER_TYPE_WIFI = 1 << 1;
52     static final int ADAPTER_TYPE_CELLULAR = 1 << 2;
53     static final int ADAPTER_TYPE_VPN = 1 << 3;
54     static final int ADAPTER_TYPE_LOOPBACK = 1 << 4;
55 
56     public int networkIgnoreMask;
57     public boolean disableEncryption;
58     public boolean disableNetworkMonitor;
59   }
60 
61   // |context| is an android.content.Context object, but we keep it untyped here
62   // to allow building on non-Android platforms.
63   // Callers may specify either |initializeAudio| or |initializeVideo| as false
64   // to skip initializing the respective engine (and avoid the need for the
65   // respective permissions).
66   // |renderEGLContext| can be provided to suport HW video decoding to
67   // texture and will be used to create a shared EGL context on video
68   // decoding thread.
initializeAndroidGlobals( Object context, boolean initializeAudio, boolean initializeVideo, boolean videoHwAcceleration)69   public static native boolean initializeAndroidGlobals(
70       Object context, boolean initializeAudio, boolean initializeVideo,
71       boolean videoHwAcceleration);
72 
73   // Field trial initialization. Must be called before PeerConnectionFactory
74   // is created.
initializeFieldTrials(String fieldTrialsInitString)75   public static native void initializeFieldTrials(String fieldTrialsInitString);
76   // Internal tracing initialization. Must be called before PeerConnectionFactory is created to
77   // prevent racing with tracing code.
initializeInternalTracer()78   public static native void initializeInternalTracer();
79   // Internal tracing shutdown, called to prevent resource leaks. Must be called after
80   // PeerConnectionFactory is gone to prevent races with code performing tracing.
shutdownInternalTracer()81   public static native void shutdownInternalTracer();
82   // Start/stop internal capturing of internal tracing.
startInternalTracingCapture(String tracing_filename)83   public static native boolean startInternalTracingCapture(String tracing_filename);
stopInternalTracingCapture()84   public static native void stopInternalTracingCapture();
85 
PeerConnectionFactory()86   public PeerConnectionFactory() {
87     nativeFactory = nativeCreatePeerConnectionFactory();
88     if (nativeFactory == 0) {
89       throw new RuntimeException("Failed to initialize PeerConnectionFactory!");
90     }
91   }
92 
createPeerConnection( PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, PeerConnection.Observer observer)93   public PeerConnection createPeerConnection(
94       PeerConnection.RTCConfiguration rtcConfig,
95       MediaConstraints constraints,
96       PeerConnection.Observer observer) {
97     long nativeObserver = nativeCreateObserver(observer);
98     if (nativeObserver == 0) {
99       return null;
100     }
101     long nativePeerConnection = nativeCreatePeerConnection(
102         nativeFactory, rtcConfig, constraints, nativeObserver);
103     if (nativePeerConnection == 0) {
104       return null;
105     }
106     return new PeerConnection(nativePeerConnection, nativeObserver);
107   }
108 
createPeerConnection( List<PeerConnection.IceServer> iceServers, MediaConstraints constraints, PeerConnection.Observer observer)109   public PeerConnection createPeerConnection(
110       List<PeerConnection.IceServer> iceServers,
111       MediaConstraints constraints,
112       PeerConnection.Observer observer) {
113     PeerConnection.RTCConfiguration rtcConfig =
114         new PeerConnection.RTCConfiguration(iceServers);
115     return createPeerConnection(rtcConfig, constraints, observer);
116   }
117 
createLocalMediaStream(String label)118   public MediaStream createLocalMediaStream(String label) {
119     return new MediaStream(
120         nativeCreateLocalMediaStream(nativeFactory, label));
121   }
122 
createVideoSource( VideoCapturer capturer, MediaConstraints constraints)123   public VideoSource createVideoSource(
124       VideoCapturer capturer, MediaConstraints constraints) {
125     return new VideoSource(nativeCreateVideoSource(
126         nativeFactory, capturer.takeNativeVideoCapturer(), constraints));
127   }
128 
createVideoTrack(String id, VideoSource source)129   public VideoTrack createVideoTrack(String id, VideoSource source) {
130     return new VideoTrack(nativeCreateVideoTrack(
131         nativeFactory, id, source.nativeSource));
132   }
133 
createAudioSource(MediaConstraints constraints)134   public AudioSource createAudioSource(MediaConstraints constraints) {
135     return new AudioSource(nativeCreateAudioSource(nativeFactory, constraints));
136   }
137 
createAudioTrack(String id, AudioSource source)138   public AudioTrack createAudioTrack(String id, AudioSource source) {
139     return new AudioTrack(nativeCreateAudioTrack(
140         nativeFactory, id, source.nativeSource));
141   }
142 
143   // Starts recording an AEC dump. Ownership of the file is transfered to the
144   // native code. If an AEC dump is already in progress, it will be stopped and
145   // a new one will start using the provided file.
startAecDump(int file_descriptor)146   public boolean startAecDump(int file_descriptor) {
147     return nativeStartAecDump(nativeFactory, file_descriptor);
148   }
149 
150   // Stops recording an AEC dump. If no AEC dump is currently being recorded,
151   // this call will have no effect.
stopAecDump()152   public void stopAecDump() {
153     nativeStopAecDump(nativeFactory);
154   }
155 
156   // Starts recording an RTC event log. Ownership of the file is transfered to
157   // the native code. If an RTC event log is already being recorded, it will be
158   // stopped and a new one will start using the provided file.
startRtcEventLog(int file_descriptor)159   public boolean startRtcEventLog(int file_descriptor) {
160     return nativeStartRtcEventLog(nativeFactory, file_descriptor);
161   }
162 
163   // Stops recording an RTC event log. If no RTC event log is currently being
164   // recorded, this call will have no effect.
StopRtcEventLog()165   public void StopRtcEventLog() {
166     nativeStopRtcEventLog(nativeFactory);
167   }
168 
setOptions(Options options)169   public void setOptions(Options options) {
170     nativeSetOptions(nativeFactory, options);
171   }
172 
173   @Deprecated
setVideoHwAccelerationOptions(Object renderEGLContext)174   public void setVideoHwAccelerationOptions(Object renderEGLContext) {
175     nativeSetVideoHwAccelerationOptions(nativeFactory, renderEGLContext, renderEGLContext);
176   }
177 
178   /** Set the EGL context used by HW Video encoding and decoding.
179    *
180    *
181    * @param localEGLContext   An instance of javax.microedition.khronos.egl.EGLContext.
182    *                          Must be the same as used by VideoCapturerAndroid and any local
183    *                          video renderer.
184    * @param remoteEGLContext  An instance of javax.microedition.khronos.egl.EGLContext.
185    *                          Must be the same as used by any remote video renderer.
186    */
setVideoHwAccelerationOptions(Object localEGLContext, Object remoteEGLContext)187   public void setVideoHwAccelerationOptions(Object localEGLContext, Object remoteEGLContext) {
188     nativeSetVideoHwAccelerationOptions(nativeFactory, localEGLContext, remoteEGLContext);
189   }
190 
dispose()191   public void dispose() {
192     nativeFreeFactory(nativeFactory);
193     signalingThread = null;
194     workerThread = null;
195   }
196 
threadsCallbacks()197   public void threadsCallbacks() {
198     nativeThreadsCallbacks(nativeFactory);
199   }
200 
printStackTrace(Thread thread, String threadName)201   private static void printStackTrace(Thread thread, String threadName) {
202     if (thread != null) {
203       StackTraceElement[] stackTraces = thread.getStackTrace();
204       if (stackTraces.length > 0) {
205         Logging.d(TAG, threadName + " stacks trace:");
206         for (StackTraceElement stackTrace : stackTraces) {
207           Logging.d(TAG, stackTrace.toString());
208         }
209       }
210     }
211   }
212 
printStackTraces()213   public static void printStackTraces() {
214     printStackTrace(workerThread, "Worker thread");
215     printStackTrace(signalingThread, "Signaling thread");
216   }
217 
onWorkerThreadReady()218   private static void onWorkerThreadReady() {
219     workerThread = Thread.currentThread();
220     Logging.d(TAG, "onWorkerThreadReady");
221   }
222 
onSignalingThreadReady()223   private static void onSignalingThreadReady() {
224     signalingThread = Thread.currentThread();
225     Logging.d(TAG, "onSignalingThreadReady");
226   }
227 
nativeCreatePeerConnectionFactory()228   private static native long nativeCreatePeerConnectionFactory();
229 
nativeCreateObserver( PeerConnection.Observer observer)230   private static native long nativeCreateObserver(
231       PeerConnection.Observer observer);
232 
nativeCreatePeerConnection( long nativeFactory, PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver)233   private static native long nativeCreatePeerConnection(
234       long nativeFactory, PeerConnection.RTCConfiguration rtcConfig,
235       MediaConstraints constraints, long nativeObserver);
236 
nativeCreateLocalMediaStream( long nativeFactory, String label)237   private static native long nativeCreateLocalMediaStream(
238       long nativeFactory, String label);
239 
nativeCreateVideoSource( long nativeFactory, long nativeVideoCapturer, MediaConstraints constraints)240   private static native long nativeCreateVideoSource(
241       long nativeFactory, long nativeVideoCapturer,
242       MediaConstraints constraints);
243 
nativeCreateVideoTrack( long nativeFactory, String id, long nativeVideoSource)244   private static native long nativeCreateVideoTrack(
245       long nativeFactory, String id, long nativeVideoSource);
246 
nativeCreateAudioSource( long nativeFactory, MediaConstraints constraints)247   private static native long nativeCreateAudioSource(
248       long nativeFactory, MediaConstraints constraints);
249 
nativeCreateAudioTrack( long nativeFactory, String id, long nativeSource)250   private static native long nativeCreateAudioTrack(
251       long nativeFactory, String id, long nativeSource);
252 
nativeStartAecDump(long nativeFactory, int file_descriptor)253   private static native boolean nativeStartAecDump(long nativeFactory, int file_descriptor);
254 
nativeStopAecDump(long nativeFactory)255   private static native void nativeStopAecDump(long nativeFactory);
256 
nativeStartRtcEventLog(long nativeFactory, int file_descriptor)257   private static native boolean nativeStartRtcEventLog(long nativeFactory, int file_descriptor);
258 
nativeStopRtcEventLog(long nativeFactory)259   private static native void nativeStopRtcEventLog(long nativeFactory);
260 
nativeSetOptions(long nativeFactory, Options options)261   public native void nativeSetOptions(long nativeFactory, Options options);
262 
nativeSetVideoHwAccelerationOptions( long nativeFactory, Object localEGLContext, Object remoteEGLContext)263   private static native void nativeSetVideoHwAccelerationOptions(
264       long nativeFactory, Object localEGLContext, Object remoteEGLContext);
265 
nativeThreadsCallbacks(long nativeFactory)266   private static native void nativeThreadsCallbacks(long nativeFactory);
267 
nativeFreeFactory(long nativeFactory)268   private static native void nativeFreeFactory(long nativeFactory);
269 }
270