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

Unified 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: use helper NewGlobalRef function instead 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 side-by-side diff with in-line comments
Download patch
Index: talk/app/webrtc/java/jni/peerconnection_jni.cc
diff --git a/talk/app/webrtc/java/jni/peerconnection_jni.cc b/talk/app/webrtc/java/jni/peerconnection_jni.cc
index c326ccff6bede1e3e93e5605be72be86a672df7d..503a75ee88d35029c5c9a3664c3ffbcf7b3d817b 100644
--- a/talk/app/webrtc/java/jni/peerconnection_jni.cc
+++ b/talk/app/webrtc/java/jni/peerconnection_jni.cc
@@ -206,7 +206,11 @@ class PCOJava : public PeerConnectionObserver {
jni, *j_data_channel_class_, "<init>", "(J)V")) {
}
- virtual ~PCOJava() {}
+ virtual ~PCOJava() {
+ ScopedLocalRefFrame local_ref_frame(jni());
+ while (!remote_streams_.empty())
+ DisposeRemoteStream(remote_streams_.begin());
+ }
void OnIceCandidate(const IceCandidateInterface* candidate) override {
ScopedLocalRefFrame local_ref_frame(jni());
@@ -272,16 +276,22 @@ class PCOJava : public PeerConnectionObserver {
void OnAddStream(MediaStreamInterface* stream) override {
ScopedLocalRefFrame local_ref_frame(jni());
- jobject j_stream = jni()->NewObject(
- *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream);
+ // Java MediaStream holds one reference. Corresponding Release() is in
+ // MediaStream_free, triggered by MediaStream.dispose().
+ stream->AddRef();
+ jobject j_stream =
+ jni()->NewObject(*j_media_stream_class_, j_media_stream_ctor_,
+ reinterpret_cast<jlong>(stream));
CHECK_EXCEPTION(jni()) << "error during NewObject";
- AudioTrackVector audio_tracks = stream->GetAudioTracks();
- for (size_t i = 0; i < audio_tracks.size(); ++i) {
- AudioTrackInterface* track = audio_tracks[i];
+ for (const auto& track : stream->GetAudioTracks()) {
jstring id = JavaStringFromStdString(jni(), track->id());
- jobject j_track = jni()->NewObject(
- *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id);
+ // Java AudioTrack holds one reference. Corresponding Release() is in
+ // MediaStreamTrack_free, triggered by AudioTrack.dispose().
+ track->AddRef();
+ jobject j_track =
+ jni()->NewObject(*j_audio_track_class_, j_audio_track_ctor_,
+ reinterpret_cast<jlong>(track.get()), id);
CHECK_EXCEPTION(jni()) << "error during NewObject";
jfieldID audio_tracks_id = GetFieldID(jni(),
*j_media_stream_class_,
@@ -297,12 +307,14 @@ class PCOJava : public PeerConnectionObserver {
CHECK(added);
}
- VideoTrackVector video_tracks = stream->GetVideoTracks();
- for (size_t i = 0; i < video_tracks.size(); ++i) {
- VideoTrackInterface* track = video_tracks[i];
+ for (const auto& track : stream->GetVideoTracks()) {
jstring id = JavaStringFromStdString(jni(), track->id());
- jobject j_track = jni()->NewObject(
- *j_video_track_class_, j_video_track_ctor_, (jlong)track, id);
+ // Java VideoTrack holds one reference. Corresponding Release() is in
+ // MediaStreamTrack_free, triggered by VideoTrack.dispose().
+ track->AddRef();
+ jobject j_track =
+ jni()->NewObject(*j_video_track_class_, j_video_track_ctor_,
+ reinterpret_cast<jlong>(track.get()), id);
CHECK_EXCEPTION(jni()) << "error during NewObject";
jfieldID video_tracks_id = GetFieldID(jni(),
*j_media_stream_class_,
@@ -317,8 +329,7 @@ class PCOJava : public PeerConnectionObserver {
CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
CHECK(added);
}
- streams_[stream] = jni()->NewWeakGlobalRef(j_stream);
- CHECK_EXCEPTION(jni()) << "error during NewWeakGlobalRef";
+ remote_streams_[stream] = NewGlobalRef(jni(), j_stream);
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
"(Lorg/webrtc/MediaStream;)V");
@@ -328,18 +339,15 @@ class PCOJava : public PeerConnectionObserver {
void OnRemoveStream(MediaStreamInterface* stream) override {
ScopedLocalRefFrame local_ref_frame(jni());
- NativeToJavaStreamsMap::iterator it = streams_.find(stream);
- CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream;
-
- WeakRef s(jni(), it->second);
- streams_.erase(it);
- if (!s.obj())
- return;
-
+ NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream);
+ CHECK(it != remote_streams_.end()) << "unexpected stream: " << std::hex
+ << stream;
+ jobject j_stream = it->second;
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
"(Lorg/webrtc/MediaStream;)V");
- jni()->CallVoidMethod(*j_observer_global_, m, s.obj());
+ jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
+ DisposeRemoteStream(it);
}
void OnDataChannel(DataChannelInterface* channel) override {
@@ -378,6 +386,17 @@ class PCOJava : public PeerConnectionObserver {
const ConstraintsWrapper* constraints() { return constraints_.get(); }
private:
+ typedef std::map<MediaStreamInterface*, jobject> NativeToJavaStreamsMap;
+
+ void DisposeRemoteStream(const NativeToJavaStreamsMap::iterator& it) {
+ jobject j_stream = it->second;
+ remote_streams_.erase(it);
+ jni()->CallVoidMethod(
+ j_stream, GetMethodID(jni(), *j_media_stream_class_, "dispose", "()V"));
+ CHECK_EXCEPTION(jni()) << "error during MediaStream.dispose()";
+ DeleteGlobalRef(jni(), j_stream);
+ }
+
JNIEnv* jni() {
return AttachCurrentThreadIfNeeded();
}
@@ -392,8 +411,9 @@ class PCOJava : public PeerConnectionObserver {
const jmethodID j_video_track_ctor_;
const ScopedGlobalRef<jclass> j_data_channel_class_;
const jmethodID j_data_channel_ctor_;
- typedef std::map<void*, jweak> NativeToJavaStreamsMap;
- NativeToJavaStreamsMap streams_; // C++ -> Java streams.
+ // C++ -> Java remote streams. The stored jobects are global refs and must be
+ // manually deleted upon removal. Use DisposeRemoteStream().
+ NativeToJavaStreamsMap remote_streams_;
scoped_ptr<ConstraintsWrapper> constraints_;
};
« no previous file with comments | « talk/app/webrtc/java/jni/jni_helpers.cc ('k') | webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698