OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2013 Google Inc. | 3 * Copyright 2013 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 j_audio_track_ctor_(GetMethodID( | 199 j_audio_track_ctor_(GetMethodID( |
200 jni, *j_audio_track_class_, "<init>", "(J)V")), | 200 jni, *j_audio_track_class_, "<init>", "(J)V")), |
201 j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")), | 201 j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")), |
202 j_video_track_ctor_(GetMethodID( | 202 j_video_track_ctor_(GetMethodID( |
203 jni, *j_video_track_class_, "<init>", "(J)V")), | 203 jni, *j_video_track_class_, "<init>", "(J)V")), |
204 j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")), | 204 j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")), |
205 j_data_channel_ctor_(GetMethodID( | 205 j_data_channel_ctor_(GetMethodID( |
206 jni, *j_data_channel_class_, "<init>", "(J)V")) { | 206 jni, *j_data_channel_class_, "<init>", "(J)V")) { |
207 } | 207 } |
208 | 208 |
209 virtual ~PCOJava() {} | 209 virtual ~PCOJava() { |
| 210 ScopedLocalRefFrame local_ref_frame(jni()); |
| 211 while (!remote_streams_.empty()) |
| 212 DisposeRemoteStream(remote_streams_.begin()); |
| 213 } |
210 | 214 |
211 void OnIceCandidate(const IceCandidateInterface* candidate) override { | 215 void OnIceCandidate(const IceCandidateInterface* candidate) override { |
212 ScopedLocalRefFrame local_ref_frame(jni()); | 216 ScopedLocalRefFrame local_ref_frame(jni()); |
213 std::string sdp; | 217 std::string sdp; |
214 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp; | 218 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp; |
215 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate"); | 219 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate"); |
216 jmethodID ctor = GetMethodID(jni(), candidate_class, | 220 jmethodID ctor = GetMethodID(jni(), candidate_class, |
217 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V"); | 221 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V"); |
218 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid()); | 222 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid()); |
219 jstring j_sdp = JavaStringFromStdString(jni(), sdp); | 223 jstring j_sdp = JavaStringFromStdString(jni(), sdp); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 jni(), *j_observer_class_, "onIceGatheringChange", | 269 jni(), *j_observer_class_, "onIceGatheringChange", |
266 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V"); | 270 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V"); |
267 jobject new_state_enum = JavaEnumFromIndex( | 271 jobject new_state_enum = JavaEnumFromIndex( |
268 jni(), "PeerConnection$IceGatheringState", new_state); | 272 jni(), "PeerConnection$IceGatheringState", new_state); |
269 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum); | 273 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum); |
270 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; | 274 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; |
271 } | 275 } |
272 | 276 |
273 void OnAddStream(MediaStreamInterface* stream) override { | 277 void OnAddStream(MediaStreamInterface* stream) override { |
274 ScopedLocalRefFrame local_ref_frame(jni()); | 278 ScopedLocalRefFrame local_ref_frame(jni()); |
275 jobject j_stream = jni()->NewObject( | 279 // Java MediaStream holds one reference. Corresponding Release() is in |
276 *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream); | 280 // MediaStream_free, triggered by MediaStream.dispose(). |
| 281 stream->AddRef(); |
| 282 jobject j_stream = |
| 283 jni()->NewObject(*j_media_stream_class_, j_media_stream_ctor_, |
| 284 reinterpret_cast<jlong>(stream)); |
277 CHECK_EXCEPTION(jni()) << "error during NewObject"; | 285 CHECK_EXCEPTION(jni()) << "error during NewObject"; |
278 | 286 |
279 AudioTrackVector audio_tracks = stream->GetAudioTracks(); | 287 for (const auto& track : stream->GetAudioTracks()) { |
280 for (size_t i = 0; i < audio_tracks.size(); ++i) { | |
281 AudioTrackInterface* track = audio_tracks[i]; | |
282 jstring id = JavaStringFromStdString(jni(), track->id()); | 288 jstring id = JavaStringFromStdString(jni(), track->id()); |
283 jobject j_track = jni()->NewObject( | 289 // Java AudioTrack holds one reference. Corresponding Release() is in |
284 *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id); | 290 // MediaStreamTrack_free, triggered by AudioTrack.dispose(). |
| 291 track->AddRef(); |
| 292 jobject j_track = |
| 293 jni()->NewObject(*j_audio_track_class_, j_audio_track_ctor_, |
| 294 reinterpret_cast<jlong>(track.get()), id); |
285 CHECK_EXCEPTION(jni()) << "error during NewObject"; | 295 CHECK_EXCEPTION(jni()) << "error during NewObject"; |
286 jfieldID audio_tracks_id = GetFieldID(jni(), | 296 jfieldID audio_tracks_id = GetFieldID(jni(), |
287 *j_media_stream_class_, | 297 *j_media_stream_class_, |
288 "audioTracks", | 298 "audioTracks", |
289 "Ljava/util/LinkedList;"); | 299 "Ljava/util/LinkedList;"); |
290 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id); | 300 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id); |
291 jmethodID add = GetMethodID(jni(), | 301 jmethodID add = GetMethodID(jni(), |
292 GetObjectClass(jni(), audio_tracks), | 302 GetObjectClass(jni(), audio_tracks), |
293 "add", | 303 "add", |
294 "(Ljava/lang/Object;)Z"); | 304 "(Ljava/lang/Object;)Z"); |
295 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track); | 305 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track); |
296 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod"; | 306 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod"; |
297 CHECK(added); | 307 CHECK(added); |
298 } | 308 } |
299 | 309 |
300 VideoTrackVector video_tracks = stream->GetVideoTracks(); | 310 for (const auto& track : stream->GetVideoTracks()) { |
301 for (size_t i = 0; i < video_tracks.size(); ++i) { | |
302 VideoTrackInterface* track = video_tracks[i]; | |
303 jstring id = JavaStringFromStdString(jni(), track->id()); | 311 jstring id = JavaStringFromStdString(jni(), track->id()); |
304 jobject j_track = jni()->NewObject( | 312 // Java VideoTrack holds one reference. Corresponding Release() is in |
305 *j_video_track_class_, j_video_track_ctor_, (jlong)track, id); | 313 // MediaStreamTrack_free, triggered by VideoTrack.dispose(). |
| 314 track->AddRef(); |
| 315 jobject j_track = |
| 316 jni()->NewObject(*j_video_track_class_, j_video_track_ctor_, |
| 317 reinterpret_cast<jlong>(track.get()), id); |
306 CHECK_EXCEPTION(jni()) << "error during NewObject"; | 318 CHECK_EXCEPTION(jni()) << "error during NewObject"; |
307 jfieldID video_tracks_id = GetFieldID(jni(), | 319 jfieldID video_tracks_id = GetFieldID(jni(), |
308 *j_media_stream_class_, | 320 *j_media_stream_class_, |
309 "videoTracks", | 321 "videoTracks", |
310 "Ljava/util/LinkedList;"); | 322 "Ljava/util/LinkedList;"); |
311 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id); | 323 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id); |
312 jmethodID add = GetMethodID(jni(), | 324 jmethodID add = GetMethodID(jni(), |
313 GetObjectClass(jni(), video_tracks), | 325 GetObjectClass(jni(), video_tracks), |
314 "add", | 326 "add", |
315 "(Ljava/lang/Object;)Z"); | 327 "(Ljava/lang/Object;)Z"); |
316 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track); | 328 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track); |
317 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod"; | 329 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod"; |
318 CHECK(added); | 330 CHECK(added); |
319 } | 331 } |
320 streams_[stream] = jni()->NewWeakGlobalRef(j_stream); | 332 remote_streams_[stream] = NewGlobalRef(jni(), j_stream); |
321 CHECK_EXCEPTION(jni()) << "error during NewWeakGlobalRef"; | |
322 | 333 |
323 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream", | 334 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream", |
324 "(Lorg/webrtc/MediaStream;)V"); | 335 "(Lorg/webrtc/MediaStream;)V"); |
325 jni()->CallVoidMethod(*j_observer_global_, m, j_stream); | 336 jni()->CallVoidMethod(*j_observer_global_, m, j_stream); |
326 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; | 337 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; |
327 } | 338 } |
328 | 339 |
329 void OnRemoveStream(MediaStreamInterface* stream) override { | 340 void OnRemoveStream(MediaStreamInterface* stream) override { |
330 ScopedLocalRefFrame local_ref_frame(jni()); | 341 ScopedLocalRefFrame local_ref_frame(jni()); |
331 NativeToJavaStreamsMap::iterator it = streams_.find(stream); | 342 NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream); |
332 CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream; | 343 CHECK(it != remote_streams_.end()) << "unexpected stream: " << std::hex |
333 | 344 << stream; |
334 WeakRef s(jni(), it->second); | 345 jobject j_stream = it->second; |
335 streams_.erase(it); | |
336 if (!s.obj()) | |
337 return; | |
338 | |
339 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream", | 346 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream", |
340 "(Lorg/webrtc/MediaStream;)V"); | 347 "(Lorg/webrtc/MediaStream;)V"); |
341 jni()->CallVoidMethod(*j_observer_global_, m, s.obj()); | 348 jni()->CallVoidMethod(*j_observer_global_, m, j_stream); |
342 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; | 349 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; |
| 350 DisposeRemoteStream(it); |
343 } | 351 } |
344 | 352 |
345 void OnDataChannel(DataChannelInterface* channel) override { | 353 void OnDataChannel(DataChannelInterface* channel) override { |
346 ScopedLocalRefFrame local_ref_frame(jni()); | 354 ScopedLocalRefFrame local_ref_frame(jni()); |
347 jobject j_channel = jni()->NewObject( | 355 jobject j_channel = jni()->NewObject( |
348 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel); | 356 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel); |
349 CHECK_EXCEPTION(jni()) << "error during NewObject"; | 357 CHECK_EXCEPTION(jni()) << "error during NewObject"; |
350 | 358 |
351 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel", | 359 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel", |
352 "(Lorg/webrtc/DataChannel;)V"); | 360 "(Lorg/webrtc/DataChannel;)V"); |
(...skipping 18 matching lines...) Expand all Loading... |
371 } | 379 } |
372 | 380 |
373 void SetConstraints(ConstraintsWrapper* constraints) { | 381 void SetConstraints(ConstraintsWrapper* constraints) { |
374 CHECK(!constraints_.get()) << "constraints already set!"; | 382 CHECK(!constraints_.get()) << "constraints already set!"; |
375 constraints_.reset(constraints); | 383 constraints_.reset(constraints); |
376 } | 384 } |
377 | 385 |
378 const ConstraintsWrapper* constraints() { return constraints_.get(); } | 386 const ConstraintsWrapper* constraints() { return constraints_.get(); } |
379 | 387 |
380 private: | 388 private: |
| 389 typedef std::map<MediaStreamInterface*, jobject> NativeToJavaStreamsMap; |
| 390 |
| 391 void DisposeRemoteStream(const NativeToJavaStreamsMap::iterator& it) { |
| 392 jobject j_stream = it->second; |
| 393 remote_streams_.erase(it); |
| 394 jni()->CallVoidMethod( |
| 395 j_stream, GetMethodID(jni(), *j_media_stream_class_, "dispose", "()V")); |
| 396 CHECK_EXCEPTION(jni()) << "error during MediaStream.dispose()"; |
| 397 DeleteGlobalRef(jni(), j_stream); |
| 398 } |
| 399 |
381 JNIEnv* jni() { | 400 JNIEnv* jni() { |
382 return AttachCurrentThreadIfNeeded(); | 401 return AttachCurrentThreadIfNeeded(); |
383 } | 402 } |
384 | 403 |
385 const ScopedGlobalRef<jobject> j_observer_global_; | 404 const ScopedGlobalRef<jobject> j_observer_global_; |
386 const ScopedGlobalRef<jclass> j_observer_class_; | 405 const ScopedGlobalRef<jclass> j_observer_class_; |
387 const ScopedGlobalRef<jclass> j_media_stream_class_; | 406 const ScopedGlobalRef<jclass> j_media_stream_class_; |
388 const jmethodID j_media_stream_ctor_; | 407 const jmethodID j_media_stream_ctor_; |
389 const ScopedGlobalRef<jclass> j_audio_track_class_; | 408 const ScopedGlobalRef<jclass> j_audio_track_class_; |
390 const jmethodID j_audio_track_ctor_; | 409 const jmethodID j_audio_track_ctor_; |
391 const ScopedGlobalRef<jclass> j_video_track_class_; | 410 const ScopedGlobalRef<jclass> j_video_track_class_; |
392 const jmethodID j_video_track_ctor_; | 411 const jmethodID j_video_track_ctor_; |
393 const ScopedGlobalRef<jclass> j_data_channel_class_; | 412 const ScopedGlobalRef<jclass> j_data_channel_class_; |
394 const jmethodID j_data_channel_ctor_; | 413 const jmethodID j_data_channel_ctor_; |
395 typedef std::map<void*, jweak> NativeToJavaStreamsMap; | 414 // C++ -> Java remote streams. The stored jobects are global refs and must be |
396 NativeToJavaStreamsMap streams_; // C++ -> Java streams. | 415 // manually deleted upon removal. Use DisposeRemoteStream(). |
| 416 NativeToJavaStreamsMap remote_streams_; |
397 scoped_ptr<ConstraintsWrapper> constraints_; | 417 scoped_ptr<ConstraintsWrapper> constraints_; |
398 }; | 418 }; |
399 | 419 |
400 // Wrapper for a Java MediaConstraints object. Copies all needed data so when | 420 // Wrapper for a Java MediaConstraints object. Copies all needed data so when |
401 // the constructor returns the Java object is no longer needed. | 421 // the constructor returns the Java object is no longer needed. |
402 class ConstraintsWrapper : public MediaConstraintsInterface { | 422 class ConstraintsWrapper : public MediaConstraintsInterface { |
403 public: | 423 public: |
404 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) { | 424 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) { |
405 PopulateConstraintsFromJavaPairList( | 425 PopulateConstraintsFromJavaPairList( |
406 jni, j_constraints, "mandatory", &mandatory_); | 426 jni, j_constraints, "mandatory", &mandatory_); |
(...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 } | 1697 } |
1678 | 1698 |
1679 JOW(void, VideoTrack_nativeRemoveRenderer)( | 1699 JOW(void, VideoTrack_nativeRemoveRenderer)( |
1680 JNIEnv* jni, jclass, | 1700 JNIEnv* jni, jclass, |
1681 jlong j_video_track_pointer, jlong j_renderer_pointer) { | 1701 jlong j_video_track_pointer, jlong j_renderer_pointer) { |
1682 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer( | 1702 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer( |
1683 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer)); | 1703 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer)); |
1684 } | 1704 } |
1685 | 1705 |
1686 } // namespace webrtc_jni | 1706 } // namespace webrtc_jni |
OLD | NEW |