blob: 460ad7efb37d1d627250c8155b5c630c5fec3cfd [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"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000073#include "webrtc/base/bind.h"
andresp@webrtc.org4d19e052014-09-09 11:45:44 +000074#include "webrtc/base/checks.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000075#include "webrtc/base/logging.h"
76#include "webrtc/base/messagequeue.h"
77#include "webrtc/base/ssladapter.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000078#include "webrtc/base/stringutils.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000079#include "webrtc/system_wrappers/interface/field_trial_default.h"
henrike@webrtc.org9de257d2013-07-17 14:42:53 +000080#include "webrtc/system_wrappers/interface/trace.h"
81#include "webrtc/video_engine/include/vie_base.h"
82#include "webrtc/voice_engine/include/voe_base.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083
glaznev@webrtc.org99678452014-09-15 17:52:42 +000084#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
perkj@webrtc.org83bc7212015-02-11 11:26:56 +000085#include "talk/app/webrtc/androidvideocapturer.h"
glaznev@webrtc.org18c92472015-02-18 18:42:55 +000086#include "talk/app/webrtc/java/jni/androidmediadecoder_jni.h"
87#include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h"
perkj@webrtc.org96e4db92015-02-13 12:46:51 +000088#include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h"
andresp@webrtc.org85ef7702014-09-17 11:44:51 +000089#include "webrtc/modules/video_render/video_render_internal.h"
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +000090#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
91using webrtc::LogcatTraceContext;
92#endif
93
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000094using rtc::Bind;
95using rtc::Thread;
96using rtc::ThreadManager;
97using rtc::scoped_ptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098using webrtc::AudioSourceInterface;
99using webrtc::AudioTrackInterface;
100using webrtc::AudioTrackVector;
101using webrtc::CreateSessionDescriptionObserver;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000102using webrtc::DataBuffer;
103using webrtc::DataChannelInit;
104using webrtc::DataChannelInterface;
105using webrtc::DataChannelObserver;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106using webrtc::IceCandidateInterface;
107using webrtc::MediaConstraintsInterface;
108using webrtc::MediaSourceInterface;
109using webrtc::MediaStreamInterface;
110using webrtc::MediaStreamTrackInterface;
111using webrtc::PeerConnectionFactoryInterface;
112using webrtc::PeerConnectionInterface;
113using webrtc::PeerConnectionObserver;
114using webrtc::SessionDescriptionInterface;
115using webrtc::SetSessionDescriptionObserver;
116using webrtc::StatsObserver;
117using webrtc::StatsReport;
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000118using webrtc::StatsReports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119using webrtc::VideoRendererInterface;
120using webrtc::VideoSourceInterface;
121using webrtc::VideoTrackInterface;
122using webrtc::VideoTrackVector;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000123using webrtc::kVideoCodecVP8;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000124
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000125namespace webrtc_jni {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000126
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +0000127// Field trials initialization string
128static char *field_trials_init_string = NULL;
129
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000130#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
131// Set in PeerConnectionFactory_initializeAndroidGlobals().
132static bool factory_static_initialized = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000133static bool vp8_hw_acceleration_enabled = true;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000134#endif
135
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000136extern "C" jint JNIEXPORT JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000137 jint ret = InitGlobalJniVariables(jvm);
138 if (ret < 0)
139 return -1;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000140
141 CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000142 LoadGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000143
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000144 return ret;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000145}
146
147extern "C" void JNIEXPORT JNICALL JNI_OnUnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000148 FreeGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000149 CHECK(rtc::CleanupSSL()) << "Failed to CleanupSSL()";
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000150}
151
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152// Return the (singleton) Java Enum object corresponding to |index|;
153// |state_class_fragment| is something like "MediaSource$State".
glaznev@webrtc.orgb28474c2015-02-23 17:44:27 +0000154static jobject JavaEnumFromIndex(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 JNIEnv* jni, const std::string& state_class_fragment, int index) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000156 const std::string state_class = "org/webrtc/" + state_class_fragment;
157 return JavaEnumFromIndex(jni, FindClass(jni, state_class.c_str()),
158 state_class, index);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159}
160
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000161static DataChannelInit JavaDataChannelInitToNative(
162 JNIEnv* jni, jobject j_init) {
163 DataChannelInit init;
164
165 jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init");
166 jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z");
167 jfieldID max_retransmit_time_id =
168 GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I");
169 jfieldID max_retransmits_id =
170 GetFieldID(jni, j_init_class, "maxRetransmits", "I");
171 jfieldID protocol_id =
172 GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;");
173 jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z");
174 jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I");
175
176 init.ordered = GetBooleanField(jni, j_init, ordered_id);
177 init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id);
178 init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id);
179 init.protocol = JavaToStdString(
180 jni, GetStringField(jni, j_init, protocol_id));
181 init.negotiated = GetBooleanField(jni, j_init, negotiated_id);
182 init.id = GetIntField(jni, j_init, id_id);
183
184 return init;
185}
186
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000187class ConstraintsWrapper;
188
189// Adapter between the C++ PeerConnectionObserver interface and the Java
190// PeerConnection.Observer interface. Wraps an instance of the Java interface
191// and dispatches C++ callbacks to Java.
192class PCOJava : public PeerConnectionObserver {
193 public:
194 PCOJava(JNIEnv* jni, jobject j_observer)
195 : j_observer_global_(jni, j_observer),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000196 j_observer_class_(jni, GetObjectClass(jni, *j_observer_global_)),
197 j_media_stream_class_(jni, FindClass(jni, "org/webrtc/MediaStream")),
198 j_media_stream_ctor_(GetMethodID(
199 jni, *j_media_stream_class_, "<init>", "(J)V")),
200 j_audio_track_class_(jni, FindClass(jni, "org/webrtc/AudioTrack")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000201 j_audio_track_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000202 jni, *j_audio_track_class_, "<init>", "(J)V")),
203 j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")),
204 j_video_track_ctor_(GetMethodID(
205 jni, *j_video_track_class_, "<init>", "(J)V")),
206 j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")),
207 j_data_channel_ctor_(GetMethodID(
208 jni, *j_data_channel_class_, "<init>", "(J)V")) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000209 }
210
211 virtual ~PCOJava() {}
212
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000213 void OnIceCandidate(const IceCandidateInterface* candidate) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000214 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000216 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000217 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
218 jmethodID ctor = GetMethodID(jni(), candidate_class,
219 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000220 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
221 jstring j_sdp = JavaStringFromStdString(jni(), sdp);
222 jobject j_candidate = jni()->NewObject(
223 candidate_class, ctor, j_mid, candidate->sdp_mline_index(), j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000224 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000225 jmethodID m = GetMethodID(jni(), *j_observer_class_,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226 "onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000227 jni()->CallVoidMethod(*j_observer_global_, m, j_candidate);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000228 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229 }
230
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000231 void OnSignalingChange(
232 PeerConnectionInterface::SignalingState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000233 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000235 jni(), *j_observer_class_, "onSignalingChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236 "(Lorg/webrtc/PeerConnection$SignalingState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000237 jobject new_state_enum =
238 JavaEnumFromIndex(jni(), "PeerConnection$SignalingState", new_state);
239 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000240 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000241 }
242
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000243 void OnIceConnectionChange(
244 PeerConnectionInterface::IceConnectionState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000245 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000246 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000247 jni(), *j_observer_class_, "onIceConnectionChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000248 "(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000249 jobject new_state_enum = JavaEnumFromIndex(
250 jni(), "PeerConnection$IceConnectionState", new_state);
251 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000252 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000253 }
254
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000255 void OnIceGatheringChange(
256 PeerConnectionInterface::IceGatheringState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000257 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000259 jni(), *j_observer_class_, "onIceGatheringChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000260 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000261 jobject new_state_enum = JavaEnumFromIndex(
262 jni(), "PeerConnection$IceGatheringState", new_state);
263 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000264 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000265 }
266
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000267 void OnAddStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000268 ScopedLocalRefFrame local_ref_frame(jni());
269 jobject j_stream = jni()->NewObject(
270 *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000271 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000272
273 AudioTrackVector audio_tracks = stream->GetAudioTracks();
274 for (size_t i = 0; i < audio_tracks.size(); ++i) {
275 AudioTrackInterface* track = audio_tracks[i];
fischman@webrtc.org41776152014-01-09 00:31:17 +0000276 jstring id = JavaStringFromStdString(jni(), track->id());
277 jobject j_track = jni()->NewObject(
278 *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000279 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000280 jfieldID audio_tracks_id = GetFieldID(jni(),
281 *j_media_stream_class_,
282 "audioTracks",
283 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000284 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000286 GetObjectClass(jni(), audio_tracks),
287 "add",
288 "(Ljava/lang/Object;)Z");
289 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000290 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
291 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000292 }
293
294 VideoTrackVector video_tracks = stream->GetVideoTracks();
295 for (size_t i = 0; i < video_tracks.size(); ++i) {
296 VideoTrackInterface* track = video_tracks[i];
fischman@webrtc.org41776152014-01-09 00:31:17 +0000297 jstring id = JavaStringFromStdString(jni(), track->id());
298 jobject j_track = jni()->NewObject(
299 *j_video_track_class_, j_video_track_ctor_, (jlong)track, id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000300 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000301 jfieldID video_tracks_id = GetFieldID(jni(),
302 *j_media_stream_class_,
303 "videoTracks",
304 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000305 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000307 GetObjectClass(jni(), video_tracks),
308 "add",
309 "(Ljava/lang/Object;)Z");
310 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000311 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
312 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000313 }
fischman@webrtc.org41776152014-01-09 00:31:17 +0000314 streams_[stream] = jni()->NewWeakGlobalRef(j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000315 CHECK_EXCEPTION(jni()) << "error during NewWeakGlobalRef";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000317 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
318 "(Lorg/webrtc/MediaStream;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000319 jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000320 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000321 }
322
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000323 void OnRemoveStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000324 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000325 NativeToJavaStreamsMap::iterator it = streams_.find(stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000326 CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000327
328 WeakRef s(jni(), it->second);
329 streams_.erase(it);
330 if (!s.obj())
331 return;
332
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000333 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
334 "(Lorg/webrtc/MediaStream;)V");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335 jni()->CallVoidMethod(*j_observer_global_, m, s.obj());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000336 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000337 }
338
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000339 void OnDataChannel(DataChannelInterface* channel) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000340 ScopedLocalRefFrame local_ref_frame(jni());
341 jobject j_channel = jni()->NewObject(
342 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000343 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000344
345 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
346 "(Lorg/webrtc/DataChannel;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000347 jni()->CallVoidMethod(*j_observer_global_, m, j_channel);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000348
349 // Channel is now owned by Java object, and will be freed from
350 // DataChannel.dispose(). Important that this be done _after_ the
351 // CallVoidMethod above as Java code might call back into native code and be
352 // surprised to see a refcount of 2.
353 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000354 CHECK(bumped_count == 2) << "Unexpected refcount OnDataChannel";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000355
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000356 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000357 }
358
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000359 void OnRenegotiationNeeded() override {
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000360 ScopedLocalRefFrame local_ref_frame(jni());
361 jmethodID m =
362 GetMethodID(jni(), *j_observer_class_, "onRenegotiationNeeded", "()V");
363 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000364 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000365 }
366
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000367 void SetConstraints(ConstraintsWrapper* constraints) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000368 CHECK(!constraints_.get()) << "constraints already set!";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000369 constraints_.reset(constraints);
370 }
371
372 const ConstraintsWrapper* constraints() { return constraints_.get(); }
373
374 private:
375 JNIEnv* jni() {
376 return AttachCurrentThreadIfNeeded();
377 }
378
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000379 const ScopedGlobalRef<jobject> j_observer_global_;
380 const ScopedGlobalRef<jclass> j_observer_class_;
381 const ScopedGlobalRef<jclass> j_media_stream_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000382 const jmethodID j_media_stream_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000383 const ScopedGlobalRef<jclass> j_audio_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384 const jmethodID j_audio_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000385 const ScopedGlobalRef<jclass> j_video_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000386 const jmethodID j_video_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000387 const ScopedGlobalRef<jclass> j_data_channel_class_;
388 const jmethodID j_data_channel_ctor_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000389 typedef std::map<void*, jweak> NativeToJavaStreamsMap;
390 NativeToJavaStreamsMap streams_; // C++ -> Java streams.
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000391 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000392};
393
394// Wrapper for a Java MediaConstraints object. Copies all needed data so when
395// the constructor returns the Java object is no longer needed.
396class ConstraintsWrapper : public MediaConstraintsInterface {
397 public:
398 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) {
399 PopulateConstraintsFromJavaPairList(
400 jni, j_constraints, "mandatory", &mandatory_);
401 PopulateConstraintsFromJavaPairList(
402 jni, j_constraints, "optional", &optional_);
403 }
404
405 virtual ~ConstraintsWrapper() {}
406
407 // MediaConstraintsInterface.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000408 const Constraints& GetMandatory() const override { return mandatory_; }
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000409
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000410 const Constraints& GetOptional() const override { return optional_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000411
412 private:
413 // Helper for translating a List<Pair<String, String>> to a Constraints.
414 static void PopulateConstraintsFromJavaPairList(
415 JNIEnv* jni, jobject j_constraints,
416 const char* field_name, Constraints* field) {
417 jfieldID j_id = GetFieldID(jni,
418 GetObjectClass(jni, j_constraints), field_name, "Ljava/util/List;");
419 jobject j_list = GetObjectField(jni, j_constraints, j_id);
420 jmethodID j_iterator_id = GetMethodID(jni,
421 GetObjectClass(jni, j_list), "iterator", "()Ljava/util/Iterator;");
422 jobject j_iterator = jni->CallObjectMethod(j_list, j_iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000423 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000424 jmethodID j_has_next = GetMethodID(jni,
425 GetObjectClass(jni, j_iterator), "hasNext", "()Z");
426 jmethodID j_next = GetMethodID(jni,
427 GetObjectClass(jni, j_iterator), "next", "()Ljava/lang/Object;");
428 while (jni->CallBooleanMethod(j_iterator, j_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000429 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000430 jobject entry = jni->CallObjectMethod(j_iterator, j_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000431 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000432 jmethodID get_key = GetMethodID(jni,
433 GetObjectClass(jni, entry), "getKey", "()Ljava/lang/String;");
434 jstring j_key = reinterpret_cast<jstring>(
435 jni->CallObjectMethod(entry, get_key));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000436 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000437 jmethodID get_value = GetMethodID(jni,
438 GetObjectClass(jni, entry), "getValue", "()Ljava/lang/String;");
439 jstring j_value = reinterpret_cast<jstring>(
440 jni->CallObjectMethod(entry, get_value));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000441 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442 field->push_back(Constraint(JavaToStdString(jni, j_key),
443 JavaToStdString(jni, j_value)));
444 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000445 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446 }
447
448 Constraints mandatory_;
449 Constraints optional_;
450};
451
452static jobject JavaSdpFromNativeSdp(
453 JNIEnv* jni, const SessionDescriptionInterface* desc) {
454 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000455 CHECK(desc->ToString(&sdp)) << "got so far: " << sdp;
fischman@webrtc.org41776152014-01-09 00:31:17 +0000456 jstring j_description = JavaStringFromStdString(jni, sdp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000457
458 jclass j_type_class = FindClass(
459 jni, "org/webrtc/SessionDescription$Type");
460 jmethodID j_type_from_canonical = GetStaticMethodID(
461 jni, j_type_class, "fromCanonicalForm",
462 "(Ljava/lang/String;)Lorg/webrtc/SessionDescription$Type;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000463 jstring j_type_string = JavaStringFromStdString(jni, desc->type());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000464 jobject j_type = jni->CallStaticObjectMethod(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000465 j_type_class, j_type_from_canonical, j_type_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000466 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467
468 jclass j_sdp_class = FindClass(jni, "org/webrtc/SessionDescription");
469 jmethodID j_sdp_ctor = GetMethodID(
470 jni, j_sdp_class, "<init>",
471 "(Lorg/webrtc/SessionDescription$Type;Ljava/lang/String;)V");
472 jobject j_sdp = jni->NewObject(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000473 j_sdp_class, j_sdp_ctor, j_type, j_description);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000474 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000475 return j_sdp;
476}
477
478template <class T> // T is one of {Create,Set}SessionDescriptionObserver.
479class SdpObserverWrapper : public T {
480 public:
481 SdpObserverWrapper(JNIEnv* jni, jobject j_observer,
482 ConstraintsWrapper* constraints)
483 : constraints_(constraints),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000484 j_observer_global_(jni, j_observer),
485 j_observer_class_(jni, GetObjectClass(jni, j_observer)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 }
487
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000488 virtual ~SdpObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000489
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000490 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 virtual void OnSuccess() {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000492 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000493 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
494 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000495 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000496 }
497
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000498 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 virtual void OnSuccess(SessionDescriptionInterface* desc) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000500 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000501 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000502 jni(), *j_observer_class_, "onCreateSuccess",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503 "(Lorg/webrtc/SessionDescription;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000504 jobject j_sdp = JavaSdpFromNativeSdp(jni(), desc);
505 jni()->CallVoidMethod(*j_observer_global_, m, j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000506 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000507 }
508
509 protected:
510 // Common implementation for failure of Set & Create types, distinguished by
511 // |op| being "Set" or "Create".
512 void OnFailure(const std::string& op, const std::string& error) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000513 jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
514 "(Ljava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000515 jstring j_error_string = JavaStringFromStdString(jni(), error);
516 jni()->CallVoidMethod(*j_observer_global_, m, j_error_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000517 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000518 }
519
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520 JNIEnv* jni() {
521 return AttachCurrentThreadIfNeeded();
522 }
523
fischman@webrtc.org41776152014-01-09 00:31:17 +0000524 private:
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000525 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000526 const ScopedGlobalRef<jobject> j_observer_global_;
527 const ScopedGlobalRef<jclass> j_observer_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528};
529
530class CreateSdpObserverWrapper
531 : public SdpObserverWrapper<CreateSessionDescriptionObserver> {
532 public:
533 CreateSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
534 ConstraintsWrapper* constraints)
535 : SdpObserverWrapper(jni, j_observer, constraints) {}
536
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000537 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000538 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000539 SdpObserverWrapper::OnFailure(std::string("Create"), error);
540 }
541};
542
543class SetSdpObserverWrapper
544 : public SdpObserverWrapper<SetSessionDescriptionObserver> {
545 public:
546 SetSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
547 ConstraintsWrapper* constraints)
548 : SdpObserverWrapper(jni, j_observer, constraints) {}
549
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000550 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000551 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000552 SdpObserverWrapper::OnFailure(std::string("Set"), error);
553 }
554};
555
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000556// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
557// and dispatching the callback from C++ back to Java.
558class DataChannelObserverWrapper : public DataChannelObserver {
559 public:
560 DataChannelObserverWrapper(JNIEnv* jni, jobject j_observer)
561 : j_observer_global_(jni, j_observer),
562 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
pbos@webrtc.orgb648b9d2014-08-26 11:08:06 +0000563 j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000564 j_on_state_change_mid_(GetMethodID(jni, *j_observer_class_,
565 "onStateChange", "()V")),
566 j_on_message_mid_(GetMethodID(jni, *j_observer_class_, "onMessage",
567 "(Lorg/webrtc/DataChannel$Buffer;)V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000568 j_buffer_ctor_(GetMethodID(jni, *j_buffer_class_,
569 "<init>", "(Ljava/nio/ByteBuffer;Z)V")) {
570 }
571
572 virtual ~DataChannelObserverWrapper() {}
573
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000574 void OnStateChange() override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000575 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000576 jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000577 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000578 }
579
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000580 void OnMessage(const DataBuffer& buffer) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000581 ScopedLocalRefFrame local_ref_frame(jni());
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000582 jobject byte_buffer = jni()->NewDirectByteBuffer(
Karl Wiberg94784372015-04-20 14:03:07 +0200583 const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000584 jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_,
585 byte_buffer, buffer.binary);
586 jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000587 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000588 }
589
590 private:
591 JNIEnv* jni() {
592 return AttachCurrentThreadIfNeeded();
593 }
594
595 const ScopedGlobalRef<jobject> j_observer_global_;
596 const ScopedGlobalRef<jclass> j_observer_class_;
597 const ScopedGlobalRef<jclass> j_buffer_class_;
598 const jmethodID j_on_state_change_mid_;
599 const jmethodID j_on_message_mid_;
600 const jmethodID j_buffer_ctor_;
601};
602
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603// Adapter for a Java StatsObserver presenting a C++ StatsObserver and
604// dispatching the callback from C++ back to Java.
605class StatsObserverWrapper : public StatsObserver {
606 public:
607 StatsObserverWrapper(JNIEnv* jni, jobject j_observer)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000608 : j_observer_global_(jni, j_observer),
609 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
610 j_stats_report_class_(jni, FindClass(jni, "org/webrtc/StatsReport")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611 j_stats_report_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000612 jni, *j_stats_report_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000613 "(Ljava/lang/String;Ljava/lang/String;D"
614 "[Lorg/webrtc/StatsReport$Value;)V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000615 j_value_class_(jni, FindClass(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 jni, "org/webrtc/StatsReport$Value")),
617 j_value_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000618 jni, *j_value_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619 "(Ljava/lang/String;Ljava/lang/String;)V")) {
620 }
621
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000622 virtual ~StatsObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000623
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000624 void OnComplete(const StatsReports& reports) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000625 ScopedLocalRefFrame local_ref_frame(jni());
626 jobjectArray j_reports = ReportsToJava(jni(), reports);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000627 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
628 "([Lorg/webrtc/StatsReport;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000629 jni()->CallVoidMethod(*j_observer_global_, m, j_reports);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000630 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631 }
632
633 private:
634 jobjectArray ReportsToJava(
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000635 JNIEnv* jni, const StatsReports& reports) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636 jobjectArray reports_array = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000637 reports.size(), *j_stats_report_class_, NULL);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000638 int i = 0;
639 for (const auto* report : reports) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000640 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000641 jstring j_id = JavaStringFromStdString(jni, report->id()->ToString());
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000642 jstring j_type = JavaStringFromStdString(jni, report->TypeToString());
643 jobjectArray j_values = ValuesToJava(jni, report->values());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000644 jobject j_report = jni->NewObject(*j_stats_report_class_,
645 j_stats_report_ctor_,
646 j_id,
647 j_type,
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000648 report->timestamp(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000649 j_values);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000650 jni->SetObjectArrayElement(reports_array, i++, j_report);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000651 }
652 return reports_array;
653 }
654
655 jobjectArray ValuesToJava(JNIEnv* jni, const StatsReport::Values& values) {
656 jobjectArray j_values = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000657 values.size(), *j_value_class_, NULL);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000658 int i = 0;
659 for (const auto& it : values) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000660 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgc57310b2014-12-12 17:41:28 +0000661 // Should we use the '.name' enum value here instead of converting the
662 // name to a string?
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000663 jstring j_name = JavaStringFromStdString(jni, it.second->display_name());
664 jstring j_value = JavaStringFromStdString(jni, it.second->ToString());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000665 jobject j_element_value =
666 jni->NewObject(*j_value_class_, j_value_ctor_, j_name, j_value);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000667 jni->SetObjectArrayElement(j_values, i++, j_element_value);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668 }
669 return j_values;
670 }
671
672 JNIEnv* jni() {
673 return AttachCurrentThreadIfNeeded();
674 }
675
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000676 const ScopedGlobalRef<jobject> j_observer_global_;
677 const ScopedGlobalRef<jclass> j_observer_class_;
678 const ScopedGlobalRef<jclass> j_stats_report_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 const jmethodID j_stats_report_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000680 const ScopedGlobalRef<jclass> j_value_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681 const jmethodID j_value_ctor_;
682};
683
684// Adapter presenting a cricket::VideoRenderer as a
685// webrtc::VideoRendererInterface.
686class VideoRendererWrapper : public VideoRendererInterface {
687 public:
688 static VideoRendererWrapper* Create(cricket::VideoRenderer* renderer) {
689 if (renderer)
690 return new VideoRendererWrapper(renderer);
691 return NULL;
692 }
693
694 virtual ~VideoRendererWrapper() {}
695
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000696 // This wraps VideoRenderer which still has SetSize.
697 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000698 ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000699 const cricket::VideoFrame* frame =
700 video_frame->GetCopyWithRotationApplied();
701 if (width_ != frame->GetWidth() || height_ != frame->GetHeight()) {
702 width_ = frame->GetWidth();
703 height_ = frame->GetHeight();
704 renderer_->SetSize(width_, height_, 0);
705 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000706 renderer_->RenderFrame(frame);
707 }
708
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000709 // TODO(guoweis): Remove this once chrome code base is updated.
710 bool CanApplyRotation() override { return true; }
711
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000712 private:
713 explicit VideoRendererWrapper(cricket::VideoRenderer* renderer)
Henrik Kjellander7c027b62015-04-22 13:21:30 +0200714 : width_(0), height_(0), renderer_(renderer) {}
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000715 int width_, height_;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000716 scoped_ptr<cricket::VideoRenderer> renderer_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717};
718
719// Wrapper dispatching webrtc::VideoRendererInterface to a Java VideoRenderer
720// instance.
721class JavaVideoRendererWrapper : public VideoRendererInterface {
722 public:
723 JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000724 : j_callbacks_(jni, j_callbacks),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000725 j_render_frame_id_(GetMethodID(
726 jni, GetObjectClass(jni, j_callbacks), "renderFrame",
727 "(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000728 j_can_apply_rotation_id_(GetMethodID(
729 jni, GetObjectClass(jni, j_callbacks),
730 "canApplyRotation", "()Z")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000731 j_frame_class_(jni,
732 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000733 j_i420_frame_ctor_id_(GetMethodID(
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000734 jni, *j_frame_class_, "<init>", "(III[I[Ljava/nio/ByteBuffer;)V")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000735 j_texture_frame_ctor_id_(GetMethodID(
736 jni, *j_frame_class_, "<init>",
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000737 "(IIILjava/lang/Object;I)V")),
738 j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")),
739 can_apply_rotation_set_(false),
740 can_apply_rotation_(false) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000741 CHECK_EXCEPTION(jni);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742 }
743
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000744 virtual ~JavaVideoRendererWrapper() {}
745
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000746 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000747 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000749 // Calling CanApplyRotation here to ensure can_apply_rotation_ is set.
750 CanApplyRotation();
guoweis@webrtc.org3fffd662015-03-18 04:20:03 +0000751
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000752 const cricket::VideoFrame* frame =
753 can_apply_rotation_ ? video_frame
754 : video_frame->GetCopyWithRotationApplied();
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000755 if (frame->GetNativeHandle() != NULL) {
756 jobject j_frame = CricketToJavaTextureFrame(frame);
757 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
758 CHECK_EXCEPTION(jni());
759 } else {
760 jobject j_frame = CricketToJavaI420Frame(frame);
761 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
762 CHECK_EXCEPTION(jni());
763 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764 }
765
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000766 // TODO(guoweis): Report that rotation is supported as RenderFrame calls
767 // GetCopyWithRotationApplied.
768 virtual bool CanApplyRotation() override {
769 if (can_apply_rotation_set_) {
770 return can_apply_rotation_;
771 }
772 ScopedLocalRefFrame local_ref_frame(jni());
773 jboolean ret =
774 jni()->CallBooleanMethod(*j_callbacks_, j_can_apply_rotation_id_);
775 CHECK_EXCEPTION(jni());
776 can_apply_rotation_ = ret;
777 can_apply_rotation_set_ = true;
778 return ret;
779 }
780
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000781 private:
782 // Return a VideoRenderer.I420Frame referring to the data in |frame|.
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000783 jobject CricketToJavaI420Frame(const cricket::VideoFrame* frame) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000784 jintArray strides = jni()->NewIntArray(3);
785 jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000786 strides_array[0] = frame->GetYPitch();
787 strides_array[1] = frame->GetUPitch();
788 strides_array[2] = frame->GetVPitch();
fischman@webrtc.org41776152014-01-09 00:31:17 +0000789 jni()->ReleaseIntArrayElements(strides, strides_array, 0);
790 jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
791 jobject y_buffer = jni()->NewDirectByteBuffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000792 const_cast<uint8*>(frame->GetYPlane()),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000793 frame->GetYPitch() * frame->GetHeight());
794 jobject u_buffer = jni()->NewDirectByteBuffer(
795 const_cast<uint8*>(frame->GetUPlane()), frame->GetChromaSize());
796 jobject v_buffer = jni()->NewDirectByteBuffer(
797 const_cast<uint8*>(frame->GetVPlane()), frame->GetChromaSize());
798 jni()->SetObjectArrayElement(planes, 0, y_buffer);
799 jni()->SetObjectArrayElement(planes, 1, u_buffer);
800 jni()->SetObjectArrayElement(planes, 2, v_buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000801 return jni()->NewObject(
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000802 *j_frame_class_, j_i420_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000803 frame->GetWidth(), frame->GetHeight(),
804 static_cast<int>(frame->GetVideoRotation()),
805 strides, planes);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000806 }
807
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000808 // Return a VideoRenderer.I420Frame referring texture object in |frame|.
809 jobject CricketToJavaTextureFrame(const cricket::VideoFrame* frame) {
810 NativeHandleImpl* handle =
811 reinterpret_cast<NativeHandleImpl*>(frame->GetNativeHandle());
812 jobject texture_object = reinterpret_cast<jobject>(handle->GetHandle());
813 int texture_id = handle->GetTextureId();
814 return jni()->NewObject(
815 *j_frame_class_, j_texture_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000816 frame->GetWidth(), frame->GetHeight(),
817 static_cast<int>(frame->GetVideoRotation()),
818 texture_object, texture_id);
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000819 }
820
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000821 JNIEnv* jni() {
822 return AttachCurrentThreadIfNeeded();
823 }
824
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000825 ScopedGlobalRef<jobject> j_callbacks_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000826 jmethodID j_render_frame_id_;
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000827 jmethodID j_can_apply_rotation_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000828 ScopedGlobalRef<jclass> j_frame_class_;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000829 jmethodID j_i420_frame_ctor_id_;
830 jmethodID j_texture_frame_ctor_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000831 ScopedGlobalRef<jclass> j_byte_buffer_class_;
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000832 bool can_apply_rotation_set_;
833 bool can_apply_rotation_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000834};
835
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000836
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000837static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000838 jfieldID native_dc_id = GetFieldID(jni,
839 GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
840 jlong j_d = GetLongField(jni, j_dc, native_dc_id);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000841 return reinterpret_cast<DataChannelInterface*>(j_d);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000842}
843
844JOW(jlong, DataChannel_registerObserverNative)(
845 JNIEnv* jni, jobject j_dc, jobject j_observer) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000846 scoped_ptr<DataChannelObserverWrapper> observer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000847 new DataChannelObserverWrapper(jni, j_observer));
848 ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
fischman@webrtc.orgf41f06b2013-12-11 21:07:18 +0000849 return jlongFromPointer(observer.release());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000850}
851
852JOW(void, DataChannel_unregisterObserverNative)(
853 JNIEnv* jni, jobject j_dc, jlong native_observer) {
854 ExtractNativeDC(jni, j_dc)->UnregisterObserver();
855 delete reinterpret_cast<DataChannelObserverWrapper*>(native_observer);
856}
857
858JOW(jstring, DataChannel_label)(JNIEnv* jni, jobject j_dc) {
859 return JavaStringFromStdString(jni, ExtractNativeDC(jni, j_dc)->label());
860}
861
862JOW(jobject, DataChannel_state)(JNIEnv* jni, jobject j_dc) {
863 return JavaEnumFromIndex(
864 jni, "DataChannel$State", ExtractNativeDC(jni, j_dc)->state());
865}
866
867JOW(jlong, DataChannel_bufferedAmount)(JNIEnv* jni, jobject j_dc) {
868 uint64 buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000869 CHECK_LE(buffered_amount, std::numeric_limits<int64>::max())
870 << "buffered_amount overflowed jlong!";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000871 return static_cast<jlong>(buffered_amount);
872}
873
874JOW(void, DataChannel_close)(JNIEnv* jni, jobject j_dc) {
875 ExtractNativeDC(jni, j_dc)->Close();
876}
877
878JOW(jboolean, DataChannel_sendNative)(JNIEnv* jni, jobject j_dc,
879 jbyteArray data, jboolean binary) {
880 jbyte* bytes = jni->GetByteArrayElements(data, NULL);
881 bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000882 rtc::Buffer(bytes, jni->GetArrayLength(data)),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000883 binary));
884 jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
885 return ret;
886}
887
888JOW(void, DataChannel_dispose)(JNIEnv* jni, jobject j_dc) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000889 CHECK_RELEASE(ExtractNativeDC(jni, j_dc));
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000890}
891
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000892JOW(void, Logging_nativeEnableTracing)(
893 JNIEnv* jni, jclass, jstring j_path, jint nativeLevels,
894 jint nativeSeverity) {
895 std::string path = JavaToStdString(jni, j_path);
896 if (nativeLevels != webrtc::kTraceNone) {
andrew@webrtc.org90805182013-09-05 16:40:43 +0000897 webrtc::Trace::set_level_filter(nativeLevels);
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000898#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000899 if (path != "logcat:") {
900#endif
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000901 CHECK_EQ(0, webrtc::Trace::SetTraceFile(path.c_str(), false))
902 << "SetTraceFile failed";
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000903#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000904 } else {
905 // Intentionally leak this to avoid needing to reason about its lifecycle.
906 // It keeps no state and functions only as a dispatch point.
907 static LogcatTraceContext* g_trace_callback = new LogcatTraceContext();
908 }
909#endif
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000910 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000911 rtc::LogMessage::LogToDebug(nativeSeverity);
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000912}
913
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000914JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000915 CHECK_RELEASE(reinterpret_cast<PeerConnectionInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000916}
917
918JOW(void, PeerConnection_freeObserver)(JNIEnv*, jclass, jlong j_p) {
919 PCOJava* p = reinterpret_cast<PCOJava*>(j_p);
920 delete p;
921}
922
923JOW(void, MediaSource_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000924 CHECK_RELEASE(reinterpret_cast<MediaSourceInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000925}
926
927JOW(void, VideoCapturer_free)(JNIEnv*, jclass, jlong j_p) {
928 delete reinterpret_cast<cricket::VideoCapturer*>(j_p);
929}
930
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000931JOW(void, VideoRenderer_freeGuiVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000932 delete reinterpret_cast<VideoRendererWrapper*>(j_p);
933}
934
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000935JOW(void, VideoRenderer_freeWrappedVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
936 delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
937}
938
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000939JOW(void, MediaStreamTrack_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000940 CHECK_RELEASE(reinterpret_cast<MediaStreamTrackInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000941}
942
943JOW(jboolean, MediaStream_nativeAddAudioTrack)(
944 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000945 return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947}
948
949JOW(jboolean, MediaStream_nativeAddVideoTrack)(
950 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000951 return reinterpret_cast<MediaStreamInterface*>(pointer)
952 ->AddTrack(reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000953}
954
955JOW(jboolean, MediaStream_nativeRemoveAudioTrack)(
956 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000957 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000958 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959}
960
961JOW(jboolean, MediaStream_nativeRemoveVideoTrack)(
962 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000963 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000964 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965}
966
967JOW(jstring, MediaStream_nativeLabel)(JNIEnv* jni, jclass, jlong j_p) {
968 return JavaStringFromStdString(
969 jni, reinterpret_cast<MediaStreamInterface*>(j_p)->label());
970}
971
972JOW(void, MediaStream_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000973 CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000974}
975
976JOW(jlong, PeerConnectionFactory_nativeCreateObserver)(
977 JNIEnv * jni, jclass, jobject j_observer) {
978 return (jlong)new PCOJava(jni, j_observer);
979}
980
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +0000981#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982JOW(jboolean, PeerConnectionFactory_initializeAndroidGlobals)(
fischman@webrtc.orga150bc92014-05-14 22:00:50 +0000983 JNIEnv* jni, jclass, jobject context,
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000984 jboolean initialize_audio, jboolean initialize_video,
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000985 jboolean vp8_hw_acceleration, jobject render_egl_context) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 bool failure = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000987 vp8_hw_acceleration_enabled = vp8_hw_acceleration;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000988 if (!factory_static_initialized) {
andresp@webrtc.org85ef7702014-09-17 11:44:51 +0000989 if (initialize_video) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000990 failure |= webrtc::SetRenderAndroidVM(GetJVM());
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000991 failure |= AndroidVideoCapturerJni::SetAndroidObjects(jni, context);
andresp@webrtc.org85ef7702014-09-17 11:44:51 +0000992 }
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000993 if (initialize_audio)
henrika@webrtc.org474d1eb2015-03-09 12:39:53 +0000994 failure |= webrtc::VoiceEngine::SetAndroidObjects(GetJVM(), context);
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000995 factory_static_initialized = true;
996 }
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000997 if (initialize_video) {
glaznev@webrtc.org18c92472015-02-18 18:42:55 +0000998 failure |= MediaCodecVideoDecoderFactory::SetAndroidObjects(jni,
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000999 render_egl_context);
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001000 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001 return !failure;
1002}
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +00001003#endif // defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001004
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001005JOW(void, PeerConnectionFactory_initializeFieldTrials)(
1006 JNIEnv* jni, jclass, jstring j_trials_init_string) {
1007 field_trials_init_string = NULL;
1008 if (j_trials_init_string != NULL) {
1009 const char* init_string =
1010 jni->GetStringUTFChars(j_trials_init_string, NULL);
1011 int init_string_length = jni->GetStringUTFLength(j_trials_init_string);
1012 field_trials_init_string = new char[init_string_length + 1];
1013 rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string);
1014 jni->ReleaseStringUTFChars(j_trials_init_string, init_string);
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001015 LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string;
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001016 }
1017 webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string);
1018}
1019
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001020// Helper struct for working around the fact that CreatePeerConnectionFactory()
1021// comes in two flavors: either entirely automagical (constructing its own
1022// threads and deleting them on teardown, but no external codec factory support)
1023// or entirely manual (requires caller to delete threads after factory
1024// teardown). This struct takes ownership of its ctor's arguments to present a
1025// single thing for Java to hold and eventually free.
1026class OwnedFactoryAndThreads {
1027 public:
1028 OwnedFactoryAndThreads(Thread* worker_thread,
1029 Thread* signaling_thread,
1030 PeerConnectionFactoryInterface* factory)
1031 : worker_thread_(worker_thread),
1032 signaling_thread_(signaling_thread),
1033 factory_(factory) {}
1034
1035 ~OwnedFactoryAndThreads() { CHECK_RELEASE(factory_); }
1036
1037 PeerConnectionFactoryInterface* factory() { return factory_; }
1038
1039 private:
1040 const scoped_ptr<Thread> worker_thread_;
1041 const scoped_ptr<Thread> signaling_thread_;
1042 PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
1043};
1044
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001045JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)(
1046 JNIEnv* jni, jclass) {
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001047 // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
1048 // ThreadManager only WrapCurrentThread()s the thread where it is first
1049 // created. Since the semantics around when auto-wrapping happens in
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001050 // webrtc/base/ are convoluted, we simply wrap here to avoid having to think
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001051 // about ramifications of auto-wrapping there.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001052 rtc::ThreadManager::Instance()->WrapCurrentThread();
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001053 webrtc::Trace::CreateTrace();
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001054 Thread* worker_thread = new Thread();
1055 worker_thread->SetName("worker_thread", NULL);
1056 Thread* signaling_thread = new Thread();
1057 signaling_thread->SetName("signaling_thread", NULL);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001058 CHECK(worker_thread->Start() && signaling_thread->Start())
1059 << "Failed to start threads";
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001060 scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001061 scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001062#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +00001063 if (vp8_hw_acceleration_enabled) {
1064 encoder_factory.reset(new MediaCodecVideoEncoderFactory());
1065 decoder_factory.reset(new MediaCodecVideoDecoderFactory());
1066 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001067#endif
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001068 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001069 webrtc::CreatePeerConnectionFactory(worker_thread,
1070 signaling_thread,
1071 NULL,
1072 encoder_factory.release(),
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001073 decoder_factory.release()));
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001074 OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
1075 worker_thread, signaling_thread, factory.release());
1076 return jlongFromPointer(owned_factory);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001077}
1078
1079JOW(void, PeerConnectionFactory_freeFactory)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001080 delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001081 if (field_trials_init_string) {
1082 webrtc::field_trial::InitFieldTrialsFromString(NULL);
1083 delete field_trials_init_string;
1084 field_trials_init_string = NULL;
1085 }
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001086 webrtc::Trace::ReturnTrace();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087}
1088
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001089static PeerConnectionFactoryInterface* factoryFromJava(jlong j_p) {
1090 return reinterpret_cast<OwnedFactoryAndThreads*>(j_p)->factory();
1091}
1092
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001093JOW(jlong, PeerConnectionFactory_nativeCreateLocalMediaStream)(
1094 JNIEnv* jni, jclass, jlong native_factory, jstring label) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001095 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001096 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001097 rtc::scoped_refptr<MediaStreamInterface> stream(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001098 factory->CreateLocalMediaStream(JavaToStdString(jni, label)));
1099 return (jlong)stream.release();
1100}
1101
1102JOW(jlong, PeerConnectionFactory_nativeCreateVideoSource)(
1103 JNIEnv* jni, jclass, jlong native_factory, jlong native_capturer,
1104 jobject j_constraints) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001105 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001106 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001107 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001108 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001109 rtc::scoped_refptr<VideoSourceInterface> source(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001110 factory->CreateVideoSource(
1111 reinterpret_cast<cricket::VideoCapturer*>(native_capturer),
1112 constraints.get()));
1113 return (jlong)source.release();
1114}
1115
1116JOW(jlong, PeerConnectionFactory_nativeCreateVideoTrack)(
1117 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1118 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001119 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001120 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001121 rtc::scoped_refptr<VideoTrackInterface> track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001122 factory->CreateVideoTrack(
1123 JavaToStdString(jni, id),
1124 reinterpret_cast<VideoSourceInterface*>(native_source)));
1125 return (jlong)track.release();
1126}
1127
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001128JOW(jlong, PeerConnectionFactory_nativeCreateAudioSource)(
1129 JNIEnv* jni, jclass, jlong native_factory, jobject j_constraints) {
1130 scoped_ptr<ConstraintsWrapper> constraints(
1131 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001132 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001133 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001134 rtc::scoped_refptr<AudioSourceInterface> source(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001135 factory->CreateAudioSource(constraints.get()));
1136 return (jlong)source.release();
1137}
1138
1139JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack)(
1140 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1141 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001142 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001143 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001144 rtc::scoped_refptr<AudioTrackInterface> track(factory->CreateAudioTrack(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001145 JavaToStdString(jni, id),
1146 reinterpret_cast<AudioSourceInterface*>(native_source)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001147 return (jlong)track.release();
1148}
1149
phoglund@webrtc.org006521d2015-02-12 09:23:59 +00001150JOW(void, PeerConnectionFactory_nativeSetOptions)(
1151 JNIEnv* jni, jclass, jlong native_factory, jobject options) {
1152 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
1153 factoryFromJava(native_factory));
1154 jclass options_class = jni->GetObjectClass(options);
1155 jfieldID network_ignore_mask_field =
1156 jni->GetFieldID(options_class, "networkIgnoreMask", "I");
1157 int network_ignore_mask =
1158 jni->GetIntField(options, network_ignore_mask_field);
1159 PeerConnectionFactoryInterface::Options options_to_set;
1160
1161 // This doesn't necessarily match the c++ version of this struct; feel free
1162 // to add more parameters as necessary.
1163 options_to_set.network_ignore_mask = network_ignore_mask;
1164 factory->SetOptions(options_to_set);
1165}
1166
Jiayang Liucac1b382015-04-30 12:35:24 -07001167static std::string
1168GetJavaEnumName(JNIEnv* jni, const std::string& className, jobject j_enum) {
1169 jclass enumClass = FindClass(jni, className.c_str());
1170 jmethodID nameMethod =
1171 GetMethodID(jni, enumClass, "name", "()Ljava/lang/String;");
1172 jstring name =
1173 reinterpret_cast<jstring>(jni->CallObjectMethod(j_enum, nameMethod));
1174 CHECK_EXCEPTION(jni) << "error during CallObjectMethod for "
1175 << className << ".name";
1176 return JavaToStdString(jni, name);
1177}
1178
1179static PeerConnectionInterface::IceTransportsType
1180JavaIceTransportsTypeToNativeType(JNIEnv* jni, jobject j_ice_transports_type) {
1181 std::string enum_name = GetJavaEnumName(
1182 jni, "org/webrtc/PeerConnection$IceTransportsType",
1183 j_ice_transports_type);
1184
1185 if (enum_name == "ALL")
1186 return PeerConnectionInterface::kAll;
1187
1188 if (enum_name == "RELAY")
1189 return PeerConnectionInterface::kRelay;
1190
1191 if (enum_name == "NOHOST")
1192 return PeerConnectionInterface::kNoHost;
1193
1194 if (enum_name == "NONE")
1195 return PeerConnectionInterface::kNone;
1196
1197 CHECK(false) << "Unexpected IceTransportsType enum_name " << enum_name;
1198 return PeerConnectionInterface::kAll;
1199}
1200
1201static PeerConnectionInterface::BundlePolicy
1202JavaBundlePolicyToNativeType(JNIEnv* jni, jobject j_bundle_policy) {
1203 std::string enum_name = GetJavaEnumName(
1204 jni, "org/webrtc/PeerConnection$BundlePolicy",
1205 j_bundle_policy);
1206
1207 if (enum_name == "BALANCED")
1208 return PeerConnectionInterface::kBundlePolicyBalanced;
1209
1210 if (enum_name == "MAXBUNDLE")
1211 return PeerConnectionInterface::kBundlePolicyMaxBundle;
1212
1213 if (enum_name == "MAXCOMPAT")
1214 return PeerConnectionInterface::kBundlePolicyMaxCompat;
1215
1216 CHECK(false) << "Unexpected BundlePolicy enum_name " << enum_name;
1217 return PeerConnectionInterface::kBundlePolicyBalanced;
1218}
1219
1220static PeerConnectionInterface::TcpCandidatePolicy
1221JavaTcpCandidatePolicyToNativeType(
1222 JNIEnv* jni, jobject j_tcp_candidate_policy) {
1223 std::string enum_name = GetJavaEnumName(
1224 jni, "org/webrtc/PeerConnection$TcpCandidatePolicy",
1225 j_tcp_candidate_policy);
1226
1227 if (enum_name == "ENABLED")
1228 return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
1229
1230 if (enum_name == "DISABLED")
1231 return PeerConnectionInterface::kTcpCandidatePolicyDisabled;
1232
1233 CHECK(false) << "Unexpected TcpCandidatePolicy enum_name " << enum_name;
1234 return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
1235}
1236
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001237static void JavaIceServersToJsepIceServers(
1238 JNIEnv* jni, jobject j_ice_servers,
1239 PeerConnectionInterface::IceServers* ice_servers) {
1240 jclass list_class = GetObjectClass(jni, j_ice_servers);
1241 jmethodID iterator_id = GetMethodID(
1242 jni, list_class, "iterator", "()Ljava/util/Iterator;");
1243 jobject iterator = jni->CallObjectMethod(j_ice_servers, iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001244 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245 jmethodID iterator_has_next = GetMethodID(
1246 jni, GetObjectClass(jni, iterator), "hasNext", "()Z");
1247 jmethodID iterator_next = GetMethodID(
1248 jni, GetObjectClass(jni, iterator), "next", "()Ljava/lang/Object;");
1249 while (jni->CallBooleanMethod(iterator, iterator_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001250 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001251 jobject j_ice_server = jni->CallObjectMethod(iterator, iterator_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001252 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253 jclass j_ice_server_class = GetObjectClass(jni, j_ice_server);
1254 jfieldID j_ice_server_uri_id =
1255 GetFieldID(jni, j_ice_server_class, "uri", "Ljava/lang/String;");
1256 jfieldID j_ice_server_username_id =
1257 GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;");
1258 jfieldID j_ice_server_password_id =
1259 GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;");
1260 jstring uri = reinterpret_cast<jstring>(
1261 GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
1262 jstring username = reinterpret_cast<jstring>(
1263 GetObjectField(jni, j_ice_server, j_ice_server_username_id));
1264 jstring password = reinterpret_cast<jstring>(
1265 GetObjectField(jni, j_ice_server, j_ice_server_password_id));
1266 PeerConnectionInterface::IceServer server;
1267 server.uri = JavaToStdString(jni, uri);
1268 server.username = JavaToStdString(jni, username);
1269 server.password = JavaToStdString(jni, password);
1270 ice_servers->push_back(server);
1271 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001272 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001273}
1274
1275JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
Jiayang Liucac1b382015-04-30 12:35:24 -07001276 JNIEnv *jni, jclass, jlong factory, jobject j_rtc_config,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001277 jobject j_constraints, jlong observer_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001278 rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001279 reinterpret_cast<PeerConnectionFactoryInterface*>(
1280 factoryFromJava(factory)));
Jiayang Liucac1b382015-04-30 12:35:24 -07001281
1282 jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config);
1283
1284 jfieldID j_ice_transports_type_id = GetFieldID(
1285 jni, j_rtc_config_class, "iceTransportsType",
1286 "Lorg/webrtc/PeerConnection$IceTransportsType;");
1287 jobject j_ice_transports_type = GetObjectField(
1288 jni, j_rtc_config, j_ice_transports_type_id);
1289
1290 jfieldID j_bundle_policy_id = GetFieldID(
1291 jni, j_rtc_config_class, "bundlePolicy",
1292 "Lorg/webrtc/PeerConnection$BundlePolicy;");
1293 jobject j_bundle_policy = GetObjectField(
1294 jni, j_rtc_config, j_bundle_policy_id);
1295
1296 jfieldID j_tcp_candidate_policy_id = GetFieldID(
1297 jni, j_rtc_config_class, "tcpCandidatePolicy",
1298 "Lorg/webrtc/PeerConnection$TcpCandidatePolicy;");
1299 jobject j_tcp_candidate_policy = GetObjectField(
1300 jni, j_rtc_config, j_tcp_candidate_policy_id);
1301
1302 jfieldID j_ice_servers_id = GetFieldID(
1303 jni, j_rtc_config_class, "iceServers",
1304 "Ljava/util/List;");
1305 jobject j_ice_servers = GetObjectField(jni, j_rtc_config, j_ice_servers_id);
1306
1307 PeerConnectionInterface::RTCConfiguration rtc_config;
1308
1309 rtc_config.type =
1310 JavaIceTransportsTypeToNativeType(jni, j_ice_transports_type);
1311 rtc_config.bundle_policy = JavaBundlePolicyToNativeType(jni, j_bundle_policy);
1312 rtc_config.tcp_candidate_policy =
1313 JavaTcpCandidatePolicyToNativeType(jni, j_tcp_candidate_policy);
1314 JavaIceServersToJsepIceServers(jni, j_ice_servers, &rtc_config.servers);
1315
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316 PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
1317 observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001318 rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
Jiayang Liucac1b382015-04-30 12:35:24 -07001319 rtc_config, observer->constraints(), NULL, NULL, observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001320 return (jlong)pc.release();
1321}
1322
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001323static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324 JNIEnv* jni, jobject j_pc) {
1325 jfieldID native_pc_id = GetFieldID(jni,
1326 GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
1327 jlong j_p = GetLongField(jni, j_pc, native_pc_id);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001328 return rtc::scoped_refptr<PeerConnectionInterface>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329 reinterpret_cast<PeerConnectionInterface*>(j_p));
1330}
1331
1332JOW(jobject, PeerConnection_getLocalDescription)(JNIEnv* jni, jobject j_pc) {
1333 const SessionDescriptionInterface* sdp =
1334 ExtractNativePC(jni, j_pc)->local_description();
1335 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1336}
1337
1338JOW(jobject, PeerConnection_getRemoteDescription)(JNIEnv* jni, jobject j_pc) {
1339 const SessionDescriptionInterface* sdp =
1340 ExtractNativePC(jni, j_pc)->remote_description();
1341 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1342}
1343
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001344JOW(jobject, PeerConnection_createDataChannel)(
1345 JNIEnv* jni, jobject j_pc, jstring j_label, jobject j_init) {
1346 DataChannelInit init = JavaDataChannelInitToNative(jni, j_init);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001347 rtc::scoped_refptr<DataChannelInterface> channel(
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001348 ExtractNativePC(jni, j_pc)->CreateDataChannel(
1349 JavaToStdString(jni, j_label), &init));
fischman@webrtc.org87881672013-09-03 18:58:12 +00001350 // Mustn't pass channel.get() directly through NewObject to avoid reading its
1351 // vararg parameter as 64-bit and reading memory that doesn't belong to the
1352 // 32-bit parameter.
1353 jlong nativeChannelPtr = jlongFromPointer(channel.get());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001354 CHECK(nativeChannelPtr) << "Failed to create DataChannel";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001355 jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
1356 jmethodID j_data_channel_ctor = GetMethodID(
1357 jni, j_data_channel_class, "<init>", "(J)V");
1358 jobject j_channel = jni->NewObject(
fischman@webrtc.org87881672013-09-03 18:58:12 +00001359 j_data_channel_class, j_data_channel_ctor, nativeChannelPtr);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001360 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001361 // Channel is now owned by Java object, and will be freed from there.
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001362 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001363 CHECK(bumped_count == 2) << "Unexpected refcount";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001364 return j_channel;
1365}
1366
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367JOW(void, PeerConnection_createOffer)(
1368 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1369 ConstraintsWrapper* constraints =
1370 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001371 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1372 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001373 jni, j_observer, constraints));
1374 ExtractNativePC(jni, j_pc)->CreateOffer(observer, constraints);
1375}
1376
1377JOW(void, PeerConnection_createAnswer)(
1378 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1379 ConstraintsWrapper* constraints =
1380 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001381 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1382 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001383 jni, j_observer, constraints));
1384 ExtractNativePC(jni, j_pc)->CreateAnswer(observer, constraints);
1385}
1386
1387// Helper to create a SessionDescriptionInterface from a SessionDescription.
1388static SessionDescriptionInterface* JavaSdpToNativeSdp(
1389 JNIEnv* jni, jobject j_sdp) {
1390 jfieldID j_type_id = GetFieldID(
1391 jni, GetObjectClass(jni, j_sdp), "type",
1392 "Lorg/webrtc/SessionDescription$Type;");
1393 jobject j_type = GetObjectField(jni, j_sdp, j_type_id);
1394 jmethodID j_canonical_form_id = GetMethodID(
1395 jni, GetObjectClass(jni, j_type), "canonicalForm",
1396 "()Ljava/lang/String;");
1397 jstring j_type_string = (jstring)jni->CallObjectMethod(
1398 j_type, j_canonical_form_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001399 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001400 std::string std_type = JavaToStdString(jni, j_type_string);
1401
1402 jfieldID j_description_id = GetFieldID(
1403 jni, GetObjectClass(jni, j_sdp), "description", "Ljava/lang/String;");
1404 jstring j_description = (jstring)GetObjectField(jni, j_sdp, j_description_id);
1405 std::string std_description = JavaToStdString(jni, j_description);
1406
1407 return webrtc::CreateSessionDescription(
1408 std_type, std_description, NULL);
1409}
1410
1411JOW(void, PeerConnection_setLocalDescription)(
1412 JNIEnv* jni, jobject j_pc,
1413 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001414 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1415 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001416 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1417 ExtractNativePC(jni, j_pc)->SetLocalDescription(
1418 observer, JavaSdpToNativeSdp(jni, j_sdp));
1419}
1420
1421JOW(void, PeerConnection_setRemoteDescription)(
1422 JNIEnv* jni, jobject j_pc,
1423 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001424 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1425 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001426 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1427 ExtractNativePC(jni, j_pc)->SetRemoteDescription(
1428 observer, JavaSdpToNativeSdp(jni, j_sdp));
1429}
1430
1431JOW(jboolean, PeerConnection_updateIce)(
1432 JNIEnv* jni, jobject j_pc, jobject j_ice_servers, jobject j_constraints) {
1433 PeerConnectionInterface::IceServers ice_servers;
1434 JavaIceServersToJsepIceServers(jni, j_ice_servers, &ice_servers);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001435 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001436 new ConstraintsWrapper(jni, j_constraints));
1437 return ExtractNativePC(jni, j_pc)->UpdateIce(ice_servers, constraints.get());
1438}
1439
1440JOW(jboolean, PeerConnection_nativeAddIceCandidate)(
1441 JNIEnv* jni, jobject j_pc, jstring j_sdp_mid,
1442 jint j_sdp_mline_index, jstring j_candidate_sdp) {
1443 std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
1444 std::string sdp = JavaToStdString(jni, j_candidate_sdp);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001445 scoped_ptr<IceCandidateInterface> candidate(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001446 webrtc::CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, NULL));
1447 return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
1448}
1449
1450JOW(jboolean, PeerConnection_nativeAddLocalStream)(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001451 JNIEnv* jni, jobject j_pc, jlong native_stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001452 return ExtractNativePC(jni, j_pc)->AddStream(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001453 reinterpret_cast<MediaStreamInterface*>(native_stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001454}
1455
1456JOW(void, PeerConnection_nativeRemoveLocalStream)(
1457 JNIEnv* jni, jobject j_pc, jlong native_stream) {
1458 ExtractNativePC(jni, j_pc)->RemoveStream(
1459 reinterpret_cast<MediaStreamInterface*>(native_stream));
1460}
1461
1462JOW(bool, PeerConnection_nativeGetStats)(
1463 JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001464 rtc::scoped_refptr<StatsObserverWrapper> observer(
1465 new rtc::RefCountedObject<StatsObserverWrapper>(jni, j_observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001466 return ExtractNativePC(jni, j_pc)->GetStats(
jiayl@webrtc.orgdb41b4d2014-03-03 21:30:06 +00001467 observer,
1468 reinterpret_cast<MediaStreamTrackInterface*>(native_track),
1469 PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001470}
1471
1472JOW(jobject, PeerConnection_signalingState)(JNIEnv* jni, jobject j_pc) {
1473 PeerConnectionInterface::SignalingState state =
1474 ExtractNativePC(jni, j_pc)->signaling_state();
1475 return JavaEnumFromIndex(jni, "PeerConnection$SignalingState", state);
1476}
1477
1478JOW(jobject, PeerConnection_iceConnectionState)(JNIEnv* jni, jobject j_pc) {
1479 PeerConnectionInterface::IceConnectionState state =
1480 ExtractNativePC(jni, j_pc)->ice_connection_state();
1481 return JavaEnumFromIndex(jni, "PeerConnection$IceConnectionState", state);
1482}
1483
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001484JOW(jobject, PeerConnection_iceGatheringState)(JNIEnv* jni, jobject j_pc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001485 PeerConnectionInterface::IceGatheringState state =
1486 ExtractNativePC(jni, j_pc)->ice_gathering_state();
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001487 return JavaEnumFromIndex(jni, "PeerConnection$IceGatheringState", state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001488}
1489
1490JOW(void, PeerConnection_close)(JNIEnv* jni, jobject j_pc) {
1491 ExtractNativePC(jni, j_pc)->Close();
1492 return;
1493}
1494
1495JOW(jobject, MediaSource_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001496 rtc::scoped_refptr<MediaSourceInterface> p(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497 reinterpret_cast<MediaSourceInterface*>(j_p));
1498 return JavaEnumFromIndex(jni, "MediaSource$State", p->state());
1499}
1500
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001501JOW(jobject, VideoCapturer_nativeCreateVideoCapturer)(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001502 JNIEnv* jni, jclass, jstring j_device_name) {
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001503// Since we can't create platform specific java implementations in Java, we
1504// defer the creation to C land.
1505#if defined(ANDROID)
1506 jclass j_video_capturer_class(
1507 FindClass(jni, "org/webrtc/VideoCapturerAndroid"));
1508 const jmethodID j_videocapturer_ctor(GetMethodID(
1509 jni, j_video_capturer_class, "<init>", "()V"));
1510 jobject j_video_capturer = jni->NewObject(j_video_capturer_class,
1511 j_videocapturer_ctor);
1512 CHECK_EXCEPTION(jni) << "error during NewObject";
1513
Per33544192015-04-02 12:30:51 +02001514 rtc::scoped_refptr<AndroidVideoCapturerJni> delegate =
perkj@webrtc.org112f1272015-02-25 09:20:07 +00001515 AndroidVideoCapturerJni::Create(jni, j_video_capturer, j_device_name);
1516 if (!delegate.get())
perkj@webrtc.org3db042e2015-02-19 08:43:38 +00001517 return nullptr;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001518 rtc::scoped_ptr<webrtc::AndroidVideoCapturer> capturer(
Per33544192015-04-02 12:30:51 +02001519 new webrtc::AndroidVideoCapturer(delegate));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001520
1521#else
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001522 std::string device_name = JavaToStdString(jni, j_device_name);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001523 scoped_ptr<cricket::DeviceManagerInterface> device_manager(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 cricket::DeviceManagerFactory::Create());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001525 CHECK(device_manager->Init()) << "DeviceManager::Init() failed";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526 cricket::Device device;
1527 if (!device_manager->GetVideoCaptureDevice(device_name, &device)) {
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001528 LOG(LS_ERROR) << "GetVideoCaptureDevice failed for " << device_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001529 return 0;
1530 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001531 scoped_ptr<cricket::VideoCapturer> capturer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532 device_manager->CreateVideoCapturer(device));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001533
1534 jclass j_video_capturer_class(
1535 FindClass(jni, "org/webrtc/VideoCapturer"));
1536 const jmethodID j_videocapturer_ctor(GetMethodID(
1537 jni, j_video_capturer_class, "<init>", "()V"));
1538 jobject j_video_capturer =
1539 jni->NewObject(j_video_capturer_class,
1540 j_videocapturer_ctor);
1541 CHECK_EXCEPTION(jni) << "error during creation of VideoCapturer";
1542
1543#endif
1544 const jmethodID j_videocapturer_set_native_capturer(GetMethodID(
1545 jni, j_video_capturer_class, "setNativeCapturer", "(J)V"));
1546 jni->CallVoidMethod(j_video_capturer,
1547 j_videocapturer_set_native_capturer,
1548 (jlong)capturer.release());
1549 CHECK_EXCEPTION(jni) << "error during setNativeCapturer";
1550 return j_video_capturer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001551}
1552
1553JOW(jlong, VideoRenderer_nativeCreateGuiVideoRenderer)(
1554 JNIEnv* jni, jclass, int x, int y) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001555 scoped_ptr<VideoRendererWrapper> renderer(VideoRendererWrapper::Create(
1556 cricket::VideoRendererFactory::CreateGuiVideoRenderer(x, y)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001557 return (jlong)renderer.release();
1558}
1559
1560JOW(jlong, VideoRenderer_nativeWrapVideoRenderer)(
1561 JNIEnv* jni, jclass, jobject j_callbacks) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001562 scoped_ptr<JavaVideoRendererWrapper> renderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001563 new JavaVideoRendererWrapper(jni, j_callbacks));
1564 return (jlong)renderer.release();
1565}
1566
glaznev@webrtc.orgf6932292015-02-05 17:29:59 +00001567JOW(void, VideoRenderer_nativeCopyPlane)(
1568 JNIEnv *jni, jclass, jobject j_src_buffer, jint width, jint height,
1569 jint src_stride, jobject j_dst_buffer, jint dst_stride) {
1570 size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer);
1571 size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
1572 CHECK(src_stride >= width) << "Wrong source stride " << src_stride;
1573 CHECK(dst_stride >= width) << "Wrong destination stride " << dst_stride;
1574 CHECK(src_size >= src_stride * height)
1575 << "Insufficient source buffer capacity " << src_size;
1576 CHECK(dst_size >= dst_stride * height)
1577 << "Isufficient destination buffer capacity " << dst_size;
1578 uint8_t *src =
1579 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer));
1580 uint8_t *dst =
1581 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
1582 if (src_stride == dst_stride) {
1583 memcpy(dst, src, src_stride * height);
1584 } else {
1585 for (int i = 0; i < height; i++) {
1586 memcpy(dst, src, width);
1587 src += src_stride;
1588 dst += dst_stride;
1589 }
1590 }
1591}
1592
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001593JOW(void, VideoSource_stop)(JNIEnv* jni, jclass, jlong j_p) {
1594 reinterpret_cast<VideoSourceInterface*>(j_p)->Stop();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001595}
1596
1597JOW(void, VideoSource_restart)(
1598 JNIEnv* jni, jclass, jlong j_p_source, jlong j_p_format) {
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001599 reinterpret_cast<VideoSourceInterface*>(j_p_source)->Restart();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001600}
1601
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001602JOW(jstring, MediaStreamTrack_nativeId)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001603 return JavaStringFromStdString(
1604 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001605}
1606
1607JOW(jstring, MediaStreamTrack_nativeKind)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001608 return JavaStringFromStdString(
1609 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->kind());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610}
1611
1612JOW(jboolean, MediaStreamTrack_nativeEnabled)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001613 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->enabled();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001614}
1615
1616JOW(jobject, MediaStreamTrack_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001617 return JavaEnumFromIndex(
1618 jni,
1619 "MediaStreamTrack$State",
1620 reinterpret_cast<MediaStreamTrackInterface*>(j_p)->state());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621}
1622
1623JOW(jboolean, MediaStreamTrack_nativeSetState)(
1624 JNIEnv* jni, jclass, jlong j_p, jint j_new_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001625 MediaStreamTrackInterface::TrackState new_state =
1626 (MediaStreamTrackInterface::TrackState)j_new_state;
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001627 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1628 ->set_state(new_state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001629}
1630
1631JOW(jboolean, MediaStreamTrack_nativeSetEnabled)(
1632 JNIEnv* jni, jclass, jlong j_p, jboolean enabled) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001633 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1634 ->set_enabled(enabled);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635}
1636
1637JOW(void, VideoTrack_nativeAddRenderer)(
1638 JNIEnv* jni, jclass,
1639 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001640 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->AddRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001641 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1642}
1643
1644JOW(void, VideoTrack_nativeRemoveRenderer)(
1645 JNIEnv* jni, jclass,
1646 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001647 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001648 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1649}
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001650
1651} // namespace webrtc_jni