diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java index dfe4b6109c..71a258e6c0 100644 --- a/sdk/android/api/org/webrtc/PeerConnection.java +++ b/sdk/android/api/org/webrtc/PeerConnection.java @@ -109,6 +109,13 @@ public class PeerConnection { * setRemoteDescription. */ @CalledByNative("Observer") void onAddTrack(RtpReceiver receiver, MediaStream[] mediaStreams); + + /** + * Triggered when the signaling from SetRemoteDescription indicates that a transceiver + * will be receiving media from a remote endpoint. This is only called if UNIFIED_PLAN + * semantics are specified. The transceiver will be disposed automatically. + */ + @CalledByNative("Observer") default void onTrack(RtpTransceiver transceiver){}; } /** Java version of PeerConnectionInterface.IceServer. */ diff --git a/sdk/android/api/org/webrtc/RtpTransceiver.java b/sdk/android/api/org/webrtc/RtpTransceiver.java index d77ecb408e..3086950dc3 100644 --- a/sdk/android/api/org/webrtc/RtpTransceiver.java +++ b/sdk/android/api/org/webrtc/RtpTransceiver.java @@ -196,6 +196,7 @@ public class RtpTransceiver { nativeStop(nativeRtpTransceiver); } + @CalledByNative public void dispose() { cachedSender.dispose(); cachedReceiver.dispose(); diff --git a/sdk/android/src/jni/pc/peerconnection.cc b/sdk/android/src/jni/pc/peerconnection.cc index 16e40d17df..225443f9ec 100644 --- a/sdk/android/src/jni/pc/peerconnection.cc +++ b/sdk/android/src/jni/pc/peerconnection.cc @@ -49,7 +49,6 @@ #include "sdk/android/src/jni/pc/mediastreamtrack.h" #include "sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h" #include "sdk/android/src/jni/pc/rtpsender.h" -#include "sdk/android/src/jni/pc/rtptransceiver.h" #include "sdk/android/src/jni/pc/sdpobserver.h" #include "sdk/android/src/jni/pc/sessiondescription.h" #include "sdk/android/src/jni/pc/statsobserver.h" @@ -335,6 +334,16 @@ void PeerConnectionObserverJni::OnAddTrack( NativeToJavaMediaStreamArray(env, streams)); } +void PeerConnectionObserverJni::OnTrack( + rtc::scoped_refptr transceiver) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedJavaLocalRef j_rtp_transceiver = + NativeToJavaRtpTransceiver(env, transceiver); + rtp_transceivers_.emplace_back(env, j_rtp_transceiver); + + Java_Observer_onTrack(env, j_observer_global_, j_rtp_transceiver); +} + // If the NativeToJavaStreamsMap contains the stream, return it. // Otherwise, create a new Java MediaStream. JavaMediaStream& PeerConnectionObserverJni::GetOrCreateJavaStream( diff --git a/sdk/android/src/jni/pc/peerconnection.h b/sdk/android/src/jni/pc/peerconnection.h index 6b021a0c46..669d360ec1 100644 --- a/sdk/android/src/jni/pc/peerconnection.h +++ b/sdk/android/src/jni/pc/peerconnection.h @@ -21,6 +21,7 @@ #include "sdk/android/src/jni/pc/mediaconstraints.h" #include "sdk/android/src/jni/pc/mediastream.h" #include "sdk/android/src/jni/pc/rtpreceiver.h" +#include "sdk/android/src/jni/pc/rtptransceiver.h" namespace webrtc { namespace jni { @@ -60,6 +61,8 @@ class PeerConnectionObserverJni : public PeerConnectionObserver { void OnAddTrack(rtc::scoped_refptr receiver, const std::vector>& streams) override; + void OnTrack( + rtc::scoped_refptr transceiver) override; private: typedef std::map @@ -83,6 +86,10 @@ class PeerConnectionObserverJni : public PeerConnectionObserver { // C++ -> Java remote streams. NativeToJavaStreamsMap remote_streams_; std::vector rtp_receivers_; + // Holds a reference to the Java transceivers given to the AddTrack + // callback, so that the shared ownership by the Java object will be + // properly disposed. + std::vector rtp_transceivers_; }; // PeerConnection doesn't take ownership of the observer. In Java API, we don't diff --git a/sdk/android/src/jni/pc/rtptransceiver.cc b/sdk/android/src/jni/pc/rtptransceiver.cc index f142d5868e..0a115c291f 100644 --- a/sdk/android/src/jni/pc/rtptransceiver.cc +++ b/sdk/android/src/jni/pc/rtptransceiver.cc @@ -62,6 +62,20 @@ ScopedJavaLocalRef NativeToJavaRtpTransceiver( env, jlongFromPointer(transceiver.release())); } +JavaRtpTransceiverGlobalOwner::JavaRtpTransceiverGlobalOwner( + JNIEnv* env, + const JavaRef& j_transceiver) + : j_transceiver_(env, j_transceiver){}; + +JavaRtpTransceiverGlobalOwner::JavaRtpTransceiverGlobalOwner( + JavaRtpTransceiverGlobalOwner&& other) = default; + +JavaRtpTransceiverGlobalOwner::~JavaRtpTransceiverGlobalOwner() { + if (j_transceiver_.obj()) { + Java_RtpTransceiver_dispose(AttachCurrentThreadIfNeeded(), j_transceiver_); + } +} + ScopedJavaLocalRef JNI_RtpTransceiver_GetMediaType( JNIEnv* jni, const base::android::JavaParamRef&, diff --git a/sdk/android/src/jni/pc/rtptransceiver.h b/sdk/android/src/jni/pc/rtptransceiver.h index 9017c2fcc2..61f3e0cafc 100644 --- a/sdk/android/src/jni/pc/rtptransceiver.h +++ b/sdk/android/src/jni/pc/rtptransceiver.h @@ -27,6 +27,19 @@ ScopedJavaLocalRef NativeToJavaRtpTransceiver( JNIEnv* env, rtc::scoped_refptr transceiver); +// This takes ownership of the of the |j_transceiver| and stores it as a global +// reference. This calls the Java Transceiver's dispose() method with the dtor. +class JavaRtpTransceiverGlobalOwner { + public: + JavaRtpTransceiverGlobalOwner(JNIEnv* env, + const JavaRef& j_transceiver); + JavaRtpTransceiverGlobalOwner(JavaRtpTransceiverGlobalOwner&& other); + ~JavaRtpTransceiverGlobalOwner(); + + private: + ScopedJavaGlobalRef j_transceiver_; +}; + } // namespace jni } // namespace webrtc