blob: 1329000aabe413085d031c7a155c9162de96d986 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2013 Google Inc.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004 *
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// Hints for future visitors:
29// This entire file is an implementation detail of the org.webrtc Java package,
30// the most interesting bits of which are org.webrtc.PeerConnection{,Factory}.
31// The layout of this file is roughly:
32// - various helper C++ functions & classes that wrap Java counterparts and
33// expose a C++ interface that can be passed to the C++ PeerConnection APIs
34// - implementations of methods declared "static" in the Java package (named
35// things like Java_org_webrtc_OMG_Can_This_Name_Be_Any_Longer, prescribed by
36// the JNI spec).
37//
38// Lifecycle notes: objects are owned where they will be called; in other words
39// FooObservers are owned by C++-land, and user-callable objects (e.g.
40// PeerConnection and VideoTrack) are owned by Java-land.
41// When this file allocates C++ RefCountInterfaces it AddRef()s an artificial
42// ref simulating the jlong held in Java-land, and then Release()s the ref in
43// the respective free call. Sometimes this AddRef is implicit in the
44// construction of a scoped_refptr<> which is then .release()d.
45// Any persistent (non-local) references from C++ to Java must be global or weak
46// (in which case they must be checked before use)!
47//
48// Exception notes: pretty much all JNI calls can throw Java exceptions, so each
49// call through a JNIEnv* pointer needs to be followed by an ExceptionCheck()
50// call. In this file this is done in CHECK_EXCEPTION, making for much easier
51// debugging in case of failure (the alternative is to wait for control to
52// return to the Java frame that called code in this file, at which point it's
53// impossible to tell which JNI call broke).
54
55#include <jni.h>
56#undef JNIEXPORT
57#define JNIEXPORT __attribute__((visibility("default")))
58
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000059#include <limits>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060
perkj@webrtc.org96e4db92015-02-13 12:46:51 +000061#include "talk/app/webrtc/java/jni/classreferenceholder.h"
62#include "talk/app/webrtc/java/jni/jni_helpers.h"
glaznev@webrtc.org18c92472015-02-18 18:42:55 +000063#include "talk/app/webrtc/java/jni/native_handle_impl.h"
glaznev97579a42015-09-01 11:31:27 -070064#include "talk/app/webrtc/dtlsidentitystore.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065#include "talk/app/webrtc/mediaconstraintsinterface.h"
66#include "talk/app/webrtc/peerconnectioninterface.h"
67#include "talk/app/webrtc/videosourceinterface.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068#include "talk/media/base/videocapturer.h"
69#include "talk/media/base/videorenderer.h"
70#include "talk/media/devices/videorendererfactory.h"
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +000071#include "talk/media/webrtc/webrtcvideodecoderfactory.h"
fischman@webrtc.org540acde2014-02-13 03:56:14 +000072#include "talk/media/webrtc/webrtcvideoencoderfactory.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000073#include "webrtc/base/bind.h"
andresp@webrtc.org4d19e052014-09-09 11:45:44 +000074#include "webrtc/base/checks.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000075#include "webrtc/base/logging.h"
76#include "webrtc/base/messagequeue.h"
77#include "webrtc/base/ssladapter.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000078#include "webrtc/base/stringutils.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000079#include "webrtc/system_wrappers/interface/field_trial_default.h"
henrike@webrtc.org9de257d2013-07-17 14:42:53 +000080#include "webrtc/system_wrappers/interface/trace.h"
henrike@webrtc.org9de257d2013-07-17 14:42:53 +000081#include "webrtc/voice_engine/include/voe_base.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082
glaznev@webrtc.org99678452014-09-15 17:52:42 +000083#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
perkj@webrtc.org83bc7212015-02-11 11:26:56 +000084#include "talk/app/webrtc/androidvideocapturer.h"
glaznev@webrtc.org18c92472015-02-18 18:42:55 +000085#include "talk/app/webrtc/java/jni/androidmediadecoder_jni.h"
86#include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h"
perkj@webrtc.org96e4db92015-02-13 12:46:51 +000087#include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h"
andresp@webrtc.org85ef7702014-09-17 11:44:51 +000088#include "webrtc/modules/video_render/video_render_internal.h"
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +000089#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
90using webrtc::LogcatTraceContext;
91#endif
92
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000093using rtc::Bind;
94using rtc::Thread;
95using rtc::ThreadManager;
96using rtc::scoped_ptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097using webrtc::AudioSourceInterface;
98using webrtc::AudioTrackInterface;
99using webrtc::AudioTrackVector;
100using webrtc::CreateSessionDescriptionObserver;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000101using webrtc::DataBuffer;
102using webrtc::DataChannelInit;
103using webrtc::DataChannelInterface;
104using webrtc::DataChannelObserver;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105using webrtc::IceCandidateInterface;
106using webrtc::MediaConstraintsInterface;
107using webrtc::MediaSourceInterface;
108using webrtc::MediaStreamInterface;
109using webrtc::MediaStreamTrackInterface;
110using webrtc::PeerConnectionFactoryInterface;
111using webrtc::PeerConnectionInterface;
112using webrtc::PeerConnectionObserver;
113using webrtc::SessionDescriptionInterface;
114using webrtc::SetSessionDescriptionObserver;
115using webrtc::StatsObserver;
116using webrtc::StatsReport;
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000117using webrtc::StatsReports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118using webrtc::VideoRendererInterface;
119using webrtc::VideoSourceInterface;
120using webrtc::VideoTrackInterface;
121using webrtc::VideoTrackVector;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000122using webrtc::kVideoCodecVP8;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000123
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000124namespace webrtc_jni {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +0000126// Field trials initialization string
127static char *field_trials_init_string = NULL;
128
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000129#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
130// Set in PeerConnectionFactory_initializeAndroidGlobals().
131static bool factory_static_initialized = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000132static bool vp8_hw_acceleration_enabled = true;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000133#endif
134
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000135extern "C" jint JNIEXPORT JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000136 jint ret = InitGlobalJniVariables(jvm);
137 if (ret < 0)
138 return -1;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000139
140 CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000141 LoadGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000142
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000143 return ret;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000144}
145
146extern "C" void JNIEXPORT JNICALL JNI_OnUnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000147 FreeGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000148 CHECK(rtc::CleanupSSL()) << "Failed to CleanupSSL()";
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000149}
150
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000151// Return the (singleton) Java Enum object corresponding to |index|;
152// |state_class_fragment| is something like "MediaSource$State".
glaznev@webrtc.orgb28474c2015-02-23 17:44:27 +0000153static jobject JavaEnumFromIndex(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000154 JNIEnv* jni, const std::string& state_class_fragment, int index) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000155 const std::string state_class = "org/webrtc/" + state_class_fragment;
156 return JavaEnumFromIndex(jni, FindClass(jni, state_class.c_str()),
157 state_class, index);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000158}
159
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000160static DataChannelInit JavaDataChannelInitToNative(
161 JNIEnv* jni, jobject j_init) {
162 DataChannelInit init;
163
164 jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init");
165 jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z");
166 jfieldID max_retransmit_time_id =
167 GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I");
168 jfieldID max_retransmits_id =
169 GetFieldID(jni, j_init_class, "maxRetransmits", "I");
170 jfieldID protocol_id =
171 GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;");
172 jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z");
173 jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I");
174
175 init.ordered = GetBooleanField(jni, j_init, ordered_id);
176 init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id);
177 init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id);
178 init.protocol = JavaToStdString(
179 jni, GetStringField(jni, j_init, protocol_id));
180 init.negotiated = GetBooleanField(jni, j_init, negotiated_id);
181 init.id = GetIntField(jni, j_init, id_id);
182
183 return init;
184}
185
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000186class ConstraintsWrapper;
187
188// Adapter between the C++ PeerConnectionObserver interface and the Java
189// PeerConnection.Observer interface. Wraps an instance of the Java interface
190// and dispatches C++ callbacks to Java.
191class PCOJava : public PeerConnectionObserver {
192 public:
193 PCOJava(JNIEnv* jni, jobject j_observer)
194 : j_observer_global_(jni, j_observer),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000195 j_observer_class_(jni, GetObjectClass(jni, *j_observer_global_)),
196 j_media_stream_class_(jni, FindClass(jni, "org/webrtc/MediaStream")),
197 j_media_stream_ctor_(GetMethodID(
198 jni, *j_media_stream_class_, "<init>", "(J)V")),
199 j_audio_track_class_(jni, FindClass(jni, "org/webrtc/AudioTrack")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000200 j_audio_track_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000201 jni, *j_audio_track_class_, "<init>", "(J)V")),
202 j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")),
203 j_video_track_ctor_(GetMethodID(
204 jni, *j_video_track_class_, "<init>", "(J)V")),
205 j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")),
206 j_data_channel_ctor_(GetMethodID(
207 jni, *j_data_channel_class_, "<init>", "(J)V")) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208 }
209
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200210 virtual ~PCOJava() {
211 ScopedLocalRefFrame local_ref_frame(jni());
212 while (!remote_streams_.empty())
213 DisposeRemoteStream(remote_streams_.begin());
214 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000216 void OnIceCandidate(const IceCandidateInterface* candidate) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000217 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000218 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000219 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000220 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
221 jmethodID ctor = GetMethodID(jni(), candidate_class,
222 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000223 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
224 jstring j_sdp = JavaStringFromStdString(jni(), sdp);
225 jobject j_candidate = jni()->NewObject(
226 candidate_class, ctor, j_mid, candidate->sdp_mline_index(), j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000227 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000228 jmethodID m = GetMethodID(jni(), *j_observer_class_,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229 "onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000230 jni()->CallVoidMethod(*j_observer_global_, m, j_candidate);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000231 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000232 }
233
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000234 void OnSignalingChange(
235 PeerConnectionInterface::SignalingState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000236 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000237 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000238 jni(), *j_observer_class_, "onSignalingChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000239 "(Lorg/webrtc/PeerConnection$SignalingState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000240 jobject new_state_enum =
241 JavaEnumFromIndex(jni(), "PeerConnection$SignalingState", new_state);
242 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000243 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000244 }
245
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000246 void OnIceConnectionChange(
247 PeerConnectionInterface::IceConnectionState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000248 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000249 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000250 jni(), *j_observer_class_, "onIceConnectionChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251 "(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000252 jobject new_state_enum = JavaEnumFromIndex(
253 jni(), "PeerConnection$IceConnectionState", new_state);
254 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000255 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256 }
257
Peter Thatcher54360512015-07-08 11:08:35 -0700258 void OnIceConnectionReceivingChange(bool receiving) override {
259 ScopedLocalRefFrame local_ref_frame(jni());
260 jmethodID m = GetMethodID(
261 jni(), *j_observer_class_, "onIceConnectionReceivingChange", "(Z)V");
262 jni()->CallVoidMethod(*j_observer_global_, m, receiving);
263 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
264 }
265
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000266 void OnIceGatheringChange(
267 PeerConnectionInterface::IceGatheringState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000268 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000269 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000270 jni(), *j_observer_class_, "onIceGatheringChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000272 jobject new_state_enum = JavaEnumFromIndex(
273 jni(), "PeerConnection$IceGatheringState", new_state);
274 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000275 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000276 }
277
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000278 void OnAddStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000279 ScopedLocalRefFrame local_ref_frame(jni());
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200280 // Java MediaStream holds one reference. Corresponding Release() is in
281 // MediaStream_free, triggered by MediaStream.dispose().
282 stream->AddRef();
283 jobject j_stream =
284 jni()->NewObject(*j_media_stream_class_, j_media_stream_ctor_,
285 reinterpret_cast<jlong>(stream));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000286 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200288 for (const auto& track : stream->GetAudioTracks()) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000289 jstring id = JavaStringFromStdString(jni(), track->id());
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200290 // Java AudioTrack holds one reference. Corresponding Release() is in
291 // MediaStreamTrack_free, triggered by AudioTrack.dispose().
292 track->AddRef();
293 jobject j_track =
294 jni()->NewObject(*j_audio_track_class_, j_audio_track_ctor_,
295 reinterpret_cast<jlong>(track.get()), id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000296 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000297 jfieldID audio_tracks_id = GetFieldID(jni(),
298 *j_media_stream_class_,
299 "audioTracks",
300 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000301 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000302 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000303 GetObjectClass(jni(), audio_tracks),
304 "add",
305 "(Ljava/lang/Object;)Z");
306 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000307 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
308 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000309 }
310
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200311 for (const auto& track : stream->GetVideoTracks()) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000312 jstring id = JavaStringFromStdString(jni(), track->id());
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200313 // Java VideoTrack holds one reference. Corresponding Release() is in
314 // MediaStreamTrack_free, triggered by VideoTrack.dispose().
315 track->AddRef();
316 jobject j_track =
317 jni()->NewObject(*j_video_track_class_, j_video_track_ctor_,
318 reinterpret_cast<jlong>(track.get()), id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000319 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000320 jfieldID video_tracks_id = GetFieldID(jni(),
321 *j_media_stream_class_,
322 "videoTracks",
323 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000324 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000325 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000326 GetObjectClass(jni(), video_tracks),
327 "add",
328 "(Ljava/lang/Object;)Z");
329 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000330 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
331 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000332 }
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200333 remote_streams_[stream] = NewGlobalRef(jni(), j_stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000334
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000335 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
336 "(Lorg/webrtc/MediaStream;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000337 jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000338 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000339 }
340
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000341 void OnRemoveStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000342 ScopedLocalRefFrame local_ref_frame(jni());
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200343 NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream);
344 CHECK(it != remote_streams_.end()) << "unexpected stream: " << std::hex
345 << stream;
346 jobject j_stream = it->second;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000347 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
348 "(Lorg/webrtc/MediaStream;)V");
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200349 jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000350 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200351 DisposeRemoteStream(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000352 }
353
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000354 void OnDataChannel(DataChannelInterface* channel) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000355 ScopedLocalRefFrame local_ref_frame(jni());
356 jobject j_channel = jni()->NewObject(
357 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000358 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000359
360 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
361 "(Lorg/webrtc/DataChannel;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000362 jni()->CallVoidMethod(*j_observer_global_, m, j_channel);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000363
364 // Channel is now owned by Java object, and will be freed from
365 // DataChannel.dispose(). Important that this be done _after_ the
366 // CallVoidMethod above as Java code might call back into native code and be
367 // surprised to see a refcount of 2.
368 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000369 CHECK(bumped_count == 2) << "Unexpected refcount OnDataChannel";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000370
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000371 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000372 }
373
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000374 void OnRenegotiationNeeded() override {
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000375 ScopedLocalRefFrame local_ref_frame(jni());
376 jmethodID m =
377 GetMethodID(jni(), *j_observer_class_, "onRenegotiationNeeded", "()V");
378 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000379 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000380 }
381
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000382 void SetConstraints(ConstraintsWrapper* constraints) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000383 CHECK(!constraints_.get()) << "constraints already set!";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384 constraints_.reset(constraints);
385 }
386
387 const ConstraintsWrapper* constraints() { return constraints_.get(); }
388
389 private:
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200390 typedef std::map<MediaStreamInterface*, jobject> NativeToJavaStreamsMap;
391
392 void DisposeRemoteStream(const NativeToJavaStreamsMap::iterator& it) {
393 jobject j_stream = it->second;
394 remote_streams_.erase(it);
395 jni()->CallVoidMethod(
396 j_stream, GetMethodID(jni(), *j_media_stream_class_, "dispose", "()V"));
397 CHECK_EXCEPTION(jni()) << "error during MediaStream.dispose()";
398 DeleteGlobalRef(jni(), j_stream);
399 }
400
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000401 JNIEnv* jni() {
402 return AttachCurrentThreadIfNeeded();
403 }
404
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000405 const ScopedGlobalRef<jobject> j_observer_global_;
406 const ScopedGlobalRef<jclass> j_observer_class_;
407 const ScopedGlobalRef<jclass> j_media_stream_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000408 const jmethodID j_media_stream_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000409 const ScopedGlobalRef<jclass> j_audio_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000410 const jmethodID j_audio_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000411 const ScopedGlobalRef<jclass> j_video_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 const jmethodID j_video_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000413 const ScopedGlobalRef<jclass> j_data_channel_class_;
414 const jmethodID j_data_channel_ctor_;
Magnus Jedvert1c3dd382015-08-27 13:39:58 +0200415 // C++ -> Java remote streams. The stored jobects are global refs and must be
416 // manually deleted upon removal. Use DisposeRemoteStream().
417 NativeToJavaStreamsMap remote_streams_;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000418 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000419};
420
421// Wrapper for a Java MediaConstraints object. Copies all needed data so when
422// the constructor returns the Java object is no longer needed.
423class ConstraintsWrapper : public MediaConstraintsInterface {
424 public:
425 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) {
426 PopulateConstraintsFromJavaPairList(
427 jni, j_constraints, "mandatory", &mandatory_);
428 PopulateConstraintsFromJavaPairList(
429 jni, j_constraints, "optional", &optional_);
430 }
431
432 virtual ~ConstraintsWrapper() {}
433
434 // MediaConstraintsInterface.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000435 const Constraints& GetMandatory() const override { return mandatory_; }
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000436
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000437 const Constraints& GetOptional() const override { return optional_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438
439 private:
440 // Helper for translating a List<Pair<String, String>> to a Constraints.
441 static void PopulateConstraintsFromJavaPairList(
442 JNIEnv* jni, jobject j_constraints,
443 const char* field_name, Constraints* field) {
444 jfieldID j_id = GetFieldID(jni,
445 GetObjectClass(jni, j_constraints), field_name, "Ljava/util/List;");
446 jobject j_list = GetObjectField(jni, j_constraints, j_id);
447 jmethodID j_iterator_id = GetMethodID(jni,
448 GetObjectClass(jni, j_list), "iterator", "()Ljava/util/Iterator;");
449 jobject j_iterator = jni->CallObjectMethod(j_list, j_iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000450 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000451 jmethodID j_has_next = GetMethodID(jni,
452 GetObjectClass(jni, j_iterator), "hasNext", "()Z");
453 jmethodID j_next = GetMethodID(jni,
454 GetObjectClass(jni, j_iterator), "next", "()Ljava/lang/Object;");
455 while (jni->CallBooleanMethod(j_iterator, j_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000456 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000457 jobject entry = jni->CallObjectMethod(j_iterator, j_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000458 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000459 jmethodID get_key = GetMethodID(jni,
460 GetObjectClass(jni, entry), "getKey", "()Ljava/lang/String;");
461 jstring j_key = reinterpret_cast<jstring>(
462 jni->CallObjectMethod(entry, get_key));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000463 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000464 jmethodID get_value = GetMethodID(jni,
465 GetObjectClass(jni, entry), "getValue", "()Ljava/lang/String;");
466 jstring j_value = reinterpret_cast<jstring>(
467 jni->CallObjectMethod(entry, get_value));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000468 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000469 field->push_back(Constraint(JavaToStdString(jni, j_key),
470 JavaToStdString(jni, j_value)));
471 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000472 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000473 }
474
475 Constraints mandatory_;
476 Constraints optional_;
477};
478
479static jobject JavaSdpFromNativeSdp(
480 JNIEnv* jni, const SessionDescriptionInterface* desc) {
481 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000482 CHECK(desc->ToString(&sdp)) << "got so far: " << sdp;
fischman@webrtc.org41776152014-01-09 00:31:17 +0000483 jstring j_description = JavaStringFromStdString(jni, sdp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484
485 jclass j_type_class = FindClass(
486 jni, "org/webrtc/SessionDescription$Type");
487 jmethodID j_type_from_canonical = GetStaticMethodID(
488 jni, j_type_class, "fromCanonicalForm",
489 "(Ljava/lang/String;)Lorg/webrtc/SessionDescription$Type;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000490 jstring j_type_string = JavaStringFromStdString(jni, desc->type());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 jobject j_type = jni->CallStaticObjectMethod(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000492 j_type_class, j_type_from_canonical, j_type_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000493 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000494
495 jclass j_sdp_class = FindClass(jni, "org/webrtc/SessionDescription");
496 jmethodID j_sdp_ctor = GetMethodID(
497 jni, j_sdp_class, "<init>",
498 "(Lorg/webrtc/SessionDescription$Type;Ljava/lang/String;)V");
499 jobject j_sdp = jni->NewObject(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000500 j_sdp_class, j_sdp_ctor, j_type, j_description);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000501 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000502 return j_sdp;
503}
504
505template <class T> // T is one of {Create,Set}SessionDescriptionObserver.
506class SdpObserverWrapper : public T {
507 public:
508 SdpObserverWrapper(JNIEnv* jni, jobject j_observer,
509 ConstraintsWrapper* constraints)
510 : constraints_(constraints),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000511 j_observer_global_(jni, j_observer),
512 j_observer_class_(jni, GetObjectClass(jni, j_observer)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000513 }
514
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000515 virtual ~SdpObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000516
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000517 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000518 virtual void OnSuccess() {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000519 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000520 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
521 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000522 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000523 }
524
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000525 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526 virtual void OnSuccess(SessionDescriptionInterface* desc) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000527 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000529 jni(), *j_observer_class_, "onCreateSuccess",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 "(Lorg/webrtc/SessionDescription;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000531 jobject j_sdp = JavaSdpFromNativeSdp(jni(), desc);
532 jni()->CallVoidMethod(*j_observer_global_, m, j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000533 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000534 }
535
536 protected:
537 // Common implementation for failure of Set & Create types, distinguished by
538 // |op| being "Set" or "Create".
539 void OnFailure(const std::string& op, const std::string& error) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000540 jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
541 "(Ljava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000542 jstring j_error_string = JavaStringFromStdString(jni(), error);
543 jni()->CallVoidMethod(*j_observer_global_, m, j_error_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000544 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000545 }
546
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 JNIEnv* jni() {
548 return AttachCurrentThreadIfNeeded();
549 }
550
fischman@webrtc.org41776152014-01-09 00:31:17 +0000551 private:
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000552 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000553 const ScopedGlobalRef<jobject> j_observer_global_;
554 const ScopedGlobalRef<jclass> j_observer_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000555};
556
557class CreateSdpObserverWrapper
558 : public SdpObserverWrapper<CreateSessionDescriptionObserver> {
559 public:
560 CreateSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
561 ConstraintsWrapper* constraints)
562 : SdpObserverWrapper(jni, j_observer, constraints) {}
563
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000564 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000565 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000566 SdpObserverWrapper::OnFailure(std::string("Create"), error);
567 }
568};
569
570class SetSdpObserverWrapper
571 : public SdpObserverWrapper<SetSessionDescriptionObserver> {
572 public:
573 SetSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
574 ConstraintsWrapper* constraints)
575 : SdpObserverWrapper(jni, j_observer, constraints) {}
576
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000577 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000578 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 SdpObserverWrapper::OnFailure(std::string("Set"), error);
580 }
581};
582
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000583// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
584// and dispatching the callback from C++ back to Java.
585class DataChannelObserverWrapper : public DataChannelObserver {
586 public:
587 DataChannelObserverWrapper(JNIEnv* jni, jobject j_observer)
588 : j_observer_global_(jni, j_observer),
589 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
pbos@webrtc.orgb648b9d2014-08-26 11:08:06 +0000590 j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")),
bemasc0edd50c2015-07-01 13:34:33 -0700591 j_on_buffered_amount_change_mid_(GetMethodID(
592 jni, *j_observer_class_, "onBufferedAmountChange", "(J)V")),
593 j_on_state_change_mid_(
594 GetMethodID(jni, *j_observer_class_, "onStateChange", "()V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000595 j_on_message_mid_(GetMethodID(jni, *j_observer_class_, "onMessage",
596 "(Lorg/webrtc/DataChannel$Buffer;)V")),
bemasc0edd50c2015-07-01 13:34:33 -0700597 j_buffer_ctor_(GetMethodID(jni, *j_buffer_class_, "<init>",
598 "(Ljava/nio/ByteBuffer;Z)V")) {}
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000599
600 virtual ~DataChannelObserverWrapper() {}
601
bemasc0edd50c2015-07-01 13:34:33 -0700602 void OnBufferedAmountChange(uint64 previous_amount) override {
603 ScopedLocalRefFrame local_ref_frame(jni());
604 jni()->CallVoidMethod(*j_observer_global_, j_on_buffered_amount_change_mid_,
605 previous_amount);
606 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
607 }
608
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000609 void OnStateChange() override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000610 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000611 jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000612 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000613 }
614
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000615 void OnMessage(const DataBuffer& buffer) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000616 ScopedLocalRefFrame local_ref_frame(jni());
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000617 jobject byte_buffer = jni()->NewDirectByteBuffer(
Karl Wiberg94784372015-04-20 14:03:07 +0200618 const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000619 jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_,
620 byte_buffer, buffer.binary);
621 jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000622 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000623 }
624
625 private:
626 JNIEnv* jni() {
627 return AttachCurrentThreadIfNeeded();
628 }
629
630 const ScopedGlobalRef<jobject> j_observer_global_;
631 const ScopedGlobalRef<jclass> j_observer_class_;
632 const ScopedGlobalRef<jclass> j_buffer_class_;
bemasc0edd50c2015-07-01 13:34:33 -0700633 const jmethodID j_on_buffered_amount_change_mid_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000634 const jmethodID j_on_state_change_mid_;
635 const jmethodID j_on_message_mid_;
636 const jmethodID j_buffer_ctor_;
637};
638
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000639// Adapter for a Java StatsObserver presenting a C++ StatsObserver and
640// dispatching the callback from C++ back to Java.
641class StatsObserverWrapper : public StatsObserver {
642 public:
643 StatsObserverWrapper(JNIEnv* jni, jobject j_observer)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000644 : j_observer_global_(jni, j_observer),
645 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
646 j_stats_report_class_(jni, FindClass(jni, "org/webrtc/StatsReport")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647 j_stats_report_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000648 jni, *j_stats_report_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649 "(Ljava/lang/String;Ljava/lang/String;D"
650 "[Lorg/webrtc/StatsReport$Value;)V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000651 j_value_class_(jni, FindClass(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652 jni, "org/webrtc/StatsReport$Value")),
653 j_value_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000654 jni, *j_value_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655 "(Ljava/lang/String;Ljava/lang/String;)V")) {
656 }
657
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000658 virtual ~StatsObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000659
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000660 void OnComplete(const StatsReports& reports) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000661 ScopedLocalRefFrame local_ref_frame(jni());
662 jobjectArray j_reports = ReportsToJava(jni(), reports);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000663 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
664 "([Lorg/webrtc/StatsReport;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000665 jni()->CallVoidMethod(*j_observer_global_, m, j_reports);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000666 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 }
668
669 private:
670 jobjectArray ReportsToJava(
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000671 JNIEnv* jni, const StatsReports& reports) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672 jobjectArray reports_array = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000673 reports.size(), *j_stats_report_class_, NULL);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000674 int i = 0;
675 for (const auto* report : reports) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000676 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000677 jstring j_id = JavaStringFromStdString(jni, report->id()->ToString());
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000678 jstring j_type = JavaStringFromStdString(jni, report->TypeToString());
679 jobjectArray j_values = ValuesToJava(jni, report->values());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000680 jobject j_report = jni->NewObject(*j_stats_report_class_,
681 j_stats_report_ctor_,
682 j_id,
683 j_type,
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000684 report->timestamp(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000685 j_values);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000686 jni->SetObjectArrayElement(reports_array, i++, j_report);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 }
688 return reports_array;
689 }
690
691 jobjectArray ValuesToJava(JNIEnv* jni, const StatsReport::Values& values) {
692 jobjectArray j_values = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000693 values.size(), *j_value_class_, NULL);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000694 int i = 0;
695 for (const auto& it : values) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000696 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgc57310b2014-12-12 17:41:28 +0000697 // Should we use the '.name' enum value here instead of converting the
698 // name to a string?
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000699 jstring j_name = JavaStringFromStdString(jni, it.second->display_name());
700 jstring j_value = JavaStringFromStdString(jni, it.second->ToString());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000701 jobject j_element_value =
702 jni->NewObject(*j_value_class_, j_value_ctor_, j_name, j_value);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000703 jni->SetObjectArrayElement(j_values, i++, j_element_value);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000704 }
705 return j_values;
706 }
707
708 JNIEnv* jni() {
709 return AttachCurrentThreadIfNeeded();
710 }
711
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000712 const ScopedGlobalRef<jobject> j_observer_global_;
713 const ScopedGlobalRef<jclass> j_observer_class_;
714 const ScopedGlobalRef<jclass> j_stats_report_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715 const jmethodID j_stats_report_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000716 const ScopedGlobalRef<jclass> j_value_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717 const jmethodID j_value_ctor_;
718};
719
720// Adapter presenting a cricket::VideoRenderer as a
721// webrtc::VideoRendererInterface.
722class VideoRendererWrapper : public VideoRendererInterface {
723 public:
724 static VideoRendererWrapper* Create(cricket::VideoRenderer* renderer) {
725 if (renderer)
726 return new VideoRendererWrapper(renderer);
727 return NULL;
728 }
729
730 virtual ~VideoRendererWrapper() {}
731
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000732 // This wraps VideoRenderer which still has SetSize.
733 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000734 ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000735 const cricket::VideoFrame* frame =
736 video_frame->GetCopyWithRotationApplied();
737 if (width_ != frame->GetWidth() || height_ != frame->GetHeight()) {
738 width_ = frame->GetWidth();
739 height_ = frame->GetHeight();
740 renderer_->SetSize(width_, height_, 0);
741 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742 renderer_->RenderFrame(frame);
743 }
744
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000745 // TODO(guoweis): Remove this once chrome code base is updated.
746 bool CanApplyRotation() override { return true; }
747
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748 private:
749 explicit VideoRendererWrapper(cricket::VideoRenderer* renderer)
Henrik Kjellander7c027b62015-04-22 13:21:30 +0200750 : width_(0), height_(0), renderer_(renderer) {}
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000751 int width_, height_;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000752 scoped_ptr<cricket::VideoRenderer> renderer_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000753};
754
755// Wrapper dispatching webrtc::VideoRendererInterface to a Java VideoRenderer
756// instance.
757class JavaVideoRendererWrapper : public VideoRendererInterface {
758 public:
759 JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000760 : j_callbacks_(jni, j_callbacks),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000761 j_render_frame_id_(GetMethodID(
762 jni, GetObjectClass(jni, j_callbacks), "renderFrame",
763 "(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
764 j_frame_class_(jni,
765 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000766 j_i420_frame_ctor_id_(GetMethodID(
Magnus Jedverta6cba3a2015-08-29 15:57:43 +0200767 jni, *j_frame_class_, "<init>", "(III[I[Ljava/nio/ByteBuffer;J)V")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000768 j_texture_frame_ctor_id_(GetMethodID(
769 jni, *j_frame_class_, "<init>",
Magnus Jedverta6cba3a2015-08-29 15:57:43 +0200770 "(IIILjava/lang/Object;IJ)V")),
Magnus Jedvert7ef9d912015-08-25 09:32:06 +0200771 j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000772 CHECK_EXCEPTION(jni);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773 }
774
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000775 virtual ~JavaVideoRendererWrapper() {}
776
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000777 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000778 ScopedLocalRefFrame local_ref_frame(jni());
Magnus Jedverta6cba3a2015-08-29 15:57:43 +0200779 // Make a shallow copy. |j_callbacks_| is responsible for releasing the
780 // copy by calling VideoRenderer.renderFrameDone().
781 video_frame = video_frame->Copy();
Magnus Jedvert7ef9d912015-08-25 09:32:06 +0200782 jobject j_frame = (video_frame->GetNativeHandle() != nullptr)
783 ? CricketToJavaTextureFrame(video_frame)
784 : CricketToJavaI420Frame(video_frame);
785 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
786 CHECK_EXCEPTION(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000787 }
788
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000789 // TODO(guoweis): Report that rotation is supported as RenderFrame calls
790 // GetCopyWithRotationApplied.
Magnus Jedvert7ef9d912015-08-25 09:32:06 +0200791 virtual bool CanApplyRotation() override { return true; }
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000792
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 private:
794 // Return a VideoRenderer.I420Frame referring to the data in |frame|.
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000795 jobject CricketToJavaI420Frame(const cricket::VideoFrame* frame) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000796 jintArray strides = jni()->NewIntArray(3);
797 jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000798 strides_array[0] = frame->GetYPitch();
799 strides_array[1] = frame->GetUPitch();
800 strides_array[2] = frame->GetVPitch();
fischman@webrtc.org41776152014-01-09 00:31:17 +0000801 jni()->ReleaseIntArrayElements(strides, strides_array, 0);
802 jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
803 jobject y_buffer = jni()->NewDirectByteBuffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000804 const_cast<uint8*>(frame->GetYPlane()),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000805 frame->GetYPitch() * frame->GetHeight());
806 jobject u_buffer = jni()->NewDirectByteBuffer(
807 const_cast<uint8*>(frame->GetUPlane()), frame->GetChromaSize());
808 jobject v_buffer = jni()->NewDirectByteBuffer(
809 const_cast<uint8*>(frame->GetVPlane()), frame->GetChromaSize());
810 jni()->SetObjectArrayElement(planes, 0, y_buffer);
811 jni()->SetObjectArrayElement(planes, 1, u_buffer);
812 jni()->SetObjectArrayElement(planes, 2, v_buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000813 return jni()->NewObject(
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000814 *j_frame_class_, j_i420_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000815 frame->GetWidth(), frame->GetHeight(),
816 static_cast<int>(frame->GetVideoRotation()),
Magnus Jedverta6cba3a2015-08-29 15:57:43 +0200817 strides, planes, frame);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000818 }
819
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000820 // Return a VideoRenderer.I420Frame referring texture object in |frame|.
821 jobject CricketToJavaTextureFrame(const cricket::VideoFrame* frame) {
822 NativeHandleImpl* handle =
823 reinterpret_cast<NativeHandleImpl*>(frame->GetNativeHandle());
824 jobject texture_object = reinterpret_cast<jobject>(handle->GetHandle());
825 int texture_id = handle->GetTextureId();
826 return jni()->NewObject(
827 *j_frame_class_, j_texture_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000828 frame->GetWidth(), frame->GetHeight(),
829 static_cast<int>(frame->GetVideoRotation()),
Magnus Jedverta6cba3a2015-08-29 15:57:43 +0200830 texture_object, texture_id, frame);
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000831 }
832
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000833 JNIEnv* jni() {
834 return AttachCurrentThreadIfNeeded();
835 }
836
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000837 ScopedGlobalRef<jobject> j_callbacks_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000838 jmethodID j_render_frame_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000839 ScopedGlobalRef<jclass> j_frame_class_;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000840 jmethodID j_i420_frame_ctor_id_;
841 jmethodID j_texture_frame_ctor_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000842 ScopedGlobalRef<jclass> j_byte_buffer_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000843};
844
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000845
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000846static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000847 jfieldID native_dc_id = GetFieldID(jni,
848 GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
849 jlong j_d = GetLongField(jni, j_dc, native_dc_id);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000850 return reinterpret_cast<DataChannelInterface*>(j_d);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000851}
852
853JOW(jlong, DataChannel_registerObserverNative)(
854 JNIEnv* jni, jobject j_dc, jobject j_observer) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000855 scoped_ptr<DataChannelObserverWrapper> observer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000856 new DataChannelObserverWrapper(jni, j_observer));
857 ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
fischman@webrtc.orgf41f06b2013-12-11 21:07:18 +0000858 return jlongFromPointer(observer.release());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000859}
860
861JOW(void, DataChannel_unregisterObserverNative)(
862 JNIEnv* jni, jobject j_dc, jlong native_observer) {
863 ExtractNativeDC(jni, j_dc)->UnregisterObserver();
864 delete reinterpret_cast<DataChannelObserverWrapper*>(native_observer);
865}
866
867JOW(jstring, DataChannel_label)(JNIEnv* jni, jobject j_dc) {
868 return JavaStringFromStdString(jni, ExtractNativeDC(jni, j_dc)->label());
869}
870
871JOW(jobject, DataChannel_state)(JNIEnv* jni, jobject j_dc) {
872 return JavaEnumFromIndex(
873 jni, "DataChannel$State", ExtractNativeDC(jni, j_dc)->state());
874}
875
876JOW(jlong, DataChannel_bufferedAmount)(JNIEnv* jni, jobject j_dc) {
877 uint64 buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000878 CHECK_LE(buffered_amount, std::numeric_limits<int64>::max())
879 << "buffered_amount overflowed jlong!";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000880 return static_cast<jlong>(buffered_amount);
881}
882
883JOW(void, DataChannel_close)(JNIEnv* jni, jobject j_dc) {
884 ExtractNativeDC(jni, j_dc)->Close();
885}
886
887JOW(jboolean, DataChannel_sendNative)(JNIEnv* jni, jobject j_dc,
888 jbyteArray data, jboolean binary) {
889 jbyte* bytes = jni->GetByteArrayElements(data, NULL);
890 bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000891 rtc::Buffer(bytes, jni->GetArrayLength(data)),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000892 binary));
893 jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
894 return ret;
895}
896
897JOW(void, DataChannel_dispose)(JNIEnv* jni, jobject j_dc) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000898 CHECK_RELEASE(ExtractNativeDC(jni, j_dc));
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000899}
900
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000901JOW(void, Logging_nativeEnableTracing)(
902 JNIEnv* jni, jclass, jstring j_path, jint nativeLevels,
903 jint nativeSeverity) {
904 std::string path = JavaToStdString(jni, j_path);
905 if (nativeLevels != webrtc::kTraceNone) {
andrew@webrtc.org90805182013-09-05 16:40:43 +0000906 webrtc::Trace::set_level_filter(nativeLevels);
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000907#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000908 if (path != "logcat:") {
909#endif
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000910 CHECK_EQ(0, webrtc::Trace::SetTraceFile(path.c_str(), false))
911 << "SetTraceFile failed";
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000912#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000913 } else {
914 // Intentionally leak this to avoid needing to reason about its lifecycle.
915 // It keeps no state and functions only as a dispatch point.
916 static LogcatTraceContext* g_trace_callback = new LogcatTraceContext();
917 }
918#endif
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000919 }
Tommi0eefb4d2015-05-23 09:54:07 +0200920 if (nativeSeverity >= rtc::LS_SENSITIVE && nativeSeverity <= rtc::LS_ERROR) {
921 rtc::LogMessage::LogToDebug(
922 static_cast<rtc::LoggingSeverity>(nativeSeverity));
923 }
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000924}
925
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000927 CHECK_RELEASE(reinterpret_cast<PeerConnectionInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000928}
929
930JOW(void, PeerConnection_freeObserver)(JNIEnv*, jclass, jlong j_p) {
931 PCOJava* p = reinterpret_cast<PCOJava*>(j_p);
932 delete p;
933}
934
935JOW(void, MediaSource_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000936 CHECK_RELEASE(reinterpret_cast<MediaSourceInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937}
938
939JOW(void, VideoCapturer_free)(JNIEnv*, jclass, jlong j_p) {
940 delete reinterpret_cast<cricket::VideoCapturer*>(j_p);
941}
942
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000943JOW(void, VideoRenderer_freeGuiVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 delete reinterpret_cast<VideoRendererWrapper*>(j_p);
945}
946
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000947JOW(void, VideoRenderer_freeWrappedVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
948 delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
949}
950
Magnus Jedverta6cba3a2015-08-29 15:57:43 +0200951JOW(void, VideoRenderer_releaseNativeFrame)(
952 JNIEnv* jni, jclass, jlong j_frame_ptr) {
953 delete reinterpret_cast<const cricket::VideoFrame*>(j_frame_ptr);
954}
955
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000956JOW(void, MediaStreamTrack_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000957 CHECK_RELEASE(reinterpret_cast<MediaStreamTrackInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000958}
959
960JOW(jboolean, MediaStream_nativeAddAudioTrack)(
961 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000962 return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000964}
965
966JOW(jboolean, MediaStream_nativeAddVideoTrack)(
967 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000968 return reinterpret_cast<MediaStreamInterface*>(pointer)
969 ->AddTrack(reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000970}
971
972JOW(jboolean, MediaStream_nativeRemoveAudioTrack)(
973 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000974 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000976}
977
978JOW(jboolean, MediaStream_nativeRemoveVideoTrack)(
979 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000980 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000981 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982}
983
984JOW(jstring, MediaStream_nativeLabel)(JNIEnv* jni, jclass, jlong j_p) {
985 return JavaStringFromStdString(
986 jni, reinterpret_cast<MediaStreamInterface*>(j_p)->label());
987}
988
989JOW(void, MediaStream_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000990 CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000991}
992
993JOW(jlong, PeerConnectionFactory_nativeCreateObserver)(
994 JNIEnv * jni, jclass, jobject j_observer) {
995 return (jlong)new PCOJava(jni, j_observer);
996}
997
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +0000998#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000999JOW(jboolean, PeerConnectionFactory_initializeAndroidGlobals)(
fischman@webrtc.orga150bc92014-05-14 22:00:50 +00001000 JNIEnv* jni, jclass, jobject context,
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001001 jboolean initialize_audio, jboolean initialize_video,
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +00001002 jboolean vp8_hw_acceleration, jobject render_egl_context) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001003 bool failure = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +00001004 vp8_hw_acceleration_enabled = vp8_hw_acceleration;
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001005 if (!factory_static_initialized) {
andresp@webrtc.org85ef7702014-09-17 11:44:51 +00001006 if (initialize_video) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001007 failure |= webrtc::SetRenderAndroidVM(GetJVM());
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001008 failure |= AndroidVideoCapturerJni::SetAndroidObjects(jni, context);
andresp@webrtc.org85ef7702014-09-17 11:44:51 +00001009 }
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001010 if (initialize_audio)
henrika@webrtc.org474d1eb2015-03-09 12:39:53 +00001011 failure |= webrtc::VoiceEngine::SetAndroidObjects(GetJVM(), context);
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001012 factory_static_initialized = true;
1013 }
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001014 if (initialize_video) {
glaznev@webrtc.org18c92472015-02-18 18:42:55 +00001015 failure |= MediaCodecVideoDecoderFactory::SetAndroidObjects(jni,
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001016 render_egl_context);
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001017 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001018 return !failure;
1019}
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +00001020#endif // defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001021
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001022JOW(void, PeerConnectionFactory_initializeFieldTrials)(
1023 JNIEnv* jni, jclass, jstring j_trials_init_string) {
1024 field_trials_init_string = NULL;
1025 if (j_trials_init_string != NULL) {
1026 const char* init_string =
1027 jni->GetStringUTFChars(j_trials_init_string, NULL);
1028 int init_string_length = jni->GetStringUTFLength(j_trials_init_string);
1029 field_trials_init_string = new char[init_string_length + 1];
1030 rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string);
1031 jni->ReleaseStringUTFChars(j_trials_init_string, init_string);
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001032 LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string;
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001033 }
1034 webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string);
1035}
1036
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001037// Helper struct for working around the fact that CreatePeerConnectionFactory()
1038// comes in two flavors: either entirely automagical (constructing its own
1039// threads and deleting them on teardown, but no external codec factory support)
1040// or entirely manual (requires caller to delete threads after factory
1041// teardown). This struct takes ownership of its ctor's arguments to present a
1042// single thing for Java to hold and eventually free.
1043class OwnedFactoryAndThreads {
1044 public:
1045 OwnedFactoryAndThreads(Thread* worker_thread,
1046 Thread* signaling_thread,
1047 PeerConnectionFactoryInterface* factory)
1048 : worker_thread_(worker_thread),
1049 signaling_thread_(signaling_thread),
1050 factory_(factory) {}
1051
1052 ~OwnedFactoryAndThreads() { CHECK_RELEASE(factory_); }
1053
1054 PeerConnectionFactoryInterface* factory() { return factory_; }
1055
1056 private:
1057 const scoped_ptr<Thread> worker_thread_;
1058 const scoped_ptr<Thread> signaling_thread_;
1059 PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
1060};
1061
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001062JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)(
1063 JNIEnv* jni, jclass) {
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001064 // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
1065 // ThreadManager only WrapCurrentThread()s the thread where it is first
1066 // created. Since the semantics around when auto-wrapping happens in
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001067 // webrtc/base/ are convoluted, we simply wrap here to avoid having to think
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001068 // about ramifications of auto-wrapping there.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001069 rtc::ThreadManager::Instance()->WrapCurrentThread();
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001070 webrtc::Trace::CreateTrace();
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001071 Thread* worker_thread = new Thread();
1072 worker_thread->SetName("worker_thread", NULL);
1073 Thread* signaling_thread = new Thread();
1074 signaling_thread->SetName("signaling_thread", NULL);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001075 CHECK(worker_thread->Start() && signaling_thread->Start())
1076 << "Failed to start threads";
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001077 scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001078 scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001079#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +00001080 if (vp8_hw_acceleration_enabled) {
1081 encoder_factory.reset(new MediaCodecVideoEncoderFactory());
1082 decoder_factory.reset(new MediaCodecVideoDecoderFactory());
1083 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001084#endif
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001085 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001086 webrtc::CreatePeerConnectionFactory(worker_thread,
1087 signaling_thread,
1088 NULL,
1089 encoder_factory.release(),
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001090 decoder_factory.release()));
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001091 OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
1092 worker_thread, signaling_thread, factory.release());
1093 return jlongFromPointer(owned_factory);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094}
1095
1096JOW(void, PeerConnectionFactory_freeFactory)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001097 delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001098 if (field_trials_init_string) {
1099 webrtc::field_trial::InitFieldTrialsFromString(NULL);
1100 delete field_trials_init_string;
1101 field_trials_init_string = NULL;
1102 }
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001103 webrtc::Trace::ReturnTrace();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001104}
1105
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001106static PeerConnectionFactoryInterface* factoryFromJava(jlong j_p) {
1107 return reinterpret_cast<OwnedFactoryAndThreads*>(j_p)->factory();
1108}
1109
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001110JOW(jlong, PeerConnectionFactory_nativeCreateLocalMediaStream)(
1111 JNIEnv* jni, jclass, jlong native_factory, jstring label) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001112 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001113 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001114 rtc::scoped_refptr<MediaStreamInterface> stream(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001115 factory->CreateLocalMediaStream(JavaToStdString(jni, label)));
1116 return (jlong)stream.release();
1117}
1118
1119JOW(jlong, PeerConnectionFactory_nativeCreateVideoSource)(
1120 JNIEnv* jni, jclass, jlong native_factory, jlong native_capturer,
1121 jobject j_constraints) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001122 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001123 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001124 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001125 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001126 rtc::scoped_refptr<VideoSourceInterface> source(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001127 factory->CreateVideoSource(
1128 reinterpret_cast<cricket::VideoCapturer*>(native_capturer),
1129 constraints.get()));
1130 return (jlong)source.release();
1131}
1132
1133JOW(jlong, PeerConnectionFactory_nativeCreateVideoTrack)(
1134 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1135 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001136 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001137 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001138 rtc::scoped_refptr<VideoTrackInterface> track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001139 factory->CreateVideoTrack(
1140 JavaToStdString(jni, id),
1141 reinterpret_cast<VideoSourceInterface*>(native_source)));
1142 return (jlong)track.release();
1143}
1144
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001145JOW(jlong, PeerConnectionFactory_nativeCreateAudioSource)(
1146 JNIEnv* jni, jclass, jlong native_factory, jobject j_constraints) {
1147 scoped_ptr<ConstraintsWrapper> constraints(
1148 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001149 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001150 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001151 rtc::scoped_refptr<AudioSourceInterface> source(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001152 factory->CreateAudioSource(constraints.get()));
1153 return (jlong)source.release();
1154}
1155
1156JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack)(
1157 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1158 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001159 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001160 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001161 rtc::scoped_refptr<AudioTrackInterface> track(factory->CreateAudioTrack(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001162 JavaToStdString(jni, id),
1163 reinterpret_cast<AudioSourceInterface*>(native_source)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 return (jlong)track.release();
1165}
1166
phoglund@webrtc.org006521d2015-02-12 09:23:59 +00001167JOW(void, PeerConnectionFactory_nativeSetOptions)(
1168 JNIEnv* jni, jclass, jlong native_factory, jobject options) {
1169 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
1170 factoryFromJava(native_factory));
1171 jclass options_class = jni->GetObjectClass(options);
1172 jfieldID network_ignore_mask_field =
1173 jni->GetFieldID(options_class, "networkIgnoreMask", "I");
1174 int network_ignore_mask =
1175 jni->GetIntField(options, network_ignore_mask_field);
Jiayang Liu61093862015-07-08 15:25:45 -07001176
1177 jfieldID disable_encryption_field =
1178 jni->GetFieldID(options_class, "disableEncryption", "Z");
1179 bool disable_encryption =
1180 jni->GetBooleanField(options, disable_encryption_field);
1181
phoglund@webrtc.org006521d2015-02-12 09:23:59 +00001182 PeerConnectionFactoryInterface::Options options_to_set;
1183
1184 // This doesn't necessarily match the c++ version of this struct; feel free
1185 // to add more parameters as necessary.
1186 options_to_set.network_ignore_mask = network_ignore_mask;
Jiayang Liu61093862015-07-08 15:25:45 -07001187 options_to_set.disable_encryption = disable_encryption;
phoglund@webrtc.org006521d2015-02-12 09:23:59 +00001188 factory->SetOptions(options_to_set);
1189}
1190
Jiayang Liucac1b382015-04-30 12:35:24 -07001191static std::string
1192GetJavaEnumName(JNIEnv* jni, const std::string& className, jobject j_enum) {
1193 jclass enumClass = FindClass(jni, className.c_str());
1194 jmethodID nameMethod =
1195 GetMethodID(jni, enumClass, "name", "()Ljava/lang/String;");
1196 jstring name =
1197 reinterpret_cast<jstring>(jni->CallObjectMethod(j_enum, nameMethod));
1198 CHECK_EXCEPTION(jni) << "error during CallObjectMethod for "
1199 << className << ".name";
1200 return JavaToStdString(jni, name);
1201}
1202
1203static PeerConnectionInterface::IceTransportsType
1204JavaIceTransportsTypeToNativeType(JNIEnv* jni, jobject j_ice_transports_type) {
1205 std::string enum_name = GetJavaEnumName(
1206 jni, "org/webrtc/PeerConnection$IceTransportsType",
1207 j_ice_transports_type);
1208
1209 if (enum_name == "ALL")
1210 return PeerConnectionInterface::kAll;
1211
1212 if (enum_name == "RELAY")
1213 return PeerConnectionInterface::kRelay;
1214
1215 if (enum_name == "NOHOST")
1216 return PeerConnectionInterface::kNoHost;
1217
1218 if (enum_name == "NONE")
1219 return PeerConnectionInterface::kNone;
1220
1221 CHECK(false) << "Unexpected IceTransportsType enum_name " << enum_name;
1222 return PeerConnectionInterface::kAll;
1223}
1224
1225static PeerConnectionInterface::BundlePolicy
1226JavaBundlePolicyToNativeType(JNIEnv* jni, jobject j_bundle_policy) {
1227 std::string enum_name = GetJavaEnumName(
1228 jni, "org/webrtc/PeerConnection$BundlePolicy",
1229 j_bundle_policy);
1230
1231 if (enum_name == "BALANCED")
1232 return PeerConnectionInterface::kBundlePolicyBalanced;
1233
1234 if (enum_name == "MAXBUNDLE")
1235 return PeerConnectionInterface::kBundlePolicyMaxBundle;
1236
1237 if (enum_name == "MAXCOMPAT")
1238 return PeerConnectionInterface::kBundlePolicyMaxCompat;
1239
1240 CHECK(false) << "Unexpected BundlePolicy enum_name " << enum_name;
1241 return PeerConnectionInterface::kBundlePolicyBalanced;
1242}
1243
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001244static PeerConnectionInterface::RtcpMuxPolicy
1245JavaRtcpMuxPolicyToNativeType(JNIEnv* jni, jobject j_rtcp_mux_policy) {
1246 std::string enum_name = GetJavaEnumName(
1247 jni, "org/webrtc/PeerConnection$RtcpMuxPolicy",
1248 j_rtcp_mux_policy);
1249
1250 if (enum_name == "NEGOTIATE")
1251 return PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
1252
1253 if (enum_name == "REQUIRE")
1254 return PeerConnectionInterface::kRtcpMuxPolicyRequire;
1255
1256 CHECK(false) << "Unexpected RtcpMuxPolicy enum_name " << enum_name;
1257 return PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
1258}
1259
Jiayang Liucac1b382015-04-30 12:35:24 -07001260static PeerConnectionInterface::TcpCandidatePolicy
1261JavaTcpCandidatePolicyToNativeType(
1262 JNIEnv* jni, jobject j_tcp_candidate_policy) {
1263 std::string enum_name = GetJavaEnumName(
1264 jni, "org/webrtc/PeerConnection$TcpCandidatePolicy",
1265 j_tcp_candidate_policy);
1266
1267 if (enum_name == "ENABLED")
1268 return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
1269
1270 if (enum_name == "DISABLED")
1271 return PeerConnectionInterface::kTcpCandidatePolicyDisabled;
1272
1273 CHECK(false) << "Unexpected TcpCandidatePolicy enum_name " << enum_name;
1274 return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
1275}
1276
glaznev97579a42015-09-01 11:31:27 -07001277static rtc::KeyType JavaKeyTypeToNativeType(JNIEnv* jni, jobject j_key_type) {
1278 std::string enum_name = GetJavaEnumName(
1279 jni, "org/webrtc/PeerConnection$KeyType", j_key_type);
1280
1281 if (enum_name == "RSA")
1282 return rtc::KT_RSA;
1283 if (enum_name == "ECDSA")
1284 return rtc::KT_ECDSA;
1285
1286 CHECK(false) << "Unexpected KeyType enum_name " << enum_name;
1287 return rtc::KT_ECDSA;
1288}
1289
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290static void JavaIceServersToJsepIceServers(
1291 JNIEnv* jni, jobject j_ice_servers,
1292 PeerConnectionInterface::IceServers* ice_servers) {
1293 jclass list_class = GetObjectClass(jni, j_ice_servers);
1294 jmethodID iterator_id = GetMethodID(
1295 jni, list_class, "iterator", "()Ljava/util/Iterator;");
1296 jobject iterator = jni->CallObjectMethod(j_ice_servers, iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001297 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001298 jmethodID iterator_has_next = GetMethodID(
1299 jni, GetObjectClass(jni, iterator), "hasNext", "()Z");
1300 jmethodID iterator_next = GetMethodID(
1301 jni, GetObjectClass(jni, iterator), "next", "()Ljava/lang/Object;");
1302 while (jni->CallBooleanMethod(iterator, iterator_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001303 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304 jobject j_ice_server = jni->CallObjectMethod(iterator, iterator_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001305 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 jclass j_ice_server_class = GetObjectClass(jni, j_ice_server);
1307 jfieldID j_ice_server_uri_id =
1308 GetFieldID(jni, j_ice_server_class, "uri", "Ljava/lang/String;");
1309 jfieldID j_ice_server_username_id =
1310 GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;");
1311 jfieldID j_ice_server_password_id =
1312 GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;");
1313 jstring uri = reinterpret_cast<jstring>(
1314 GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
1315 jstring username = reinterpret_cast<jstring>(
1316 GetObjectField(jni, j_ice_server, j_ice_server_username_id));
1317 jstring password = reinterpret_cast<jstring>(
1318 GetObjectField(jni, j_ice_server, j_ice_server_password_id));
1319 PeerConnectionInterface::IceServer server;
1320 server.uri = JavaToStdString(jni, uri);
1321 server.username = JavaToStdString(jni, username);
1322 server.password = JavaToStdString(jni, password);
1323 ice_servers->push_back(server);
1324 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001325 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326}
1327
1328JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
Jiayang Liucac1b382015-04-30 12:35:24 -07001329 JNIEnv *jni, jclass, jlong factory, jobject j_rtc_config,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001330 jobject j_constraints, jlong observer_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001331 rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001332 reinterpret_cast<PeerConnectionFactoryInterface*>(
1333 factoryFromJava(factory)));
Jiayang Liucac1b382015-04-30 12:35:24 -07001334
1335 jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config);
1336
1337 jfieldID j_ice_transports_type_id = GetFieldID(
1338 jni, j_rtc_config_class, "iceTransportsType",
1339 "Lorg/webrtc/PeerConnection$IceTransportsType;");
1340 jobject j_ice_transports_type = GetObjectField(
1341 jni, j_rtc_config, j_ice_transports_type_id);
1342
1343 jfieldID j_bundle_policy_id = GetFieldID(
1344 jni, j_rtc_config_class, "bundlePolicy",
1345 "Lorg/webrtc/PeerConnection$BundlePolicy;");
1346 jobject j_bundle_policy = GetObjectField(
1347 jni, j_rtc_config, j_bundle_policy_id);
1348
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001349 jfieldID j_rtcp_mux_policy_id = GetFieldID(
1350 jni, j_rtc_config_class, "rtcpMuxPolicy",
1351 "Lorg/webrtc/PeerConnection$RtcpMuxPolicy;");
1352 jobject j_rtcp_mux_policy = GetObjectField(
1353 jni, j_rtc_config, j_rtcp_mux_policy_id);
1354
Jiayang Liucac1b382015-04-30 12:35:24 -07001355 jfieldID j_tcp_candidate_policy_id = GetFieldID(
1356 jni, j_rtc_config_class, "tcpCandidatePolicy",
1357 "Lorg/webrtc/PeerConnection$TcpCandidatePolicy;");
1358 jobject j_tcp_candidate_policy = GetObjectField(
1359 jni, j_rtc_config, j_tcp_candidate_policy_id);
1360
1361 jfieldID j_ice_servers_id = GetFieldID(
glaznev97579a42015-09-01 11:31:27 -07001362 jni, j_rtc_config_class, "iceServers", "Ljava/util/List;");
Jiayang Liucac1b382015-04-30 12:35:24 -07001363 jobject j_ice_servers = GetObjectField(jni, j_rtc_config, j_ice_servers_id);
1364
honghaiz4edc39c2015-09-01 09:53:56 -07001365 jfieldID j_audio_jitter_buffer_max_packets_id =
1366 GetFieldID(jni, j_rtc_config_class, "audioJitterBufferMaxPackets", "I");
Henrik Lundin5263b3c2015-06-01 10:29:41 +02001367 jfieldID j_audio_jitter_buffer_fast_accelerate_id = GetFieldID(
1368 jni, j_rtc_config_class, "audioJitterBufferFastAccelerate", "Z");
Jiayang Liucac1b382015-04-30 12:35:24 -07001369
honghaiz4edc39c2015-09-01 09:53:56 -07001370 jfieldID j_ice_connection_receiving_timeout_id =
1371 GetFieldID(jni, j_rtc_config_class, "iceConnectionReceivingTimeout", "I");
1372
glaznev97579a42015-09-01 11:31:27 -07001373 jfieldID j_key_type_id = GetFieldID(jni, j_rtc_config_class, "keyType",
1374 "Lorg/webrtc/PeerConnection$KeyType;");
1375 jobject j_key_type = GetObjectField(jni, j_rtc_config, j_key_type_id);
1376
honghaiz4edc39c2015-09-01 09:53:56 -07001377 PeerConnectionInterface::RTCConfiguration rtc_config;
Jiayang Liucac1b382015-04-30 12:35:24 -07001378 rtc_config.type =
1379 JavaIceTransportsTypeToNativeType(jni, j_ice_transports_type);
1380 rtc_config.bundle_policy = JavaBundlePolicyToNativeType(jni, j_bundle_policy);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001381 rtc_config.rtcp_mux_policy =
1382 JavaRtcpMuxPolicyToNativeType(jni, j_rtcp_mux_policy);
Jiayang Liucac1b382015-04-30 12:35:24 -07001383 rtc_config.tcp_candidate_policy =
1384 JavaTcpCandidatePolicyToNativeType(jni, j_tcp_candidate_policy);
1385 JavaIceServersToJsepIceServers(jni, j_ice_servers, &rtc_config.servers);
Henrik Lundin64dad832015-05-11 12:44:23 +02001386 rtc_config.audio_jitter_buffer_max_packets =
1387 GetIntField(jni, j_rtc_config, j_audio_jitter_buffer_max_packets_id);
Henrik Lundin5263b3c2015-06-01 10:29:41 +02001388 rtc_config.audio_jitter_buffer_fast_accelerate = GetBooleanField(
1389 jni, j_rtc_config, j_audio_jitter_buffer_fast_accelerate_id);
honghaiz4edc39c2015-09-01 09:53:56 -07001390 rtc_config.ice_connection_receiving_timeout =
1391 GetIntField(jni, j_rtc_config, j_ice_connection_receiving_timeout_id);
Jiayang Liucac1b382015-04-30 12:35:24 -07001392
glaznev97579a42015-09-01 11:31:27 -07001393 // Create ECDSA certificate.
1394 if (JavaKeyTypeToNativeType(jni, j_key_type) == rtc::KT_ECDSA) {
1395 scoped_ptr<rtc::SSLIdentity> ssl_identity(
1396 rtc::SSLIdentity::Generate(webrtc::kIdentityName, rtc::KT_ECDSA));
1397 if (ssl_identity.get()) {
1398 rtc_config.certificates.push_back(
1399 rtc::RTCCertificate::Create(ssl_identity.Pass()));
1400 LOG(LS_INFO) << "ECDSA certificate created.";
1401 } else {
1402 // Failing to create certificate should not abort peer connection
1403 // creation. Instead default encryption (currently RSA) will be used.
1404 LOG(LS_WARNING) <<
1405 "Failed to generate SSLIdentity. Default encryption will be used.";
1406 }
1407 }
1408
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001409 PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
1410 observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001411 rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
Jiayang Liucac1b382015-04-30 12:35:24 -07001412 rtc_config, observer->constraints(), NULL, NULL, observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001413 return (jlong)pc.release();
1414}
1415
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001416static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001417 JNIEnv* jni, jobject j_pc) {
1418 jfieldID native_pc_id = GetFieldID(jni,
1419 GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
1420 jlong j_p = GetLongField(jni, j_pc, native_pc_id);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001421 return rtc::scoped_refptr<PeerConnectionInterface>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001422 reinterpret_cast<PeerConnectionInterface*>(j_p));
1423}
1424
1425JOW(jobject, PeerConnection_getLocalDescription)(JNIEnv* jni, jobject j_pc) {
1426 const SessionDescriptionInterface* sdp =
1427 ExtractNativePC(jni, j_pc)->local_description();
1428 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1429}
1430
1431JOW(jobject, PeerConnection_getRemoteDescription)(JNIEnv* jni, jobject j_pc) {
1432 const SessionDescriptionInterface* sdp =
1433 ExtractNativePC(jni, j_pc)->remote_description();
1434 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1435}
1436
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001437JOW(jobject, PeerConnection_createDataChannel)(
1438 JNIEnv* jni, jobject j_pc, jstring j_label, jobject j_init) {
1439 DataChannelInit init = JavaDataChannelInitToNative(jni, j_init);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001440 rtc::scoped_refptr<DataChannelInterface> channel(
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001441 ExtractNativePC(jni, j_pc)->CreateDataChannel(
1442 JavaToStdString(jni, j_label), &init));
fischman@webrtc.org87881672013-09-03 18:58:12 +00001443 // Mustn't pass channel.get() directly through NewObject to avoid reading its
1444 // vararg parameter as 64-bit and reading memory that doesn't belong to the
1445 // 32-bit parameter.
1446 jlong nativeChannelPtr = jlongFromPointer(channel.get());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001447 CHECK(nativeChannelPtr) << "Failed to create DataChannel";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001448 jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
1449 jmethodID j_data_channel_ctor = GetMethodID(
1450 jni, j_data_channel_class, "<init>", "(J)V");
1451 jobject j_channel = jni->NewObject(
fischman@webrtc.org87881672013-09-03 18:58:12 +00001452 j_data_channel_class, j_data_channel_ctor, nativeChannelPtr);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001453 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001454 // Channel is now owned by Java object, and will be freed from there.
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001455 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001456 CHECK(bumped_count == 2) << "Unexpected refcount";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001457 return j_channel;
1458}
1459
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001460JOW(void, PeerConnection_createOffer)(
1461 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1462 ConstraintsWrapper* constraints =
1463 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001464 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1465 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001466 jni, j_observer, constraints));
1467 ExtractNativePC(jni, j_pc)->CreateOffer(observer, constraints);
1468}
1469
1470JOW(void, PeerConnection_createAnswer)(
1471 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1472 ConstraintsWrapper* constraints =
1473 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001474 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1475 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001476 jni, j_observer, constraints));
1477 ExtractNativePC(jni, j_pc)->CreateAnswer(observer, constraints);
1478}
1479
1480// Helper to create a SessionDescriptionInterface from a SessionDescription.
1481static SessionDescriptionInterface* JavaSdpToNativeSdp(
1482 JNIEnv* jni, jobject j_sdp) {
1483 jfieldID j_type_id = GetFieldID(
1484 jni, GetObjectClass(jni, j_sdp), "type",
1485 "Lorg/webrtc/SessionDescription$Type;");
1486 jobject j_type = GetObjectField(jni, j_sdp, j_type_id);
1487 jmethodID j_canonical_form_id = GetMethodID(
1488 jni, GetObjectClass(jni, j_type), "canonicalForm",
1489 "()Ljava/lang/String;");
1490 jstring j_type_string = (jstring)jni->CallObjectMethod(
1491 j_type, j_canonical_form_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001492 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001493 std::string std_type = JavaToStdString(jni, j_type_string);
1494
1495 jfieldID j_description_id = GetFieldID(
1496 jni, GetObjectClass(jni, j_sdp), "description", "Ljava/lang/String;");
1497 jstring j_description = (jstring)GetObjectField(jni, j_sdp, j_description_id);
1498 std::string std_description = JavaToStdString(jni, j_description);
1499
1500 return webrtc::CreateSessionDescription(
1501 std_type, std_description, NULL);
1502}
1503
1504JOW(void, PeerConnection_setLocalDescription)(
1505 JNIEnv* jni, jobject j_pc,
1506 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001507 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1508 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1510 ExtractNativePC(jni, j_pc)->SetLocalDescription(
1511 observer, JavaSdpToNativeSdp(jni, j_sdp));
1512}
1513
1514JOW(void, PeerConnection_setRemoteDescription)(
1515 JNIEnv* jni, jobject j_pc,
1516 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001517 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1518 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001519 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1520 ExtractNativePC(jni, j_pc)->SetRemoteDescription(
1521 observer, JavaSdpToNativeSdp(jni, j_sdp));
1522}
1523
1524JOW(jboolean, PeerConnection_updateIce)(
1525 JNIEnv* jni, jobject j_pc, jobject j_ice_servers, jobject j_constraints) {
1526 PeerConnectionInterface::IceServers ice_servers;
1527 JavaIceServersToJsepIceServers(jni, j_ice_servers, &ice_servers);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001528 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001529 new ConstraintsWrapper(jni, j_constraints));
1530 return ExtractNativePC(jni, j_pc)->UpdateIce(ice_servers, constraints.get());
1531}
1532
1533JOW(jboolean, PeerConnection_nativeAddIceCandidate)(
1534 JNIEnv* jni, jobject j_pc, jstring j_sdp_mid,
1535 jint j_sdp_mline_index, jstring j_candidate_sdp) {
1536 std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
1537 std::string sdp = JavaToStdString(jni, j_candidate_sdp);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001538 scoped_ptr<IceCandidateInterface> candidate(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 webrtc::CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, NULL));
1540 return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
1541}
1542
1543JOW(jboolean, PeerConnection_nativeAddLocalStream)(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001544 JNIEnv* jni, jobject j_pc, jlong native_stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545 return ExtractNativePC(jni, j_pc)->AddStream(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001546 reinterpret_cast<MediaStreamInterface*>(native_stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547}
1548
1549JOW(void, PeerConnection_nativeRemoveLocalStream)(
1550 JNIEnv* jni, jobject j_pc, jlong native_stream) {
1551 ExtractNativePC(jni, j_pc)->RemoveStream(
1552 reinterpret_cast<MediaStreamInterface*>(native_stream));
1553}
1554
1555JOW(bool, PeerConnection_nativeGetStats)(
1556 JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001557 rtc::scoped_refptr<StatsObserverWrapper> observer(
1558 new rtc::RefCountedObject<StatsObserverWrapper>(jni, j_observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559 return ExtractNativePC(jni, j_pc)->GetStats(
jiayl@webrtc.orgdb41b4d2014-03-03 21:30:06 +00001560 observer,
1561 reinterpret_cast<MediaStreamTrackInterface*>(native_track),
1562 PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001563}
1564
1565JOW(jobject, PeerConnection_signalingState)(JNIEnv* jni, jobject j_pc) {
1566 PeerConnectionInterface::SignalingState state =
1567 ExtractNativePC(jni, j_pc)->signaling_state();
1568 return JavaEnumFromIndex(jni, "PeerConnection$SignalingState", state);
1569}
1570
1571JOW(jobject, PeerConnection_iceConnectionState)(JNIEnv* jni, jobject j_pc) {
1572 PeerConnectionInterface::IceConnectionState state =
1573 ExtractNativePC(jni, j_pc)->ice_connection_state();
1574 return JavaEnumFromIndex(jni, "PeerConnection$IceConnectionState", state);
1575}
1576
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001577JOW(jobject, PeerConnection_iceGatheringState)(JNIEnv* jni, jobject j_pc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001578 PeerConnectionInterface::IceGatheringState state =
1579 ExtractNativePC(jni, j_pc)->ice_gathering_state();
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001580 return JavaEnumFromIndex(jni, "PeerConnection$IceGatheringState", state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001581}
1582
1583JOW(void, PeerConnection_close)(JNIEnv* jni, jobject j_pc) {
1584 ExtractNativePC(jni, j_pc)->Close();
1585 return;
1586}
1587
1588JOW(jobject, MediaSource_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001589 rtc::scoped_refptr<MediaSourceInterface> p(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001590 reinterpret_cast<MediaSourceInterface*>(j_p));
1591 return JavaEnumFromIndex(jni, "MediaSource$State", p->state());
1592}
1593
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001594JOW(jobject, VideoCapturer_nativeCreateVideoCapturer)(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001595 JNIEnv* jni, jclass, jstring j_device_name) {
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001596// Since we can't create platform specific java implementations in Java, we
1597// defer the creation to C land.
1598#if defined(ANDROID)
1599 jclass j_video_capturer_class(
1600 FindClass(jni, "org/webrtc/VideoCapturerAndroid"));
1601 const jmethodID j_videocapturer_ctor(GetMethodID(
1602 jni, j_video_capturer_class, "<init>", "()V"));
1603 jobject j_video_capturer = jni->NewObject(j_video_capturer_class,
1604 j_videocapturer_ctor);
1605 CHECK_EXCEPTION(jni) << "error during NewObject";
1606
Per33544192015-04-02 12:30:51 +02001607 rtc::scoped_refptr<AndroidVideoCapturerJni> delegate =
perkj@webrtc.org112f1272015-02-25 09:20:07 +00001608 AndroidVideoCapturerJni::Create(jni, j_video_capturer, j_device_name);
1609 if (!delegate.get())
perkj@webrtc.org3db042e2015-02-19 08:43:38 +00001610 return nullptr;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001611 rtc::scoped_ptr<webrtc::AndroidVideoCapturer> capturer(
Per33544192015-04-02 12:30:51 +02001612 new webrtc::AndroidVideoCapturer(delegate));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001613
1614#else
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615 std::string device_name = JavaToStdString(jni, j_device_name);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001616 scoped_ptr<cricket::DeviceManagerInterface> device_manager(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 cricket::DeviceManagerFactory::Create());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001618 CHECK(device_manager->Init()) << "DeviceManager::Init() failed";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001619 cricket::Device device;
1620 if (!device_manager->GetVideoCaptureDevice(device_name, &device)) {
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001621 LOG(LS_ERROR) << "GetVideoCaptureDevice failed for " << device_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622 return 0;
1623 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001624 scoped_ptr<cricket::VideoCapturer> capturer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001625 device_manager->CreateVideoCapturer(device));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001626
1627 jclass j_video_capturer_class(
1628 FindClass(jni, "org/webrtc/VideoCapturer"));
1629 const jmethodID j_videocapturer_ctor(GetMethodID(
1630 jni, j_video_capturer_class, "<init>", "()V"));
1631 jobject j_video_capturer =
1632 jni->NewObject(j_video_capturer_class,
1633 j_videocapturer_ctor);
1634 CHECK_EXCEPTION(jni) << "error during creation of VideoCapturer";
1635
1636#endif
1637 const jmethodID j_videocapturer_set_native_capturer(GetMethodID(
1638 jni, j_video_capturer_class, "setNativeCapturer", "(J)V"));
1639 jni->CallVoidMethod(j_video_capturer,
1640 j_videocapturer_set_native_capturer,
1641 (jlong)capturer.release());
1642 CHECK_EXCEPTION(jni) << "error during setNativeCapturer";
1643 return j_video_capturer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001644}
1645
1646JOW(jlong, VideoRenderer_nativeCreateGuiVideoRenderer)(
1647 JNIEnv* jni, jclass, int x, int y) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001648 scoped_ptr<VideoRendererWrapper> renderer(VideoRendererWrapper::Create(
1649 cricket::VideoRendererFactory::CreateGuiVideoRenderer(x, y)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 return (jlong)renderer.release();
1651}
1652
1653JOW(jlong, VideoRenderer_nativeWrapVideoRenderer)(
1654 JNIEnv* jni, jclass, jobject j_callbacks) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001655 scoped_ptr<JavaVideoRendererWrapper> renderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001656 new JavaVideoRendererWrapper(jni, j_callbacks));
1657 return (jlong)renderer.release();
1658}
1659
glaznev@webrtc.orgf6932292015-02-05 17:29:59 +00001660JOW(void, VideoRenderer_nativeCopyPlane)(
1661 JNIEnv *jni, jclass, jobject j_src_buffer, jint width, jint height,
1662 jint src_stride, jobject j_dst_buffer, jint dst_stride) {
1663 size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer);
1664 size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
1665 CHECK(src_stride >= width) << "Wrong source stride " << src_stride;
1666 CHECK(dst_stride >= width) << "Wrong destination stride " << dst_stride;
1667 CHECK(src_size >= src_stride * height)
1668 << "Insufficient source buffer capacity " << src_size;
1669 CHECK(dst_size >= dst_stride * height)
1670 << "Isufficient destination buffer capacity " << dst_size;
1671 uint8_t *src =
1672 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer));
1673 uint8_t *dst =
1674 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
1675 if (src_stride == dst_stride) {
1676 memcpy(dst, src, src_stride * height);
1677 } else {
1678 for (int i = 0; i < height; i++) {
1679 memcpy(dst, src, width);
1680 src += src_stride;
1681 dst += dst_stride;
1682 }
1683 }
1684}
1685
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001686JOW(void, VideoSource_stop)(JNIEnv* jni, jclass, jlong j_p) {
1687 reinterpret_cast<VideoSourceInterface*>(j_p)->Stop();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001688}
1689
1690JOW(void, VideoSource_restart)(
1691 JNIEnv* jni, jclass, jlong j_p_source, jlong j_p_format) {
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001692 reinterpret_cast<VideoSourceInterface*>(j_p_source)->Restart();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001693}
1694
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695JOW(jstring, MediaStreamTrack_nativeId)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001696 return JavaStringFromStdString(
1697 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001698}
1699
1700JOW(jstring, MediaStreamTrack_nativeKind)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001701 return JavaStringFromStdString(
1702 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->kind());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001703}
1704
1705JOW(jboolean, MediaStreamTrack_nativeEnabled)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001706 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->enabled();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001707}
1708
1709JOW(jobject, MediaStreamTrack_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001710 return JavaEnumFromIndex(
1711 jni,
1712 "MediaStreamTrack$State",
1713 reinterpret_cast<MediaStreamTrackInterface*>(j_p)->state());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001714}
1715
1716JOW(jboolean, MediaStreamTrack_nativeSetState)(
1717 JNIEnv* jni, jclass, jlong j_p, jint j_new_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001718 MediaStreamTrackInterface::TrackState new_state =
1719 (MediaStreamTrackInterface::TrackState)j_new_state;
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001720 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1721 ->set_state(new_state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722}
1723
1724JOW(jboolean, MediaStreamTrack_nativeSetEnabled)(
1725 JNIEnv* jni, jclass, jlong j_p, jboolean enabled) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001726 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1727 ->set_enabled(enabled);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001728}
1729
1730JOW(void, VideoTrack_nativeAddRenderer)(
1731 JNIEnv* jni, jclass,
1732 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001733 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->AddRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001734 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1735}
1736
1737JOW(void, VideoTrack_nativeRemoveRenderer)(
1738 JNIEnv* jni, jclass,
1739 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001740 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1742}
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001743
1744} // namespace webrtc_jni