Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: talk/app/webrtc/java/jni/peerconnection_jni.cc

Issue 1308733004: Android: Fix memory leak for remote MediaStream (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | talk/app/webrtc/java/testcommon/src/org/webrtc/PeerConnectionTest.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 while (!streams_.empty())
211 OnRemoveStream(streams_.begin()->first);
AlexG 2015/08/25 17:16:58 it is probably not worth to call OnRemoveStream he
magjed_webrtc 2015/08/25 21:30:52 Done.
212 }
210 213
211 void OnIceCandidate(const IceCandidateInterface* candidate) override { 214 void OnIceCandidate(const IceCandidateInterface* candidate) override {
212 ScopedLocalRefFrame local_ref_frame(jni()); 215 ScopedLocalRefFrame local_ref_frame(jni());
213 std::string sdp; 216 std::string sdp;
214 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp; 217 CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp;
215 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate"); 218 jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
216 jmethodID ctor = GetMethodID(jni(), candidate_class, 219 jmethodID ctor = GetMethodID(jni(), candidate_class,
217 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V"); 220 "<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
218 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid()); 221 jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
219 jstring j_sdp = JavaStringFromStdString(jni(), sdp); 222 jstring j_sdp = JavaStringFromStdString(jni(), sdp);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 jni(), *j_observer_class_, "onIceGatheringChange", 268 jni(), *j_observer_class_, "onIceGatheringChange",
266 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V"); 269 "(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
267 jobject new_state_enum = JavaEnumFromIndex( 270 jobject new_state_enum = JavaEnumFromIndex(
268 jni(), "PeerConnection$IceGatheringState", new_state); 271 jni(), "PeerConnection$IceGatheringState", new_state);
269 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum); 272 jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
270 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; 273 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
271 } 274 }
272 275
273 void OnAddStream(MediaStreamInterface* stream) override { 276 void OnAddStream(MediaStreamInterface* stream) override {
274 ScopedLocalRefFrame local_ref_frame(jni()); 277 ScopedLocalRefFrame local_ref_frame(jni());
275 jobject j_stream = jni()->NewObject( 278 // Java MediaStream takes ownership of one reference. It is released in
AlexG 2015/08/25 17:16:58 Why is this extra change needed? Old code looks sh
magjed_webrtc 2015/08/25 21:30:52 I wanted to avoid using raw pointers for ref count
276 *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream); 279 // MediaStream_free.
280 rtc::scoped_refptr<MediaStreamInterface> stream_refcounted(stream);
281 jobject j_stream =
282 jni()->NewObject(*j_media_stream_class_, j_media_stream_ctor_,
283 (jlong)stream_refcounted.release());
tommi 2015/08/25 16:45:21 reinterpret_cast<>
magjed_webrtc 2015/08/25 21:30:52 Done.
277 CHECK_EXCEPTION(jni()) << "error during NewObject"; 284 CHECK_EXCEPTION(jni()) << "error during NewObject";
278 285
279 AudioTrackVector audio_tracks = stream->GetAudioTracks(); 286 for (rtc::scoped_refptr<AudioTrackInterface> track :
AlexG 2015/08/25 17:16:58 ditto - do we need this change?
magjed_webrtc 2015/08/25 21:30:52 Same here, need to balance the Release() in MediaS
280 for (size_t i = 0; i < audio_tracks.size(); ++i) { 287 stream->GetAudioTracks()) {
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 takes ownership of one reference. It is released in
284 *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id); 290 // MediaStreamTrack_free.
291 jobject j_track =
292 jni()->NewObject(*j_audio_track_class_, j_audio_track_ctor_,
293 (jlong)track.release(), id);
285 CHECK_EXCEPTION(jni()) << "error during NewObject"; 294 CHECK_EXCEPTION(jni()) << "error during NewObject";
286 jfieldID audio_tracks_id = GetFieldID(jni(), 295 jfieldID audio_tracks_id = GetFieldID(jni(),
287 *j_media_stream_class_, 296 *j_media_stream_class_,
288 "audioTracks", 297 "audioTracks",
289 "Ljava/util/LinkedList;"); 298 "Ljava/util/LinkedList;");
290 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id); 299 jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
291 jmethodID add = GetMethodID(jni(), 300 jmethodID add = GetMethodID(jni(),
292 GetObjectClass(jni(), audio_tracks), 301 GetObjectClass(jni(), audio_tracks),
293 "add", 302 "add",
294 "(Ljava/lang/Object;)Z"); 303 "(Ljava/lang/Object;)Z");
295 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track); 304 jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
296 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod"; 305 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
297 CHECK(added); 306 CHECK(added);
298 } 307 }
299 308
300 VideoTrackVector video_tracks = stream->GetVideoTracks(); 309 for (rtc::scoped_refptr<VideoTrackInterface> track :
AlexG 2015/08/25 17:16:58 ditto - no need in this change?
magjed_webrtc 2015/08/25 21:30:52 ditto.
301 for (size_t i = 0; i < video_tracks.size(); ++i) { 310 stream->GetVideoTracks()) {
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 takes ownership of one reference. It is released in
305 *j_video_track_class_, j_video_track_ctor_, (jlong)track, id); 313 // MediaStreamTrack_free.
314 jobject j_track =
315 jni()->NewObject(*j_video_track_class_, j_video_track_ctor_,
316 (jlong)track.release(), id);
306 CHECK_EXCEPTION(jni()) << "error during NewObject"; 317 CHECK_EXCEPTION(jni()) << "error during NewObject";
307 jfieldID video_tracks_id = GetFieldID(jni(), 318 jfieldID video_tracks_id = GetFieldID(jni(),
308 *j_media_stream_class_, 319 *j_media_stream_class_,
309 "videoTracks", 320 "videoTracks",
310 "Ljava/util/LinkedList;"); 321 "Ljava/util/LinkedList;");
311 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id); 322 jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
312 jmethodID add = GetMethodID(jni(), 323 jmethodID add = GetMethodID(jni(),
313 GetObjectClass(jni(), video_tracks), 324 GetObjectClass(jni(), video_tracks),
314 "add", 325 "add",
315 "(Ljava/lang/Object;)Z"); 326 "(Ljava/lang/Object;)Z");
316 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track); 327 jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
317 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod"; 328 CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
318 CHECK(added); 329 CHECK(added);
319 } 330 }
320 streams_[stream] = jni()->NewWeakGlobalRef(j_stream); 331 streams_[stream] = jni()->NewGlobalRef(j_stream);
321 CHECK_EXCEPTION(jni()) << "error during NewWeakGlobalRef"; 332 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 = streams_.find(stream);
332 CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream; 343 CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream;
333 344
334 WeakRef s(jni(), it->second); 345 jobject j_stream = it->second;
AlexG 2015/08/25 17:16:58 Remove WekRef class from jni_helpers.h - I don't t
magjed_webrtc 2015/08/25 21:30:52 Good catch.
335 streams_.erase(it); 346 streams_.erase(it);
336 if (!s.obj())
337 return;
338 347
339 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream", 348 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
340 "(Lorg/webrtc/MediaStream;)V"); 349 "(Lorg/webrtc/MediaStream;)V");
341 jni()->CallVoidMethod(*j_observer_global_, m, s.obj()); 350 jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
342 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; 351 CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
352
353 jni()->CallVoidMethod(
AlexG 2015/08/25 17:16:58 With this change no need to call stream.videoTrack
AlexG 2015/08/25 17:19:59 Sorry - ignore this comment - didn't notice you've
magjed_webrtc 2015/08/25 21:30:52 Exactly, MediaStream.dispose() will tear down the
354 j_stream, GetMethodID(jni(), *j_media_stream_class_, "dispose", "()V"));
355 CHECK_EXCEPTION(jni()) << "error during MediaStream.dispose()";
356 DeleteGlobalRef(jni(), j_stream);
343 } 357 }
344 358
345 void OnDataChannel(DataChannelInterface* channel) override { 359 void OnDataChannel(DataChannelInterface* channel) override {
346 ScopedLocalRefFrame local_ref_frame(jni()); 360 ScopedLocalRefFrame local_ref_frame(jni());
347 jobject j_channel = jni()->NewObject( 361 jobject j_channel = jni()->NewObject(
348 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel); 362 *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
349 CHECK_EXCEPTION(jni()) << "error during NewObject"; 363 CHECK_EXCEPTION(jni()) << "error during NewObject";
350 364
351 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel", 365 jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
352 "(Lorg/webrtc/DataChannel;)V"); 366 "(Lorg/webrtc/DataChannel;)V");
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 const ScopedGlobalRef<jobject> j_observer_global_; 399 const ScopedGlobalRef<jobject> j_observer_global_;
386 const ScopedGlobalRef<jclass> j_observer_class_; 400 const ScopedGlobalRef<jclass> j_observer_class_;
387 const ScopedGlobalRef<jclass> j_media_stream_class_; 401 const ScopedGlobalRef<jclass> j_media_stream_class_;
388 const jmethodID j_media_stream_ctor_; 402 const jmethodID j_media_stream_ctor_;
389 const ScopedGlobalRef<jclass> j_audio_track_class_; 403 const ScopedGlobalRef<jclass> j_audio_track_class_;
390 const jmethodID j_audio_track_ctor_; 404 const jmethodID j_audio_track_ctor_;
391 const ScopedGlobalRef<jclass> j_video_track_class_; 405 const ScopedGlobalRef<jclass> j_video_track_class_;
392 const jmethodID j_video_track_ctor_; 406 const jmethodID j_video_track_ctor_;
393 const ScopedGlobalRef<jclass> j_data_channel_class_; 407 const ScopedGlobalRef<jclass> j_data_channel_class_;
394 const jmethodID j_data_channel_ctor_; 408 const jmethodID j_data_channel_ctor_;
395 typedef std::map<void*, jweak> NativeToJavaStreamsMap; 409 typedef std::map<MediaStreamInterface*, jobject> NativeToJavaStreamsMap;
396 NativeToJavaStreamsMap streams_; // C++ -> Java streams. 410 // C++ -> Java streams. The stored jobects are global refs and must be
AlexG 2015/08/25 17:16:58 nit: add "remote" for clarity - i.e. "C++ -> Java
magjed_webrtc 2015/08/25 21:30:51 Done.
411 // manually deleted upon removal.
412 NativeToJavaStreamsMap streams_;
AlexG 2015/08/25 17:16:58 nit: streams_ -> remote_streams_
magjed_webrtc 2015/08/25 21:30:51 Done.
397 scoped_ptr<ConstraintsWrapper> constraints_; 413 scoped_ptr<ConstraintsWrapper> constraints_;
398 }; 414 };
399 415
400 // Wrapper for a Java MediaConstraints object. Copies all needed data so when 416 // Wrapper for a Java MediaConstraints object. Copies all needed data so when
401 // the constructor returns the Java object is no longer needed. 417 // the constructor returns the Java object is no longer needed.
402 class ConstraintsWrapper : public MediaConstraintsInterface { 418 class ConstraintsWrapper : public MediaConstraintsInterface {
403 public: 419 public:
404 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) { 420 ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) {
405 PopulateConstraintsFromJavaPairList( 421 PopulateConstraintsFromJavaPairList(
406 jni, j_constraints, "mandatory", &mandatory_); 422 jni, j_constraints, "mandatory", &mandatory_);
(...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 } 1693 }
1678 1694
1679 JOW(void, VideoTrack_nativeRemoveRenderer)( 1695 JOW(void, VideoTrack_nativeRemoveRenderer)(
1680 JNIEnv* jni, jclass, 1696 JNIEnv* jni, jclass,
1681 jlong j_video_track_pointer, jlong j_renderer_pointer) { 1697 jlong j_video_track_pointer, jlong j_renderer_pointer) {
1682 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer( 1698 reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer(
1683 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer)); 1699 reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
1684 } 1700 }
1685 1701
1686 } // namespace webrtc_jni 1702 } // namespace webrtc_jni
OLDNEW
« no previous file with comments | « no previous file | talk/app/webrtc/java/testcommon/src/org/webrtc/PeerConnectionTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698