From de5afcfcbfd97d5156e10bfbf65ad89a7364f0e2 Mon Sep 17 00:00:00 2001 From: Magnus Jedvert Date: Sun, 10 Dec 2017 14:58:29 +0100 Subject: [PATCH] Android: Merge peerconnectionobserver_jni and peerconnection_jni The generated JNI files are actually implementation files that can only be included from one place. For generating JNI code for PeerConnection.java, this means we need to collect all JNI PeerConnection code into one place. This CL moves peerconnectionobserver_jni.h to peerconnection.h, and merges peerconnectionobserver_jni.cc and peerconnection_jni.cc. It also moves converter functions JavaToNativeIceServers and JavaToNativeRTCConfiguration to peerconnection.h since they are also related to PeerConnection.java. This CL does not contain anything else than a pure code move. TBR=sakal@webrtc.org Bug: webrtc:8278 Change-Id: I31c696c1aab495e09f95e5ba5d79f95df7c34a0e Reviewed-on: https://webrtc-review.googlesource.com/31483 Reviewed-by: Magnus Jedvert Commit-Queue: Magnus Jedvert Cr-Commit-Position: refs/heads/master@{#21200} --- sdk/android/BUILD.gn | 5 +- .../src/jni/pc/java_native_conversion.cc | 188 ---- .../src/jni/pc/java_native_conversion.h | 9 - sdk/android/src/jni/pc/peerconnection.cc | 804 ++++++++++++++++++ ...nectionobserver_jni.h => peerconnection.h} | 15 +- sdk/android/src/jni/pc/peerconnection_jni.cc | 366 -------- .../src/jni/pc/peerconnectionfactory_jni.cc | 2 +- .../src/jni/pc/peerconnectionobserver_jni.cc | 273 ------ 8 files changed, 819 insertions(+), 843 deletions(-) create mode 100644 sdk/android/src/jni/pc/peerconnection.cc rename sdk/android/src/jni/pc/{peerconnectionobserver_jni.h => peerconnection.h} (91%) delete mode 100644 sdk/android/src/jni/pc/peerconnection_jni.cc delete mode 100644 sdk/android/src/jni/pc/peerconnectionobserver_jni.cc diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index 2f024c7afe..f75cfdb072 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -329,10 +329,9 @@ rtc_static_library("peerconnection_jni") { "src/jni/pc/mediastreamtrack_jni.cc", "src/jni/pc/ownedfactoryandthreads.cc", "src/jni/pc/ownedfactoryandthreads.h", - "src/jni/pc/peerconnection_jni.cc", + "src/jni/pc/peerconnection.cc", + "src/jni/pc/peerconnection.h", "src/jni/pc/peerconnectionfactory_jni.cc", - "src/jni/pc/peerconnectionobserver_jni.cc", - "src/jni/pc/peerconnectionobserver_jni.h", "src/jni/pc/rtcstatscollectorcallbackwrapper.cc", "src/jni/pc/rtcstatscollectorcallbackwrapper.h", "src/jni/pc/rtpreceiver.cc", diff --git a/sdk/android/src/jni/pc/java_native_conversion.cc b/sdk/android/src/jni/pc/java_native_conversion.cc index 52ccfec1ad..1c1fdd71cd 100644 --- a/sdk/android/src/jni/pc/java_native_conversion.cc +++ b/sdk/android/src/jni/pc/java_native_conversion.cc @@ -289,194 +289,6 @@ PeerConnectionInterface::TlsCertPolicy JavaToNativeTlsCertPolicy( return PeerConnectionInterface::kTlsCertPolicySecure; } -void JavaToNativeIceServers(JNIEnv* jni, - jobject j_ice_servers, - PeerConnectionInterface::IceServers* ice_servers) { - for (jobject j_ice_server : Iterable(jni, j_ice_servers)) { - jclass j_ice_server_class = GetObjectClass(jni, j_ice_server); - jfieldID j_ice_server_urls_id = - GetFieldID(jni, j_ice_server_class, "urls", "Ljava/util/List;"); - jfieldID j_ice_server_username_id = - GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;"); - jfieldID j_ice_server_password_id = - GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;"); - jfieldID j_ice_server_tls_cert_policy_id = - GetFieldID(jni, j_ice_server_class, "tlsCertPolicy", - "Lorg/webrtc/PeerConnection$TlsCertPolicy;"); - jobject j_ice_server_tls_cert_policy = - GetObjectField(jni, j_ice_server, j_ice_server_tls_cert_policy_id); - jfieldID j_ice_server_hostname_id = - GetFieldID(jni, j_ice_server_class, "hostname", "Ljava/lang/String;"); - jfieldID j_ice_server_tls_alpn_protocols_id = GetFieldID( - jni, j_ice_server_class, "tlsAlpnProtocols", "Ljava/util/List;"); - jfieldID j_ice_server_tls_elliptic_curves_id = GetFieldID( - jni, j_ice_server_class, "tlsEllipticCurves", "Ljava/util/List;"); - jobject urls = GetObjectField(jni, j_ice_server, j_ice_server_urls_id); - jstring username = reinterpret_cast( - GetObjectField(jni, j_ice_server, j_ice_server_username_id)); - jstring password = reinterpret_cast( - GetObjectField(jni, j_ice_server, j_ice_server_password_id)); - PeerConnectionInterface::TlsCertPolicy tls_cert_policy = - JavaToNativeTlsCertPolicy(jni, j_ice_server_tls_cert_policy); - jstring hostname = reinterpret_cast( - GetObjectField(jni, j_ice_server, j_ice_server_hostname_id)); - jobject tls_alpn_protocols = GetNullableObjectField( - jni, j_ice_server, j_ice_server_tls_alpn_protocols_id); - jobject tls_elliptic_curves = GetNullableObjectField( - jni, j_ice_server, j_ice_server_tls_elliptic_curves_id); - PeerConnectionInterface::IceServer server; - server.urls = JavaToStdVectorStrings(jni, urls); - server.username = JavaToStdString(jni, username); - server.password = JavaToStdString(jni, password); - server.tls_cert_policy = tls_cert_policy; - server.hostname = JavaToStdString(jni, hostname); - server.tls_alpn_protocols = JavaToStdVectorStrings(jni, tls_alpn_protocols); - server.tls_elliptic_curves = - JavaToStdVectorStrings(jni, tls_elliptic_curves); - ice_servers->push_back(server); - } -} - -void JavaToNativeRTCConfiguration( - JNIEnv* jni, - jobject j_rtc_config, - PeerConnectionInterface::RTCConfiguration* rtc_config) { - jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config); - - jfieldID j_ice_transports_type_id = - GetFieldID(jni, j_rtc_config_class, "iceTransportsType", - "Lorg/webrtc/PeerConnection$IceTransportsType;"); - jobject j_ice_transports_type = - GetObjectField(jni, j_rtc_config, j_ice_transports_type_id); - - jfieldID j_bundle_policy_id = - GetFieldID(jni, j_rtc_config_class, "bundlePolicy", - "Lorg/webrtc/PeerConnection$BundlePolicy;"); - jobject j_bundle_policy = - GetObjectField(jni, j_rtc_config, j_bundle_policy_id); - - jfieldID j_rtcp_mux_policy_id = - GetFieldID(jni, j_rtc_config_class, "rtcpMuxPolicy", - "Lorg/webrtc/PeerConnection$RtcpMuxPolicy;"); - jobject j_rtcp_mux_policy = - GetObjectField(jni, j_rtc_config, j_rtcp_mux_policy_id); - - jfieldID j_tcp_candidate_policy_id = - GetFieldID(jni, j_rtc_config_class, "tcpCandidatePolicy", - "Lorg/webrtc/PeerConnection$TcpCandidatePolicy;"); - jobject j_tcp_candidate_policy = - GetObjectField(jni, j_rtc_config, j_tcp_candidate_policy_id); - - jfieldID j_candidate_network_policy_id = - GetFieldID(jni, j_rtc_config_class, "candidateNetworkPolicy", - "Lorg/webrtc/PeerConnection$CandidateNetworkPolicy;"); - jobject j_candidate_network_policy = - GetObjectField(jni, j_rtc_config, j_candidate_network_policy_id); - - jfieldID j_ice_servers_id = - GetFieldID(jni, j_rtc_config_class, "iceServers", "Ljava/util/List;"); - jobject j_ice_servers = GetObjectField(jni, j_rtc_config, j_ice_servers_id); - - jfieldID j_audio_jitter_buffer_max_packets_id = - GetFieldID(jni, j_rtc_config_class, "audioJitterBufferMaxPackets", "I"); - jfieldID j_audio_jitter_buffer_fast_accelerate_id = GetFieldID( - jni, j_rtc_config_class, "audioJitterBufferFastAccelerate", "Z"); - - jfieldID j_ice_connection_receiving_timeout_id = - GetFieldID(jni, j_rtc_config_class, "iceConnectionReceivingTimeout", "I"); - - jfieldID j_ice_backup_candidate_pair_ping_interval_id = GetFieldID( - jni, j_rtc_config_class, "iceBackupCandidatePairPingInterval", "I"); - - jfieldID j_continual_gathering_policy_id = - GetFieldID(jni, j_rtc_config_class, "continualGatheringPolicy", - "Lorg/webrtc/PeerConnection$ContinualGatheringPolicy;"); - jobject j_continual_gathering_policy = - GetObjectField(jni, j_rtc_config, j_continual_gathering_policy_id); - - jfieldID j_ice_candidate_pool_size_id = - GetFieldID(jni, j_rtc_config_class, "iceCandidatePoolSize", "I"); - jfieldID j_presume_writable_when_fully_relayed_id = GetFieldID( - jni, j_rtc_config_class, "presumeWritableWhenFullyRelayed", "Z"); - - jfieldID j_prune_turn_ports_id = - GetFieldID(jni, j_rtc_config_class, "pruneTurnPorts", "Z"); - - jfieldID j_ice_check_min_interval_id = GetFieldID( - jni, j_rtc_config_class, "iceCheckMinInterval", "Ljava/lang/Integer;"); - - jfieldID j_disable_ipv6_on_wifi_id = - GetFieldID(jni, j_rtc_config_class, "disableIPv6OnWifi", "Z"); - - jfieldID j_max_ipv6_networks_id = - GetFieldID(jni, j_rtc_config_class, "maxIPv6Networks", "I"); - - jfieldID j_ice_regather_interval_range_id = - GetFieldID(jni, j_rtc_config_class, "iceRegatherIntervalRange", - "Lorg/webrtc/PeerConnection$IntervalRange;"); - jclass j_interval_range_class = - jni->FindClass("org/webrtc/PeerConnection$IntervalRange"); - jmethodID get_min_id = - GetMethodID(jni, j_interval_range_class, "getMin", "()I"); - jmethodID get_max_id = - GetMethodID(jni, j_interval_range_class, "getMax", "()I"); - - jfieldID j_turn_customizer_type_id = GetFieldID( - jni, j_rtc_config_class, "turnCustomizer", "Lorg/webrtc/TurnCustomizer;"); - jobject j_turn_customizer = - GetNullableObjectField(jni, j_rtc_config, j_turn_customizer_type_id); - - jclass j_turn_customizer_class = jni->FindClass("org/webrtc/TurnCustomizer"); - jfieldID j_native_turn_customizer_id = - GetFieldID(jni, j_turn_customizer_class, "nativeTurnCustomizer", "J"); - - rtc_config->type = JavaToNativeIceTransportsType(jni, j_ice_transports_type); - rtc_config->bundle_policy = JavaToNativeBundlePolicy(jni, j_bundle_policy); - rtc_config->rtcp_mux_policy = - JavaToNativeRtcpMuxPolicy(jni, j_rtcp_mux_policy); - rtc_config->tcp_candidate_policy = - JavaToNativeTcpCandidatePolicy(jni, j_tcp_candidate_policy); - rtc_config->candidate_network_policy = - JavaToNativeCandidateNetworkPolicy(jni, j_candidate_network_policy); - JavaToNativeIceServers(jni, j_ice_servers, &rtc_config->servers); - rtc_config->audio_jitter_buffer_max_packets = - GetIntField(jni, j_rtc_config, j_audio_jitter_buffer_max_packets_id); - rtc_config->audio_jitter_buffer_fast_accelerate = GetBooleanField( - jni, j_rtc_config, j_audio_jitter_buffer_fast_accelerate_id); - rtc_config->ice_connection_receiving_timeout = - GetIntField(jni, j_rtc_config, j_ice_connection_receiving_timeout_id); - rtc_config->ice_backup_candidate_pair_ping_interval = GetIntField( - jni, j_rtc_config, j_ice_backup_candidate_pair_ping_interval_id); - rtc_config->continual_gathering_policy = - JavaToNativeContinualGatheringPolicy(jni, j_continual_gathering_policy); - rtc_config->ice_candidate_pool_size = - GetIntField(jni, j_rtc_config, j_ice_candidate_pool_size_id); - rtc_config->prune_turn_ports = - GetBooleanField(jni, j_rtc_config, j_prune_turn_ports_id); - rtc_config->presume_writable_when_fully_relayed = GetBooleanField( - jni, j_rtc_config, j_presume_writable_when_fully_relayed_id); - jobject j_ice_check_min_interval = - GetNullableObjectField(jni, j_rtc_config, j_ice_check_min_interval_id); - rtc_config->ice_check_min_interval = - JavaToNativeOptionalInt(jni, j_ice_check_min_interval); - rtc_config->disable_ipv6_on_wifi = - GetBooleanField(jni, j_rtc_config, j_disable_ipv6_on_wifi_id); - rtc_config->max_ipv6_networks = - GetIntField(jni, j_rtc_config, j_max_ipv6_networks_id); - jobject j_ice_regather_interval_range = GetNullableObjectField( - jni, j_rtc_config, j_ice_regather_interval_range_id); - if (!IsNull(jni, j_ice_regather_interval_range)) { - int min = jni->CallIntMethod(j_ice_regather_interval_range, get_min_id); - int max = jni->CallIntMethod(j_ice_regather_interval_range, get_max_id); - rtc_config->ice_regather_interval_range.emplace(min, max); - } - - if (!IsNull(jni, j_turn_customizer)) { - rtc_config->turn_customizer = reinterpret_cast( - GetLongField(jni, j_turn_customizer, j_native_turn_customizer_id)); - } -} - RtpParameters JavaToNativeRtpParameters(JNIEnv* jni, jobject j_parameters) { RtpParameters parameters; jclass parameters_class = jni->FindClass("org/webrtc/RtpParameters"); diff --git a/sdk/android/src/jni/pc/java_native_conversion.h b/sdk/android/src/jni/pc/java_native_conversion.h index c3580f52dc..f4649b05b2 100644 --- a/sdk/android/src/jni/pc/java_native_conversion.h +++ b/sdk/android/src/jni/pc/java_native_conversion.h @@ -87,15 +87,6 @@ PeerConnectionInterface::TlsCertPolicy JavaToNativeTlsCertPolicy( JNIEnv* jni, jobject j_ice_server_tls_cert_policy); -void JavaToNativeIceServers(JNIEnv* jni, - jobject j_ice_servers, - PeerConnectionInterface::IceServers* ice_servers); - -void JavaToNativeRTCConfiguration( - JNIEnv* jni, - jobject j_rtc_config, - PeerConnectionInterface::RTCConfiguration* rtc_config); - /********************************************************* * RtpParameters, used for RtpSender and RtpReceiver APIs. *********************************************************/ diff --git a/sdk/android/src/jni/pc/peerconnection.cc b/sdk/android/src/jni/pc/peerconnection.cc new file mode 100644 index 0000000000..45a2323ff9 --- /dev/null +++ b/sdk/android/src/jni/pc/peerconnection.cc @@ -0,0 +1,804 @@ +/* + * Copyright 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Lifecycle notes: objects are owned where they will be called; in other words +// FooObservers are owned by C++-land, and user-callable objects (e.g. +// PeerConnection and VideoTrack) are owned by Java-land. +// When this file (or other files in this directory) allocates C++ +// RefCountInterfaces it AddRef()s an artificial ref simulating the jlong held +// in Java-land, and then Release()s the ref in the respective free call. +// Sometimes this AddRef is implicit in the construction of a scoped_refptr<> +// which is then .release()d. Any persistent (non-local) references from C++ to +// Java must be global or weak (in which case they must be checked before use)! +// +// Exception notes: pretty much all JNI calls can throw Java exceptions, so each +// call through a JNIEnv* pointer needs to be followed by an ExceptionCheck() +// call. In this file this is done in CHECK_EXCEPTION, making for much easier +// debugging in case of failure (the alternative is to wait for control to +// return to the Java frame that called code in this file, at which point it's +// impossible to tell which JNI call broke). + +#include "sdk/android/src/jni/pc/peerconnection.h" + +#include +#include +#include +#include + +#include "api/mediaconstraintsinterface.h" +#include "api/peerconnectioninterface.h" +#include "api/rtpreceiverinterface.h" +#include "api/rtpsenderinterface.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "rtc_base/ptr_util.h" +#include "sdk/android/generated_peerconnection_jni/jni/MediaStream_jni.h" +#include "sdk/android/generated_peerconnection_jni/jni/PeerConnection_jni.h" +#include "sdk/android/generated_peerconnection_jni/jni/RtpSender_jni.h" +#include "sdk/android/src/jni/classreferenceholder.h" +#include "sdk/android/src/jni/jni_helpers.h" +#include "sdk/android/src/jni/pc/datachannel.h" +#include "sdk/android/src/jni/pc/java_native_conversion.h" +#include "sdk/android/src/jni/pc/mediaconstraints_jni.h" +#include "sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h" +#include "sdk/android/src/jni/pc/sdpobserver_jni.h" +#include "sdk/android/src/jni/pc/statsobserver_jni.h" + +namespace webrtc { +namespace jni { + +namespace { + +rtc::scoped_refptr ExtractNativePC(JNIEnv* jni, + jobject j_pc) { + jfieldID native_pc_id = + GetFieldID(jni, GetObjectClass(jni, j_pc), "nativePeerConnection", "J"); + jlong j_p = GetLongField(jni, j_pc, native_pc_id); + return rtc::scoped_refptr( + reinterpret_cast(j_p)); +} + +jobject NativeToJavaRtpSender(JNIEnv* env, + rtc::scoped_refptr sender) { + if (!sender) + return nullptr; + // Sender is now owned by the Java object, and will be freed from + // RtpSender.dispose(), called by PeerConnection.dispose() or getSenders(). + return Java_RtpSender_Constructor(env, jlongFromPointer(sender.release())); +} + +// Convenience, used since callbacks occur on the signaling thread, which may +// be a non-Java thread. +JNIEnv* jni() { + return AttachCurrentThreadIfNeeded(); +} + +} // namespace + +void JavaToNativeIceServers(JNIEnv* jni, + jobject j_ice_servers, + PeerConnectionInterface::IceServers* ice_servers) { + for (jobject j_ice_server : Iterable(jni, j_ice_servers)) { + jclass j_ice_server_class = GetObjectClass(jni, j_ice_server); + jfieldID j_ice_server_urls_id = + GetFieldID(jni, j_ice_server_class, "urls", "Ljava/util/List;"); + jfieldID j_ice_server_username_id = + GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;"); + jfieldID j_ice_server_password_id = + GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;"); + jfieldID j_ice_server_tls_cert_policy_id = + GetFieldID(jni, j_ice_server_class, "tlsCertPolicy", + "Lorg/webrtc/PeerConnection$TlsCertPolicy;"); + jobject j_ice_server_tls_cert_policy = + GetObjectField(jni, j_ice_server, j_ice_server_tls_cert_policy_id); + jfieldID j_ice_server_hostname_id = + GetFieldID(jni, j_ice_server_class, "hostname", "Ljava/lang/String;"); + jfieldID j_ice_server_tls_alpn_protocols_id = GetFieldID( + jni, j_ice_server_class, "tlsAlpnProtocols", "Ljava/util/List;"); + jfieldID j_ice_server_tls_elliptic_curves_id = GetFieldID( + jni, j_ice_server_class, "tlsEllipticCurves", "Ljava/util/List;"); + jobject urls = GetObjectField(jni, j_ice_server, j_ice_server_urls_id); + jstring username = reinterpret_cast( + GetObjectField(jni, j_ice_server, j_ice_server_username_id)); + jstring password = reinterpret_cast( + GetObjectField(jni, j_ice_server, j_ice_server_password_id)); + PeerConnectionInterface::TlsCertPolicy tls_cert_policy = + JavaToNativeTlsCertPolicy(jni, j_ice_server_tls_cert_policy); + jstring hostname = reinterpret_cast( + GetObjectField(jni, j_ice_server, j_ice_server_hostname_id)); + jobject tls_alpn_protocols = GetNullableObjectField( + jni, j_ice_server, j_ice_server_tls_alpn_protocols_id); + jobject tls_elliptic_curves = GetNullableObjectField( + jni, j_ice_server, j_ice_server_tls_elliptic_curves_id); + PeerConnectionInterface::IceServer server; + server.urls = JavaToStdVectorStrings(jni, urls); + server.username = JavaToStdString(jni, username); + server.password = JavaToStdString(jni, password); + server.tls_cert_policy = tls_cert_policy; + server.hostname = JavaToStdString(jni, hostname); + server.tls_alpn_protocols = JavaToStdVectorStrings(jni, tls_alpn_protocols); + server.tls_elliptic_curves = + JavaToStdVectorStrings(jni, tls_elliptic_curves); + ice_servers->push_back(server); + } +} + +void JavaToNativeRTCConfiguration( + JNIEnv* jni, + jobject j_rtc_config, + PeerConnectionInterface::RTCConfiguration* rtc_config) { + jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config); + + jfieldID j_ice_transports_type_id = + GetFieldID(jni, j_rtc_config_class, "iceTransportsType", + "Lorg/webrtc/PeerConnection$IceTransportsType;"); + jobject j_ice_transports_type = + GetObjectField(jni, j_rtc_config, j_ice_transports_type_id); + + jfieldID j_bundle_policy_id = + GetFieldID(jni, j_rtc_config_class, "bundlePolicy", + "Lorg/webrtc/PeerConnection$BundlePolicy;"); + jobject j_bundle_policy = + GetObjectField(jni, j_rtc_config, j_bundle_policy_id); + + jfieldID j_rtcp_mux_policy_id = + GetFieldID(jni, j_rtc_config_class, "rtcpMuxPolicy", + "Lorg/webrtc/PeerConnection$RtcpMuxPolicy;"); + jobject j_rtcp_mux_policy = + GetObjectField(jni, j_rtc_config, j_rtcp_mux_policy_id); + + jfieldID j_tcp_candidate_policy_id = + GetFieldID(jni, j_rtc_config_class, "tcpCandidatePolicy", + "Lorg/webrtc/PeerConnection$TcpCandidatePolicy;"); + jobject j_tcp_candidate_policy = + GetObjectField(jni, j_rtc_config, j_tcp_candidate_policy_id); + + jfieldID j_candidate_network_policy_id = + GetFieldID(jni, j_rtc_config_class, "candidateNetworkPolicy", + "Lorg/webrtc/PeerConnection$CandidateNetworkPolicy;"); + jobject j_candidate_network_policy = + GetObjectField(jni, j_rtc_config, j_candidate_network_policy_id); + + jfieldID j_ice_servers_id = + GetFieldID(jni, j_rtc_config_class, "iceServers", "Ljava/util/List;"); + jobject j_ice_servers = GetObjectField(jni, j_rtc_config, j_ice_servers_id); + + jfieldID j_audio_jitter_buffer_max_packets_id = + GetFieldID(jni, j_rtc_config_class, "audioJitterBufferMaxPackets", "I"); + jfieldID j_audio_jitter_buffer_fast_accelerate_id = GetFieldID( + jni, j_rtc_config_class, "audioJitterBufferFastAccelerate", "Z"); + + jfieldID j_ice_connection_receiving_timeout_id = + GetFieldID(jni, j_rtc_config_class, "iceConnectionReceivingTimeout", "I"); + + jfieldID j_ice_backup_candidate_pair_ping_interval_id = GetFieldID( + jni, j_rtc_config_class, "iceBackupCandidatePairPingInterval", "I"); + + jfieldID j_continual_gathering_policy_id = + GetFieldID(jni, j_rtc_config_class, "continualGatheringPolicy", + "Lorg/webrtc/PeerConnection$ContinualGatheringPolicy;"); + jobject j_continual_gathering_policy = + GetObjectField(jni, j_rtc_config, j_continual_gathering_policy_id); + + jfieldID j_ice_candidate_pool_size_id = + GetFieldID(jni, j_rtc_config_class, "iceCandidatePoolSize", "I"); + jfieldID j_presume_writable_when_fully_relayed_id = GetFieldID( + jni, j_rtc_config_class, "presumeWritableWhenFullyRelayed", "Z"); + + jfieldID j_prune_turn_ports_id = + GetFieldID(jni, j_rtc_config_class, "pruneTurnPorts", "Z"); + + jfieldID j_ice_check_min_interval_id = GetFieldID( + jni, j_rtc_config_class, "iceCheckMinInterval", "Ljava/lang/Integer;"); + + jfieldID j_disable_ipv6_on_wifi_id = + GetFieldID(jni, j_rtc_config_class, "disableIPv6OnWifi", "Z"); + + jfieldID j_max_ipv6_networks_id = + GetFieldID(jni, j_rtc_config_class, "maxIPv6Networks", "I"); + + jfieldID j_ice_regather_interval_range_id = + GetFieldID(jni, j_rtc_config_class, "iceRegatherIntervalRange", + "Lorg/webrtc/PeerConnection$IntervalRange;"); + jclass j_interval_range_class = + jni->FindClass("org/webrtc/PeerConnection$IntervalRange"); + jmethodID get_min_id = + GetMethodID(jni, j_interval_range_class, "getMin", "()I"); + jmethodID get_max_id = + GetMethodID(jni, j_interval_range_class, "getMax", "()I"); + + jfieldID j_turn_customizer_type_id = GetFieldID( + jni, j_rtc_config_class, "turnCustomizer", "Lorg/webrtc/TurnCustomizer;"); + jobject j_turn_customizer = + GetNullableObjectField(jni, j_rtc_config, j_turn_customizer_type_id); + + jclass j_turn_customizer_class = jni->FindClass("org/webrtc/TurnCustomizer"); + jfieldID j_native_turn_customizer_id = + GetFieldID(jni, j_turn_customizer_class, "nativeTurnCustomizer", "J"); + + rtc_config->type = JavaToNativeIceTransportsType(jni, j_ice_transports_type); + rtc_config->bundle_policy = JavaToNativeBundlePolicy(jni, j_bundle_policy); + rtc_config->rtcp_mux_policy = + JavaToNativeRtcpMuxPolicy(jni, j_rtcp_mux_policy); + rtc_config->tcp_candidate_policy = + JavaToNativeTcpCandidatePolicy(jni, j_tcp_candidate_policy); + rtc_config->candidate_network_policy = + JavaToNativeCandidateNetworkPolicy(jni, j_candidate_network_policy); + JavaToNativeIceServers(jni, j_ice_servers, &rtc_config->servers); + rtc_config->audio_jitter_buffer_max_packets = + GetIntField(jni, j_rtc_config, j_audio_jitter_buffer_max_packets_id); + rtc_config->audio_jitter_buffer_fast_accelerate = GetBooleanField( + jni, j_rtc_config, j_audio_jitter_buffer_fast_accelerate_id); + rtc_config->ice_connection_receiving_timeout = + GetIntField(jni, j_rtc_config, j_ice_connection_receiving_timeout_id); + rtc_config->ice_backup_candidate_pair_ping_interval = GetIntField( + jni, j_rtc_config, j_ice_backup_candidate_pair_ping_interval_id); + rtc_config->continual_gathering_policy = + JavaToNativeContinualGatheringPolicy(jni, j_continual_gathering_policy); + rtc_config->ice_candidate_pool_size = + GetIntField(jni, j_rtc_config, j_ice_candidate_pool_size_id); + rtc_config->prune_turn_ports = + GetBooleanField(jni, j_rtc_config, j_prune_turn_ports_id); + rtc_config->presume_writable_when_fully_relayed = GetBooleanField( + jni, j_rtc_config, j_presume_writable_when_fully_relayed_id); + jobject j_ice_check_min_interval = + GetNullableObjectField(jni, j_rtc_config, j_ice_check_min_interval_id); + rtc_config->ice_check_min_interval = + JavaToNativeOptionalInt(jni, j_ice_check_min_interval); + rtc_config->disable_ipv6_on_wifi = + GetBooleanField(jni, j_rtc_config, j_disable_ipv6_on_wifi_id); + rtc_config->max_ipv6_networks = + GetIntField(jni, j_rtc_config, j_max_ipv6_networks_id); + jobject j_ice_regather_interval_range = GetNullableObjectField( + jni, j_rtc_config, j_ice_regather_interval_range_id); + if (!IsNull(jni, j_ice_regather_interval_range)) { + int min = jni->CallIntMethod(j_ice_regather_interval_range, get_min_id); + int max = jni->CallIntMethod(j_ice_regather_interval_range, get_max_id); + rtc_config->ice_regather_interval_range.emplace(min, max); + } + + if (!IsNull(jni, j_turn_customizer)) { + rtc_config->turn_customizer = reinterpret_cast( + GetLongField(jni, j_turn_customizer, j_native_turn_customizer_id)); + } +} + +PeerConnectionObserverJni::PeerConnectionObserverJni(JNIEnv* jni, + jobject j_observer) + : j_observer_global_(jni, j_observer) {} + +PeerConnectionObserverJni::~PeerConnectionObserverJni() { + ScopedLocalRefFrame local_ref_frame(jni()); + while (!remote_streams_.empty()) + DisposeRemoteStream(remote_streams_.begin()); +} + +void PeerConnectionObserverJni::OnIceCandidate( + const IceCandidateInterface* candidate) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onIceCandidate(env, *j_observer_global_, + NativeToJavaIceCandidate(env, *candidate)); +} + +void PeerConnectionObserverJni::OnIceCandidatesRemoved( + const std::vector& candidates) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onIceCandidatesRemoved( + env, *j_observer_global_, NativeToJavaCandidateArray(env, candidates)); +} + +void PeerConnectionObserverJni::OnSignalingChange( + PeerConnectionInterface::SignalingState new_state) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onSignalingChange( + env, *j_observer_global_, + Java_SignalingState_fromNativeIndex(env, new_state)); +} + +void PeerConnectionObserverJni::OnIceConnectionChange( + PeerConnectionInterface::IceConnectionState new_state) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onIceConnectionChange( + env, *j_observer_global_, + Java_IceConnectionState_fromNativeIndex(env, new_state)); +} + +void PeerConnectionObserverJni::OnIceConnectionReceivingChange(bool receiving) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onIceConnectionReceivingChange(env, *j_observer_global_, + receiving); +} + +void PeerConnectionObserverJni::OnIceGatheringChange( + PeerConnectionInterface::IceGatheringState new_state) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onIceGatheringChange( + env, *j_observer_global_, + Java_IceGatheringState_fromNativeIndex(env, new_state)); +} + +void PeerConnectionObserverJni::OnAddStream( + rtc::scoped_refptr stream) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + // The stream could be added into the remote_streams_ map when calling + // OnAddTrack. + jobject j_stream = GetOrCreateJavaStream(stream); + + for (const auto& track : stream->GetAudioTracks()) { + AddNativeAudioTrackToJavaStream(track, j_stream); + } + for (const auto& track : stream->GetVideoTracks()) { + AddNativeVideoTrackToJavaStream(track, j_stream); + } + + Java_Observer_onAddStream(env, *j_observer_global_, j_stream); + + // Create an observer to update the Java stream when the native stream's set + // of tracks changes. + auto observer = rtc::MakeUnique(stream); + observer->SignalAudioTrackRemoved.connect( + this, &PeerConnectionObserverJni::OnAudioTrackRemovedFromStream); + observer->SignalVideoTrackRemoved.connect( + this, &PeerConnectionObserverJni::OnVideoTrackRemovedFromStream); + observer->SignalAudioTrackAdded.connect( + this, &PeerConnectionObserverJni::OnAudioTrackAddedToStream); + observer->SignalVideoTrackAdded.connect( + this, &PeerConnectionObserverJni::OnVideoTrackAddedToStream); + stream_observers_.push_back(std::move(observer)); +} + +void PeerConnectionObserverJni::AddNativeAudioTrackToJavaStream( + rtc::scoped_refptr track, + jobject j_stream) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + Java_MediaStream_addNativeAudioTrack(env, j_stream, + jlongFromPointer(track.release())); +} + +void PeerConnectionObserverJni::AddNativeVideoTrackToJavaStream( + rtc::scoped_refptr track, + jobject j_stream) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + Java_MediaStream_addNativeVideoTrack(env, j_stream, + jlongFromPointer(track.release())); +} + +void PeerConnectionObserverJni::OnAudioTrackAddedToStream( + AudioTrackInterface* track, + MediaStreamInterface* stream) { + ScopedLocalRefFrame local_ref_frame(jni()); + jobject j_stream = GetOrCreateJavaStream(stream); + AddNativeAudioTrackToJavaStream(track, j_stream); +} + +void PeerConnectionObserverJni::OnVideoTrackAddedToStream( + VideoTrackInterface* track, + MediaStreamInterface* stream) { + ScopedLocalRefFrame local_ref_frame(jni()); + jobject j_stream = GetOrCreateJavaStream(stream); + AddNativeVideoTrackToJavaStream(track, j_stream); +} + +void PeerConnectionObserverJni::OnAudioTrackRemovedFromStream( + AudioTrackInterface* track, + MediaStreamInterface* stream) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + jobject j_stream = GetOrCreateJavaStream(stream); + Java_MediaStream_removeAudioTrack(env, j_stream, jlongFromPointer(track)); +} + +void PeerConnectionObserverJni::OnVideoTrackRemovedFromStream( + VideoTrackInterface* track, + MediaStreamInterface* stream) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + jobject j_stream = GetOrCreateJavaStream(stream); + Java_MediaStream_removeVideoTrack(env, j_stream, jlongFromPointer(track)); +} + +void PeerConnectionObserverJni::OnRemoveStream( + rtc::scoped_refptr stream) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream); + RTC_CHECK(it != remote_streams_.end()) + << "unexpected stream: " << std::hex << stream; + Java_Observer_onRemoveStream(env, *j_observer_global_, it->second); + + // Release the refptr reference so that DisposeRemoteStream can assert + // it removes the final reference. + stream = nullptr; + DisposeRemoteStream(it); +} + +void PeerConnectionObserverJni::OnDataChannel( + rtc::scoped_refptr channel) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onDataChannel(env, *j_observer_global_, + WrapNativeDataChannel(env, channel)); +} + +void PeerConnectionObserverJni::OnRenegotiationNeeded() { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + Java_Observer_onRenegotiationNeeded(env, *j_observer_global_); +} + +void PeerConnectionObserverJni::OnAddTrack( + rtc::scoped_refptr receiver, + const std::vector>& streams) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + jobject j_rtp_receiver = NativeToJavaRtpReceiver(env, receiver); + rtp_receivers_.emplace_back(env, j_rtp_receiver); + + Java_Observer_onAddTrack(env, *j_observer_global_, j_rtp_receiver, + NativeToJavaMediaStreamArray(env, streams)); +} + +void PeerConnectionObserverJni::SetConstraints( + std::unique_ptr constraints) { + RTC_CHECK(!constraints_.get()) << "constraints already set!"; + constraints_ = std::move(constraints); +} + +void PeerConnectionObserverJni::DisposeRemoteStream( + const NativeToJavaStreamsMap::iterator& it) { + MediaStreamInterface* stream = it->first; + jobject j_stream = it->second; + + // Remove the observer first, so it doesn't react to events during deletion. + stream_observers_.erase( + std::remove_if( + stream_observers_.begin(), stream_observers_.end(), + [stream](const std::unique_ptr& observer) { + return observer->stream() == stream; + }), + stream_observers_.end()); + + remote_streams_.erase(it); + JNIEnv* env = AttachCurrentThreadIfNeeded(); + Java_MediaStream_dispose(env, j_stream); + DeleteGlobalRef(env, j_stream); +} + +// If the NativeToJavaStreamsMap contains the stream, return it. +// Otherwise, create a new Java MediaStream. +jobject PeerConnectionObserverJni::GetOrCreateJavaStream( + const rtc::scoped_refptr& stream) { + NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream); + 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(); + jobject j_stream = + Java_MediaStream_Constructor(jni(), jlongFromPointer(stream.get())); + + remote_streams_[stream] = NewGlobalRef(jni(), j_stream); + return j_stream; +} + +jobjectArray PeerConnectionObserverJni::NativeToJavaMediaStreamArray( + JNIEnv* jni, + const std::vector>& streams) { + jobjectArray java_streams = jni->NewObjectArray( + streams.size(), org_webrtc_MediaStream_clazz(jni), nullptr); + CHECK_EXCEPTION(jni) << "error during NewObjectArray"; + for (size_t i = 0; i < streams.size(); ++i) { + jobject j_stream = GetOrCreateJavaStream(streams[i]); + jni->SetObjectArrayElement(java_streams, i, j_stream); + } + return java_streams; +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_freeObserver, + JNIEnv*, + jclass, + jlong j_p) { + PeerConnectionObserverJni* p = + reinterpret_cast(j_p); + delete p; +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_getLocalDescription, + JNIEnv* jni, + jobject j_pc) { + const SessionDescriptionInterface* sdp = + ExtractNativePC(jni, j_pc)->local_description(); + return sdp ? NativeToJavaSessionDescription(jni, sdp) : NULL; +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_getRemoteDescription, + JNIEnv* jni, + jobject j_pc) { + const SessionDescriptionInterface* sdp = + ExtractNativePC(jni, j_pc)->remote_description(); + return sdp ? NativeToJavaSessionDescription(jni, sdp) : NULL; +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_createDataChannel, + JNIEnv* jni, + jobject j_pc, + jstring j_label, + jobject j_init) { + DataChannelInit init = JavaToNativeDataChannelInit(jni, j_init); + rtc::scoped_refptr channel( + ExtractNativePC(jni, j_pc)->CreateDataChannel( + JavaToStdString(jni, j_label), &init)); + return WrapNativeDataChannel(jni, channel); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_createOffer, + JNIEnv* jni, + jobject j_pc, + jobject j_observer, + jobject j_constraints) { + std::unique_ptr constraints = + JavaToNativeMediaConstraints(jni, j_constraints); + rtc::scoped_refptr observer( + new rtc::RefCountedObject(jni, j_observer, + std::move(constraints))); + ExtractNativePC(jni, j_pc)->CreateOffer(observer, observer->constraints()); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_createAnswer, + JNIEnv* jni, + jobject j_pc, + jobject j_observer, + jobject j_constraints) { + std::unique_ptr constraints = + JavaToNativeMediaConstraints(jni, j_constraints); + rtc::scoped_refptr observer( + new rtc::RefCountedObject(jni, j_observer, + std::move(constraints))); + ExtractNativePC(jni, j_pc)->CreateAnswer(observer, observer->constraints()); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_setLocalDescription, + JNIEnv* jni, + jobject j_pc, + jobject j_observer, + jobject j_sdp) { + rtc::scoped_refptr observer( + new rtc::RefCountedObject(jni, j_observer, nullptr)); + ExtractNativePC(jni, j_pc)->SetLocalDescription( + observer, JavaToNativeSessionDescription(jni, j_sdp).release()); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_setRemoteDescription, + JNIEnv* jni, + jobject j_pc, + jobject j_observer, + jobject j_sdp) { + rtc::scoped_refptr observer( + new rtc::RefCountedObject(jni, j_observer, nullptr)); + ExtractNativePC(jni, j_pc)->SetRemoteDescription( + observer, JavaToNativeSessionDescription(jni, j_sdp).release()); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_setAudioPlayout, + JNIEnv* jni, + jobject j_pc, + jboolean playout) { + ExtractNativePC(jni, j_pc)->SetAudioPlayout(playout); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_setAudioRecording, + JNIEnv* jni, + jobject j_pc, + jboolean recording) { + ExtractNativePC(jni, j_pc)->SetAudioRecording(recording); +} + +JNI_FUNCTION_DECLARATION(jboolean, + PeerConnection_setNativeConfiguration, + JNIEnv* jni, + jobject j_pc, + jobject j_rtc_config, + jlong native_observer) { + // Need to merge constraints into RTCConfiguration again, which are stored + // in the observer object. + PeerConnectionObserverJni* observer = + reinterpret_cast(native_observer); + PeerConnectionInterface::RTCConfiguration rtc_config( + PeerConnectionInterface::RTCConfigurationType::kAggressive); + JavaToNativeRTCConfiguration(jni, j_rtc_config, &rtc_config); + CopyConstraintsIntoRtcConfiguration(observer->constraints(), &rtc_config); + return ExtractNativePC(jni, j_pc)->SetConfiguration(rtc_config); +} + +JNI_FUNCTION_DECLARATION(jboolean, + PeerConnection_addNativeIceCandidate, + JNIEnv* jni, + jobject j_pc, + jstring j_sdp_mid, + jint j_sdp_mline_index, + jstring j_candidate_sdp) { + std::string sdp_mid = JavaToStdString(jni, j_sdp_mid); + std::string sdp = JavaToStdString(jni, j_candidate_sdp); + std::unique_ptr candidate( + CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, nullptr)); + return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get()); +} + +JNI_FUNCTION_DECLARATION(jboolean, + PeerConnection_removeNativeIceCandidates, + JNIEnv* jni, + jobject j_pc, + jobjectArray j_candidates) { + std::vector candidates = + JavaToNativeVector(jni, j_candidates, + &JavaToNativeCandidate); + return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates); +} + +JNI_FUNCTION_DECLARATION(jboolean, + PeerConnection_addNativeLocalStream, + JNIEnv* jni, + jobject j_pc, + jlong native_stream) { + return ExtractNativePC(jni, j_pc)->AddStream( + reinterpret_cast(native_stream)); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_removeNativeLocalStream, + JNIEnv* jni, + jobject j_pc, + jlong native_stream) { + ExtractNativePC(jni, j_pc)->RemoveStream( + reinterpret_cast(native_stream)); +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_createNativeSender, + JNIEnv* jni, + jobject j_pc, + jstring j_kind, + jstring j_stream_id) { + std::string kind = JavaToStdString(jni, j_kind); + std::string stream_id = JavaToStdString(jni, j_stream_id); + rtc::scoped_refptr sender = + ExtractNativePC(jni, j_pc)->CreateSender(kind, stream_id); + return NativeToJavaRtpSender(jni, sender); +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_getNativeSenders, + JNIEnv* jni, + jobject j_pc) { + return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetSenders(), + &NativeToJavaRtpSender); +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_getNativeReceivers, + JNIEnv* jni, + jobject j_pc) { + return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetReceivers(), + &NativeToJavaRtpReceiver); +} + +JNI_FUNCTION_DECLARATION(bool, + PeerConnection_oldGetNativeStats, + JNIEnv* jni, + jobject j_pc, + jobject j_observer, + jlong native_track) { + rtc::scoped_refptr observer( + new rtc::RefCountedObject(jni, j_observer)); + return ExtractNativePC(jni, j_pc)->GetStats( + observer, reinterpret_cast(native_track), + PeerConnectionInterface::kStatsOutputLevelStandard); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_newGetNativeStats, + JNIEnv* jni, + jobject j_pc, + jobject j_callback) { + rtc::scoped_refptr callback( + new rtc::RefCountedObject(jni, + j_callback)); + ExtractNativePC(jni, j_pc)->GetStats(callback); +} + +JNI_FUNCTION_DECLARATION(jboolean, + PeerConnection_setBitrate, + JNIEnv* jni, + jobject j_pc, + jobject j_min, + jobject j_current, + jobject j_max) { + PeerConnectionInterface::BitrateParameters params; + params.min_bitrate_bps = JavaToNativeOptionalInt(jni, j_min); + params.current_bitrate_bps = JavaToNativeOptionalInt(jni, j_current); + params.max_bitrate_bps = JavaToNativeOptionalInt(jni, j_max); + return ExtractNativePC(jni, j_pc)->SetBitrate(params).ok(); +} + +JNI_FUNCTION_DECLARATION(bool, + PeerConnection_startNativeRtcEventLog, + JNIEnv* jni, + jobject j_pc, + int file_descriptor, + int max_size_bytes) { + return ExtractNativePC(jni, j_pc)->StartRtcEventLog(file_descriptor, + max_size_bytes); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_stopNativeRtcEventLog, + JNIEnv* jni, + jobject j_pc) { + ExtractNativePC(jni, j_pc)->StopRtcEventLog(); +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_signalingState, + JNIEnv* jni, + jobject j_pc) { + PeerConnectionInterface::SignalingState state = + ExtractNativePC(jni, j_pc)->signaling_state(); + return JavaEnumFromIndexAndClassName(jni, "PeerConnection$SignalingState", + state); +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_iceConnectionState, + JNIEnv* jni, + jobject j_pc) { + PeerConnectionInterface::IceConnectionState state = + ExtractNativePC(jni, j_pc)->ice_connection_state(); + return JavaEnumFromIndexAndClassName(jni, "PeerConnection$IceConnectionState", + state); +} + +JNI_FUNCTION_DECLARATION(jobject, + PeerConnection_iceGatheringState, + JNIEnv* jni, + jobject j_pc) { + PeerConnectionInterface::IceGatheringState state = + ExtractNativePC(jni, j_pc)->ice_gathering_state(); + return JavaEnumFromIndexAndClassName(jni, "PeerConnection$IceGatheringState", + state); +} + +JNI_FUNCTION_DECLARATION(void, + PeerConnection_close, + JNIEnv* jni, + jobject j_pc) { + ExtractNativePC(jni, j_pc)->Close(); + return; +} + +} // namespace jni +} // namespace webrtc diff --git a/sdk/android/src/jni/pc/peerconnectionobserver_jni.h b/sdk/android/src/jni/pc/peerconnection.h similarity index 91% rename from sdk/android/src/jni/pc/peerconnectionobserver_jni.h rename to sdk/android/src/jni/pc/peerconnection.h index 46e68cb5ce..9349f878ed 100644 --- a/sdk/android/src/jni/pc/peerconnectionobserver_jni.h +++ b/sdk/android/src/jni/pc/peerconnection.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef SDK_ANDROID_SRC_JNI_PC_PEERCONNECTIONOBSERVER_JNI_H_ -#define SDK_ANDROID_SRC_JNI_PC_PEERCONNECTIONOBSERVER_JNI_H_ +#ifndef SDK_ANDROID_SRC_JNI_PC_PEERCONNECTION_H_ +#define SDK_ANDROID_SRC_JNI_PC_PEERCONNECTION_H_ #include #include @@ -24,6 +24,15 @@ namespace webrtc { namespace jni { +void JavaToNativeIceServers(JNIEnv* jni, + jobject j_ice_servers, + PeerConnectionInterface::IceServers* ice_servers); + +void JavaToNativeRTCConfiguration( + JNIEnv* jni, + jobject j_rtc_config, + PeerConnectionInterface::RTCConfiguration* rtc_config); + // Adapter between the C++ PeerConnectionObserver interface and the Java // PeerConnection.Observer interface. Wraps an instance of the Java interface // and dispatches C++ callbacks to Java. @@ -111,4 +120,4 @@ class PeerConnectionObserverJni : public PeerConnectionObserver, } // namespace jni } // namespace webrtc -#endif // SDK_ANDROID_SRC_JNI_PC_PEERCONNECTIONOBSERVER_JNI_H_ +#endif // SDK_ANDROID_SRC_JNI_PC_PEERCONNECTION_H_ diff --git a/sdk/android/src/jni/pc/peerconnection_jni.cc b/sdk/android/src/jni/pc/peerconnection_jni.cc deleted file mode 100644 index 3867ec91d9..0000000000 --- a/sdk/android/src/jni/pc/peerconnection_jni.cc +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Lifecycle notes: objects are owned where they will be called; in other words -// FooObservers are owned by C++-land, and user-callable objects (e.g. -// PeerConnection and VideoTrack) are owned by Java-land. -// When this file (or other files in this directory) allocates C++ -// RefCountInterfaces it AddRef()s an artificial ref simulating the jlong held -// in Java-land, and then Release()s the ref in the respective free call. -// Sometimes this AddRef is implicit in the construction of a scoped_refptr<> -// which is then .release()d. Any persistent (non-local) references from C++ to -// Java must be global or weak (in which case they must be checked before use)! -// -// Exception notes: pretty much all JNI calls can throw Java exceptions, so each -// call through a JNIEnv* pointer needs to be followed by an ExceptionCheck() -// call. In this file this is done in CHECK_EXCEPTION, making for much easier -// debugging in case of failure (the alternative is to wait for control to -// return to the Java frame that called code in this file, at which point it's -// impossible to tell which JNI call broke). - -#include -#include -#include - -#include "api/mediaconstraintsinterface.h" -#include "api/peerconnectioninterface.h" -#include "api/rtpreceiverinterface.h" -#include "api/rtpsenderinterface.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "sdk/android/generated_peerconnection_jni/jni/RtpSender_jni.h" -#include "sdk/android/src/jni/classreferenceholder.h" -#include "sdk/android/src/jni/jni_helpers.h" -#include "sdk/android/src/jni/pc/datachannel.h" -#include "sdk/android/src/jni/pc/java_native_conversion.h" -#include "sdk/android/src/jni/pc/mediaconstraints_jni.h" -#include "sdk/android/src/jni/pc/peerconnectionobserver_jni.h" -#include "sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h" -#include "sdk/android/src/jni/pc/sdpobserver_jni.h" -#include "sdk/android/src/jni/pc/statsobserver_jni.h" - -namespace webrtc { -namespace jni { - -namespace { - -rtc::scoped_refptr ExtractNativePC(JNIEnv* jni, - jobject j_pc) { - jfieldID native_pc_id = - GetFieldID(jni, GetObjectClass(jni, j_pc), "nativePeerConnection", "J"); - jlong j_p = GetLongField(jni, j_pc, native_pc_id); - return rtc::scoped_refptr( - reinterpret_cast(j_p)); -} - -jobject NativeToJavaRtpSender(JNIEnv* env, - rtc::scoped_refptr sender) { - if (!sender) - return nullptr; - // Sender is now owned by the Java object, and will be freed from - // RtpSender.dispose(), called by PeerConnection.dispose() or getSenders(). - return Java_RtpSender_Constructor(env, jlongFromPointer(sender.release())); -} - -} // namespace - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_freeObserver, - JNIEnv*, - jclass, - jlong j_p) { - PeerConnectionObserverJni* p = - reinterpret_cast(j_p); - delete p; -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_getLocalDescription, - JNIEnv* jni, - jobject j_pc) { - const SessionDescriptionInterface* sdp = - ExtractNativePC(jni, j_pc)->local_description(); - return sdp ? NativeToJavaSessionDescription(jni, sdp) : NULL; -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_getRemoteDescription, - JNIEnv* jni, - jobject j_pc) { - const SessionDescriptionInterface* sdp = - ExtractNativePC(jni, j_pc)->remote_description(); - return sdp ? NativeToJavaSessionDescription(jni, sdp) : NULL; -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_createDataChannel, - JNIEnv* jni, - jobject j_pc, - jstring j_label, - jobject j_init) { - DataChannelInit init = JavaToNativeDataChannelInit(jni, j_init); - rtc::scoped_refptr channel( - ExtractNativePC(jni, j_pc)->CreateDataChannel( - JavaToStdString(jni, j_label), &init)); - return WrapNativeDataChannel(jni, channel); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_createOffer, - JNIEnv* jni, - jobject j_pc, - jobject j_observer, - jobject j_constraints) { - std::unique_ptr constraints = - JavaToNativeMediaConstraints(jni, j_constraints); - rtc::scoped_refptr observer( - new rtc::RefCountedObject(jni, j_observer, - std::move(constraints))); - ExtractNativePC(jni, j_pc)->CreateOffer(observer, observer->constraints()); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_createAnswer, - JNIEnv* jni, - jobject j_pc, - jobject j_observer, - jobject j_constraints) { - std::unique_ptr constraints = - JavaToNativeMediaConstraints(jni, j_constraints); - rtc::scoped_refptr observer( - new rtc::RefCountedObject(jni, j_observer, - std::move(constraints))); - ExtractNativePC(jni, j_pc)->CreateAnswer(observer, observer->constraints()); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_setLocalDescription, - JNIEnv* jni, - jobject j_pc, - jobject j_observer, - jobject j_sdp) { - rtc::scoped_refptr observer( - new rtc::RefCountedObject(jni, j_observer, nullptr)); - ExtractNativePC(jni, j_pc)->SetLocalDescription( - observer, JavaToNativeSessionDescription(jni, j_sdp).release()); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_setRemoteDescription, - JNIEnv* jni, - jobject j_pc, - jobject j_observer, - jobject j_sdp) { - rtc::scoped_refptr observer( - new rtc::RefCountedObject(jni, j_observer, nullptr)); - ExtractNativePC(jni, j_pc)->SetRemoteDescription( - observer, JavaToNativeSessionDescription(jni, j_sdp).release()); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_setAudioPlayout, - JNIEnv* jni, - jobject j_pc, - jboolean playout) { - ExtractNativePC(jni, j_pc)->SetAudioPlayout(playout); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_setAudioRecording, - JNIEnv* jni, - jobject j_pc, - jboolean recording) { - ExtractNativePC(jni, j_pc)->SetAudioRecording(recording); -} - -JNI_FUNCTION_DECLARATION(jboolean, - PeerConnection_setNativeConfiguration, - JNIEnv* jni, - jobject j_pc, - jobject j_rtc_config, - jlong native_observer) { - // Need to merge constraints into RTCConfiguration again, which are stored - // in the observer object. - PeerConnectionObserverJni* observer = - reinterpret_cast(native_observer); - PeerConnectionInterface::RTCConfiguration rtc_config( - PeerConnectionInterface::RTCConfigurationType::kAggressive); - JavaToNativeRTCConfiguration(jni, j_rtc_config, &rtc_config); - CopyConstraintsIntoRtcConfiguration(observer->constraints(), &rtc_config); - return ExtractNativePC(jni, j_pc)->SetConfiguration(rtc_config); -} - -JNI_FUNCTION_DECLARATION(jboolean, - PeerConnection_addNativeIceCandidate, - JNIEnv* jni, - jobject j_pc, - jstring j_sdp_mid, - jint j_sdp_mline_index, - jstring j_candidate_sdp) { - std::string sdp_mid = JavaToStdString(jni, j_sdp_mid); - std::string sdp = JavaToStdString(jni, j_candidate_sdp); - std::unique_ptr candidate( - CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, nullptr)); - return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get()); -} - -JNI_FUNCTION_DECLARATION(jboolean, - PeerConnection_removeNativeIceCandidates, - JNIEnv* jni, - jobject j_pc, - jobjectArray j_candidates) { - std::vector candidates = - JavaToNativeVector(jni, j_candidates, - &JavaToNativeCandidate); - return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates); -} - -JNI_FUNCTION_DECLARATION(jboolean, - PeerConnection_addNativeLocalStream, - JNIEnv* jni, - jobject j_pc, - jlong native_stream) { - return ExtractNativePC(jni, j_pc)->AddStream( - reinterpret_cast(native_stream)); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_removeNativeLocalStream, - JNIEnv* jni, - jobject j_pc, - jlong native_stream) { - ExtractNativePC(jni, j_pc)->RemoveStream( - reinterpret_cast(native_stream)); -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_createNativeSender, - JNIEnv* jni, - jobject j_pc, - jstring j_kind, - jstring j_stream_id) { - std::string kind = JavaToStdString(jni, j_kind); - std::string stream_id = JavaToStdString(jni, j_stream_id); - rtc::scoped_refptr sender = - ExtractNativePC(jni, j_pc)->CreateSender(kind, stream_id); - return NativeToJavaRtpSender(jni, sender); -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_getNativeSenders, - JNIEnv* jni, - jobject j_pc) { - return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetSenders(), - &NativeToJavaRtpSender); -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_getNativeReceivers, - JNIEnv* jni, - jobject j_pc) { - return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetReceivers(), - &NativeToJavaRtpReceiver); -} - -JNI_FUNCTION_DECLARATION(bool, - PeerConnection_oldGetNativeStats, - JNIEnv* jni, - jobject j_pc, - jobject j_observer, - jlong native_track) { - rtc::scoped_refptr observer( - new rtc::RefCountedObject(jni, j_observer)); - return ExtractNativePC(jni, j_pc)->GetStats( - observer, reinterpret_cast(native_track), - PeerConnectionInterface::kStatsOutputLevelStandard); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_newGetNativeStats, - JNIEnv* jni, - jobject j_pc, - jobject j_callback) { - rtc::scoped_refptr callback( - new rtc::RefCountedObject(jni, - j_callback)); - ExtractNativePC(jni, j_pc)->GetStats(callback); -} - -JNI_FUNCTION_DECLARATION(jboolean, - PeerConnection_setBitrate, - JNIEnv* jni, - jobject j_pc, - jobject j_min, - jobject j_current, - jobject j_max) { - PeerConnectionInterface::BitrateParameters params; - params.min_bitrate_bps = JavaToNativeOptionalInt(jni, j_min); - params.current_bitrate_bps = JavaToNativeOptionalInt(jni, j_current); - params.max_bitrate_bps = JavaToNativeOptionalInt(jni, j_max); - return ExtractNativePC(jni, j_pc)->SetBitrate(params).ok(); -} - -JNI_FUNCTION_DECLARATION(bool, - PeerConnection_startNativeRtcEventLog, - JNIEnv* jni, - jobject j_pc, - int file_descriptor, - int max_size_bytes) { - return ExtractNativePC(jni, j_pc)->StartRtcEventLog(file_descriptor, - max_size_bytes); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_stopNativeRtcEventLog, - JNIEnv* jni, - jobject j_pc) { - ExtractNativePC(jni, j_pc)->StopRtcEventLog(); -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_signalingState, - JNIEnv* jni, - jobject j_pc) { - PeerConnectionInterface::SignalingState state = - ExtractNativePC(jni, j_pc)->signaling_state(); - return JavaEnumFromIndexAndClassName(jni, "PeerConnection$SignalingState", - state); -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_iceConnectionState, - JNIEnv* jni, - jobject j_pc) { - PeerConnectionInterface::IceConnectionState state = - ExtractNativePC(jni, j_pc)->ice_connection_state(); - return JavaEnumFromIndexAndClassName(jni, "PeerConnection$IceConnectionState", - state); -} - -JNI_FUNCTION_DECLARATION(jobject, - PeerConnection_iceGatheringState, - JNIEnv* jni, - jobject j_pc) { - PeerConnectionInterface::IceGatheringState state = - ExtractNativePC(jni, j_pc)->ice_gathering_state(); - return JavaEnumFromIndexAndClassName(jni, "PeerConnection$IceGatheringState", - state); -} - -JNI_FUNCTION_DECLARATION(void, - PeerConnection_close, - JNIEnv* jni, - jobject j_pc) { - ExtractNativePC(jni, j_pc)->Close(); - return; -} - -} // namespace jni -} // namespace webrtc diff --git a/sdk/android/src/jni/pc/peerconnectionfactory_jni.cc b/sdk/android/src/jni/pc/peerconnectionfactory_jni.cc index fdae2f0550..714c771a19 100644 --- a/sdk/android/src/jni/pc/peerconnectionfactory_jni.cc +++ b/sdk/android/src/jni/pc/peerconnectionfactory_jni.cc @@ -29,7 +29,7 @@ #include "sdk/android/src/jni/pc/java_native_conversion.h" #include "sdk/android/src/jni/pc/media_jni.h" #include "sdk/android/src/jni/pc/ownedfactoryandthreads.h" -#include "sdk/android/src/jni/pc/peerconnectionobserver_jni.h" +#include "sdk/android/src/jni/pc/peerconnection.h" #include "sdk/android/src/jni/pc/video_jni.h" #include "system_wrappers/include/field_trial.h" // Adding 'nogncheck' to disable the gn include headers check. diff --git a/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc b/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc deleted file mode 100644 index db5b3ddb52..0000000000 --- a/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "sdk/android/src/jni/pc/peerconnectionobserver_jni.h" - -#include -#include - -#include "rtc_base/ptr_util.h" -#include "sdk/android/generated_peerconnection_jni/jni/MediaStream_jni.h" -#include "sdk/android/generated_peerconnection_jni/jni/PeerConnection_jni.h" -#include "sdk/android/src/jni/classreferenceholder.h" -#include "sdk/android/src/jni/jni_helpers.h" -#include "sdk/android/src/jni/pc/datachannel.h" -#include "sdk/android/src/jni/pc/java_native_conversion.h" - -namespace webrtc { -namespace jni { - -// Convenience, used since callbacks occur on the signaling thread, which may -// be a non-Java thread. -static JNIEnv* jni() { - return AttachCurrentThreadIfNeeded(); -} - -PeerConnectionObserverJni::PeerConnectionObserverJni(JNIEnv* jni, - jobject j_observer) - : j_observer_global_(jni, j_observer) {} - -PeerConnectionObserverJni::~PeerConnectionObserverJni() { - ScopedLocalRefFrame local_ref_frame(jni()); - while (!remote_streams_.empty()) - DisposeRemoteStream(remote_streams_.begin()); -} - -void PeerConnectionObserverJni::OnIceCandidate( - const IceCandidateInterface* candidate) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onIceCandidate(env, *j_observer_global_, - NativeToJavaIceCandidate(env, *candidate)); -} - -void PeerConnectionObserverJni::OnIceCandidatesRemoved( - const std::vector& candidates) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onIceCandidatesRemoved( - env, *j_observer_global_, NativeToJavaCandidateArray(env, candidates)); -} - -void PeerConnectionObserverJni::OnSignalingChange( - PeerConnectionInterface::SignalingState new_state) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onSignalingChange( - env, *j_observer_global_, - Java_SignalingState_fromNativeIndex(env, new_state)); -} - -void PeerConnectionObserverJni::OnIceConnectionChange( - PeerConnectionInterface::IceConnectionState new_state) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onIceConnectionChange( - env, *j_observer_global_, - Java_IceConnectionState_fromNativeIndex(env, new_state)); -} - -void PeerConnectionObserverJni::OnIceConnectionReceivingChange(bool receiving) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onIceConnectionReceivingChange(env, *j_observer_global_, - receiving); -} - -void PeerConnectionObserverJni::OnIceGatheringChange( - PeerConnectionInterface::IceGatheringState new_state) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onIceGatheringChange( - env, *j_observer_global_, - Java_IceGatheringState_fromNativeIndex(env, new_state)); -} - -void PeerConnectionObserverJni::OnAddStream( - rtc::scoped_refptr stream) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - // The stream could be added into the remote_streams_ map when calling - // OnAddTrack. - jobject j_stream = GetOrCreateJavaStream(stream); - - for (const auto& track : stream->GetAudioTracks()) { - AddNativeAudioTrackToJavaStream(track, j_stream); - } - for (const auto& track : stream->GetVideoTracks()) { - AddNativeVideoTrackToJavaStream(track, j_stream); - } - - Java_Observer_onAddStream(env, *j_observer_global_, j_stream); - - // Create an observer to update the Java stream when the native stream's set - // of tracks changes. - auto observer = rtc::MakeUnique(stream); - observer->SignalAudioTrackRemoved.connect( - this, &PeerConnectionObserverJni::OnAudioTrackRemovedFromStream); - observer->SignalVideoTrackRemoved.connect( - this, &PeerConnectionObserverJni::OnVideoTrackRemovedFromStream); - observer->SignalAudioTrackAdded.connect( - this, &PeerConnectionObserverJni::OnAudioTrackAddedToStream); - observer->SignalVideoTrackAdded.connect( - this, &PeerConnectionObserverJni::OnVideoTrackAddedToStream); - stream_observers_.push_back(std::move(observer)); -} - -void PeerConnectionObserverJni::AddNativeAudioTrackToJavaStream( - rtc::scoped_refptr track, - jobject j_stream) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - Java_MediaStream_addNativeAudioTrack(env, j_stream, - jlongFromPointer(track.release())); -} - -void PeerConnectionObserverJni::AddNativeVideoTrackToJavaStream( - rtc::scoped_refptr track, - jobject j_stream) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - Java_MediaStream_addNativeVideoTrack(env, j_stream, - jlongFromPointer(track.release())); -} - -void PeerConnectionObserverJni::OnAudioTrackAddedToStream( - AudioTrackInterface* track, - MediaStreamInterface* stream) { - ScopedLocalRefFrame local_ref_frame(jni()); - jobject j_stream = GetOrCreateJavaStream(stream); - AddNativeAudioTrackToJavaStream(track, j_stream); -} - -void PeerConnectionObserverJni::OnVideoTrackAddedToStream( - VideoTrackInterface* track, - MediaStreamInterface* stream) { - ScopedLocalRefFrame local_ref_frame(jni()); - jobject j_stream = GetOrCreateJavaStream(stream); - AddNativeVideoTrackToJavaStream(track, j_stream); -} - -void PeerConnectionObserverJni::OnAudioTrackRemovedFromStream( - AudioTrackInterface* track, - MediaStreamInterface* stream) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - jobject j_stream = GetOrCreateJavaStream(stream); - Java_MediaStream_removeAudioTrack(env, j_stream, jlongFromPointer(track)); -} - -void PeerConnectionObserverJni::OnVideoTrackRemovedFromStream( - VideoTrackInterface* track, - MediaStreamInterface* stream) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - jobject j_stream = GetOrCreateJavaStream(stream); - Java_MediaStream_removeVideoTrack(env, j_stream, jlongFromPointer(track)); -} - -void PeerConnectionObserverJni::OnRemoveStream( - rtc::scoped_refptr stream) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream); - RTC_CHECK(it != remote_streams_.end()) - << "unexpected stream: " << std::hex << stream; - Java_Observer_onRemoveStream(env, *j_observer_global_, it->second); - - // Release the refptr reference so that DisposeRemoteStream can assert - // it removes the final reference. - stream = nullptr; - DisposeRemoteStream(it); -} - -void PeerConnectionObserverJni::OnDataChannel( - rtc::scoped_refptr channel) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onDataChannel(env, *j_observer_global_, - WrapNativeDataChannel(env, channel)); -} - -void PeerConnectionObserverJni::OnRenegotiationNeeded() { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - Java_Observer_onRenegotiationNeeded(env, *j_observer_global_); -} - -void PeerConnectionObserverJni::OnAddTrack( - rtc::scoped_refptr receiver, - const std::vector>& streams) { - JNIEnv* env = AttachCurrentThreadIfNeeded(); - ScopedLocalRefFrame local_ref_frame(env); - jobject j_rtp_receiver = NativeToJavaRtpReceiver(env, receiver); - rtp_receivers_.emplace_back(env, j_rtp_receiver); - - Java_Observer_onAddTrack(env, *j_observer_global_, j_rtp_receiver, - NativeToJavaMediaStreamArray(env, streams)); -} - -void PeerConnectionObserverJni::SetConstraints( - std::unique_ptr constraints) { - RTC_CHECK(!constraints_.get()) << "constraints already set!"; - constraints_ = std::move(constraints); -} - -void PeerConnectionObserverJni::DisposeRemoteStream( - const NativeToJavaStreamsMap::iterator& it) { - MediaStreamInterface* stream = it->first; - jobject j_stream = it->second; - - // Remove the observer first, so it doesn't react to events during deletion. - stream_observers_.erase( - std::remove_if( - stream_observers_.begin(), stream_observers_.end(), - [stream](const std::unique_ptr& observer) { - return observer->stream() == stream; - }), - stream_observers_.end()); - - remote_streams_.erase(it); - JNIEnv* env = AttachCurrentThreadIfNeeded(); - Java_MediaStream_dispose(env, j_stream); - DeleteGlobalRef(env, j_stream); -} - -// If the NativeToJavaStreamsMap contains the stream, return it. -// Otherwise, create a new Java MediaStream. -jobject PeerConnectionObserverJni::GetOrCreateJavaStream( - const rtc::scoped_refptr& stream) { - NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream); - 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(); - jobject j_stream = - Java_MediaStream_Constructor(jni(), jlongFromPointer(stream.get())); - - remote_streams_[stream] = NewGlobalRef(jni(), j_stream); - return j_stream; -} - -jobjectArray PeerConnectionObserverJni::NativeToJavaMediaStreamArray( - JNIEnv* jni, - const std::vector>& streams) { - jobjectArray java_streams = jni->NewObjectArray( - streams.size(), org_webrtc_MediaStream_clazz(jni), nullptr); - CHECK_EXCEPTION(jni) << "error during NewObjectArray"; - for (size_t i = 0; i < streams.size(); ++i) { - jobject j_stream = GetOrCreateJavaStream(streams[i]); - jni->SetObjectArrayElement(java_streams, i, j_stream); - } - return java_streams; -} - -} // namespace jni -} // namespace webrtc