blob: 2b6cbc7377396890ab7b85b752553a6bad74d41e [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"
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +000070#include "talk/media/webrtc/webrtcvideodecoderfactory.h"
fischman@webrtc.org540acde2014-02-13 03:56:14 +000071#include "talk/media/webrtc/webrtcvideoencoderfactory.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000072#include "webrtc/base/bind.h"
andresp@webrtc.org4d19e052014-09-09 11:45:44 +000073#include "webrtc/base/checks.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000074#include "webrtc/base/logging.h"
75#include "webrtc/base/messagequeue.h"
76#include "webrtc/base/ssladapter.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000077#include "webrtc/base/stringutils.h"
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +000078#include "webrtc/system_wrappers/interface/field_trial_default.h"
henrike@webrtc.org9de257d2013-07-17 14:42:53 +000079#include "webrtc/system_wrappers/interface/trace.h"
henrike@webrtc.org9de257d2013-07-17 14:42:53 +000080#include "webrtc/voice_engine/include/voe_base.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081
glaznev@webrtc.org99678452014-09-15 17:52:42 +000082#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
perkj@webrtc.org83bc7212015-02-11 11:26:56 +000083#include "talk/app/webrtc/androidvideocapturer.h"
glaznev@webrtc.org18c92472015-02-18 18:42:55 +000084#include "talk/app/webrtc/java/jni/androidmediadecoder_jni.h"
85#include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h"
perkj@webrtc.org96e4db92015-02-13 12:46:51 +000086#include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h"
andresp@webrtc.org85ef7702014-09-17 11:44:51 +000087#include "webrtc/modules/video_render/video_render_internal.h"
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +000088#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
89using webrtc::LogcatTraceContext;
90#endif
91
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000092using rtc::Bind;
93using rtc::Thread;
94using rtc::ThreadManager;
95using rtc::scoped_ptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096using webrtc::AudioSourceInterface;
97using webrtc::AudioTrackInterface;
98using webrtc::AudioTrackVector;
99using webrtc::CreateSessionDescriptionObserver;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000100using webrtc::DataBuffer;
101using webrtc::DataChannelInit;
102using webrtc::DataChannelInterface;
103using webrtc::DataChannelObserver;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104using webrtc::IceCandidateInterface;
105using webrtc::MediaConstraintsInterface;
106using webrtc::MediaSourceInterface;
107using webrtc::MediaStreamInterface;
108using webrtc::MediaStreamTrackInterface;
109using webrtc::PeerConnectionFactoryInterface;
110using webrtc::PeerConnectionInterface;
111using webrtc::PeerConnectionObserver;
112using webrtc::SessionDescriptionInterface;
113using webrtc::SetSessionDescriptionObserver;
114using webrtc::StatsObserver;
115using webrtc::StatsReport;
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000116using webrtc::StatsReports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117using webrtc::VideoRendererInterface;
118using webrtc::VideoSourceInterface;
119using webrtc::VideoTrackInterface;
120using webrtc::VideoTrackVector;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000121using webrtc::kVideoCodecVP8;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000123namespace webrtc_jni {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000124
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +0000125// Field trials initialization string
126static char *field_trials_init_string = NULL;
127
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000128#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
129// Set in PeerConnectionFactory_initializeAndroidGlobals().
130static bool factory_static_initialized = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000131static bool vp8_hw_acceleration_enabled = true;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000132#endif
133
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000134extern "C" jint JNIEXPORT JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000135 jint ret = InitGlobalJniVariables(jvm);
136 if (ret < 0)
137 return -1;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000138
139 CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000140 LoadGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000141
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000142 return ret;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000143}
144
145extern "C" void JNIEXPORT JNICALL JNI_OnUnLoad(JavaVM *jvm, void *reserved) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000146 FreeGlobalClassReferenceHolder();
perkj@webrtc.org83bc7212015-02-11 11:26:56 +0000147 CHECK(rtc::CleanupSSL()) << "Failed to CleanupSSL()";
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000148}
149
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000150// Return the (singleton) Java Enum object corresponding to |index|;
151// |state_class_fragment| is something like "MediaSource$State".
glaznev@webrtc.orgb28474c2015-02-23 17:44:27 +0000152static jobject JavaEnumFromIndex(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000153 JNIEnv* jni, const std::string& state_class_fragment, int index) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +0000154 const std::string state_class = "org/webrtc/" + state_class_fragment;
155 return JavaEnumFromIndex(jni, FindClass(jni, state_class.c_str()),
156 state_class, index);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157}
158
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000159static DataChannelInit JavaDataChannelInitToNative(
160 JNIEnv* jni, jobject j_init) {
161 DataChannelInit init;
162
163 jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init");
164 jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z");
165 jfieldID max_retransmit_time_id =
166 GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I");
167 jfieldID max_retransmits_id =
168 GetFieldID(jni, j_init_class, "maxRetransmits", "I");
169 jfieldID protocol_id =
170 GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;");
171 jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z");
172 jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I");
173
174 init.ordered = GetBooleanField(jni, j_init, ordered_id);
175 init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id);
176 init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id);
177 init.protocol = JavaToStdString(
178 jni, GetStringField(jni, j_init, protocol_id));
179 init.negotiated = GetBooleanField(jni, j_init, negotiated_id);
180 init.id = GetIntField(jni, j_init, id_id);
181
182 return init;
183}
184
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000185class ConstraintsWrapper;
186
187// Adapter between the C++ PeerConnectionObserver interface and the Java
188// PeerConnection.Observer interface. Wraps an instance of the Java interface
189// and dispatches C++ callbacks to Java.
190class PCOJava : public PeerConnectionObserver {
191 public:
192 PCOJava(JNIEnv* jni, jobject j_observer)
193 : j_observer_global_(jni, j_observer),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000194 j_observer_class_(jni, GetObjectClass(jni, *j_observer_global_)),
195 j_media_stream_class_(jni, FindClass(jni, "org/webrtc/MediaStream")),
196 j_media_stream_ctor_(GetMethodID(
197 jni, *j_media_stream_class_, "<init>", "(J)V")),
198 j_audio_track_class_(jni, FindClass(jni, "org/webrtc/AudioTrack")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199 j_audio_track_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000200 jni, *j_audio_track_class_, "<init>", "(J)V")),
201 j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")),
202 j_video_track_ctor_(GetMethodID(
203 jni, *j_video_track_class_, "<init>", "(J)V")),
204 j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")),
205 j_data_channel_ctor_(GetMethodID(
206 jni, *j_data_channel_class_, "<init>", "(J)V")) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 }
208
209 virtual ~PCOJava() {}
210
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000211 void OnIceCandidate(const IceCandidateInterface* candidate) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000212 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000213 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000214 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
216 jmethodID ctor = GetMethodID(jni(), candidate_class,
217 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000218 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
219 jstring j_sdp = JavaStringFromStdString(jni(), sdp);
220 jobject j_candidate = jni()->NewObject(
221 candidate_class, ctor, j_mid, candidate->sdp_mline_index(), j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000222 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000223 jmethodID m = GetMethodID(jni(), *j_observer_class_,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000224 "onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000225 jni()->CallVoidMethod(*j_observer_global_, m, j_candidate);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000226 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000227 }
228
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000229 void OnSignalingChange(
230 PeerConnectionInterface::SignalingState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000231 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000232 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000233 jni(), *j_observer_class_, "onSignalingChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234 "(Lorg/webrtc/PeerConnection$SignalingState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000235 jobject new_state_enum =
236 JavaEnumFromIndex(jni(), "PeerConnection$SignalingState", new_state);
237 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000238 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000239 }
240
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000241 void OnIceConnectionChange(
242 PeerConnectionInterface::IceConnectionState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000243 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000244 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000245 jni(), *j_observer_class_, "onIceConnectionChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000246 "(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000247 jobject new_state_enum = JavaEnumFromIndex(
248 jni(), "PeerConnection$IceConnectionState", new_state);
249 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000250 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251 }
252
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000253 void OnIceGatheringChange(
254 PeerConnectionInterface::IceGatheringState new_state) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000255 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000257 jni(), *j_observer_class_, "onIceGatheringChange",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000259 jobject new_state_enum = JavaEnumFromIndex(
260 jni(), "PeerConnection$IceGatheringState", new_state);
261 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000262 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000263 }
264
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000265 void OnAddStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000266 ScopedLocalRefFrame local_ref_frame(jni());
267 jobject j_stream = jni()->NewObject(
268 *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000269 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000270
271 AudioTrackVector audio_tracks = stream->GetAudioTracks();
272 for (size_t i = 0; i < audio_tracks.size(); ++i) {
273 AudioTrackInterface* track = audio_tracks[i];
fischman@webrtc.org41776152014-01-09 00:31:17 +0000274 jstring id = JavaStringFromStdString(jni(), track->id());
275 jobject j_track = jni()->NewObject(
276 *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000277 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000278 jfieldID audio_tracks_id = GetFieldID(jni(),
279 *j_media_stream_class_,
280 "audioTracks",
281 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000282 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000284 GetObjectClass(jni(), audio_tracks),
285 "add",
286 "(Ljava/lang/Object;)Z");
287 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000288 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
289 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290 }
291
292 VideoTrackVector video_tracks = stream->GetVideoTracks();
293 for (size_t i = 0; i < video_tracks.size(); ++i) {
294 VideoTrackInterface* track = video_tracks[i];
fischman@webrtc.org41776152014-01-09 00:31:17 +0000295 jstring id = JavaStringFromStdString(jni(), track->id());
296 jobject j_track = jni()->NewObject(
297 *j_video_track_class_, j_video_track_ctor_, (jlong)track, id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000298 CHECK_EXCEPTION(jni()) << "error during NewObject";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000299 jfieldID video_tracks_id = GetFieldID(jni(),
300 *j_media_stream_class_,
301 "videoTracks",
302 "Ljava/util/LinkedList;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000303 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304 jmethodID add = GetMethodID(jni(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000305 GetObjectClass(jni(), video_tracks),
306 "add",
307 "(Ljava/lang/Object;)Z");
308 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000309 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
310 CHECK(added);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 }
fischman@webrtc.org41776152014-01-09 00:31:17 +0000312 streams_[stream] = jni()->NewWeakGlobalRef(j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000313 CHECK_EXCEPTION(jni()) << "error during NewWeakGlobalRef";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000315 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
316 "(Lorg/webrtc/MediaStream;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000317 jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000318 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000319 }
320
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000321 void OnRemoveStream(MediaStreamInterface* stream) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000322 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000323 NativeToJavaStreamsMap::iterator it = streams_.find(stream);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000324 CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000325
326 WeakRef s(jni(), it->second);
327 streams_.erase(it);
328 if (!s.obj())
329 return;
330
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000331 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
332 "(Lorg/webrtc/MediaStream;)V");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000333 jni()->CallVoidMethod(*j_observer_global_, m, s.obj());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000334 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335 }
336
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000337 void OnDataChannel(DataChannelInterface* channel) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000338 ScopedLocalRefFrame local_ref_frame(jni());
339 jobject j_channel = jni()->NewObject(
340 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000341 CHECK_EXCEPTION(jni()) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000342
343 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
344 "(Lorg/webrtc/DataChannel;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000345 jni()->CallVoidMethod(*j_observer_global_, m, j_channel);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000346
347 // Channel is now owned by Java object, and will be freed from
348 // DataChannel.dispose(). Important that this be done _after_ the
349 // CallVoidMethod above as Java code might call back into native code and be
350 // surprised to see a refcount of 2.
351 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000352 CHECK(bumped_count == 2) << "Unexpected refcount OnDataChannel";
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000353
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000354 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000355 }
356
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000357 void OnRenegotiationNeeded() override {
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000358 ScopedLocalRefFrame local_ref_frame(jni());
359 jmethodID m =
360 GetMethodID(jni(), *j_observer_class_, "onRenegotiationNeeded", "()V");
361 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000362 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
fischman@webrtc.orgd7568a02014-01-13 22:04:12 +0000363 }
364
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365 void SetConstraints(ConstraintsWrapper* constraints) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000366 CHECK(!constraints_.get()) << "constraints already set!";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000367 constraints_.reset(constraints);
368 }
369
370 const ConstraintsWrapper* constraints() { return constraints_.get(); }
371
372 private:
373 JNIEnv* jni() {
374 return AttachCurrentThreadIfNeeded();
375 }
376
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000377 const ScopedGlobalRef<jobject> j_observer_global_;
378 const ScopedGlobalRef<jclass> j_observer_class_;
379 const ScopedGlobalRef<jclass> j_media_stream_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380 const jmethodID j_media_stream_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000381 const ScopedGlobalRef<jclass> j_audio_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000382 const jmethodID j_audio_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000383 const ScopedGlobalRef<jclass> j_video_track_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384 const jmethodID j_video_track_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000385 const ScopedGlobalRef<jclass> j_data_channel_class_;
386 const jmethodID j_data_channel_ctor_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387 typedef std::map<void*, jweak> NativeToJavaStreamsMap;
388 NativeToJavaStreamsMap streams_; // C++ -> Java streams.
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000389 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000390};
391
392// Wrapper for a Java MediaConstraints object. Copies all needed data so when
393// the constructor returns the Java object is no longer needed.
394class ConstraintsWrapper : public MediaConstraintsInterface {
395 public:
396 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) {
397 PopulateConstraintsFromJavaPairList(
398 jni, j_constraints, "mandatory", &mandatory_);
399 PopulateConstraintsFromJavaPairList(
400 jni, j_constraints, "optional", &optional_);
401 }
402
403 virtual ~ConstraintsWrapper() {}
404
405 // MediaConstraintsInterface.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000406 const Constraints& GetMandatory() const override { return mandatory_; }
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000407
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000408 const Constraints& GetOptional() const override { return optional_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409
410 private:
411 // Helper for translating a List<Pair<String, String>> to a Constraints.
412 static void PopulateConstraintsFromJavaPairList(
413 JNIEnv* jni, jobject j_constraints,
414 const char* field_name, Constraints* field) {
415 jfieldID j_id = GetFieldID(jni,
416 GetObjectClass(jni, j_constraints), field_name, "Ljava/util/List;");
417 jobject j_list = GetObjectField(jni, j_constraints, j_id);
418 jmethodID j_iterator_id = GetMethodID(jni,
419 GetObjectClass(jni, j_list), "iterator", "()Ljava/util/Iterator;");
420 jobject j_iterator = jni->CallObjectMethod(j_list, j_iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000421 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000422 jmethodID j_has_next = GetMethodID(jni,
423 GetObjectClass(jni, j_iterator), "hasNext", "()Z");
424 jmethodID j_next = GetMethodID(jni,
425 GetObjectClass(jni, j_iterator), "next", "()Ljava/lang/Object;");
426 while (jni->CallBooleanMethod(j_iterator, j_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000427 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000428 jobject entry = jni->CallObjectMethod(j_iterator, j_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000429 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000430 jmethodID get_key = GetMethodID(jni,
431 GetObjectClass(jni, entry), "getKey", "()Ljava/lang/String;");
432 jstring j_key = reinterpret_cast<jstring>(
433 jni->CallObjectMethod(entry, get_key));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000434 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435 jmethodID get_value = GetMethodID(jni,
436 GetObjectClass(jni, entry), "getValue", "()Ljava/lang/String;");
437 jstring j_value = reinterpret_cast<jstring>(
438 jni->CallObjectMethod(entry, get_value));
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000439 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 field->push_back(Constraint(JavaToStdString(jni, j_key),
441 JavaToStdString(jni, j_value)));
442 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000443 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444 }
445
446 Constraints mandatory_;
447 Constraints optional_;
448};
449
450static jobject JavaSdpFromNativeSdp(
451 JNIEnv* jni, const SessionDescriptionInterface* desc) {
452 std::string sdp;
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000453 CHECK(desc->ToString(&sdp)) << "got so far: " << sdp;
fischman@webrtc.org41776152014-01-09 00:31:17 +0000454 jstring j_description = JavaStringFromStdString(jni, sdp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000455
456 jclass j_type_class = FindClass(
457 jni, "org/webrtc/SessionDescription$Type");
458 jmethodID j_type_from_canonical = GetStaticMethodID(
459 jni, j_type_class, "fromCanonicalForm",
460 "(Ljava/lang/String;)Lorg/webrtc/SessionDescription$Type;");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000461 jstring j_type_string = JavaStringFromStdString(jni, desc->type());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000462 jobject j_type = jni->CallStaticObjectMethod(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000463 j_type_class, j_type_from_canonical, j_type_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000464 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465
466 jclass j_sdp_class = FindClass(jni, "org/webrtc/SessionDescription");
467 jmethodID j_sdp_ctor = GetMethodID(
468 jni, j_sdp_class, "<init>",
469 "(Lorg/webrtc/SessionDescription$Type;Ljava/lang/String;)V");
470 jobject j_sdp = jni->NewObject(
fischman@webrtc.org41776152014-01-09 00:31:17 +0000471 j_sdp_class, j_sdp_ctor, j_type, j_description);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000472 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000473 return j_sdp;
474}
475
476template <class T> // T is one of {Create,Set}SessionDescriptionObserver.
477class SdpObserverWrapper : public T {
478 public:
479 SdpObserverWrapper(JNIEnv* jni, jobject j_observer,
480 ConstraintsWrapper* constraints)
481 : constraints_(constraints),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000482 j_observer_global_(jni, j_observer),
483 j_observer_class_(jni, GetObjectClass(jni, j_observer)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484 }
485
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000486 virtual ~SdpObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000488 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000489 virtual void OnSuccess() {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000490 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000491 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
492 jni()->CallVoidMethod(*j_observer_global_, m);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000493 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000494 }
495
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000496 // Can't mark override because of templating.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000497 virtual void OnSuccess(SessionDescriptionInterface* desc) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000498 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 jmethodID m = GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000500 jni(), *j_observer_class_, "onCreateSuccess",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000501 "(Lorg/webrtc/SessionDescription;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000502 jobject j_sdp = JavaSdpFromNativeSdp(jni(), desc);
503 jni()->CallVoidMethod(*j_observer_global_, m, j_sdp);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000504 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000505 }
506
507 protected:
508 // Common implementation for failure of Set & Create types, distinguished by
509 // |op| being "Set" or "Create".
510 void OnFailure(const std::string& op, const std::string& error) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000511 jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
512 "(Ljava/lang/String;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000513 jstring j_error_string = JavaStringFromStdString(jni(), error);
514 jni()->CallVoidMethod(*j_observer_global_, m, j_error_string);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000515 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000516 }
517
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000518 JNIEnv* jni() {
519 return AttachCurrentThreadIfNeeded();
520 }
521
fischman@webrtc.org41776152014-01-09 00:31:17 +0000522 private:
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000523 scoped_ptr<ConstraintsWrapper> constraints_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000524 const ScopedGlobalRef<jobject> j_observer_global_;
525 const ScopedGlobalRef<jclass> j_observer_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526};
527
528class CreateSdpObserverWrapper
529 : public SdpObserverWrapper<CreateSessionDescriptionObserver> {
530 public:
531 CreateSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
532 ConstraintsWrapper* constraints)
533 : SdpObserverWrapper(jni, j_observer, constraints) {}
534
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000535 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000536 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000537 SdpObserverWrapper::OnFailure(std::string("Create"), error);
538 }
539};
540
541class SetSdpObserverWrapper
542 : public SdpObserverWrapper<SetSessionDescriptionObserver> {
543 public:
544 SetSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
545 ConstraintsWrapper* constraints)
546 : SdpObserverWrapper(jni, j_observer, constraints) {}
547
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000548 void OnFailure(const std::string& error) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000549 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000550 SdpObserverWrapper::OnFailure(std::string("Set"), error);
551 }
552};
553
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000554// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
555// and dispatching the callback from C++ back to Java.
556class DataChannelObserverWrapper : public DataChannelObserver {
557 public:
558 DataChannelObserverWrapper(JNIEnv* jni, jobject j_observer)
559 : j_observer_global_(jni, j_observer),
560 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
pbos@webrtc.orgb648b9d2014-08-26 11:08:06 +0000561 j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")),
bemasc0edd50c2015-07-01 13:34:33 -0700562 j_on_buffered_amount_change_mid_(GetMethodID(
563 jni, *j_observer_class_, "onBufferedAmountChange", "(J)V")),
564 j_on_state_change_mid_(
565 GetMethodID(jni, *j_observer_class_, "onStateChange", "()V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000566 j_on_message_mid_(GetMethodID(jni, *j_observer_class_, "onMessage",
567 "(Lorg/webrtc/DataChannel$Buffer;)V")),
bemasc0edd50c2015-07-01 13:34:33 -0700568 j_buffer_ctor_(GetMethodID(jni, *j_buffer_class_, "<init>",
569 "(Ljava/nio/ByteBuffer;Z)V")) {}
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000570
571 virtual ~DataChannelObserverWrapper() {}
572
bemasc0edd50c2015-07-01 13:34:33 -0700573 void OnBufferedAmountChange(uint64 previous_amount) override {
574 ScopedLocalRefFrame local_ref_frame(jni());
575 jni()->CallVoidMethod(*j_observer_global_, j_on_buffered_amount_change_mid_,
576 previous_amount);
577 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
578 }
579
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000580 void OnStateChange() override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000581 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000582 jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000583 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000584 }
585
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000586 void OnMessage(const DataBuffer& buffer) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000587 ScopedLocalRefFrame local_ref_frame(jni());
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000588 jobject byte_buffer = jni()->NewDirectByteBuffer(
Karl Wiberg94784372015-04-20 14:03:07 +0200589 const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000590 jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_,
591 byte_buffer, buffer.binary);
592 jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000593 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000594 }
595
596 private:
597 JNIEnv* jni() {
598 return AttachCurrentThreadIfNeeded();
599 }
600
601 const ScopedGlobalRef<jobject> j_observer_global_;
602 const ScopedGlobalRef<jclass> j_observer_class_;
603 const ScopedGlobalRef<jclass> j_buffer_class_;
bemasc0edd50c2015-07-01 13:34:33 -0700604 const jmethodID j_on_buffered_amount_change_mid_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000605 const jmethodID j_on_state_change_mid_;
606 const jmethodID j_on_message_mid_;
607 const jmethodID j_buffer_ctor_;
608};
609
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610// Adapter for a Java StatsObserver presenting a C++ StatsObserver and
611// dispatching the callback from C++ back to Java.
612class StatsObserverWrapper : public StatsObserver {
613 public:
614 StatsObserverWrapper(JNIEnv* jni, jobject j_observer)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000615 : j_observer_global_(jni, j_observer),
616 j_observer_class_(jni, GetObjectClass(jni, j_observer)),
617 j_stats_report_class_(jni, FindClass(jni, "org/webrtc/StatsReport")),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000618 j_stats_report_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000619 jni, *j_stats_report_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000620 "(Ljava/lang/String;Ljava/lang/String;D"
621 "[Lorg/webrtc/StatsReport$Value;)V")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000622 j_value_class_(jni, FindClass(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000623 jni, "org/webrtc/StatsReport$Value")),
624 j_value_ctor_(GetMethodID(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000625 jni, *j_value_class_, "<init>",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 "(Ljava/lang/String;Ljava/lang/String;)V")) {
627 }
628
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000629 virtual ~StatsObserverWrapper() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000630
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000631 void OnComplete(const StatsReports& reports) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000632 ScopedLocalRefFrame local_ref_frame(jni());
633 jobjectArray j_reports = ReportsToJava(jni(), reports);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000634 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
635 "([Lorg/webrtc/StatsReport;)V");
fischman@webrtc.org41776152014-01-09 00:31:17 +0000636 jni()->CallVoidMethod(*j_observer_global_, m, j_reports);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000637 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000638 }
639
640 private:
641 jobjectArray ReportsToJava(
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000642 JNIEnv* jni, const StatsReports& reports) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643 jobjectArray reports_array = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000644 reports.size(), *j_stats_report_class_, NULL);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000645 int i = 0;
646 for (const auto* report : reports) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000647 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000648 jstring j_id = JavaStringFromStdString(jni, report->id()->ToString());
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000649 jstring j_type = JavaStringFromStdString(jni, report->TypeToString());
650 jobjectArray j_values = ValuesToJava(jni, report->values());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000651 jobject j_report = jni->NewObject(*j_stats_report_class_,
652 j_stats_report_ctor_,
653 j_id,
654 j_type,
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000655 report->timestamp(),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000656 j_values);
tommi@webrtc.orge2e199b2014-12-15 13:22:54 +0000657 jni->SetObjectArrayElement(reports_array, i++, j_report);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658 }
659 return reports_array;
660 }
661
662 jobjectArray ValuesToJava(JNIEnv* jni, const StatsReport::Values& values) {
663 jobjectArray j_values = jni->NewObjectArray(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000664 values.size(), *j_value_class_, NULL);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000665 int i = 0;
666 for (const auto& it : values) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000667 ScopedLocalRefFrame local_ref_frame(jni);
tommi@webrtc.orgc57310b2014-12-12 17:41:28 +0000668 // Should we use the '.name' enum value here instead of converting the
669 // name to a string?
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000670 jstring j_name = JavaStringFromStdString(jni, it.second->display_name());
671 jstring j_value = JavaStringFromStdString(jni, it.second->ToString());
fischman@webrtc.org41776152014-01-09 00:31:17 +0000672 jobject j_element_value =
673 jni->NewObject(*j_value_class_, j_value_ctor_, j_name, j_value);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000674 jni->SetObjectArrayElement(j_values, i++, j_element_value);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000675 }
676 return j_values;
677 }
678
679 JNIEnv* jni() {
680 return AttachCurrentThreadIfNeeded();
681 }
682
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000683 const ScopedGlobalRef<jobject> j_observer_global_;
684 const ScopedGlobalRef<jclass> j_observer_class_;
685 const ScopedGlobalRef<jclass> j_stats_report_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 const jmethodID j_stats_report_ctor_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000687 const ScopedGlobalRef<jclass> j_value_class_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 const jmethodID j_value_ctor_;
689};
690
691// Adapter presenting a cricket::VideoRenderer as a
692// webrtc::VideoRendererInterface.
693class VideoRendererWrapper : public VideoRendererInterface {
694 public:
695 static VideoRendererWrapper* Create(cricket::VideoRenderer* renderer) {
696 if (renderer)
697 return new VideoRendererWrapper(renderer);
698 return NULL;
699 }
700
701 virtual ~VideoRendererWrapper() {}
702
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000703 // This wraps VideoRenderer which still has SetSize.
704 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000705 ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000706 const cricket::VideoFrame* frame =
707 video_frame->GetCopyWithRotationApplied();
708 if (width_ != frame->GetWidth() || height_ != frame->GetHeight()) {
709 width_ = frame->GetWidth();
710 height_ = frame->GetHeight();
711 renderer_->SetSize(width_, height_, 0);
712 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 renderer_->RenderFrame(frame);
714 }
715
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000716 // TODO(guoweis): Remove this once chrome code base is updated.
717 bool CanApplyRotation() override { return true; }
718
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000719 private:
720 explicit VideoRendererWrapper(cricket::VideoRenderer* renderer)
Henrik Kjellander7c027b62015-04-22 13:21:30 +0200721 : width_(0), height_(0), renderer_(renderer) {}
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000722 int width_, height_;
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000723 scoped_ptr<cricket::VideoRenderer> renderer_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000724};
725
726// Wrapper dispatching webrtc::VideoRendererInterface to a Java VideoRenderer
727// instance.
728class JavaVideoRendererWrapper : public VideoRendererInterface {
729 public:
730 JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000731 : j_callbacks_(jni, j_callbacks),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000732 j_render_frame_id_(GetMethodID(
733 jni, GetObjectClass(jni, j_callbacks), "renderFrame",
734 "(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000735 j_can_apply_rotation_id_(GetMethodID(
736 jni, GetObjectClass(jni, j_callbacks),
737 "canApplyRotation", "()Z")),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000738 j_frame_class_(jni,
739 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000740 j_i420_frame_ctor_id_(GetMethodID(
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000741 jni, *j_frame_class_, "<init>", "(III[I[Ljava/nio/ByteBuffer;)V")),
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000742 j_texture_frame_ctor_id_(GetMethodID(
743 jni, *j_frame_class_, "<init>",
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000744 "(IIILjava/lang/Object;I)V")),
745 j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")),
746 can_apply_rotation_set_(false),
747 can_apply_rotation_(false) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000748 CHECK_EXCEPTION(jni);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000749 }
750
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000751 virtual ~JavaVideoRendererWrapper() {}
752
guoweis@webrtc.org00c509a2015-03-12 21:37:26 +0000753 void RenderFrame(const cricket::VideoFrame* video_frame) override {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000754 ScopedLocalRefFrame local_ref_frame(jni());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000755
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000756 // Calling CanApplyRotation here to ensure can_apply_rotation_ is set.
757 CanApplyRotation();
guoweis@webrtc.org3fffd662015-03-18 04:20:03 +0000758
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000759 const cricket::VideoFrame* frame =
760 can_apply_rotation_ ? video_frame
761 : video_frame->GetCopyWithRotationApplied();
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000762 if (frame->GetNativeHandle() != NULL) {
763 jobject j_frame = CricketToJavaTextureFrame(frame);
764 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
765 CHECK_EXCEPTION(jni());
766 } else {
767 jobject j_frame = CricketToJavaI420Frame(frame);
768 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
769 CHECK_EXCEPTION(jni());
770 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000771 }
772
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000773 // TODO(guoweis): Report that rotation is supported as RenderFrame calls
774 // GetCopyWithRotationApplied.
775 virtual bool CanApplyRotation() override {
776 if (can_apply_rotation_set_) {
777 return can_apply_rotation_;
778 }
779 ScopedLocalRefFrame local_ref_frame(jni());
780 jboolean ret =
781 jni()->CallBooleanMethod(*j_callbacks_, j_can_apply_rotation_id_);
782 CHECK_EXCEPTION(jni());
783 can_apply_rotation_ = ret;
784 can_apply_rotation_set_ = true;
785 return ret;
786 }
787
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788 private:
789 // Return a VideoRenderer.I420Frame referring to the data in |frame|.
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000790 jobject CricketToJavaI420Frame(const cricket::VideoFrame* frame) {
fischman@webrtc.org41776152014-01-09 00:31:17 +0000791 jintArray strides = jni()->NewIntArray(3);
792 jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 strides_array[0] = frame->GetYPitch();
794 strides_array[1] = frame->GetUPitch();
795 strides_array[2] = frame->GetVPitch();
fischman@webrtc.org41776152014-01-09 00:31:17 +0000796 jni()->ReleaseIntArrayElements(strides, strides_array, 0);
797 jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
798 jobject y_buffer = jni()->NewDirectByteBuffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000799 const_cast<uint8*>(frame->GetYPlane()),
fischman@webrtc.org41776152014-01-09 00:31:17 +0000800 frame->GetYPitch() * frame->GetHeight());
801 jobject u_buffer = jni()->NewDirectByteBuffer(
802 const_cast<uint8*>(frame->GetUPlane()), frame->GetChromaSize());
803 jobject v_buffer = jni()->NewDirectByteBuffer(
804 const_cast<uint8*>(frame->GetVPlane()), frame->GetChromaSize());
805 jni()->SetObjectArrayElement(planes, 0, y_buffer);
806 jni()->SetObjectArrayElement(planes, 1, u_buffer);
807 jni()->SetObjectArrayElement(planes, 2, v_buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000808 return jni()->NewObject(
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000809 *j_frame_class_, j_i420_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000810 frame->GetWidth(), frame->GetHeight(),
811 static_cast<int>(frame->GetVideoRotation()),
812 strides, planes);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000813 }
814
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000815 // Return a VideoRenderer.I420Frame referring texture object in |frame|.
816 jobject CricketToJavaTextureFrame(const cricket::VideoFrame* frame) {
817 NativeHandleImpl* handle =
818 reinterpret_cast<NativeHandleImpl*>(frame->GetNativeHandle());
819 jobject texture_object = reinterpret_cast<jobject>(handle->GetHandle());
820 int texture_id = handle->GetTextureId();
821 return jni()->NewObject(
822 *j_frame_class_, j_texture_frame_ctor_id_,
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000823 frame->GetWidth(), frame->GetHeight(),
824 static_cast<int>(frame->GetVideoRotation()),
825 texture_object, texture_id);
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000826 }
827
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000828 JNIEnv* jni() {
829 return AttachCurrentThreadIfNeeded();
830 }
831
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000832 ScopedGlobalRef<jobject> j_callbacks_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000833 jmethodID j_render_frame_id_;
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000834 jmethodID j_can_apply_rotation_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000835 ScopedGlobalRef<jclass> j_frame_class_;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000836 jmethodID j_i420_frame_ctor_id_;
837 jmethodID j_texture_frame_ctor_id_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000838 ScopedGlobalRef<jclass> j_byte_buffer_class_;
guoweis@webrtc.org840da7b2015-03-18 16:58:13 +0000839 bool can_apply_rotation_set_;
840 bool can_apply_rotation_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000841};
842
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000843
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000844static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000845 jfieldID native_dc_id = GetFieldID(jni,
846 GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
847 jlong j_d = GetLongField(jni, j_dc, native_dc_id);
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000848 return reinterpret_cast<DataChannelInterface*>(j_d);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000849}
850
851JOW(jlong, DataChannel_registerObserverNative)(
852 JNIEnv* jni, jobject j_dc, jobject j_observer) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +0000853 scoped_ptr<DataChannelObserverWrapper> observer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000854 new DataChannelObserverWrapper(jni, j_observer));
855 ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
fischman@webrtc.orgf41f06b2013-12-11 21:07:18 +0000856 return jlongFromPointer(observer.release());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000857}
858
859JOW(void, DataChannel_unregisterObserverNative)(
860 JNIEnv* jni, jobject j_dc, jlong native_observer) {
861 ExtractNativeDC(jni, j_dc)->UnregisterObserver();
862 delete reinterpret_cast<DataChannelObserverWrapper*>(native_observer);
863}
864
865JOW(jstring, DataChannel_label)(JNIEnv* jni, jobject j_dc) {
866 return JavaStringFromStdString(jni, ExtractNativeDC(jni, j_dc)->label());
867}
868
869JOW(jobject, DataChannel_state)(JNIEnv* jni, jobject j_dc) {
870 return JavaEnumFromIndex(
871 jni, "DataChannel$State", ExtractNativeDC(jni, j_dc)->state());
872}
873
874JOW(jlong, DataChannel_bufferedAmount)(JNIEnv* jni, jobject j_dc) {
875 uint64 buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000876 CHECK_LE(buffered_amount, std::numeric_limits<int64>::max())
877 << "buffered_amount overflowed jlong!";
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000878 return static_cast<jlong>(buffered_amount);
879}
880
881JOW(void, DataChannel_close)(JNIEnv* jni, jobject j_dc) {
882 ExtractNativeDC(jni, j_dc)->Close();
883}
884
885JOW(jboolean, DataChannel_sendNative)(JNIEnv* jni, jobject j_dc,
886 jbyteArray data, jboolean binary) {
887 jbyte* bytes = jni->GetByteArrayElements(data, NULL);
888 bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000889 rtc::Buffer(bytes, jni->GetArrayLength(data)),
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000890 binary));
891 jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
892 return ret;
893}
894
895JOW(void, DataChannel_dispose)(JNIEnv* jni, jobject j_dc) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000896 CHECK_RELEASE(ExtractNativeDC(jni, j_dc));
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000897}
898
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000899JOW(void, Logging_nativeEnableTracing)(
900 JNIEnv* jni, jclass, jstring j_path, jint nativeLevels,
901 jint nativeSeverity) {
902 std::string path = JavaToStdString(jni, j_path);
903 if (nativeLevels != webrtc::kTraceNone) {
andrew@webrtc.org90805182013-09-05 16:40:43 +0000904 webrtc::Trace::set_level_filter(nativeLevels);
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000905#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000906 if (path != "logcat:") {
907#endif
andresp@webrtc.org4d19e052014-09-09 11:45:44 +0000908 CHECK_EQ(0, webrtc::Trace::SetTraceFile(path.c_str(), false))
909 << "SetTraceFile failed";
glaznev@webrtc.orge6581242014-09-19 16:53:46 +0000910#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
fischman@webrtc.org7e4d0df2013-10-01 02:40:43 +0000911 } else {
912 // Intentionally leak this to avoid needing to reason about its lifecycle.
913 // It keeps no state and functions only as a dispatch point.
914 static LogcatTraceContext* g_trace_callback = new LogcatTraceContext();
915 }
916#endif
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000917 }
Tommi0eefb4d2015-05-23 09:54:07 +0200918 if (nativeSeverity >= rtc::LS_SENSITIVE && nativeSeverity <= rtc::LS_ERROR) {
919 rtc::LogMessage::LogToDebug(
920 static_cast<rtc::LoggingSeverity>(nativeSeverity));
921 }
fischman@webrtc.orgc883fdc2013-08-06 19:00:53 +0000922}
923
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000924JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000925 CHECK_RELEASE(reinterpret_cast<PeerConnectionInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926}
927
928JOW(void, PeerConnection_freeObserver)(JNIEnv*, jclass, jlong j_p) {
929 PCOJava* p = reinterpret_cast<PCOJava*>(j_p);
930 delete p;
931}
932
933JOW(void, MediaSource_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000934 CHECK_RELEASE(reinterpret_cast<MediaSourceInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935}
936
937JOW(void, VideoCapturer_free)(JNIEnv*, jclass, jlong j_p) {
938 delete reinterpret_cast<cricket::VideoCapturer*>(j_p);
939}
940
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000941JOW(void, VideoRenderer_freeGuiVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942 delete reinterpret_cast<VideoRendererWrapper*>(j_p);
943}
944
glaznev@webrtc.orga59c5012014-09-17 03:26:59 +0000945JOW(void, VideoRenderer_freeWrappedVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
946 delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
947}
948
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000949JOW(void, MediaStreamTrack_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000950 CHECK_RELEASE(reinterpret_cast<MediaStreamTrackInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000951}
952
953JOW(jboolean, MediaStream_nativeAddAudioTrack)(
954 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000955 return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000956 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000957}
958
959JOW(jboolean, MediaStream_nativeAddVideoTrack)(
960 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000961 return reinterpret_cast<MediaStreamInterface*>(pointer)
962 ->AddTrack(reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963}
964
965JOW(jboolean, MediaStream_nativeRemoveAudioTrack)(
966 JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000967 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000968 reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969}
970
971JOW(jboolean, MediaStream_nativeRemoveVideoTrack)(
972 JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000973 return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000974 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975}
976
977JOW(jstring, MediaStream_nativeLabel)(JNIEnv* jni, jclass, jlong j_p) {
978 return JavaStringFromStdString(
979 jni, reinterpret_cast<MediaStreamInterface*>(j_p)->label());
980}
981
982JOW(void, MediaStream_free)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +0000983 CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000984}
985
986JOW(jlong, PeerConnectionFactory_nativeCreateObserver)(
987 JNIEnv * jni, jclass, jobject j_observer) {
988 return (jlong)new PCOJava(jni, j_observer);
989}
990
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +0000991#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992JOW(jboolean, PeerConnectionFactory_initializeAndroidGlobals)(
fischman@webrtc.orga150bc92014-05-14 22:00:50 +0000993 JNIEnv* jni, jclass, jobject context,
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000994 jboolean initialize_audio, jboolean initialize_video,
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000995 jboolean vp8_hw_acceleration, jobject render_egl_context) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000996 bool failure = false;
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +0000997 vp8_hw_acceleration_enabled = vp8_hw_acceleration;
glaznev@webrtc.org99678452014-09-15 17:52:42 +0000998 if (!factory_static_initialized) {
andresp@webrtc.org85ef7702014-09-17 11:44:51 +0000999 if (initialize_video) {
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001000 failure |= webrtc::SetRenderAndroidVM(GetJVM());
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001001 failure |= AndroidVideoCapturerJni::SetAndroidObjects(jni, context);
andresp@webrtc.org85ef7702014-09-17 11:44:51 +00001002 }
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001003 if (initialize_audio)
henrika@webrtc.org474d1eb2015-03-09 12:39:53 +00001004 failure |= webrtc::VoiceEngine::SetAndroidObjects(GetJVM(), context);
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001005 factory_static_initialized = true;
1006 }
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001007 if (initialize_video) {
glaznev@webrtc.org18c92472015-02-18 18:42:55 +00001008 failure |= MediaCodecVideoDecoderFactory::SetAndroidObjects(jni,
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001009 render_egl_context);
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001010 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001011 return !failure;
1012}
glaznev@webrtc.org1d53f642014-09-11 16:58:25 +00001013#endif // defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001015JOW(void, PeerConnectionFactory_initializeFieldTrials)(
1016 JNIEnv* jni, jclass, jstring j_trials_init_string) {
1017 field_trials_init_string = NULL;
1018 if (j_trials_init_string != NULL) {
1019 const char* init_string =
1020 jni->GetStringUTFChars(j_trials_init_string, NULL);
1021 int init_string_length = jni->GetStringUTFLength(j_trials_init_string);
1022 field_trials_init_string = new char[init_string_length + 1];
1023 rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string);
1024 jni->ReleaseStringUTFChars(j_trials_init_string, init_string);
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001025 LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string;
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001026 }
1027 webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string);
1028}
1029
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001030// Helper struct for working around the fact that CreatePeerConnectionFactory()
1031// comes in two flavors: either entirely automagical (constructing its own
1032// threads and deleting them on teardown, but no external codec factory support)
1033// or entirely manual (requires caller to delete threads after factory
1034// teardown). This struct takes ownership of its ctor's arguments to present a
1035// single thing for Java to hold and eventually free.
1036class OwnedFactoryAndThreads {
1037 public:
1038 OwnedFactoryAndThreads(Thread* worker_thread,
1039 Thread* signaling_thread,
1040 PeerConnectionFactoryInterface* factory)
1041 : worker_thread_(worker_thread),
1042 signaling_thread_(signaling_thread),
1043 factory_(factory) {}
1044
1045 ~OwnedFactoryAndThreads() { CHECK_RELEASE(factory_); }
1046
1047 PeerConnectionFactoryInterface* factory() { return factory_; }
1048
1049 private:
1050 const scoped_ptr<Thread> worker_thread_;
1051 const scoped_ptr<Thread> signaling_thread_;
1052 PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
1053};
1054
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001055JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)(
1056 JNIEnv* jni, jclass) {
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001057 // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
1058 // ThreadManager only WrapCurrentThread()s the thread where it is first
1059 // created. Since the semantics around when auto-wrapping happens in
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001060 // webrtc/base/ are convoluted, we simply wrap here to avoid having to think
fischman@webrtc.org2c98af72014-05-14 17:33:32 +00001061 // about ramifications of auto-wrapping there.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001062 rtc::ThreadManager::Instance()->WrapCurrentThread();
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001063 webrtc::Trace::CreateTrace();
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001064 Thread* worker_thread = new Thread();
1065 worker_thread->SetName("worker_thread", NULL);
1066 Thread* signaling_thread = new Thread();
1067 signaling_thread->SetName("signaling_thread", NULL);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001068 CHECK(worker_thread->Start() && signaling_thread->Start())
1069 << "Failed to start threads";
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001070 scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001071 scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
glaznev@webrtc.org99678452014-09-15 17:52:42 +00001072#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
glaznev@webrtc.orgdea51732014-12-01 20:02:13 +00001073 if (vp8_hw_acceleration_enabled) {
1074 encoder_factory.reset(new MediaCodecVideoEncoderFactory());
1075 decoder_factory.reset(new MediaCodecVideoDecoderFactory());
1076 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001077#endif
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001078 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001079 webrtc::CreatePeerConnectionFactory(worker_thread,
1080 signaling_thread,
1081 NULL,
1082 encoder_factory.release(),
glaznev@webrtc.orgefe4b9a2014-07-22 17:44:53 +00001083 decoder_factory.release()));
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001084 OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
1085 worker_thread, signaling_thread, factory.release());
1086 return jlongFromPointer(owned_factory);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087}
1088
1089JOW(void, PeerConnectionFactory_freeFactory)(JNIEnv*, jclass, jlong j_p) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001090 delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
glaznev@webrtc.org44ae4c82015-02-09 23:25:58 +00001091 if (field_trials_init_string) {
1092 webrtc::field_trial::InitFieldTrialsFromString(NULL);
1093 delete field_trials_init_string;
1094 field_trials_init_string = NULL;
1095 }
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001096 webrtc::Trace::ReturnTrace();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001097}
1098
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001099static PeerConnectionFactoryInterface* factoryFromJava(jlong j_p) {
1100 return reinterpret_cast<OwnedFactoryAndThreads*>(j_p)->factory();
1101}
1102
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001103JOW(jlong, PeerConnectionFactory_nativeCreateLocalMediaStream)(
1104 JNIEnv* jni, jclass, jlong native_factory, jstring label) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001105 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001106 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001107 rtc::scoped_refptr<MediaStreamInterface> stream(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001108 factory->CreateLocalMediaStream(JavaToStdString(jni, label)));
1109 return (jlong)stream.release();
1110}
1111
1112JOW(jlong, PeerConnectionFactory_nativeCreateVideoSource)(
1113 JNIEnv* jni, jclass, jlong native_factory, jlong native_capturer,
1114 jobject j_constraints) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001115 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001116 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001117 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001118 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001119 rtc::scoped_refptr<VideoSourceInterface> source(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001120 factory->CreateVideoSource(
1121 reinterpret_cast<cricket::VideoCapturer*>(native_capturer),
1122 constraints.get()));
1123 return (jlong)source.release();
1124}
1125
1126JOW(jlong, PeerConnectionFactory_nativeCreateVideoTrack)(
1127 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1128 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001129 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001130 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001131 rtc::scoped_refptr<VideoTrackInterface> track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001132 factory->CreateVideoTrack(
1133 JavaToStdString(jni, id),
1134 reinterpret_cast<VideoSourceInterface*>(native_source)));
1135 return (jlong)track.release();
1136}
1137
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001138JOW(jlong, PeerConnectionFactory_nativeCreateAudioSource)(
1139 JNIEnv* jni, jclass, jlong native_factory, jobject j_constraints) {
1140 scoped_ptr<ConstraintsWrapper> constraints(
1141 new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001142 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001143 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001144 rtc::scoped_refptr<AudioSourceInterface> source(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001145 factory->CreateAudioSource(constraints.get()));
1146 return (jlong)source.release();
1147}
1148
1149JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack)(
1150 JNIEnv* jni, jclass, jlong native_factory, jstring id,
1151 jlong native_source) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001152 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001153 factoryFromJava(native_factory));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001154 rtc::scoped_refptr<AudioTrackInterface> track(factory->CreateAudioTrack(
fischman@webrtc.org3eda6432014-02-13 04:01:04 +00001155 JavaToStdString(jni, id),
1156 reinterpret_cast<AudioSourceInterface*>(native_source)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001157 return (jlong)track.release();
1158}
1159
phoglund@webrtc.org006521d2015-02-12 09:23:59 +00001160JOW(void, PeerConnectionFactory_nativeSetOptions)(
1161 JNIEnv* jni, jclass, jlong native_factory, jobject options) {
1162 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
1163 factoryFromJava(native_factory));
1164 jclass options_class = jni->GetObjectClass(options);
1165 jfieldID network_ignore_mask_field =
1166 jni->GetFieldID(options_class, "networkIgnoreMask", "I");
1167 int network_ignore_mask =
1168 jni->GetIntField(options, network_ignore_mask_field);
1169 PeerConnectionFactoryInterface::Options options_to_set;
1170
1171 // This doesn't necessarily match the c++ version of this struct; feel free
1172 // to add more parameters as necessary.
1173 options_to_set.network_ignore_mask = network_ignore_mask;
1174 factory->SetOptions(options_to_set);
1175}
1176
Jiayang Liucac1b382015-04-30 12:35:24 -07001177static std::string
1178GetJavaEnumName(JNIEnv* jni, const std::string& className, jobject j_enum) {
1179 jclass enumClass = FindClass(jni, className.c_str());
1180 jmethodID nameMethod =
1181 GetMethodID(jni, enumClass, "name", "()Ljava/lang/String;");
1182 jstring name =
1183 reinterpret_cast<jstring>(jni->CallObjectMethod(j_enum, nameMethod));
1184 CHECK_EXCEPTION(jni) << "error during CallObjectMethod for "
1185 << className << ".name";
1186 return JavaToStdString(jni, name);
1187}
1188
1189static PeerConnectionInterface::IceTransportsType
1190JavaIceTransportsTypeToNativeType(JNIEnv* jni, jobject j_ice_transports_type) {
1191 std::string enum_name = GetJavaEnumName(
1192 jni, "org/webrtc/PeerConnection$IceTransportsType",
1193 j_ice_transports_type);
1194
1195 if (enum_name == "ALL")
1196 return PeerConnectionInterface::kAll;
1197
1198 if (enum_name == "RELAY")
1199 return PeerConnectionInterface::kRelay;
1200
1201 if (enum_name == "NOHOST")
1202 return PeerConnectionInterface::kNoHost;
1203
1204 if (enum_name == "NONE")
1205 return PeerConnectionInterface::kNone;
1206
1207 CHECK(false) << "Unexpected IceTransportsType enum_name " << enum_name;
1208 return PeerConnectionInterface::kAll;
1209}
1210
1211static PeerConnectionInterface::BundlePolicy
1212JavaBundlePolicyToNativeType(JNIEnv* jni, jobject j_bundle_policy) {
1213 std::string enum_name = GetJavaEnumName(
1214 jni, "org/webrtc/PeerConnection$BundlePolicy",
1215 j_bundle_policy);
1216
1217 if (enum_name == "BALANCED")
1218 return PeerConnectionInterface::kBundlePolicyBalanced;
1219
1220 if (enum_name == "MAXBUNDLE")
1221 return PeerConnectionInterface::kBundlePolicyMaxBundle;
1222
1223 if (enum_name == "MAXCOMPAT")
1224 return PeerConnectionInterface::kBundlePolicyMaxCompat;
1225
1226 CHECK(false) << "Unexpected BundlePolicy enum_name " << enum_name;
1227 return PeerConnectionInterface::kBundlePolicyBalanced;
1228}
1229
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001230static PeerConnectionInterface::RtcpMuxPolicy
1231JavaRtcpMuxPolicyToNativeType(JNIEnv* jni, jobject j_rtcp_mux_policy) {
1232 std::string enum_name = GetJavaEnumName(
1233 jni, "org/webrtc/PeerConnection$RtcpMuxPolicy",
1234 j_rtcp_mux_policy);
1235
1236 if (enum_name == "NEGOTIATE")
1237 return PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
1238
1239 if (enum_name == "REQUIRE")
1240 return PeerConnectionInterface::kRtcpMuxPolicyRequire;
1241
1242 CHECK(false) << "Unexpected RtcpMuxPolicy enum_name " << enum_name;
1243 return PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
1244}
1245
Jiayang Liucac1b382015-04-30 12:35:24 -07001246static PeerConnectionInterface::TcpCandidatePolicy
1247JavaTcpCandidatePolicyToNativeType(
1248 JNIEnv* jni, jobject j_tcp_candidate_policy) {
1249 std::string enum_name = GetJavaEnumName(
1250 jni, "org/webrtc/PeerConnection$TcpCandidatePolicy",
1251 j_tcp_candidate_policy);
1252
1253 if (enum_name == "ENABLED")
1254 return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
1255
1256 if (enum_name == "DISABLED")
1257 return PeerConnectionInterface::kTcpCandidatePolicyDisabled;
1258
1259 CHECK(false) << "Unexpected TcpCandidatePolicy enum_name " << enum_name;
1260 return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
1261}
1262
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001263static void JavaIceServersToJsepIceServers(
1264 JNIEnv* jni, jobject j_ice_servers,
1265 PeerConnectionInterface::IceServers* ice_servers) {
1266 jclass list_class = GetObjectClass(jni, j_ice_servers);
1267 jmethodID iterator_id = GetMethodID(
1268 jni, list_class, "iterator", "()Ljava/util/Iterator;");
1269 jobject iterator = jni->CallObjectMethod(j_ice_servers, iterator_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001270 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001271 jmethodID iterator_has_next = GetMethodID(
1272 jni, GetObjectClass(jni, iterator), "hasNext", "()Z");
1273 jmethodID iterator_next = GetMethodID(
1274 jni, GetObjectClass(jni, iterator), "next", "()Ljava/lang/Object;");
1275 while (jni->CallBooleanMethod(iterator, iterator_has_next)) {
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001276 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001277 jobject j_ice_server = jni->CallObjectMethod(iterator, iterator_next);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001278 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001279 jclass j_ice_server_class = GetObjectClass(jni, j_ice_server);
1280 jfieldID j_ice_server_uri_id =
1281 GetFieldID(jni, j_ice_server_class, "uri", "Ljava/lang/String;");
1282 jfieldID j_ice_server_username_id =
1283 GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;");
1284 jfieldID j_ice_server_password_id =
1285 GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;");
1286 jstring uri = reinterpret_cast<jstring>(
1287 GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
1288 jstring username = reinterpret_cast<jstring>(
1289 GetObjectField(jni, j_ice_server, j_ice_server_username_id));
1290 jstring password = reinterpret_cast<jstring>(
1291 GetObjectField(jni, j_ice_server, j_ice_server_password_id));
1292 PeerConnectionInterface::IceServer server;
1293 server.uri = JavaToStdString(jni, uri);
1294 server.username = JavaToStdString(jni, username);
1295 server.password = JavaToStdString(jni, password);
1296 ice_servers->push_back(server);
1297 }
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001298 CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001299}
1300
1301JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
Jiayang Liucac1b382015-04-30 12:35:24 -07001302 JNIEnv *jni, jclass, jlong factory, jobject j_rtc_config,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001303 jobject j_constraints, jlong observer_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001304 rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001305 reinterpret_cast<PeerConnectionFactoryInterface*>(
1306 factoryFromJava(factory)));
Jiayang Liucac1b382015-04-30 12:35:24 -07001307
1308 jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config);
1309
1310 jfieldID j_ice_transports_type_id = GetFieldID(
1311 jni, j_rtc_config_class, "iceTransportsType",
1312 "Lorg/webrtc/PeerConnection$IceTransportsType;");
1313 jobject j_ice_transports_type = GetObjectField(
1314 jni, j_rtc_config, j_ice_transports_type_id);
1315
1316 jfieldID j_bundle_policy_id = GetFieldID(
1317 jni, j_rtc_config_class, "bundlePolicy",
1318 "Lorg/webrtc/PeerConnection$BundlePolicy;");
1319 jobject j_bundle_policy = GetObjectField(
1320 jni, j_rtc_config, j_bundle_policy_id);
1321
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001322 jfieldID j_rtcp_mux_policy_id = GetFieldID(
1323 jni, j_rtc_config_class, "rtcpMuxPolicy",
1324 "Lorg/webrtc/PeerConnection$RtcpMuxPolicy;");
1325 jobject j_rtcp_mux_policy = GetObjectField(
1326 jni, j_rtc_config, j_rtcp_mux_policy_id);
1327
Jiayang Liucac1b382015-04-30 12:35:24 -07001328 jfieldID j_tcp_candidate_policy_id = GetFieldID(
1329 jni, j_rtc_config_class, "tcpCandidatePolicy",
1330 "Lorg/webrtc/PeerConnection$TcpCandidatePolicy;");
1331 jobject j_tcp_candidate_policy = GetObjectField(
1332 jni, j_rtc_config, j_tcp_candidate_policy_id);
1333
1334 jfieldID j_ice_servers_id = GetFieldID(
1335 jni, j_rtc_config_class, "iceServers",
1336 "Ljava/util/List;");
1337 jobject j_ice_servers = GetObjectField(jni, j_rtc_config, j_ice_servers_id);
1338
Henrik Lundin64dad832015-05-11 12:44:23 +02001339 jfieldID j_audio_jitter_buffer_max_packets_id = GetFieldID(
1340 jni, j_rtc_config_class, "audioJitterBufferMaxPackets",
1341 "I");
Henrik Lundin5263b3c2015-06-01 10:29:41 +02001342 jfieldID j_audio_jitter_buffer_fast_accelerate_id = GetFieldID(
1343 jni, j_rtc_config_class, "audioJitterBufferFastAccelerate", "Z");
Jiayang Liucac1b382015-04-30 12:35:24 -07001344 PeerConnectionInterface::RTCConfiguration rtc_config;
1345
1346 rtc_config.type =
1347 JavaIceTransportsTypeToNativeType(jni, j_ice_transports_type);
1348 rtc_config.bundle_policy = JavaBundlePolicyToNativeType(jni, j_bundle_policy);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001349 rtc_config.rtcp_mux_policy =
1350 JavaRtcpMuxPolicyToNativeType(jni, j_rtcp_mux_policy);
Jiayang Liucac1b382015-04-30 12:35:24 -07001351 rtc_config.tcp_candidate_policy =
1352 JavaTcpCandidatePolicyToNativeType(jni, j_tcp_candidate_policy);
1353 JavaIceServersToJsepIceServers(jni, j_ice_servers, &rtc_config.servers);
Henrik Lundin64dad832015-05-11 12:44:23 +02001354 rtc_config.audio_jitter_buffer_max_packets =
1355 GetIntField(jni, j_rtc_config, j_audio_jitter_buffer_max_packets_id);
Henrik Lundin5263b3c2015-06-01 10:29:41 +02001356 rtc_config.audio_jitter_buffer_fast_accelerate = GetBooleanField(
1357 jni, j_rtc_config, j_audio_jitter_buffer_fast_accelerate_id);
Jiayang Liucac1b382015-04-30 12:35:24 -07001358
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001359 PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
1360 observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001361 rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
Jiayang Liucac1b382015-04-30 12:35:24 -07001362 rtc_config, observer->constraints(), NULL, NULL, observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001363 return (jlong)pc.release();
1364}
1365
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001366static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367 JNIEnv* jni, jobject j_pc) {
1368 jfieldID native_pc_id = GetFieldID(jni,
1369 GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
1370 jlong j_p = GetLongField(jni, j_pc, native_pc_id);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001371 return rtc::scoped_refptr<PeerConnectionInterface>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372 reinterpret_cast<PeerConnectionInterface*>(j_p));
1373}
1374
1375JOW(jobject, PeerConnection_getLocalDescription)(JNIEnv* jni, jobject j_pc) {
1376 const SessionDescriptionInterface* sdp =
1377 ExtractNativePC(jni, j_pc)->local_description();
1378 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1379}
1380
1381JOW(jobject, PeerConnection_getRemoteDescription)(JNIEnv* jni, jobject j_pc) {
1382 const SessionDescriptionInterface* sdp =
1383 ExtractNativePC(jni, j_pc)->remote_description();
1384 return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
1385}
1386
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001387JOW(jobject, PeerConnection_createDataChannel)(
1388 JNIEnv* jni, jobject j_pc, jstring j_label, jobject j_init) {
1389 DataChannelInit init = JavaDataChannelInitToNative(jni, j_init);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001390 rtc::scoped_refptr<DataChannelInterface> channel(
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001391 ExtractNativePC(jni, j_pc)->CreateDataChannel(
1392 JavaToStdString(jni, j_label), &init));
fischman@webrtc.org87881672013-09-03 18:58:12 +00001393 // Mustn't pass channel.get() directly through NewObject to avoid reading its
1394 // vararg parameter as 64-bit and reading memory that doesn't belong to the
1395 // 32-bit parameter.
1396 jlong nativeChannelPtr = jlongFromPointer(channel.get());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001397 CHECK(nativeChannelPtr) << "Failed to create DataChannel";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001398 jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
1399 jmethodID j_data_channel_ctor = GetMethodID(
1400 jni, j_data_channel_class, "<init>", "(J)V");
1401 jobject j_channel = jni->NewObject(
fischman@webrtc.org87881672013-09-03 18:58:12 +00001402 j_data_channel_class, j_data_channel_ctor, nativeChannelPtr);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001403 CHECK_EXCEPTION(jni) << "error during NewObject";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001404 // Channel is now owned by Java object, and will be freed from there.
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001405 int bumped_count = channel->AddRef();
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001406 CHECK(bumped_count == 2) << "Unexpected refcount";
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001407 return j_channel;
1408}
1409
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001410JOW(void, PeerConnection_createOffer)(
1411 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1412 ConstraintsWrapper* constraints =
1413 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001414 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1415 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001416 jni, j_observer, constraints));
1417 ExtractNativePC(jni, j_pc)->CreateOffer(observer, constraints);
1418}
1419
1420JOW(void, PeerConnection_createAnswer)(
1421 JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
1422 ConstraintsWrapper* constraints =
1423 new ConstraintsWrapper(jni, j_constraints);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001424 rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
1425 new rtc::RefCountedObject<CreateSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001426 jni, j_observer, constraints));
1427 ExtractNativePC(jni, j_pc)->CreateAnswer(observer, constraints);
1428}
1429
1430// Helper to create a SessionDescriptionInterface from a SessionDescription.
1431static SessionDescriptionInterface* JavaSdpToNativeSdp(
1432 JNIEnv* jni, jobject j_sdp) {
1433 jfieldID j_type_id = GetFieldID(
1434 jni, GetObjectClass(jni, j_sdp), "type",
1435 "Lorg/webrtc/SessionDescription$Type;");
1436 jobject j_type = GetObjectField(jni, j_sdp, j_type_id);
1437 jmethodID j_canonical_form_id = GetMethodID(
1438 jni, GetObjectClass(jni, j_type), "canonicalForm",
1439 "()Ljava/lang/String;");
1440 jstring j_type_string = (jstring)jni->CallObjectMethod(
1441 j_type, j_canonical_form_id);
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001442 CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001443 std::string std_type = JavaToStdString(jni, j_type_string);
1444
1445 jfieldID j_description_id = GetFieldID(
1446 jni, GetObjectClass(jni, j_sdp), "description", "Ljava/lang/String;");
1447 jstring j_description = (jstring)GetObjectField(jni, j_sdp, j_description_id);
1448 std::string std_description = JavaToStdString(jni, j_description);
1449
1450 return webrtc::CreateSessionDescription(
1451 std_type, std_description, NULL);
1452}
1453
1454JOW(void, PeerConnection_setLocalDescription)(
1455 JNIEnv* jni, jobject j_pc,
1456 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001457 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1458 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001459 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1460 ExtractNativePC(jni, j_pc)->SetLocalDescription(
1461 observer, JavaSdpToNativeSdp(jni, j_sdp));
1462}
1463
1464JOW(void, PeerConnection_setRemoteDescription)(
1465 JNIEnv* jni, jobject j_pc,
1466 jobject j_observer, jobject j_sdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001467 rtc::scoped_refptr<SetSdpObserverWrapper> observer(
1468 new rtc::RefCountedObject<SetSdpObserverWrapper>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001469 jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
1470 ExtractNativePC(jni, j_pc)->SetRemoteDescription(
1471 observer, JavaSdpToNativeSdp(jni, j_sdp));
1472}
1473
1474JOW(jboolean, PeerConnection_updateIce)(
1475 JNIEnv* jni, jobject j_pc, jobject j_ice_servers, jobject j_constraints) {
1476 PeerConnectionInterface::IceServers ice_servers;
1477 JavaIceServersToJsepIceServers(jni, j_ice_servers, &ice_servers);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001478 scoped_ptr<ConstraintsWrapper> constraints(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001479 new ConstraintsWrapper(jni, j_constraints));
1480 return ExtractNativePC(jni, j_pc)->UpdateIce(ice_servers, constraints.get());
1481}
1482
1483JOW(jboolean, PeerConnection_nativeAddIceCandidate)(
1484 JNIEnv* jni, jobject j_pc, jstring j_sdp_mid,
1485 jint j_sdp_mline_index, jstring j_candidate_sdp) {
1486 std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
1487 std::string sdp = JavaToStdString(jni, j_candidate_sdp);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001488 scoped_ptr<IceCandidateInterface> candidate(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001489 webrtc::CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, NULL));
1490 return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
1491}
1492
1493JOW(jboolean, PeerConnection_nativeAddLocalStream)(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001494 JNIEnv* jni, jobject j_pc, jlong native_stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001495 return ExtractNativePC(jni, j_pc)->AddStream(
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001496 reinterpret_cast<MediaStreamInterface*>(native_stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497}
1498
1499JOW(void, PeerConnection_nativeRemoveLocalStream)(
1500 JNIEnv* jni, jobject j_pc, jlong native_stream) {
1501 ExtractNativePC(jni, j_pc)->RemoveStream(
1502 reinterpret_cast<MediaStreamInterface*>(native_stream));
1503}
1504
1505JOW(bool, PeerConnection_nativeGetStats)(
1506 JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001507 rtc::scoped_refptr<StatsObserverWrapper> observer(
1508 new rtc::RefCountedObject<StatsObserverWrapper>(jni, j_observer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 return ExtractNativePC(jni, j_pc)->GetStats(
jiayl@webrtc.orgdb41b4d2014-03-03 21:30:06 +00001510 observer,
1511 reinterpret_cast<MediaStreamTrackInterface*>(native_track),
1512 PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513}
1514
1515JOW(jobject, PeerConnection_signalingState)(JNIEnv* jni, jobject j_pc) {
1516 PeerConnectionInterface::SignalingState state =
1517 ExtractNativePC(jni, j_pc)->signaling_state();
1518 return JavaEnumFromIndex(jni, "PeerConnection$SignalingState", state);
1519}
1520
1521JOW(jobject, PeerConnection_iceConnectionState)(JNIEnv* jni, jobject j_pc) {
1522 PeerConnectionInterface::IceConnectionState state =
1523 ExtractNativePC(jni, j_pc)->ice_connection_state();
1524 return JavaEnumFromIndex(jni, "PeerConnection$IceConnectionState", state);
1525}
1526
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001527JOW(jobject, PeerConnection_iceGatheringState)(JNIEnv* jni, jobject j_pc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 PeerConnectionInterface::IceGatheringState state =
1529 ExtractNativePC(jni, j_pc)->ice_gathering_state();
braveyao@webrtc.orgfedb9ea2015-01-21 07:57:06 +00001530 return JavaEnumFromIndex(jni, "PeerConnection$IceGatheringState", state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531}
1532
1533JOW(void, PeerConnection_close)(JNIEnv* jni, jobject j_pc) {
1534 ExtractNativePC(jni, j_pc)->Close();
1535 return;
1536}
1537
1538JOW(jobject, MediaSource_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001539 rtc::scoped_refptr<MediaSourceInterface> p(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540 reinterpret_cast<MediaSourceInterface*>(j_p));
1541 return JavaEnumFromIndex(jni, "MediaSource$State", p->state());
1542}
1543
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001544JOW(jobject, VideoCapturer_nativeCreateVideoCapturer)(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545 JNIEnv* jni, jclass, jstring j_device_name) {
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001546// Since we can't create platform specific java implementations in Java, we
1547// defer the creation to C land.
1548#if defined(ANDROID)
1549 jclass j_video_capturer_class(
1550 FindClass(jni, "org/webrtc/VideoCapturerAndroid"));
1551 const jmethodID j_videocapturer_ctor(GetMethodID(
1552 jni, j_video_capturer_class, "<init>", "()V"));
1553 jobject j_video_capturer = jni->NewObject(j_video_capturer_class,
1554 j_videocapturer_ctor);
1555 CHECK_EXCEPTION(jni) << "error during NewObject";
1556
Per33544192015-04-02 12:30:51 +02001557 rtc::scoped_refptr<AndroidVideoCapturerJni> delegate =
perkj@webrtc.org112f1272015-02-25 09:20:07 +00001558 AndroidVideoCapturerJni::Create(jni, j_video_capturer, j_device_name);
1559 if (!delegate.get())
perkj@webrtc.org3db042e2015-02-19 08:43:38 +00001560 return nullptr;
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001561 rtc::scoped_ptr<webrtc::AndroidVideoCapturer> capturer(
Per33544192015-04-02 12:30:51 +02001562 new webrtc::AndroidVideoCapturer(delegate));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001563
1564#else
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001565 std::string device_name = JavaToStdString(jni, j_device_name);
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001566 scoped_ptr<cricket::DeviceManagerInterface> device_manager(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001567 cricket::DeviceManagerFactory::Create());
andresp@webrtc.org4d19e052014-09-09 11:45:44 +00001568 CHECK(device_manager->Init()) << "DeviceManager::Init() failed";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 cricket::Device device;
1570 if (!device_manager->GetVideoCaptureDevice(device_name, &device)) {
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001571 LOG(LS_ERROR) << "GetVideoCaptureDevice failed for " << device_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001572 return 0;
1573 }
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001574 scoped_ptr<cricket::VideoCapturer> capturer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001575 device_manager->CreateVideoCapturer(device));
perkj@webrtc.org83bc7212015-02-11 11:26:56 +00001576
1577 jclass j_video_capturer_class(
1578 FindClass(jni, "org/webrtc/VideoCapturer"));
1579 const jmethodID j_videocapturer_ctor(GetMethodID(
1580 jni, j_video_capturer_class, "<init>", "()V"));
1581 jobject j_video_capturer =
1582 jni->NewObject(j_video_capturer_class,
1583 j_videocapturer_ctor);
1584 CHECK_EXCEPTION(jni) << "error during creation of VideoCapturer";
1585
1586#endif
1587 const jmethodID j_videocapturer_set_native_capturer(GetMethodID(
1588 jni, j_video_capturer_class, "setNativeCapturer", "(J)V"));
1589 jni->CallVoidMethod(j_video_capturer,
1590 j_videocapturer_set_native_capturer,
1591 (jlong)capturer.release());
1592 CHECK_EXCEPTION(jni) << "error during setNativeCapturer";
1593 return j_video_capturer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001594}
1595
1596JOW(jlong, VideoRenderer_nativeCreateGuiVideoRenderer)(
1597 JNIEnv* jni, jclass, int x, int y) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001598 scoped_ptr<VideoRendererWrapper> renderer(VideoRendererWrapper::Create(
1599 cricket::VideoRendererFactory::CreateGuiVideoRenderer(x, y)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001600 return (jlong)renderer.release();
1601}
1602
1603JOW(jlong, VideoRenderer_nativeWrapVideoRenderer)(
1604 JNIEnv* jni, jclass, jobject j_callbacks) {
fischman@webrtc.org540acde2014-02-13 03:56:14 +00001605 scoped_ptr<JavaVideoRendererWrapper> renderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606 new JavaVideoRendererWrapper(jni, j_callbacks));
1607 return (jlong)renderer.release();
1608}
1609
glaznev@webrtc.orgf6932292015-02-05 17:29:59 +00001610JOW(void, VideoRenderer_nativeCopyPlane)(
1611 JNIEnv *jni, jclass, jobject j_src_buffer, jint width, jint height,
1612 jint src_stride, jobject j_dst_buffer, jint dst_stride) {
1613 size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer);
1614 size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
1615 CHECK(src_stride >= width) << "Wrong source stride " << src_stride;
1616 CHECK(dst_stride >= width) << "Wrong destination stride " << dst_stride;
1617 CHECK(src_size >= src_stride * height)
1618 << "Insufficient source buffer capacity " << src_size;
1619 CHECK(dst_size >= dst_stride * height)
1620 << "Isufficient destination buffer capacity " << dst_size;
1621 uint8_t *src =
1622 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer));
1623 uint8_t *dst =
1624 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
1625 if (src_stride == dst_stride) {
1626 memcpy(dst, src, src_stride * height);
1627 } else {
1628 for (int i = 0; i < height; i++) {
1629 memcpy(dst, src, width);
1630 src += src_stride;
1631 dst += dst_stride;
1632 }
1633 }
1634}
1635
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001636JOW(void, VideoSource_stop)(JNIEnv* jni, jclass, jlong j_p) {
1637 reinterpret_cast<VideoSourceInterface*>(j_p)->Stop();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001638}
1639
1640JOW(void, VideoSource_restart)(
1641 JNIEnv* jni, jclass, jlong j_p_source, jlong j_p_format) {
perkj@webrtc.org8f605e82015-02-17 13:53:56 +00001642 reinterpret_cast<VideoSourceInterface*>(j_p_source)->Restart();
fischman@webrtc.org4e65e072013-10-03 18:23:13 +00001643}
1644
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001645JOW(jstring, MediaStreamTrack_nativeId)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001646 return JavaStringFromStdString(
1647 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001648}
1649
1650JOW(jstring, MediaStreamTrack_nativeKind)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001651 return JavaStringFromStdString(
1652 jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->kind());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001653}
1654
1655JOW(jboolean, MediaStreamTrack_nativeEnabled)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001656 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->enabled();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657}
1658
1659JOW(jobject, MediaStreamTrack_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001660 return JavaEnumFromIndex(
1661 jni,
1662 "MediaStreamTrack$State",
1663 reinterpret_cast<MediaStreamTrackInterface*>(j_p)->state());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664}
1665
1666JOW(jboolean, MediaStreamTrack_nativeSetState)(
1667 JNIEnv* jni, jclass, jlong j_p, jint j_new_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668 MediaStreamTrackInterface::TrackState new_state =
1669 (MediaStreamTrackInterface::TrackState)j_new_state;
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001670 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1671 ->set_state(new_state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001672}
1673
1674JOW(jboolean, MediaStreamTrack_nativeSetEnabled)(
1675 JNIEnv* jni, jclass, jlong j_p, jboolean enabled) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001676 return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
1677 ->set_enabled(enabled);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001678}
1679
1680JOW(void, VideoTrack_nativeAddRenderer)(
1681 JNIEnv* jni, jclass,
1682 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001683 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->AddRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001684 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1685}
1686
1687JOW(void, VideoTrack_nativeRemoveRenderer)(
1688 JNIEnv* jni, jclass,
1689 jlong j_video_track_pointer, jlong j_renderer_pointer) {
fischman@webrtc.org32001ef2013-08-12 23:26:21 +00001690 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001691 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1692}
perkj@webrtc.org96e4db92015-02-13 12:46:51 +00001693
1694} // namespace webrtc_jni