| 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 |