| Index: webrtc/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc
|
| diff --git a/webrtc/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc b/webrtc/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc
|
| index 18767925933ffb6006845d83b1fd2d3edb0954f5..8182abb42fc9f0722ce610bff187cee55e80fac5 100644
|
| --- a/webrtc/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc
|
| +++ b/webrtc/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc
|
| @@ -10,6 +10,7 @@
|
|
|
| #include "webrtc/sdk/android/src/jni/pc/peerconnectionobserver_jni.h"
|
|
|
| +#include <webrtc/pc/mediastreamobserver.h>
|
| #include <string>
|
|
|
| #include "webrtc/sdk/android/src/jni/classreferenceholder.h"
|
| @@ -45,6 +46,12 @@ PeerConnectionObserverJni::PeerConnectionObserverJni(JNIEnv* jni,
|
|
|
| PeerConnectionObserverJni::~PeerConnectionObserverJni() {
|
| ScopedLocalRefFrame local_ref_frame(jni());
|
| + stream_observers_.clear();
|
| + while (!remote_tracks_.empty()) {
|
| + NativeToJavaMediaTrackMap::iterator it = remote_tracks_.begin();
|
| + DeleteGlobalRef(jni(), it->second);
|
| + remote_tracks_.erase(it);
|
| + }
|
| while (!remote_streams_.empty())
|
| DisposeRemoteStream(remote_streams_.begin());
|
| while (!rtp_receivers_.empty())
|
| @@ -131,48 +138,144 @@ void PeerConnectionObserverJni::OnAddStream(
|
| // OnAddTrack.
|
| jobject j_stream = GetOrCreateJavaStream(stream);
|
|
|
| - for (const auto& track : stream->GetAudioTracks()) {
|
| - jstring id = JavaStringFromStdString(jni(), 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_, "audioTracks", "Ljava/util/LinkedList;");
|
| - jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
|
| - jmethodID add = GetMethodID(jni(), GetObjectClass(jni(), audio_tracks),
|
| - "add", "(Ljava/lang/Object;)Z");
|
| - jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
|
| - CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
| - RTC_CHECK(added);
|
| - }
|
| -
|
| - for (const auto& track : stream->GetVideoTracks()) {
|
| - jstring id = JavaStringFromStdString(jni(), 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_, "videoTracks", "Ljava/util/LinkedList;");
|
| - jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
|
| - jmethodID add = GetMethodID(jni(), GetObjectClass(jni(), video_tracks),
|
| - "add", "(Ljava/lang/Object;)Z");
|
| - jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
|
| - CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
| - RTC_CHECK(added);
|
| - }
|
| -
|
| jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
|
| "(Lorg/webrtc/MediaStream;)V");
|
| jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
|
| CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
| +
|
| + webrtc::MediaStreamObserver* observer =
|
| + new webrtc::MediaStreamObserver(stream);
|
| + observer->SignalAudioTrackRemoved.connect(
|
| + this, &PeerConnectionObserverJni::OnAudioTrackRemoved);
|
| + observer->SignalVideoTrackRemoved.connect(
|
| + this, &PeerConnectionObserverJni::OnVideoTrackRemoved);
|
| + stream_observers_.push_back(
|
| + std::unique_ptr<webrtc::MediaStreamObserver>(observer));
|
| +}
|
| +
|
| +void PeerConnectionObserverJni::OnAudioTrackAdded(
|
| + webrtc::AudioTrackInterface* track,
|
| + webrtc::MediaStreamInterface* stream) {
|
| + ScopedLocalRefFrame local_ref_frame(jni());
|
| + jstring id = JavaStringFromStdString(jni(), track->id());
|
| + jobject j_stream = GetOrCreateJavaStream(stream);
|
| + // 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), id);
|
| + CHECK_EXCEPTION(jni()) << "error during NewObject";
|
| + remote_tracks_[track] = NewGlobalRef(jni(), j_track);
|
| + jfieldID audio_tracks_id = GetFieldID(
|
| + jni(), *j_media_stream_class_, "audioTracks", "Ljava/util/LinkedList;");
|
| + jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
|
| + jmethodID add = GetMethodID(jni(), GetObjectClass(jni(), audio_tracks), "add",
|
| + "(Ljava/lang/Object;)Z");
|
| + jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
|
| + CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
| + RTC_CHECK(added);
|
| +}
|
| +
|
| +void PeerConnectionObserverJni::OnVideoTrackAdded(
|
| + webrtc::VideoTrackInterface* track,
|
| + webrtc::MediaStreamInterface* stream) {
|
| + ScopedLocalRefFrame local_ref_frame(jni());
|
| + jobject j_stream = GetOrCreateJavaStream(stream);
|
| +
|
| + jstring id = JavaStringFromStdString(jni(), 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), id);
|
| + CHECK_EXCEPTION(jni()) << "error during NewObject";
|
| + remote_tracks_[track] = NewGlobalRef(jni(), j_track);
|
| + jfieldID video_tracks_id = GetFieldID(
|
| + jni(), *j_media_stream_class_, "videoTracks", "Ljava/util/LinkedList;");
|
| + jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
|
| + jmethodID add = GetMethodID(jni(), GetObjectClass(jni(), video_tracks), "add",
|
| + "(Ljava/lang/Object;)Z");
|
| + jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
|
| + CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
| + RTC_CHECK(added);
|
| +}
|
| +
|
| +void PeerConnectionObserverJni::OnAudioTrackRemoved(
|
| + webrtc::AudioTrackInterface* track,
|
| + webrtc::MediaStreamInterface* stream) {
|
| + ScopedLocalRefFrame local_ref_frame(jni());
|
| + jobject j_stream = GetOrCreateJavaStream(stream);
|
| + NativeToJavaMediaTrackMap::iterator track_it = remote_tracks_.find(track);
|
| + RTC_CHECK(track_it != remote_tracks_.end());
|
| + NativeMediaStreamTrackToNativeRtpReceiver::iterator receiver_it =
|
| + track_to_receiver_.find(track);
|
| + RTC_CHECK(receiver_it != track_to_receiver_.end());
|
| + NativeToJavaRtpReceiverMap::iterator j_receiver_it =
|
| + rtp_receivers_.find(receiver_it->second);
|
| + RTC_CHECK(j_receiver_it != rtp_receivers_.end());
|
| +
|
| + jobject j_track = track_it->second;
|
| + jobject j_receiver = j_receiver_it->second;
|
| +
|
| + jfieldID audio_tracks_id = GetFieldID(
|
| + jni(), *j_media_stream_class_, "audioTracks", "Ljava/util/LinkedList;");
|
| + jobject video_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
|
| + jmethodID remove = GetMethodID(jni(), GetObjectClass(jni(), video_tracks),
|
| + "remove", "(Ljava/lang/Object;)Z");
|
| + jboolean removed = jni()->CallBooleanMethod(video_tracks, remove, j_track);
|
| + CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
| + RTC_CHECK(removed);
|
| +
|
| + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams;
|
| + streams.push_back(rtc::scoped_refptr<webrtc::MediaStreamInterface>(stream));
|
| + jobjectArray j_stream_array = NativeToJavaMediaStreamArray(jni(), streams);
|
| + jmethodID m =
|
| + GetMethodID(jni(), *j_observer_class_, "onRemoveTrack",
|
| + "(Lorg/webrtc/RtpReceiver;[Lorg/webrtc/MediaStream;)V");
|
| + jni()->CallVoidMethod(*j_observer_global_, m, j_receiver, j_stream_array);
|
| + CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod";
|
| +
|
| + DisposeRemoteTrack(track_it);
|
| + DisposeRtpReceiver(j_receiver_it);
|
| +}
|
| +
|
| +void PeerConnectionObserverJni::OnVideoTrackRemoved(
|
| + webrtc::VideoTrackInterface* track,
|
| + webrtc::MediaStreamInterface* stream) {
|
| + ScopedLocalRefFrame local_ref_frame(jni());
|
| + jobject j_stream = GetOrCreateJavaStream(stream);
|
| + NativeToJavaMediaTrackMap::iterator track_it = remote_tracks_.find(track);
|
| + RTC_CHECK(track_it != remote_tracks_.end());
|
| + NativeMediaStreamTrackToNativeRtpReceiver::iterator receiver_it =
|
| + track_to_receiver_.find(track);
|
| + RTC_CHECK(receiver_it != track_to_receiver_.end());
|
| + NativeToJavaRtpReceiverMap::iterator j_receiver_it =
|
| + rtp_receivers_.find(receiver_it->second);
|
| + RTC_CHECK(j_receiver_it != rtp_receivers_.end());
|
| +
|
| + jobject j_track = track_it->second;
|
| + jobject j_receiver = j_receiver_it->second;
|
| +
|
| + jfieldID video_tracks_id = GetFieldID(
|
| + jni(), *j_media_stream_class_, "videoTracks", "Ljava/util/LinkedList;");
|
| + jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
|
| + jmethodID remove = GetMethodID(jni(), GetObjectClass(jni(), video_tracks),
|
| + "remove", "(Ljava/lang/Object;)Z");
|
| + jboolean removed = jni()->CallBooleanMethod(video_tracks, remove, j_track);
|
| + CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
| + RTC_CHECK(removed);
|
| +
|
| + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams;
|
| + streams.push_back(rtc::scoped_refptr<webrtc::MediaStreamInterface>(stream));
|
| + jobjectArray j_stream_array = NativeToJavaMediaStreamArray(jni(), streams);
|
| + jmethodID m =
|
| + GetMethodID(jni(), *j_observer_class_, "onRemoveTrack",
|
| + "(Lorg/webrtc/RtpReceiver;[Lorg/webrtc/MediaStream;)V");
|
| + jni()->CallVoidMethod(*j_observer_global_, m, j_receiver, j_stream_array);
|
| + CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod";
|
| +
|
| + DisposeRemoteTrack(track_it);
|
| + DisposeRtpReceiver(j_receiver_it);
|
| }
|
|
|
| void PeerConnectionObserverJni::OnRemoveStream(
|
| @@ -186,6 +289,16 @@ void PeerConnectionObserverJni::OnRemoveStream(
|
| "(Lorg/webrtc/MediaStream;)V");
|
| jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
|
| CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
| +
|
| + stream_observers_.erase(
|
| + std::remove_if(
|
| + stream_observers_.begin(), stream_observers_.end(),
|
| + [stream](
|
| + const std::unique_ptr<webrtc::MediaStreamObserver>& observer) {
|
| + return observer->stream() == stream;
|
| + }),
|
| + stream_observers_.end());
|
| +
|
| // Release the refptr reference so that DisposeRemoteStream can assert
|
| // it removes the final reference.
|
| stream = nullptr;
|
| @@ -233,6 +346,22 @@ void PeerConnectionObserverJni::OnAddTrack(
|
| CHECK_EXCEPTION(jni()) << "error during NewObject";
|
| receiver->AddRef();
|
| rtp_receivers_[receiver] = NewGlobalRef(jni(), j_rtp_receiver);
|
| + track_to_receiver_[receiver->track()] = receiver;
|
| + for (auto stream : streams) {
|
| + if (receiver->media_type() == cricket::MediaType::MEDIA_TYPE_AUDIO) {
|
| + webrtc::AudioTrackInterface* track =
|
| + reinterpret_cast<webrtc::AudioTrackInterface*>(
|
| + receiver->track().get());
|
| + OnAudioTrackAdded(track, stream);
|
| + } else if (receiver->media_type() == cricket::MediaType::MEDIA_TYPE_VIDEO) {
|
| + webrtc::VideoTrackInterface* track =
|
| + reinterpret_cast<webrtc::VideoTrackInterface*>(
|
| + receiver->track().get());
|
| + OnVideoTrackAdded(track, stream);
|
| + } else {
|
| + RTC_NOTREACHED();
|
| + }
|
| + }
|
|
|
| jobjectArray j_stream_array = NativeToJavaMediaStreamArray(jni(), streams);
|
| jmethodID m =
|
| @@ -269,6 +398,23 @@ void PeerConnectionObserverJni::DisposeRtpReceiver(
|
| DeleteGlobalRef(jni(), j_rtp_receiver);
|
| }
|
|
|
| +void PeerConnectionObserverJni::DisposeRemoteTrack(
|
| + const NativeToJavaMediaTrackMap::iterator& it) {
|
| + RTC_CHECK(it != remote_tracks_.end());
|
| + webrtc::MediaStreamTrackInterface* track = it->first;
|
| + jobject j_track = it->second;
|
| + remote_tracks_.erase(it);
|
| + jmethodID dispose;
|
| + if (track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
|
| + dispose = GetMethodID(jni(), *j_video_track_class_, "dispose", "()V");
|
| + } else {
|
| + dispose = GetMethodID(jni(), *j_audio_track_class_, "dispose", "()V");
|
| + }
|
| + jni()->CallVoidMethod(j_track, dispose);
|
| + CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
| + DeleteGlobalRef(jni(), j_track);
|
| +}
|
| +
|
| // If the NativeToJavaStreamsMap contains the stream, return it.
|
| // Otherwise, create a new Java MediaStream.
|
| jobject PeerConnectionObserverJni::GetOrCreateJavaStream(
|
| @@ -277,7 +423,6 @@ jobject PeerConnectionObserverJni::GetOrCreateJavaStream(
|
| if (it != remote_streams_.end()) {
|
| return it->second;
|
| }
|
| -
|
| // Java MediaStream holds one reference. Corresponding Release() is in
|
| // MediaStream_free, triggered by MediaStream.dispose().
|
| stream->AddRef();
|
|
|