blob: 721c65466aa8070cd65ae0e023ad611294bb7f80 [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"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064#include "talk/app/webrtc/mediaconstraintsinterface.h"
65#include "talk/app/webrtc/peerconnectioninterface.h"
66#include "talk/app/webrtc/videosourceinterface.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067#include "talk/media/base/videocapturer.h"
68#include "talk/media/base/videorenderer.h"
69#include "talk/media/devices/videorendererfactory.h"
70#include "talk/media/webrtc/webrtcvideocapturer.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"
fischman@webrtc.org3d496fb2013-07-30 17:14:35 +000073#include "third_party/icu/source/common/unicode/unistr.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000074#include "webrtc/base/bind.h"
andresp@webrtc.org4d19e052014-09-09 11:45:44 +000075#include "webrtc/base/checks.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000076#include "webrtc/base/logging.h"
77#include "webrtc/base/messagequeue.h"
78#include "webrtc/base/ssladapter.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000079#include "webrtc/base/stringutils.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000080#include "webrtc/system_wrappers/interface/field_trial_default.h"
henrike@webrtc.org9de257d2013-07-17 14:42:53 +000081#include "webrtc/system_wrappers/interface/trace.h"
82#include "webrtc/video_engine/include/vie_base.h"
83#include "webrtc/voice_engine/include/voe_base.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
glaznev@webrtc.org99678452014-09-15 17:52:42 +000085#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
perkj@webrtc.org83bc7212015-02-11 11:26:56 +000086#include "talk/app/webrtc/androidvideocapturer.h"
glaznev@webrtc.org18c92472015-02-18 18:42:55 +000087#include "talk/app/webrtc/java/jni/androidmediadecoder_jni.h"
88#include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h"
perkj@webrtc.org96e4db92015-02-13 12:46:51 +000089#include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h"
andresp@webrtc.org85ef7702014-09-17 11:44:51 +000090#include "webrtc/modules/video_render/video_render_internal.h"
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +000091#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
92using webrtc::LogcatTraceContext;
93#endif
94
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000095using rtc::Bind;
96using rtc::Thread;
97using rtc::ThreadManager;
98using rtc::scoped_ptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099using webrtc::AudioSourceInterface;
100using webrtc::AudioTrackInterface;
101using webrtc::AudioTrackVector;
102using webrtc::CreateSessionDescriptionObserver;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000103using webrtc::DataBuffer;
104using webrtc::DataChannelInit;
105using webrtc::DataChannelInterface;
106using webrtc::DataChannelObserver;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107using webrtc::IceCandidateInterface;
108using webrtc::MediaConstraintsInterface;
109using webrtc::MediaSourceInterface;
110using webrtc::MediaStreamInterface;
111using webrtc::MediaStreamTrackInterface;
112using webrtc::PeerConnectionFactoryInterface;
113using webrtc::PeerConnectionInterface;
114using webrtc::PeerConnectionObserver;
115using webrtc::SessionDescriptionInterface;
116using webrtc::SetSessionDescriptionObserver;
117using webrtc::StatsObserver;
118using webrtc::StatsReport;
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000119using webrtc::StatsReports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000120using webrtc::VideoRendererInterface;
121using webrtc::VideoSourceInterface;
122using webrtc::VideoTrackInterface;
123using webrtc::VideoTrackVector;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000124using webrtc::kVideoCodecVP8;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000126namespace webrtc_jni {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000127
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +0000128// Field trials initialization string
129static char *field_trials_init_string = NULL;
130
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000131#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
132// Set in PeerConnectionFactory_initializeAndroidGlobals().
133static bool factory_static_initialized = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000134static bool vp8_hw_acceleration_enabled = true;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000135#endif
136
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000137extern "C" jint JNIEXPORT JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000138 jint ret = InitGlobalJniVariables(jvm);
139 if (ret < 0)
140 return -1;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000141
142 CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000143 LoadGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000144
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000145 return ret;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000146}
147
148extern "C" void JNIEXPORT JNICALL JNI_OnUnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000149 FreeGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000150 CHECK(rtc::CleanupSSL()) << "Failed to CleanupSSL()";
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000151}
152
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000153// Return the (singleton) Java Enum object corresponding to |index|;
154// |state_class_fragment| is something like "MediaSource$State".
glaznev@webrtc.orgb28474c2015-02-23 17:44:27 +0000155static jobject JavaEnumFromIndex(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000156 JNIEnv* jni, const std::string& state_class_fragment, int index) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000157 const std::string state_class = "org/webrtc/" + state_class_fragment;
158 return JavaEnumFromIndex(jni, FindClass(jni, state_class.c_str()),
159 state_class, index);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000160}
161
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000162static DataChannelInit JavaDataChannelInitToNative(
163 JNIEnv* jni, jobject j_init) {
164 DataChannelInit init;
165
166 jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init");
167 jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z");
168 jfieldID max_retransmit_time_id =
169 GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I");
170 jfieldID max_retransmits_id =
171 GetFieldID(jni, j_init_class, "maxRetransmits", "I");
172 jfieldID protocol_id =
173 GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;");
174 jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z");
175 jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I");
176
177 init.ordered = GetBooleanField(jni, j_init, ordered_id);
178 init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id);
179 init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id);
180 init.protocol = JavaToStdString(
181 jni, GetStringField(jni, j_init, protocol_id));
182 init.negotiated = GetBooleanField(jni, j_init, negotiated_id);
183 init.id = GetIntField(jni, j_init, id_id);
184
185 return init;
186}
187
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188class ConstraintsWrapper;
189
190// Adapter between the C++ PeerConnectionObserver interface and the Java
191// PeerConnection.Observer interface. Wraps an instance of the Java interface
192// and dispatches C++ callbacks to Java.
193class PCOJava : public PeerConnectionObserver {
194 public:
195 PCOJava(JNIEnv* jni, jobject j_observer)
196 : j_observer_global_(jni, j_observer),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000197 j_observer_class_(jni, GetObjectClass(jni, *j_observer_global_)),
198 j_media_stream_class_(jni, FindClass(jni, "org/webrtc/MediaStream")),
199 j_media_stream_ctor_(GetMethodID(
200 jni, *j_media_stream_class_, "<init>", "(J)V")),
201 j_audio_track_class_(jni, FindClass(jni, "org/webrtc/AudioTrack")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000202 j_audio_track_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000203 jni, *j_audio_track_class_, "<init>", "(J)V")),
204 j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")),
205 j_video_track_ctor_(GetMethodID(
206 jni, *j_video_track_class_, "<init>", "(J)V")),
207 j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")),
208 j_data_channel_ctor_(GetMethodID(
209 jni, *j_data_channel_class_, "<init>", "(J)V")) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000210 }
211
212 virtual ~PCOJava() {}
213
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000214 void OnIceCandidate(const IceCandidateInterface* candidate) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000215 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000216 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000217 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000218 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
219 jmethodID ctor = GetMethodID(jni(), candidate_class,
220 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000221 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
222 jstring j_sdp = JavaStringFromStdString(jni(), sdp);
223 jobject j_candidate = jni()->NewObject(
224 candidate_class, ctor, j_mid, candidate->sdp_mline_index(), j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000225 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000226 jmethodID m = GetMethodID(jni(), *j_observer_class_,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000227 "onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000228 jni()->CallVoidMethod(*j_observer_global_, m, j_candidate);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000229 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000230 }
231
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000232 void OnSignalingChange(
233 PeerConnectionInterface::SignalingState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000234 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000235 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000236 jni(), *j_observer_class_, "onSignalingChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000237 "(Lorg/webrtc/PeerConnection$SignalingState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000238 jobject new_state_enum =
239 JavaEnumFromIndex(jni(), "PeerConnection$SignalingState", new_state);
240 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000241 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000242 }
243
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000244 void OnIceConnectionChange(
245 PeerConnectionInterface::IceConnectionState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000246 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000247 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000248 jni(), *j_observer_class_, "onIceConnectionChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000249 "(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000250 jobject new_state_enum = JavaEnumFromIndex(
251 jni(), "PeerConnection$IceConnectionState", new_state);
252 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000253 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000254 }
255
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000256 void OnIceGatheringChange(
257 PeerConnectionInterface::IceGatheringState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000258 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000259 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000260 jni(), *j_observer_class_, "onIceGatheringChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000261 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000262 jobject new_state_enum = JavaEnumFromIndex(
263 jni(), "PeerConnection$IceGatheringState", new_state);
264 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000265 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000266 }
267
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000268 void OnAddStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000269 ScopedLocalRefFrame local_ref_frame(jni());
270 jobject j_stream = jni()->NewObject(
271 *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000272 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000273
274 AudioTrackVector audio_tracks = stream->GetAudioTracks();
275 for (size_t i = 0; i < audio_tracks.size(); ++i) {
276 AudioTrackInterface* track = audio_tracks[i];
fischman@webrtc.org41776152014-01-09 00:31:17 +0000277 jstring id = JavaStringFromStdString(jni(), track->id());
278 jobject j_track = jni()->NewObject(
279 *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000280 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000281 jfieldID audio_tracks_id = GetFieldID(jni(),
282 *j_media_stream_class_,
283 "audioTracks",
284 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000285 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000287 GetObjectClass(jni(), audio_tracks),
288 "add",
289 "(Ljava/lang/Object;)Z");
290 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000291 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
292 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000293 }
294
295 VideoTrackVector video_tracks = stream->GetVideoTracks();
296 for (size_t i = 0; i < video_tracks.size(); ++i) {
297 VideoTrackInterface* track = video_tracks[i];
fischman@webrtc.org41776152014-01-09 00:31:17 +0000298 jstring id = JavaStringFromStdString(jni(), track->id());
299 jobject j_track = jni()->NewObject(
300 *j_video_track_class_, j_video_track_ctor_, (jlong)track, id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000301 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000302 jfieldID video_tracks_id = GetFieldID(jni(),
303 *j_media_stream_class_,
304 "videoTracks",
305 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000306 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000307 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000308 GetObjectClass(jni(), video_tracks),
309 "add",
310 "(Ljava/lang/Object;)Z");
311 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000312 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
313 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 }
fischman@webrtc.org41776152014-01-09 00:31:17 +0000315 streams_[stream] = jni()->NewWeakGlobalRef(j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000316 CHECK_EXCEPTION(jni()) << "error during NewWeakGlobalRef";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000318 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
319 "(Lorg/webrtc/MediaStream;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000320 jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000321 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322 }
323
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000324 void OnRemoveStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000325 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326 NativeToJavaStreamsMap::iterator it = streams_.find(stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000327 CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328
329 WeakRef s(jni(), it->second);
330 streams_.erase(it);
331 if (!s.obj())
332 return;
333
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000334 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
335 "(Lorg/webrtc/MediaStream;)V");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000336 jni()->CallVoidMethod(*j_observer_global_, m, s.obj());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000337 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000338 }
339
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000340 void OnDataChannel(DataChannelInterface* channel) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000341 ScopedLocalRefFrame local_ref_frame(jni());
342 jobject j_channel = jni()->NewObject(
343 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000344 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000345
346 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
347 "(Lorg/webrtc/DataChannel;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000348 jni()->CallVoidMethod(*j_observer_global_, m, j_channel);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000349
350 // Channel is now owned by Java object, and will be freed from
351 // DataChannel.dispose(). Important that this be done _after_ the
352 // CallVoidMethod above as Java code might call back into native code and be
353 // surprised to see a refcount of 2.
354 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000355 CHECK(bumped_count == 2) << "Unexpected refcount OnDataChannel";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000356
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000357 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000358 }
359
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000360 void OnRenegotiationNeeded() override {
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000361 ScopedLocalRefFrame local_ref_frame(jni());
362 jmethodID m =
363 GetMethodID(jni(), *j_observer_class_, "onRenegotiationNeeded", "()V");
364 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000365 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000366 }
367
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 void SetConstraints(ConstraintsWrapper* constraints) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000369 CHECK(!constraints_.get()) << "constraints already set!";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000370 constraints_.reset(constraints);
371 }
372
373 const ConstraintsWrapper* constraints() { return constraints_.get(); }
374
375 private:
376 JNIEnv* jni() {
377 return AttachCurrentThreadIfNeeded();
378 }
379
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000380 const ScopedGlobalRef<jobject> j_observer_global_;
381 const ScopedGlobalRef<jclass> j_observer_class_;
382 const ScopedGlobalRef<jclass> j_media_stream_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000383 const jmethodID j_media_stream_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000384 const ScopedGlobalRef<jclass> j_audio_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000385 const jmethodID j_audio_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000386 const ScopedGlobalRef<jclass> j_video_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387 const jmethodID j_video_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000388 const ScopedGlobalRef<jclass> j_data_channel_class_;
389 const jmethodID j_data_channel_ctor_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000390 typedef std::map<void*, jweak> NativeToJavaStreamsMap;
391 NativeToJavaStreamsMap streams_; // C++ -> Java streams.
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000392 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000393};
394
395// Wrapper for a Java MediaConstraints object. Copies all needed data so when
396// the constructor returns the Java object is no longer needed.
397class ConstraintsWrapper : public MediaConstraintsInterface {
398 public:
399 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) {
400 PopulateConstraintsFromJavaPairList(
401 jni, j_constraints, "mandatory", &mandatory_);
402 PopulateConstraintsFromJavaPairList(
403 jni, j_constraints, "optional", &optional_);
404 }
405
406 virtual ~ConstraintsWrapper() {}
407
408 // MediaConstraintsInterface.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000409 const Constraints& GetMandatory() const override { return mandatory_; }
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000410
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000411 const Constraints& GetOptional() const override { return optional_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412
413 private:
414 // Helper for translating a List<Pair<String, String>> to a Constraints.
415 static void PopulateConstraintsFromJavaPairList(
416 JNIEnv* jni, jobject j_constraints,
417 const char* field_name, Constraints* field) {
418 jfieldID j_id = GetFieldID(jni,
419 GetObjectClass(jni, j_constraints), field_name, "Ljava/util/List;");
420 jobject j_list = GetObjectField(jni, j_constraints, j_id);
421 jmethodID j_iterator_id = GetMethodID(jni,
422 GetObjectClass(jni, j_list), "iterator", "()Ljava/util/Iterator;");
423 jobject j_iterator = jni->CallObjectMethod(j_list, j_iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000424 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425 jmethodID j_has_next = GetMethodID(jni,
426 GetObjectClass(jni, j_iterator), "hasNext", "()Z");
427 jmethodID j_next = GetMethodID(jni,
428 GetObjectClass(jni, j_iterator), "next", "()Ljava/lang/Object;");
429 while (jni->CallBooleanMethod(j_iterator, j_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000430 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000431 jobject entry = jni->CallObjectMethod(j_iterator, j_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000432 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433 jmethodID get_key = GetMethodID(jni,
434 GetObjectClass(jni, entry), "getKey", "()Ljava/lang/String;");
435 jstring j_key = reinterpret_cast<jstring>(
436 jni->CallObjectMethod(entry, get_key));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000437 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 jmethodID get_value = GetMethodID(jni,
439 GetObjectClass(jni, entry), "getValue", "()Ljava/lang/String;");
440 jstring j_value = reinterpret_cast<jstring>(
441 jni->CallObjectMethod(entry, get_value));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000442 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000443 field->push_back(Constraint(JavaToStdString(jni, j_key),
444 JavaToStdString(jni, j_value)));
445 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000446 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000447 }
448
449 Constraints mandatory_;
450 Constraints optional_;
451};
452
453static jobject JavaSdpFromNativeSdp(
454 JNIEnv* jni, const SessionDescriptionInterface* desc) {
455 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000456 CHECK(desc->ToString(&sdp)) << "got so far: " << sdp;
fischman@webrtc.org41776152014-01-09 00:31:17 +0000457 jstring j_description = JavaStringFromStdString(jni, sdp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458
459 jclass j_type_class = FindClass(
460 jni, "org/webrtc/SessionDescription$Type");
461 jmethodID j_type_from_canonical = GetStaticMethodID(
462 jni, j_type_class, "fromCanonicalForm",
463 "(Ljava/lang/String;)Lorg/webrtc/SessionDescription$Type;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000464 jstring j_type_string = JavaStringFromStdString(jni, desc->type());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465 jobject j_type = jni->CallStaticObjectMethod(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000466 j_type_class, j_type_from_canonical, j_type_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000467 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468
469 jclass j_sdp_class = FindClass(jni, "org/webrtc/SessionDescription");
470 jmethodID j_sdp_ctor = GetMethodID(
471 jni, j_sdp_class, "<init>",
472 "(Lorg/webrtc/SessionDescription$Type;Ljava/lang/String;)V");
473 jobject j_sdp = jni->NewObject(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000474 j_sdp_class, j_sdp_ctor, j_type, j_description);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000475 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000476 return j_sdp;
477}
478
479template <class T> // T is one of {Create,Set}SessionDescriptionObserver.
480class SdpObserverWrapper : public T {
481 public:
482 SdpObserverWrapper(JNIEnv* jni, jobject j_observer,
483 ConstraintsWrapper* constraints)
484 : constraints_(constraints),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000485 j_observer_global_(jni, j_observer),
486 j_observer_class_(jni, GetObjectClass(jni, j_observer)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487 }
488
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000489 virtual ~SdpObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000490
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000491 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000492 virtual void OnSuccess() {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000493 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000494 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
495 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000496 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000497 }
498
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000499 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000500 virtual void OnSuccess(SessionDescriptionInterface* desc) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000501 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000502 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000503 jni(), *j_observer_class_, "onCreateSuccess",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504 "(Lorg/webrtc/SessionDescription;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000505 jobject j_sdp = JavaSdpFromNativeSdp(jni(), desc);
506 jni()->CallVoidMethod(*j_observer_global_, m, j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000507 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000508 }
509
510 protected:
511 // Common implementation for failure of Set & Create types, distinguished by
512 // |op| being "Set" or "Create".
513 void OnFailure(const std::string& op, const std::string& error) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000514 jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
515 "(Ljava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000516 jstring j_error_string = JavaStringFromStdString(jni(), error);
517 jni()->CallVoidMethod(*j_observer_global_, m, j_error_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000518 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519 }
520
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000521 JNIEnv* jni() {
522 return AttachCurrentThreadIfNeeded();
523 }
524
fischman@webrtc.org41776152014-01-09 00:31:17 +0000525 private:
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000526 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000527 const ScopedGlobalRef<jobject> j_observer_global_;
528 const ScopedGlobalRef<jclass> j_observer_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000529};
530
531class CreateSdpObserverWrapper
532 : public SdpObserverWrapper<CreateSessionDescriptionObserver> {
533 public:
534 CreateSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
535 ConstraintsWrapper* constraints)
536 : SdpObserverWrapper(jni, j_observer, constraints) {}
537
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000538 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000539 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000540 SdpObserverWrapper::OnFailure(std::string("Create"), error);
541 }
542};
543
544class SetSdpObserverWrapper
545 : public SdpObserverWrapper<SetSessionDescriptionObserver> {
546 public:
547 SetSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
548 ConstraintsWrapper* constraints)
549 : SdpObserverWrapper(jni, j_observer, constraints) {}
550
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000551 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000552 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000553 SdpObserverWrapper::OnFailure(std::string("Set"), error);
554 }
555};
556
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000557// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
558// and dispatching the callback from C++ back to Java.
559class DataChannelObserverWrapper : public DataChannelObserver {
560 public:
561 DataChannelObserverWrapper(JNIEnv* jni, jobject j_observer)
562 : j_observer_global_(jni, j_observer),
563 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
pbos@webrtc.orgb648b9d2014-08-26 11:08:06 +0000564 j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000565 j_on_state_change_mid_(GetMethodID(jni, *j_observer_class_,
566 "onStateChange", "()V")),
567 j_on_message_mid_(GetMethodID(jni, *j_observer_class_, "onMessage",
568 "(Lorg/webrtc/DataChannel$Buffer;)V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000569 j_buffer_ctor_(GetMethodID(jni, *j_buffer_class_,
570 "<init>", "(Ljava/nio/ByteBuffer;Z)V")) {
571 }
572
573 virtual ~DataChannelObserverWrapper() {}
574
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000575 void OnStateChange() override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000576 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000577 jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000578 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000579 }
580
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000581 void OnMessage(const DataBuffer& buffer) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000582 ScopedLocalRefFrame local_ref_frame(jni());
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000583 jobject byte_buffer = jni()->NewDirectByteBuffer(
Karl Wiberg94784372015-04-20 14:03:07 +0200584 const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000585 jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_,
586 byte_buffer, buffer.binary);
587 jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000588 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000589 }
590
591 private:
592 JNIEnv* jni() {
593 return AttachCurrentThreadIfNeeded();
594 }
595
596 const ScopedGlobalRef<jobject> j_observer_global_;
597 const ScopedGlobalRef<jclass> j_observer_class_;
598 const ScopedGlobalRef<jclass> j_buffer_class_;
599 const jmethodID j_on_state_change_mid_;
600 const jmethodID j_on_message_mid_;
601 const jmethodID j_buffer_ctor_;
602};
603
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000604// Adapter for a Java StatsObserver presenting a C++ StatsObserver and
605// dispatching the callback from C++ back to Java.
606class StatsObserverWrapper : public StatsObserver {
607 public:
608 StatsObserverWrapper(JNIEnv* jni, jobject j_observer)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000609 : j_observer_global_(jni, j_observer),
610 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
611 j_stats_report_class_(jni, FindClass(jni, "org/webrtc/StatsReport")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000612 j_stats_report_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000613 jni, *j_stats_report_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000614 "(Ljava/lang/String;Ljava/lang/String;D"
615 "[Lorg/webrtc/StatsReport$Value;)V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000616 j_value_class_(jni, FindClass(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000617 jni, "org/webrtc/StatsReport$Value")),
618 j_value_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000619 jni, *j_value_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000620 "(Ljava/lang/String;Ljava/lang/String;)V")) {
621 }
622
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000623 virtual ~StatsObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000624
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000625 void OnComplete(const StatsReports& reports) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000626 ScopedLocalRefFrame local_ref_frame(jni());
627 jobjectArray j_reports = ReportsToJava(jni(), reports);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000628 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
629 "([Lorg/webrtc/StatsReport;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000630 jni()->CallVoidMethod(*j_observer_global_, m, j_reports);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000631 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632 }
633
634 private:
635 jobjectArray ReportsToJava(
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000636 JNIEnv* jni, const StatsReports& reports) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000637 jobjectArray reports_array = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000638 reports.size(), *j_stats_report_class_, NULL);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000639 int i = 0;
640 for (const auto* report : reports) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000641 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000642 jstring j_id = JavaStringFromStdString(jni, report->id()->ToString());
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000643 jstring j_type = JavaStringFromStdString(jni, report->TypeToString());
644 jobjectArray j_values = ValuesToJava(jni, report->values());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000645 jobject j_report = jni->NewObject(*j_stats_report_class_,
646 j_stats_report_ctor_,
647 j_id,
648 j_type,
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000649 report->timestamp(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000650 j_values);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000651 jni->SetObjectArrayElement(reports_array, i++, j_report);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652 }
653 return reports_array;
654 }
655
656 jobjectArray ValuesToJava(JNIEnv* jni, const StatsReport::Values& values) {
657 jobjectArray j_values = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000658 values.size(), *j_value_class_, NULL);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000659 int i = 0;
660 for (const auto& it : values) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000661 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgc57310b2014-12-12 17:41:28 +0000662 // Should we use the '.name' enum value here instead of converting the
663 // name to a string?
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000664 jstring j_name = JavaStringFromStdString(jni, it.second->display_name());
665 jstring j_value = JavaStringFromStdString(jni, it.second->ToString());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000666 jobject j_element_value =
667 jni->NewObject(*j_value_class_, j_value_ctor_, j_name, j_value);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000668 jni->SetObjectArrayElement(j_values, i++, j_element_value);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 }
670 return j_values;
671 }
672
673 JNIEnv* jni() {
674 return AttachCurrentThreadIfNeeded();
675 }
676
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000677 const ScopedGlobalRef<jobject> j_observer_global_;
678 const ScopedGlobalRef<jclass> j_observer_class_;
679 const ScopedGlobalRef<jclass> j_stats_report_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 const jmethodID j_stats_report_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000681 const ScopedGlobalRef<jclass> j_value_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000682 const jmethodID j_value_ctor_;
683};
684
685// Adapter presenting a cricket::VideoRenderer as a
686// webrtc::VideoRendererInterface.
687class VideoRendererWrapper : public VideoRendererInterface {
688 public:
689 static VideoRendererWrapper* Create(cricket::VideoRenderer* renderer) {
690 if (renderer)
691 return new VideoRendererWrapper(renderer);
692 return NULL;
693 }
694
695 virtual ~VideoRendererWrapper() {}
696
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000697 // This wraps VideoRenderer which still has SetSize.
698 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000699 ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000700 const cricket::VideoFrame* frame =
701 video_frame->GetCopyWithRotationApplied();
702 if (width_ != frame->GetWidth() || height_ != frame->GetHeight()) {
703 width_ = frame->GetWidth();
704 height_ = frame->GetHeight();
705 renderer_->SetSize(width_, height_, 0);
706 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000707 renderer_->RenderFrame(frame);
708 }
709
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000710 // TODO(guoweis): Remove this once chrome code base is updated.
711 bool CanApplyRotation() override { return true; }
712
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 private:
714 explicit VideoRendererWrapper(cricket::VideoRenderer* renderer)
Henrik Kjellander7c027b62015-04-22 13:21:30 +0200715 : width_(0), height_(0), renderer_(renderer) {}
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000716 int width_, height_;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000717 scoped_ptr<cricket::VideoRenderer> renderer_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718};
719
720// Wrapper dispatching webrtc::VideoRendererInterface to a Java VideoRenderer
721// instance.
722class JavaVideoRendererWrapper : public VideoRendererInterface {
723 public:
724 JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000725 : j_callbacks_(jni, j_callbacks),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000726 j_render_frame_id_(GetMethodID(
727 jni, GetObjectClass(jni, j_callbacks), "renderFrame",
728 "(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000729 j_can_apply_rotation_id_(GetMethodID(
730 jni, GetObjectClass(jni, j_callbacks),
731 "canApplyRotation", "()Z")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000732 j_frame_class_(jni,
733 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000734 j_i420_frame_ctor_id_(GetMethodID(
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000735 jni, *j_frame_class_, "<init>", "(III[I[Ljava/nio/ByteBuffer;)V")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000736 j_texture_frame_ctor_id_(GetMethodID(
737 jni, *j_frame_class_, "<init>",
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000738 "(IIILjava/lang/Object;I)V")),
739 j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")),
740 can_apply_rotation_set_(false),
741 can_apply_rotation_(false) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000742 CHECK_EXCEPTION(jni);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000743 }
744
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000745 virtual ~JavaVideoRendererWrapper() {}
746
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000747 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000748 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000749
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000750 // Calling CanApplyRotation here to ensure can_apply_rotation_ is set.
751 CanApplyRotation();
guoweis@webrtc.org3fffd662015-03-18 04:20:03 +0000752
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000753 const cricket::VideoFrame* frame =
754 can_apply_rotation_ ? video_frame
755 : video_frame->GetCopyWithRotationApplied();
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000756 if (frame->GetNativeHandle() != NULL) {
757 jobject j_frame = CricketToJavaTextureFrame(frame);
758 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
759 CHECK_EXCEPTION(jni());
760 } else {
761 jobject j_frame = CricketToJavaI420Frame(frame);
762 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
763 CHECK_EXCEPTION(jni());
764 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000765 }
766
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000767 // TODO(guoweis): Report that rotation is supported as RenderFrame calls
768 // GetCopyWithRotationApplied.
769 virtual bool CanApplyRotation() override {
770 if (can_apply_rotation_set_) {
771 return can_apply_rotation_;
772 }
773 ScopedLocalRefFrame local_ref_frame(jni());
774 jboolean ret =
775 jni()->CallBooleanMethod(*j_callbacks_, j_can_apply_rotation_id_);
776 CHECK_EXCEPTION(jni());
777 can_apply_rotation_ = ret;
778 can_apply_rotation_set_ = true;
779 return ret;
780 }
781
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782 private:
783 // Return a VideoRenderer.I420Frame referring to the data in |frame|.
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000784 jobject CricketToJavaI420Frame(const cricket::VideoFrame* frame) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000785 jintArray strides = jni()->NewIntArray(3);
786 jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000787 strides_array[0] = frame->GetYPitch();
788 strides_array[1] = frame->GetUPitch();
789 strides_array[2] = frame->GetVPitch();
fischman@webrtc.org41776152014-01-09 00:31:17 +0000790 jni()->ReleaseIntArrayElements(strides, strides_array, 0);
791 jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
792 jobject y_buffer = jni()->NewDirectByteBuffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 const_cast<uint8*>(frame->GetYPlane()),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000794 frame->GetYPitch() * frame->GetHeight());
795 jobject u_buffer = jni()->NewDirectByteBuffer(
796 const_cast<uint8*>(frame->GetUPlane()), frame->GetChromaSize());
797 jobject v_buffer = jni()->NewDirectByteBuffer(
798 const_cast<uint8*>(frame->GetVPlane()), frame->GetChromaSize());
799 jni()->SetObjectArrayElement(planes, 0, y_buffer);
800 jni()->SetObjectArrayElement(planes, 1, u_buffer);
801 jni()->SetObjectArrayElement(planes, 2, v_buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802 return jni()->NewObject(
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000803 *j_frame_class_, j_i420_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000804 frame->GetWidth(), frame->GetHeight(),
805 static_cast<int>(frame->GetVideoRotation()),
806 strides, planes);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 }
808
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000809 // Return a VideoRenderer.I420Frame referring texture object in |frame|.
810 jobject CricketToJavaTextureFrame(const cricket::VideoFrame* frame) {
811 NativeHandleImpl* handle =
812 reinterpret_cast<NativeHandleImpl*>(frame->GetNativeHandle());
813 jobject texture_object = reinterpret_cast<jobject>(handle->GetHandle());
814 int texture_id = handle->GetTextureId();
815 return jni()->NewObject(
816 *j_frame_class_, j_texture_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000817 frame->GetWidth(), frame->GetHeight(),
818 static_cast<int>(frame->GetVideoRotation()),
819 texture_object, texture_id);
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000820 }
821
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000822 JNIEnv* jni() {
823 return AttachCurrentThreadIfNeeded();
824 }
825
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000826 ScopedGlobalRef<jobject> j_callbacks_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000827 jmethodID j_render_frame_id_;
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000828 jmethodID j_can_apply_rotation_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000829 ScopedGlobalRef<jclass> j_frame_class_;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000830 jmethodID j_i420_frame_ctor_id_;
831 jmethodID j_texture_frame_ctor_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000832 ScopedGlobalRef<jclass> j_byte_buffer_class_;
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000833 bool can_apply_rotation_set_;
834 bool can_apply_rotation_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835};
836
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000837
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000838static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000839 jfieldID native_dc_id = GetFieldID(jni,
840 GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
841 jlong j_d = GetLongField(jni, j_dc, native_dc_id);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000842 return reinterpret_cast<DataChannelInterface*>(j_d);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000843}
844
845JOW(jlong, DataChannel_registerObserverNative)(
846 JNIEnv* jni, jobject j_dc, jobject j_observer) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000847 scoped_ptr<DataChannelObserverWrapper> observer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000848 new DataChannelObserverWrapper(jni, j_observer));
849 ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
fischman@webrtc.orgf41f06b2013-12-11 21:07:18 +0000850 return jlongFromPointer(observer.release());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000851}
852
853JOW(void, DataChannel_unregisterObserverNative)(
854 JNIEnv* jni, jobject j_dc, jlong native_observer) {
855 ExtractNativeDC(jni, j_dc)->UnregisterObserver();
856 delete reinterpret_cast<DataChannelObserverWrapper*>(native_observer);
857}
858
859JOW(jstring, DataChannel_label)(JNIEnv* jni, jobject j_dc) {
860 return JavaStringFromStdString(jni, ExtractNativeDC(jni, j_dc)->label());
861}
862
863JOW(jobject, DataChannel_state)(JNIEnv* jni, jobject j_dc) {
864 return JavaEnumFromIndex(
865 jni, "DataChannel$State", ExtractNativeDC(jni, j_dc)->state());
866}
867
868JOW(jlong, DataChannel_bufferedAmount)(JNIEnv* jni, jobject j_dc) {
869 uint64 buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000870 CHECK_LE(buffered_amount, std::numeric_limits<int64>::max())
871 << "buffered_amount overflowed jlong!";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000872 return static_cast<jlong>(buffered_amount);
873}
874
875JOW(void, DataChannel_close)(JNIEnv* jni, jobject j_dc) {
876 ExtractNativeDC(jni, j_dc)->Close();
877}
878
879JOW(jboolean, DataChannel_sendNative)(JNIEnv* jni, jobject j_dc,
880 jbyteArray data, jboolean binary) {
881 jbyte* bytes = jni->GetByteArrayElements(data, NULL);
882 bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000883 rtc::Buffer(bytes, jni->GetArrayLength(data)),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000884 binary));
885 jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
886 return ret;
887}
888
889JOW(void, DataChannel_dispose)(JNIEnv* jni, jobject j_dc) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000890 CHECK_RELEASE(ExtractNativeDC(jni, j_dc));
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000891}
892
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000893JOW(void, Logging_nativeEnableTracing)(
894 JNIEnv* jni, jclass, jstring j_path, jint nativeLevels,
895 jint nativeSeverity) {
896 std::string path = JavaToStdString(jni, j_path);
897 if (nativeLevels != webrtc::kTraceNone) {
andrew@webrtc.org90805182013-09-05 16:40:43 +0000898 webrtc::Trace::set_level_filter(nativeLevels);
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000899#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000900 if (path != "logcat:") {
901#endif
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000902 CHECK_EQ(0, webrtc::Trace::SetTraceFile(path.c_str(), false))
903 << "SetTraceFile failed";
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000904#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000905 } else {
906 // Intentionally leak this to avoid needing to reason about its lifecycle.
907 // It keeps no state and functions only as a dispatch point.
908 static LogcatTraceContext* g_trace_callback = new LogcatTraceContext();
909 }
910#endif
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000911 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000912 rtc::LogMessage::LogToDebug(nativeSeverity);
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000913}
914
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000915JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000916 CHECK_RELEASE(reinterpret_cast<PeerConnectionInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000917}
918
919JOW(void, PeerConnection_freeObserver)(JNIEnv*, jclass, jlong j_p) {
920 PCOJava* p = reinterpret_cast<PCOJava*>(j_p);
921 delete p;
922}
923
924JOW(void, MediaSource_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000925 CHECK_RELEASE(reinterpret_cast<MediaSourceInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926}
927
928JOW(void, VideoCapturer_free)(JNIEnv*, jclass, jlong j_p) {
929 delete reinterpret_cast<cricket::VideoCapturer*>(j_p);
930}
931
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000932JOW(void, VideoRenderer_freeGuiVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000933 delete reinterpret_cast<VideoRendererWrapper*>(j_p);
934}
935
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000936JOW(void, VideoRenderer_freeWrappedVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
937 delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
938}
939
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000940JOW(void, MediaStreamTrack_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000941 CHECK_RELEASE(reinterpret_cast<MediaStreamTrackInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942}
943
944JOW(jboolean, MediaStream_nativeAddAudioTrack)(
945 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000946 return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000948}
949
950JOW(jboolean, MediaStream_nativeAddVideoTrack)(
951 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000952 return reinterpret_cast<MediaStreamInterface*>(pointer)
953 ->AddTrack(reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000954}
955
956JOW(jboolean, MediaStream_nativeRemoveAudioTrack)(
957 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000958 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000960}
961
962JOW(jboolean, MediaStream_nativeRemoveVideoTrack)(
963 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000964 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000966}
967
968JOW(jstring, MediaStream_nativeLabel)(JNIEnv* jni, jclass, jlong j_p) {
969 return JavaStringFromStdString(
970 jni, reinterpret_cast<MediaStreamInterface*>(j_p)->label());
971}
972
973JOW(void, MediaStream_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000974 CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975}
976
977JOW(jlong, PeerConnectionFactory_nativeCreateObserver)(
978 JNIEnv * jni, jclass, jobject j_observer) {
979 return (jlong)new PCOJava(jni, j_observer);
980}
981
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +0000982#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000983JOW(jboolean, PeerConnectionFactory_initializeAndroidGlobals)(
fischman@webrtc.orga150bc92014-05-14 22:00:50 +0000984 JNIEnv* jni, jclass, jobject context,
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000985 jboolean initialize_audio, jboolean initialize_video,
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000986 jboolean vp8_hw_acceleration, jobject render_egl_context) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000987 bool failure = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000988 vp8_hw_acceleration_enabled = vp8_hw_acceleration;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000989 if (!factory_static_initialized) {
andresp@webrtc.org85ef7702014-09-17 11:44:51 +0000990 if (initialize_video) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000991 failure |= webrtc::SetRenderAndroidVM(GetJVM());
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000992 failure |= AndroidVideoCapturerJni::SetAndroidObjects(jni, context);
andresp@webrtc.org85ef7702014-09-17 11:44:51 +0000993 }
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000994 if (initialize_audio)
henrika@webrtc.org474d1eb2015-03-09 12:39:53 +0000995 failure |= webrtc::VoiceEngine::SetAndroidObjects(GetJVM(), context);
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000996 factory_static_initialized = true;
997 }
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000998 if (initialize_video) {
glaznev@webrtc.org18c92472015-02-18 18:42:55 +0000999 failure |= MediaCodecVideoDecoderFactory::SetAndroidObjects(jni,
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001000 render_egl_context);
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001001 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001002 return !failure;
1003}
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +00001004#endif // defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001005
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001006JOW(void, PeerConnectionFactory_initializeFieldTrials)(
1007 JNIEnv* jni, jclass, jstring j_trials_init_string) {
1008 field_trials_init_string = NULL;
1009 if (j_trials_init_string != NULL) {
1010 const char* init_string =
1011 jni->GetStringUTFChars(j_trials_init_string, NULL);
1012 int init_string_length = jni->GetStringUTFLength(j_trials_init_string);
1013 field_trials_init_string = new char[init_string_length + 1];
1014 rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string);
1015 jni->ReleaseStringUTFChars(j_trials_init_string, init_string);
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001016 LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string;
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001017 }
1018 webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string);
1019}
1020
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001021// Helper struct for working around the fact that CreatePeerConnectionFactory()
1022// comes in two flavors: either entirely automagical (constructing its own
1023// threads and deleting them on teardown, but no external codec factory support)
1024// or entirely manual (requires caller to delete threads after factory
1025// teardown). This struct takes ownership of its ctor's arguments to present a
1026// single thing for Java to hold and eventually free.
1027class OwnedFactoryAndThreads {
1028 public:
1029 OwnedFactoryAndThreads(Thread* worker_thread,
1030 Thread* signaling_thread,
1031 PeerConnectionFactoryInterface* factory)
1032 : worker_thread_(worker_thread),
1033 signaling_thread_(signaling_thread),
1034 factory_(factory) {}
1035
1036 ~OwnedFactoryAndThreads() { CHECK_RELEASE(factory_); }
1037
1038 PeerConnectionFactoryInterface* factory() { return factory_; }
1039
1040 private:
1041 const scoped_ptr<Thread> worker_thread_;
1042 const scoped_ptr<Thread> signaling_thread_;
1043 PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
1044};
1045
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001046JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)(
1047 JNIEnv* jni, jclass) {
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001048 // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
1049 // ThreadManager only WrapCurrentThread()s the thread where it is first
1050 // created. Since the semantics around when auto-wrapping happens in
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001051 // webrtc/base/ are convoluted, we simply wrap here to avoid having to think
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001052 // about ramifications of auto-wrapping there.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001053 rtc::ThreadManager::Instance()->WrapCurrentThread();
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001054 webrtc::Trace::CreateTrace();
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001055 Thread* worker_thread = new Thread();
1056 worker_thread->SetName("worker_thread", NULL);
1057 Thread* signaling_thread = new Thread();
1058 signaling_thread->SetName("signaling_thread", NULL);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001059 CHECK(worker_thread->Start() && signaling_thread->Start())
1060 << "Failed to start threads";
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001061 scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001062 scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001063#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +00001064 if (vp8_hw_acceleration_enabled) {
1065 encoder_factory.reset(new MediaCodecVideoEncoderFactory());
1066 decoder_factory.reset(new MediaCodecVideoDecoderFactory());
1067 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001068#endif
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001069 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001070 webrtc::CreatePeerConnectionFactory(worker_thread,
1071 signaling_thread,
1072 NULL,
1073 encoder_factory.release(),
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001074 decoder_factory.release()));
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001075 OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
1076 worker_thread, signaling_thread, factory.release());
1077 return jlongFromPointer(owned_factory);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001078}
1079
1080JOW(void, PeerConnectionFactory_freeFactory)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001081 delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001082 if (field_trials_init_string) {
1083 webrtc::field_trial::InitFieldTrialsFromString(NULL);
1084 delete field_trials_init_string;
1085 field_trials_init_string = NULL;
1086 }
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001087 webrtc::Trace::ReturnTrace();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001088}
1089
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001090static PeerConnectionFactoryInterface* factoryFromJava(jlong j_p) {
1091 return reinterpret_cast<OwnedFactoryAndThreads*>(j_p)->factory();
1092}
1093
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094JOW(jlong, PeerConnectionFactory_nativeCreateLocalMediaStream)(
1095 JNIEnv* jni, jclass, jlong native_factory, jstring label) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001096 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001097 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001098 rtc::scoped_refptr<MediaStreamInterface> stream(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001099 factory->CreateLocalMediaStream(JavaToStdString(jni, label)));
1100 return (jlong)stream.release();
1101}
1102
1103JOW(jlong, PeerConnectionFactory_nativeCreateVideoSource)(
1104 JNIEnv* jni, jclass, jlong native_factory, jlong native_capturer,
1105 jobject j_constraints) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001106 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001107 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001108 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001109 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001110 rtc::scoped_refptr<VideoSourceInterface> source(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001111 factory->CreateVideoSource(
1112 reinterpret_cast<cricket::VideoCapturer*>(native_capturer),
1113 constraints.get()));
1114 return (jlong)source.release();
1115}
1116
1117JOW(jlong, PeerConnectionFactory_nativeCreateVideoTrack)(
1118 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1119 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001120 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001121 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001122 rtc::scoped_refptr<VideoTrackInterface> track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001123 factory->CreateVideoTrack(
1124 JavaToStdString(jni, id),
1125 reinterpret_cast<VideoSourceInterface*>(native_source)));
1126 return (jlong)track.release();
1127}
1128
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001129JOW(jlong, PeerConnectionFactory_nativeCreateAudioSource)(
1130 JNIEnv* jni, jclass, jlong native_factory, jobject j_constraints) {
1131 scoped_ptr<ConstraintsWrapper> constraints(
1132 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001133 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001134 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001135 rtc::scoped_refptr<AudioSourceInterface> source(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001136 factory->CreateAudioSource(constraints.get()));
1137 return (jlong)source.release();
1138}
1139
1140JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack)(
1141 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1142 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001143 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001144 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001145 rtc::scoped_refptr<AudioTrackInterface> track(factory->CreateAudioTrack(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001146 JavaToStdString(jni, id),
1147 reinterpret_cast<AudioSourceInterface*>(native_source)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001148 return (jlong)track.release();
1149}
1150
phoglund@webrtc.org006521d2015-02-12 09:23:59 +00001151JOW(void, PeerConnectionFactory_nativeSetOptions)(
1152 JNIEnv* jni, jclass, jlong native_factory, jobject options) {
1153 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
1154 factoryFromJava(native_factory));
1155 jclass options_class = jni->GetObjectClass(options);
1156 jfieldID network_ignore_mask_field =
1157 jni->GetFieldID(options_class, "networkIgnoreMask", "I");
1158 int network_ignore_mask =
1159 jni->GetIntField(options, network_ignore_mask_field);
1160 PeerConnectionFactoryInterface::Options options_to_set;
1161
1162 // This doesn't necessarily match the c++ version of this struct; feel free
1163 // to add more parameters as necessary.
1164 options_to_set.network_ignore_mask = network_ignore_mask;
1165 factory->SetOptions(options_to_set);
1166}
1167
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001168static void JavaIceServersToJsepIceServers(
1169 JNIEnv* jni, jobject j_ice_servers,
1170 PeerConnectionInterface::IceServers* ice_servers) {
1171 jclass list_class = GetObjectClass(jni, j_ice_servers);
1172 jmethodID iterator_id = GetMethodID(
1173 jni, list_class, "iterator", "()Ljava/util/Iterator;");
1174 jobject iterator = jni->CallObjectMethod(j_ice_servers, iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001175 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176 jmethodID iterator_has_next = GetMethodID(
1177 jni, GetObjectClass(jni, iterator), "hasNext", "()Z");
1178 jmethodID iterator_next = GetMethodID(
1179 jni, GetObjectClass(jni, iterator), "next", "()Ljava/lang/Object;");
1180 while (jni->CallBooleanMethod(iterator, iterator_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001181 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001182 jobject j_ice_server = jni->CallObjectMethod(iterator, iterator_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001183 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001184 jclass j_ice_server_class = GetObjectClass(jni, j_ice_server);
1185 jfieldID j_ice_server_uri_id =
1186 GetFieldID(jni, j_ice_server_class, "uri", "Ljava/lang/String;");
1187 jfieldID j_ice_server_username_id =
1188 GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;");
1189 jfieldID j_ice_server_password_id =
1190 GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;");
1191 jstring uri = reinterpret_cast<jstring>(
1192 GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
1193 jstring username = reinterpret_cast<jstring>(
1194 GetObjectField(jni, j_ice_server, j_ice_server_username_id));
1195 jstring password = reinterpret_cast<jstring>(
1196 GetObjectField(jni, j_ice_server, j_ice_server_password_id));
1197 PeerConnectionInterface::IceServer server;
1198 server.uri = JavaToStdString(jni, uri);
1199 server.username = JavaToStdString(jni, username);
1200 server.password = JavaToStdString(jni, password);
1201 ice_servers->push_back(server);
1202 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001203 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204}
1205
1206JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
1207 JNIEnv *jni, jclass, jlong factory, jobject j_ice_servers,
1208 jobject j_constraints, jlong observer_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001209 rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001210 reinterpret_cast<PeerConnectionFactoryInterface*>(
1211 factoryFromJava(factory)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001212 PeerConnectionInterface::IceServers servers;
1213 JavaIceServersToJsepIceServers(jni, j_ice_servers, &servers);
1214 PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
1215 observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001216 rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
mallinath@webrtc.orga0d30672014-04-26 00:00:15 +00001217 servers, observer->constraints(), NULL, NULL, observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001218 return (jlong)pc.release();
1219}
1220
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001221static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222 JNIEnv* jni, jobject j_pc) {
1223 jfieldID native_pc_id = GetFieldID(jni,
1224 GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
1225 jlong j_p = GetLongField(jni, j_pc, native_pc_id);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001226 return rtc::scoped_refptr<PeerConnectionInterface>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001227 reinterpret_cast<PeerConnectionInterface*>(j_p));
1228}
1229
1230JOW(jobject, PeerConnection_getLocalDescription)(JNIEnv* jni, jobject j_pc) {
1231 const SessionDescriptionInterface* sdp =
1232 ExtractNativePC(jni, j_pc)->local_description();
1233 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1234}
1235
1236JOW(jobject, PeerConnection_getRemoteDescription)(JNIEnv* jni, jobject j_pc) {
1237 const SessionDescriptionInterface* sdp =
1238 ExtractNativePC(jni, j_pc)->remote_description();
1239 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1240}
1241
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001242JOW(jobject, PeerConnection_createDataChannel)(
1243 JNIEnv* jni, jobject j_pc, jstring j_label, jobject j_init) {
1244 DataChannelInit init = JavaDataChannelInitToNative(jni, j_init);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001245 rtc::scoped_refptr<DataChannelInterface> channel(
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001246 ExtractNativePC(jni, j_pc)->CreateDataChannel(
1247 JavaToStdString(jni, j_label), &init));
fischman@webrtc.org87881672013-09-03 18:58:12 +00001248 // Mustn't pass channel.get() directly through NewObject to avoid reading its
1249 // vararg parameter as 64-bit and reading memory that doesn't belong to the
1250 // 32-bit parameter.
1251 jlong nativeChannelPtr = jlongFromPointer(channel.get());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001252 CHECK(nativeChannelPtr) << "Failed to create DataChannel";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001253 jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
1254 jmethodID j_data_channel_ctor = GetMethodID(
1255 jni, j_data_channel_class, "<init>", "(J)V");
1256 jobject j_channel = jni->NewObject(
fischman@webrtc.org87881672013-09-03 18:58:12 +00001257 j_data_channel_class, j_data_channel_ctor, nativeChannelPtr);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001258 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001259 // Channel is now owned by Java object, and will be freed from there.
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001260 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001261 CHECK(bumped_count == 2) << "Unexpected refcount";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001262 return j_channel;
1263}
1264
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001265JOW(void, PeerConnection_createOffer)(
1266 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1267 ConstraintsWrapper* constraints =
1268 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001269 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1270 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001271 jni, j_observer, constraints));
1272 ExtractNativePC(jni, j_pc)->CreateOffer(observer, constraints);
1273}
1274
1275JOW(void, PeerConnection_createAnswer)(
1276 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1277 ConstraintsWrapper* constraints =
1278 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001279 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1280 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001281 jni, j_observer, constraints));
1282 ExtractNativePC(jni, j_pc)->CreateAnswer(observer, constraints);
1283}
1284
1285// Helper to create a SessionDescriptionInterface from a SessionDescription.
1286static SessionDescriptionInterface* JavaSdpToNativeSdp(
1287 JNIEnv* jni, jobject j_sdp) {
1288 jfieldID j_type_id = GetFieldID(
1289 jni, GetObjectClass(jni, j_sdp), "type",
1290 "Lorg/webrtc/SessionDescription$Type;");
1291 jobject j_type = GetObjectField(jni, j_sdp, j_type_id);
1292 jmethodID j_canonical_form_id = GetMethodID(
1293 jni, GetObjectClass(jni, j_type), "canonicalForm",
1294 "()Ljava/lang/String;");
1295 jstring j_type_string = (jstring)jni->CallObjectMethod(
1296 j_type, j_canonical_form_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 std::string std_type = JavaToStdString(jni, j_type_string);
1299
1300 jfieldID j_description_id = GetFieldID(
1301 jni, GetObjectClass(jni, j_sdp), "description", "Ljava/lang/String;");
1302 jstring j_description = (jstring)GetObjectField(jni, j_sdp, j_description_id);
1303 std::string std_description = JavaToStdString(jni, j_description);
1304
1305 return webrtc::CreateSessionDescription(
1306 std_type, std_description, NULL);
1307}
1308
1309JOW(void, PeerConnection_setLocalDescription)(
1310 JNIEnv* jni, jobject j_pc,
1311 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001312 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1313 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001314 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1315 ExtractNativePC(jni, j_pc)->SetLocalDescription(
1316 observer, JavaSdpToNativeSdp(jni, j_sdp));
1317}
1318
1319JOW(void, PeerConnection_setRemoteDescription)(
1320 JNIEnv* jni, jobject j_pc,
1321 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001322 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1323 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1325 ExtractNativePC(jni, j_pc)->SetRemoteDescription(
1326 observer, JavaSdpToNativeSdp(jni, j_sdp));
1327}
1328
1329JOW(jboolean, PeerConnection_updateIce)(
1330 JNIEnv* jni, jobject j_pc, jobject j_ice_servers, jobject j_constraints) {
1331 PeerConnectionInterface::IceServers ice_servers;
1332 JavaIceServersToJsepIceServers(jni, j_ice_servers, &ice_servers);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001333 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001334 new ConstraintsWrapper(jni, j_constraints));
1335 return ExtractNativePC(jni, j_pc)->UpdateIce(ice_servers, constraints.get());
1336}
1337
1338JOW(jboolean, PeerConnection_nativeAddIceCandidate)(
1339 JNIEnv* jni, jobject j_pc, jstring j_sdp_mid,
1340 jint j_sdp_mline_index, jstring j_candidate_sdp) {
1341 std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
1342 std::string sdp = JavaToStdString(jni, j_candidate_sdp);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001343 scoped_ptr<IceCandidateInterface> candidate(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001344 webrtc::CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, NULL));
1345 return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
1346}
1347
1348JOW(jboolean, PeerConnection_nativeAddLocalStream)(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001349 JNIEnv* jni, jobject j_pc, jlong native_stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001350 return ExtractNativePC(jni, j_pc)->AddStream(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001351 reinterpret_cast<MediaStreamInterface*>(native_stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001352}
1353
1354JOW(void, PeerConnection_nativeRemoveLocalStream)(
1355 JNIEnv* jni, jobject j_pc, jlong native_stream) {
1356 ExtractNativePC(jni, j_pc)->RemoveStream(
1357 reinterpret_cast<MediaStreamInterface*>(native_stream));
1358}
1359
1360JOW(bool, PeerConnection_nativeGetStats)(
1361 JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001362 rtc::scoped_refptr<StatsObserverWrapper> observer(
1363 new rtc::RefCountedObject<StatsObserverWrapper>(jni, j_observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001364 return ExtractNativePC(jni, j_pc)->GetStats(
jiayl@webrtc.orgdb41b4d2014-03-03 21:30:06 +00001365 observer,
1366 reinterpret_cast<MediaStreamTrackInterface*>(native_track),
1367 PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001368}
1369
1370JOW(jobject, PeerConnection_signalingState)(JNIEnv* jni, jobject j_pc) {
1371 PeerConnectionInterface::SignalingState state =
1372 ExtractNativePC(jni, j_pc)->signaling_state();
1373 return JavaEnumFromIndex(jni, "PeerConnection$SignalingState", state);
1374}
1375
1376JOW(jobject, PeerConnection_iceConnectionState)(JNIEnv* jni, jobject j_pc) {
1377 PeerConnectionInterface::IceConnectionState state =
1378 ExtractNativePC(jni, j_pc)->ice_connection_state();
1379 return JavaEnumFromIndex(jni, "PeerConnection$IceConnectionState", state);
1380}
1381
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001382JOW(jobject, PeerConnection_iceGatheringState)(JNIEnv* jni, jobject j_pc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001383 PeerConnectionInterface::IceGatheringState state =
1384 ExtractNativePC(jni, j_pc)->ice_gathering_state();
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001385 return JavaEnumFromIndex(jni, "PeerConnection$IceGatheringState", state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001386}
1387
1388JOW(void, PeerConnection_close)(JNIEnv* jni, jobject j_pc) {
1389 ExtractNativePC(jni, j_pc)->Close();
1390 return;
1391}
1392
1393JOW(jobject, MediaSource_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001394 rtc::scoped_refptr<MediaSourceInterface> p(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001395 reinterpret_cast<MediaSourceInterface*>(j_p));
1396 return JavaEnumFromIndex(jni, "MediaSource$State", p->state());
1397}
1398
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001399JOW(jobject, VideoCapturer_nativeCreateVideoCapturer)(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001400 JNIEnv* jni, jclass, jstring j_device_name) {
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001401// Since we can't create platform specific java implementations in Java, we
1402// defer the creation to C land.
1403#if defined(ANDROID)
1404 jclass j_video_capturer_class(
1405 FindClass(jni, "org/webrtc/VideoCapturerAndroid"));
1406 const jmethodID j_videocapturer_ctor(GetMethodID(
1407 jni, j_video_capturer_class, "<init>", "()V"));
1408 jobject j_video_capturer = jni->NewObject(j_video_capturer_class,
1409 j_videocapturer_ctor);
1410 CHECK_EXCEPTION(jni) << "error during NewObject";
1411
Per33544192015-04-02 12:30:51 +02001412 rtc::scoped_refptr<AndroidVideoCapturerJni> delegate =
perkj@webrtc.org112f1272015-02-25 09:20:07 +00001413 AndroidVideoCapturerJni::Create(jni, j_video_capturer, j_device_name);
1414 if (!delegate.get())
perkj@webrtc.org3db042e2015-02-19 08:43:38 +00001415 return nullptr;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001416 rtc::scoped_ptr<webrtc::AndroidVideoCapturer> capturer(
Per33544192015-04-02 12:30:51 +02001417 new webrtc::AndroidVideoCapturer(delegate));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001418
1419#else
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001420 std::string device_name = JavaToStdString(jni, j_device_name);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001421 scoped_ptr<cricket::DeviceManagerInterface> device_manager(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001422 cricket::DeviceManagerFactory::Create());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001423 CHECK(device_manager->Init()) << "DeviceManager::Init() failed";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001424 cricket::Device device;
1425 if (!device_manager->GetVideoCaptureDevice(device_name, &device)) {
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001426 LOG(LS_ERROR) << "GetVideoCaptureDevice failed for " << device_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001427 return 0;
1428 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001429 scoped_ptr<cricket::VideoCapturer> capturer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001430 device_manager->CreateVideoCapturer(device));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001431
1432 jclass j_video_capturer_class(
1433 FindClass(jni, "org/webrtc/VideoCapturer"));
1434 const jmethodID j_videocapturer_ctor(GetMethodID(
1435 jni, j_video_capturer_class, "<init>", "()V"));
1436 jobject j_video_capturer =
1437 jni->NewObject(j_video_capturer_class,
1438 j_videocapturer_ctor);
1439 CHECK_EXCEPTION(jni) << "error during creation of VideoCapturer";
1440
1441#endif
1442 const jmethodID j_videocapturer_set_native_capturer(GetMethodID(
1443 jni, j_video_capturer_class, "setNativeCapturer", "(J)V"));
1444 jni->CallVoidMethod(j_video_capturer,
1445 j_videocapturer_set_native_capturer,
1446 (jlong)capturer.release());
1447 CHECK_EXCEPTION(jni) << "error during setNativeCapturer";
1448 return j_video_capturer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001449}
1450
1451JOW(jlong, VideoRenderer_nativeCreateGuiVideoRenderer)(
1452 JNIEnv* jni, jclass, int x, int y) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001453 scoped_ptr<VideoRendererWrapper> renderer(VideoRendererWrapper::Create(
1454 cricket::VideoRendererFactory::CreateGuiVideoRenderer(x, y)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001455 return (jlong)renderer.release();
1456}
1457
1458JOW(jlong, VideoRenderer_nativeWrapVideoRenderer)(
1459 JNIEnv* jni, jclass, jobject j_callbacks) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001460 scoped_ptr<JavaVideoRendererWrapper> renderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001461 new JavaVideoRendererWrapper(jni, j_callbacks));
1462 return (jlong)renderer.release();
1463}
1464
glaznev@webrtc.orgf6932292015-02-05 17:29:59 +00001465JOW(void, VideoRenderer_nativeCopyPlane)(
1466 JNIEnv *jni, jclass, jobject j_src_buffer, jint width, jint height,
1467 jint src_stride, jobject j_dst_buffer, jint dst_stride) {
1468 size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer);
1469 size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
1470 CHECK(src_stride >= width) << "Wrong source stride " << src_stride;
1471 CHECK(dst_stride >= width) << "Wrong destination stride " << dst_stride;
1472 CHECK(src_size >= src_stride * height)
1473 << "Insufficient source buffer capacity " << src_size;
1474 CHECK(dst_size >= dst_stride * height)
1475 << "Isufficient destination buffer capacity " << dst_size;
1476 uint8_t *src =
1477 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer));
1478 uint8_t *dst =
1479 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
1480 if (src_stride == dst_stride) {
1481 memcpy(dst, src, src_stride * height);
1482 } else {
1483 for (int i = 0; i < height; i++) {
1484 memcpy(dst, src, width);
1485 src += src_stride;
1486 dst += dst_stride;
1487 }
1488 }
1489}
1490
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001491JOW(void, VideoSource_stop)(JNIEnv* jni, jclass, jlong j_p) {
1492 reinterpret_cast<VideoSourceInterface*>(j_p)->Stop();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001493}
1494
1495JOW(void, VideoSource_restart)(
1496 JNIEnv* jni, jclass, jlong j_p_source, jlong j_p_format) {
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001497 reinterpret_cast<VideoSourceInterface*>(j_p_source)->Restart();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001498}
1499
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001500JOW(jstring, MediaStreamTrack_nativeId)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001501 return JavaStringFromStdString(
1502 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001503}
1504
1505JOW(jstring, MediaStreamTrack_nativeKind)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001506 return JavaStringFromStdString(
1507 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->kind());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508}
1509
1510JOW(jboolean, MediaStreamTrack_nativeEnabled)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001511 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->enabled();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001512}
1513
1514JOW(jobject, MediaStreamTrack_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001515 return JavaEnumFromIndex(
1516 jni,
1517 "MediaStreamTrack$State",
1518 reinterpret_cast<MediaStreamTrackInterface*>(j_p)->state());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001519}
1520
1521JOW(jboolean, MediaStreamTrack_nativeSetState)(
1522 JNIEnv* jni, jclass, jlong j_p, jint j_new_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001523 MediaStreamTrackInterface::TrackState new_state =
1524 (MediaStreamTrackInterface::TrackState)j_new_state;
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001525 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1526 ->set_state(new_state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001527}
1528
1529JOW(jboolean, MediaStreamTrack_nativeSetEnabled)(
1530 JNIEnv* jni, jclass, jlong j_p, jboolean enabled) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001531 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1532 ->set_enabled(enabled);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533}
1534
1535JOW(void, VideoTrack_nativeAddRenderer)(
1536 JNIEnv* jni, jclass,
1537 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001538 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->AddRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1540}
1541
1542JOW(void, VideoTrack_nativeRemoveRenderer)(
1543 JNIEnv* jni, jclass,
1544 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001545 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1547}
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001548
1549} // namespace webrtc_jni