diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index d12e8c10b0..6b099c413a 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -46,9 +46,14 @@ generate_jar_jni("generated_external_classes_jni") { "java/lang/Integer.class", "java/lang/Double.class", "java/lang/Long.class", + "java/lang/Iterable.class", + "java/util/Iterator.class", "java/lang/Boolean.class", "java/math/BigInteger.class", - "java/lang/String.class", + "java/util/Map.class", + "java/util/LinkedHashMap.class", + "java/util/ArrayList.class", + "java/lang/Enum.class", ] jni_package = "" jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h" @@ -123,6 +128,7 @@ generate_jni("generated_video_jni") { "api/org/webrtc/VideoCodecStatus.java", "api/org/webrtc/VideoDecoder.java", "api/org/webrtc/VideoEncoder.java", + "api/org/webrtc/VideoEncoderFactory.java", "api/org/webrtc/VideoFrame.java", "api/org/webrtc/VideoSink.java", "src/java/org/webrtc/VideoDecoderWrapper.java", @@ -295,6 +301,7 @@ generate_jni("generated_peerconnection_jni") { "api/org/webrtc/RTCStatsCollectorCallback.java", "api/org/webrtc/RTCStatsReport.java", "api/org/webrtc/RtpReceiver.java", + "api/org/webrtc/RtpSender.java", "api/org/webrtc/StatsObserver.java", "api/org/webrtc/StatsReport.java", ] diff --git a/sdk/android/api/org/webrtc/RtpSender.java b/sdk/android/api/org/webrtc/RtpSender.java index fbb62db853..8100ff7785 100644 --- a/sdk/android/api/org/webrtc/RtpSender.java +++ b/sdk/android/api/org/webrtc/RtpSender.java @@ -19,13 +19,14 @@ public class RtpSender { private final DtmfSender dtmfSender; + @CalledByNative public RtpSender(long nativeRtpSender) { this.nativeRtpSender = nativeRtpSender; - long track = nativeGetTrack(nativeRtpSender); + long track = getNativeTrack(nativeRtpSender); // It may be possible for an RtpSender to be created without a track. cachedTrack = (track != 0) ? new MediaStreamTrack(track) : null; - long nativeDtmfSender = nativeGetDtmfSender(nativeRtpSender); + long nativeDtmfSender = getNativeDtmfSender(nativeRtpSender); dtmfSender = (nativeDtmfSender != 0) ? new DtmfSender(nativeDtmfSender) : null; } @@ -44,7 +45,7 @@ public class RtpSender { * @return true on success and false on failure. */ public boolean setTrack(MediaStreamTrack track, boolean takeOwnership) { - if (!nativeSetTrack(nativeRtpSender, (track == null) ? 0 : track.nativeTrack)) { + if (!setNativeTrack(nativeRtpSender, (track == null) ? 0 : track.nativeTrack)) { return false; } if (cachedTrack != null && ownsTrack) { @@ -60,15 +61,15 @@ public class RtpSender { } public boolean setParameters(RtpParameters parameters) { - return nativeSetParameters(nativeRtpSender, parameters); + return setNativeParameters(nativeRtpSender, parameters); } public RtpParameters getParameters() { - return nativeGetParameters(nativeRtpSender); + return getNativeParameters(nativeRtpSender); } public String id() { - return nativeId(nativeRtpSender); + return getNativeId(nativeRtpSender); } public DtmfSender dtmf() { @@ -85,19 +86,19 @@ public class RtpSender { JniCommon.nativeReleaseRef(nativeRtpSender); } - private static native boolean nativeSetTrack(long nativeRtpSender, long nativeTrack); + private static native boolean setNativeTrack(long nativeRtpSender, long nativeTrack); // This should increment the reference count of the track. // Will be released in dispose() or setTrack(). - private static native long nativeGetTrack(long nativeRtpSender); + private static native long getNativeTrack(long nativeRtpSender); // This should increment the reference count of the DTMF sender. // Will be released in dispose(). - private static native long nativeGetDtmfSender(long nativeRtpSender); + private static native long getNativeDtmfSender(long nativeRtpSender); - private static native boolean nativeSetParameters(long nativeRtpSender, RtpParameters parameters); + private static native boolean setNativeParameters(long nativeRtpSender, RtpParameters parameters); - private static native RtpParameters nativeGetParameters(long nativeRtpSender); + private static native RtpParameters getNativeParameters(long nativeRtpSender); - private static native String nativeId(long nativeRtpSender); + private static native String getNativeId(long nativeRtpSender); }; diff --git a/sdk/android/api/org/webrtc/VideoEncoderFactory.java b/sdk/android/api/org/webrtc/VideoEncoderFactory.java index 4445524a99..5fe7af5b34 100644 --- a/sdk/android/api/org/webrtc/VideoEncoderFactory.java +++ b/sdk/android/api/org/webrtc/VideoEncoderFactory.java @@ -13,11 +13,11 @@ package org.webrtc; /** Factory for creating VideoEncoders. */ public interface VideoEncoderFactory { /** Creates an encoder for the given video codec. */ - public VideoEncoder createEncoder(VideoCodecInfo info); + @CalledByNative VideoEncoder createEncoder(VideoCodecInfo info); /** * Enumerates the list of supported video codecs. This method will only be called once and the * result will be cached. */ - public VideoCodecInfo[] getSupportedCodecs(); + @CalledByNative VideoCodecInfo[] getSupportedCodecs(); } diff --git a/sdk/android/src/jni/jni_helpers.cc b/sdk/android/src/jni/jni_helpers.cc index 694ebead2c..4ad7c4f946 100644 --- a/sdk/android/src/jni/jni_helpers.cc +++ b/sdk/android/src/jni/jni_helpers.cc @@ -15,10 +15,16 @@ #include #include +#include "sdk/android/generated_external_classes_jni/jni/ArrayList_jni.h" #include "sdk/android/generated_external_classes_jni/jni/Boolean_jni.h" #include "sdk/android/generated_external_classes_jni/jni/Double_jni.h" +#include "sdk/android/generated_external_classes_jni/jni/Enum_jni.h" #include "sdk/android/generated_external_classes_jni/jni/Integer_jni.h" +#include "sdk/android/generated_external_classes_jni/jni/Iterable_jni.h" +#include "sdk/android/generated_external_classes_jni/jni/Iterator_jni.h" +#include "sdk/android/generated_external_classes_jni/jni/LinkedHashMap_jni.h" #include "sdk/android/generated_external_classes_jni/jni/Long_jni.h" +#include "sdk/android/generated_external_classes_jni/jni/Map_jni.h" #include "sdk/android/src/jni/class_loader.h" #include "sdk/android/src/jni/classreferenceholder.h" @@ -243,10 +249,9 @@ std::string JavaToStdString(JNIEnv* jni, const jstring& j_string) { const jclass string_class = GetObjectClass(jni, j_string); const jmethodID get_bytes = GetMethodID(jni, string_class, "getBytes", "(Ljava/lang/String;)[B"); - const jstring charset_name = jni->NewStringUTF("ISO-8859-1"); - CHECK_EXCEPTION(jni) << "error during NewStringUTF"; - const jbyteArray j_byte_array = - (jbyteArray)jni->CallObjectMethod(j_string, get_bytes, charset_name); + const jbyteArray j_byte_array = (jbyteArray)jni->CallObjectMethod( + j_string, get_bytes, NativeToJavaString(jni, "ISO-8859-1")); + CHECK_EXCEPTION(jni) << "error during CallObjectMethod"; const size_t len = jni->GetArrayLength(j_byte_array); @@ -305,8 +310,10 @@ jobject NativeToJavaInteger(JNIEnv* jni, } // Return the (singleton) Java Enum object corresponding to |index|; -jobject JavaEnumFromIndex(JNIEnv* jni, jclass state_class, - const std::string& state_class_name, int index) { +static jobject JavaEnumFromIndex(JNIEnv* jni, + jclass state_class, + const std::string& state_class_name, + int index) { jmethodID state_values_id = GetStaticMethodID( jni, state_class, "values", ("()[L" + state_class_name + ";").c_str()); jobjectArray state_values = static_cast( @@ -326,45 +333,26 @@ jobject JavaEnumFromIndexAndClassName(JNIEnv* jni, } std::string GetJavaEnumName(JNIEnv* jni, jobject j_enum) { - jclass enum_class = GetClass(jni, "java/lang/Enum"); - jmethodID nameMethod = - GetMethodID(jni, enum_class, "name", "()Ljava/lang/String;"); - jstring name = - reinterpret_cast(jni->CallObjectMethod(j_enum, nameMethod)); - CHECK_EXCEPTION(jni); - return JavaToStdString(jni, name); + return JavaToStdString(jni, JNI_Enum::Java_Enum_name(jni, j_enum)); } std::map JavaToStdMapStrings(JNIEnv* jni, jobject j_map) { - jclass map_class = jni->FindClass("java/util/Map"); - jclass set_class = jni->FindClass("java/util/Set"); - jclass iterator_class = jni->FindClass("java/util/Iterator"); + jobject j_entry_set = JNI_Map::Java_Map_entrySet(jni, j_map); jclass entry_class = jni->FindClass("java/util/Map$Entry"); - jmethodID entry_set_method = - jni->GetMethodID(map_class, "entrySet", "()Ljava/util/Set;"); - jmethodID iterator_method = - jni->GetMethodID(set_class, "iterator", "()Ljava/util/Iterator;"); - jmethodID has_next_method = - jni->GetMethodID(iterator_class, "hasNext", "()Z"); - jmethodID next_method = - jni->GetMethodID(iterator_class, "next", "()Ljava/lang/Object;"); jmethodID get_key_method = jni->GetMethodID(entry_class, "getKey", "()Ljava/lang/Object;"); jmethodID get_value_method = jni->GetMethodID(entry_class, "getValue", "()Ljava/lang/Object;"); - jobject j_entry_set = jni->CallObjectMethod(j_map, entry_set_method); - jobject j_iterator = jni->CallObjectMethod(j_entry_set, iterator_method); - std::map result; - while (jni->CallBooleanMethod(j_iterator, has_next_method)) { - jobject j_entry = jni->CallObjectMethod(j_iterator, next_method); + for (jobject j_entry : Iterable(jni, j_entry_set)) { jstring j_key = static_cast(jni->CallObjectMethod(j_entry, get_key_method)); jstring j_value = static_cast(jni->CallObjectMethod(j_entry, get_value_method)); - result[JavaToStdString(jni, j_key)] = JavaToStdString(jni, j_value); + result.insert(std::make_pair(JavaToStdString(jni, j_key), + JavaToStdString(jni, j_value))); } return result; @@ -397,18 +385,8 @@ Iterable::Iterator::Iterator() : iterator_(nullptr) {} // Creates an iterator pointing to the beginning of the specified collection. Iterable::Iterator::Iterator(JNIEnv* jni, jobject iterable) : jni_(jni) { - jclass j_class = GetObjectClass(jni, iterable); - jmethodID iterator_id = - GetMethodID(jni, j_class, "iterator", "()Ljava/util/Iterator;"); - iterator_ = jni->CallObjectMethod(iterable, iterator_id); - CHECK_EXCEPTION(jni) << "error during CallObjectMethod"; - RTC_CHECK(iterator_ != nullptr); - - jclass iterator_class = GetObjectClass(jni, iterator_); - has_next_id_ = GetMethodID(jni, iterator_class, "hasNext", "()Z"); - next_id_ = GetMethodID(jni, iterator_class, "next", "()Ljava/lang/Object;"); - remove_id_ = GetMethodID(jni, iterator_class, "remove", "()V"); - + iterator_ = JNI_Iterable::Java_Iterable_iterator(jni, iterable); + RTC_CHECK(iterator_); // Start at the first element in the collection. ++(*this); } @@ -419,8 +397,6 @@ Iterable::Iterator::Iterator(Iterator&& other) : jni_(std::move(other.jni_)), iterator_(std::move(other.iterator_)), value_(std::move(other.value_)), - has_next_id_(std::move(other.has_next_id_)), - next_id_(std::move(other.next_id_)), thread_checker_(std::move(other.thread_checker_)){}; // Advances the iterator one step. @@ -430,22 +406,19 @@ Iterable::Iterator& Iterable::Iterator::operator++() { // Can't move past the end. return *this; } - bool has_next = jni_->CallBooleanMethod(iterator_, has_next_id_); - CHECK_EXCEPTION(jni_) << "error during CallBooleanMethod"; + bool has_next = JNI_Iterator::Java_Iterator_hasNext(jni_, iterator_); if (!has_next) { iterator_ = nullptr; value_ = nullptr; return *this; } - value_ = jni_->CallObjectMethod(iterator_, next_id_); - CHECK_EXCEPTION(jni_) << "error during CallObjectMethod"; + value_ = JNI_Iterator::Java_Iterator_next(jni_, iterator_); return *this; } void Iterable::Iterator::Remove() { - jni_->CallVoidMethod(iterator_, remove_id_); - CHECK_EXCEPTION(jni_) << "error during CallVoidMethod"; + JNI_Iterator::Java_Iterator_remove(jni_, iterator_); } // Provides a way to compare the iterator with itself and with the end iterator. @@ -501,5 +474,24 @@ jobjectArray NativeToJavaStringArray( env, container, FindClass(env, "java/lang/String"), &NativeToJavaString); } +JavaMapBuilder::JavaMapBuilder(JNIEnv* env) + : env_(env), + j_map_(JNI_LinkedHashMap::Java_LinkedHashMap_ConstructorJULIHM(env)) {} + +void JavaMapBuilder::put(jobject key, jobject value) { + JNI_Map::Java_Map_put(env_, j_map_, key, value); +} + +jobject JavaMapBuilder::GetJavaMap() { + return j_map_; +} + +JavaListBuilder::JavaListBuilder(JNIEnv* env) + : env_(env), j_list_(JNI_ArrayList::Java_ArrayList_ConstructorJUALI(env)) {} + +void JavaListBuilder::add(jobject element) { + JNI_ArrayList::Java_ArrayList_addZ_JUE(env_, j_list_, element); +} + } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/jni_helpers.h b/sdk/android/src/jni/jni_helpers.h index c0982df20b..20b301fba8 100644 --- a/sdk/android/src/jni/jni_helpers.h +++ b/sdk/android/src/jni/jni_helpers.h @@ -116,10 +116,6 @@ jstring NativeToJavaString(JNIEnv* jni, const std::string& native); jobject NativeToJavaInteger(JNIEnv* jni, const rtc::Optional& optional_int); -// Return the (singleton) Java Enum object corresponding to |index|; -jobject JavaEnumFromIndex(JNIEnv* jni, jclass state_class, - const std::string& state_class_name, int index); - // Return the (singleton) Java Enum object corresponding to |index|; // |state_class_fragment| is something like "MediaSource$State". jobject JavaEnumFromIndexAndClassName(JNIEnv* jni, @@ -219,9 +215,6 @@ class Iterable { JNIEnv* jni_ = nullptr; jobject iterator_ = nullptr; jobject value_ = nullptr; - jmethodID has_next_id_ = nullptr; - jmethodID next_id_ = nullptr; - jmethodID remove_id_ = nullptr; rtc::ThreadChecker thread_checker_; RTC_DISALLOW_COPY_AND_ASSIGN(Iterator); @@ -268,6 +261,66 @@ jobjectArray NativeToJavaDoubleArray(JNIEnv* env, jobjectArray NativeToJavaStringArray(JNIEnv* env, const std::vector& container); +template +std::vector JavaToNativeVector(JNIEnv* env, + jobjectArray j_container, + Convert convert) { + std::vector container; + const size_t size = env->GetArrayLength(j_container); + container.reserve(size); + for (size_t i = 0; i < size; ++i) { + container.emplace_back( + convert(env, env->GetObjectArrayElement(j_container, i))); + } + CHECK_EXCEPTION(env) << "Error during JavaToNativeVector"; + return container; +} + +// This is a helper class for NativeToJavaList(). Use that function instead of +// using this class directly. +class JavaListBuilder { + public: + explicit JavaListBuilder(JNIEnv* env); + void add(jobject element); + jobject java_list() { return j_list_; } + + private: + JNIEnv* env_; + jobject j_list_; +}; + +template +jobject NativeToJavaList(JNIEnv* env, const C& container, Convert convert) { + JavaListBuilder builder(env); + for (const auto& e : container) + builder.add(convert(env, e)); + return builder.java_list(); +} + +// This is a helper class for NativeToJavaMap(). Use that function instead of +// using this class directly. +class JavaMapBuilder { + public: + explicit JavaMapBuilder(JNIEnv* env); + void put(jobject key, jobject value); + jobject GetJavaMap(); + + private: + JNIEnv* env_; + jobject j_map_; +}; + +template +jobject NativeToJavaMap(JNIEnv* env, const C& container, Convert convert) { + JavaMapBuilder builder(env); + for (const auto& e : container) { + ScopedLocalRefFrame local_ref_frame(env); + const auto key_value_pair = convert(env, e); + builder.put(key_value_pair.first, key_value_pair.second); + } + return builder.GetJavaMap(); +} + } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/pc/androidnetworkmonitor_jni.cc b/sdk/android/src/jni/pc/androidnetworkmonitor_jni.cc index 5cac107398..8d41596872 100644 --- a/sdk/android/src/jni/pc/androidnetworkmonitor_jni.cc +++ b/sdk/android/src/jni/pc/androidnetworkmonitor_jni.cc @@ -85,11 +85,11 @@ static rtc::AdapterType AdapterTypeFromNetworkType(NetworkType network_type) { } } -static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) { +static rtc::IPAddress JavaToNativeIpAddress(JNIEnv* jni, jobject j_ip_address) { jbyteArray j_addresses = Java_IPAddress_getAddress(jni, j_ip_address); size_t address_length = jni->GetArrayLength(j_addresses); jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr); - CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava"; + CHECK_EXCEPTION(jni) << "Error during JavaToNativeIpAddress"; if (address_length == 4) { // IP4 struct in_addr ip4_addr; @@ -105,20 +105,6 @@ static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) { return rtc::IPAddress(ip6_addr); } -static void GetIPAddressesFromJava(JNIEnv* jni, - jobjectArray j_ip_addresses, - std::vector* ip_addresses) { - ip_addresses->clear(); - size_t num_addresses = jni->GetArrayLength(j_ip_addresses); - CHECK_EXCEPTION(jni) << "Error during GetArrayLength"; - for (size_t i = 0; i < num_addresses; ++i) { - jobject j_ip_address = jni->GetObjectArrayElement(j_ip_addresses, i); - CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement"; - rtc::IPAddress ip = GetIPAddressFromJava(jni, j_ip_address); - ip_addresses->push_back(ip); - } -} - static NetworkInformation GetNetworkInformationFromJava( JNIEnv* jni, jobject j_network_info) { @@ -131,7 +117,8 @@ static NetworkInformation GetNetworkInformationFromJava( jni, Java_NetworkInformation_getConnectionType(jni, j_network_info)); jobjectArray j_ip_addresses = Java_NetworkInformation_getIpAddresses(jni, j_network_info); - GetIPAddressesFromJava(jni, j_ip_addresses, &network_info.ip_addresses); + network_info.ip_addresses = JavaToNativeVector( + jni, j_ip_addresses, &JavaToNativeIpAddress); return network_info; } @@ -363,13 +350,9 @@ void AndroidNetworkMonitor::NotifyOfActiveNetworkList( JNIEnv* env, jobject j_caller, jobjectArray j_network_infos) { - std::vector network_infos; - size_t num_networks = env->GetArrayLength(j_network_infos); - for (size_t i = 0; i < num_networks; ++i) { - jobject j_network_info = env->GetObjectArrayElement(j_network_infos, i); - CHECK_EXCEPTION(env) << "Error during GetObjectArrayElement"; - network_infos.push_back(GetNetworkInformationFromJava(env, j_network_info)); - } + std::vector network_infos = + JavaToNativeVector(env, j_network_infos, + &GetNetworkInformationFromJava); SetNetworkInfos(network_infos); } diff --git a/sdk/android/src/jni/pc/peerconnection_jni.cc b/sdk/android/src/jni/pc/peerconnection_jni.cc index e1c90beb68..fbb2bf7705 100644 --- a/sdk/android/src/jni/pc/peerconnection_jni.cc +++ b/sdk/android/src/jni/pc/peerconnection_jni.cc @@ -35,6 +35,7 @@ #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" @@ -48,9 +49,10 @@ namespace webrtc { namespace jni { -static rtc::scoped_refptr ExtractNativePC( - JNIEnv* jni, - jobject j_pc) { +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); @@ -58,6 +60,17 @@ static rtc::scoped_refptr ExtractNativePC( 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*, @@ -203,12 +216,9 @@ JNI_FUNCTION_DECLARATION(jboolean, JNIEnv* jni, jobject j_pc, jobjectArray j_candidates) { - std::vector candidates; - size_t num_candidates = jni->GetArrayLength(j_candidates); - for (size_t i = 0; i < num_candidates; ++i) { - jobject j_candidate = jni->GetObjectArrayElement(j_candidates, i); - candidates.push_back(JavaToNativeCandidate(jni, j_candidate)); - } + std::vector candidates = + JavaToNativeVector(jni, j_candidates, + &JavaToNativeCandidate); return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates); } @@ -236,77 +246,27 @@ JNI_FUNCTION_DECLARATION(jobject, jobject j_pc, jstring j_kind, jstring j_stream_id) { - jclass j_rtp_sender_class = FindClass(jni, "org/webrtc/RtpSender"); - jmethodID j_rtp_sender_ctor = - GetMethodID(jni, j_rtp_sender_class, "", "(J)V"); - 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); - if (!sender.get()) { - return nullptr; - } - jlong nativeSenderPtr = jlongFromPointer(sender.get()); - jobject j_sender = - jni->NewObject(j_rtp_sender_class, j_rtp_sender_ctor, nativeSenderPtr); - CHECK_EXCEPTION(jni) << "error during NewObject"; - // Sender is now owned by the Java object, and will be freed from - // RtpSender.dispose(), called by PeerConnection.dispose() or getSenders(). - sender->AddRef(); - return j_sender; + return NativeToJavaRtpSender(jni, sender); } JNI_FUNCTION_DECLARATION(jobject, PeerConnection_getNativeSenders, JNIEnv* jni, jobject j_pc) { - jclass j_array_list_class = FindClass(jni, "java/util/ArrayList"); - jmethodID j_array_list_ctor = - GetMethodID(jni, j_array_list_class, "", "()V"); - jmethodID j_array_list_add = - GetMethodID(jni, j_array_list_class, "add", "(Ljava/lang/Object;)Z"); - jobject j_senders = jni->NewObject(j_array_list_class, j_array_list_ctor); - CHECK_EXCEPTION(jni) << "error during NewObject"; - - jclass j_rtp_sender_class = FindClass(jni, "org/webrtc/RtpSender"); - jmethodID j_rtp_sender_ctor = - GetMethodID(jni, j_rtp_sender_class, "", "(J)V"); - - auto senders = ExtractNativePC(jni, j_pc)->GetSenders(); - for (const auto& sender : senders) { - jlong nativeSenderPtr = jlongFromPointer(sender.get()); - jobject j_sender = - jni->NewObject(j_rtp_sender_class, j_rtp_sender_ctor, nativeSenderPtr); - CHECK_EXCEPTION(jni) << "error during NewObject"; - // Sender is now owned by the Java object, and will be freed from - // RtpSender.dispose(), called by PeerConnection.dispose() or getSenders(). - sender->AddRef(); - jni->CallBooleanMethod(j_senders, j_array_list_add, j_sender); - CHECK_EXCEPTION(jni) << "error during CallBooleanMethod"; - } - return j_senders; + return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetSenders(), + &NativeToJavaRtpSender); } JNI_FUNCTION_DECLARATION(jobject, PeerConnection_getNativeReceivers, JNIEnv* jni, jobject j_pc) { - jclass j_array_list_class = FindClass(jni, "java/util/ArrayList"); - jmethodID j_array_list_ctor = - GetMethodID(jni, j_array_list_class, "", "()V"); - jmethodID j_array_list_add = - GetMethodID(jni, j_array_list_class, "add", "(Ljava/lang/Object;)Z"); - jobject j_receivers = jni->NewObject(j_array_list_class, j_array_list_ctor); - CHECK_EXCEPTION(jni) << "error during NewObject"; - - auto receivers = ExtractNativePC(jni, j_pc)->GetReceivers(); - for (const auto& receiver : receivers) { - jobject j_receiver = NativeToJavaRtpReceiver(jni, receiver); - jni->CallBooleanMethod(j_receivers, j_array_list_add, j_receiver); - CHECK_EXCEPTION(jni) << "error during CallBooleanMethod"; - } - return j_receivers; + return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetReceivers(), + &NativeToJavaRtpReceiver); } JNI_FUNCTION_DECLARATION(bool, diff --git a/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.cc b/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.cc index f4d0b81a34..6126636cc4 100644 --- a/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.cc +++ b/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.cc @@ -97,72 +97,46 @@ jobject MemberToJava(JNIEnv* env, const RTCStatsMemberInterface& member) { return nullptr; } +jobject NativeToJavaRtcStats(JNIEnv* env, const RTCStats& stats) { + JavaMapBuilder builder(env); + for (const auto& member : stats.Members()) { + if (!member->is_defined()) + continue; + ScopedLocalRefFrame local_ref_frame(env); + builder.put(NativeToJavaString(env, member->name()), + MemberToJava(env, *member)); + } + return Java_RTCStats_create( + env, stats.timestamp_us(), NativeToJavaString(env, stats.type()), + NativeToJavaString(env, stats.id()), builder.GetJavaMap()); +} + +jobject NativeToJavaRtcStatsReport( + JNIEnv* env, + const rtc::scoped_refptr& report) { + jobject j_stats_map = + NativeToJavaMap(env, *report, [](JNIEnv* env, const RTCStats& stats) { + return std::pair(NativeToJavaString(env, stats.id()), + NativeToJavaRtcStats(env, stats)); + }); + return Java_RTCStatsReport_create(env, report->timestamp_us(), j_stats_map); +} + } // namespace RTCStatsCollectorCallbackWrapper::RTCStatsCollectorCallbackWrapper( JNIEnv* jni, jobject j_callback) - : j_callback_global_(jni, j_callback), - j_linked_hash_map_class_(FindClass(jni, "java/util/LinkedHashMap")), - j_linked_hash_map_ctor_( - GetMethodID(jni, j_linked_hash_map_class_, "", "()V")), - j_linked_hash_map_put_(GetMethodID( - jni, - j_linked_hash_map_class_, - "put", - "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) {} + : j_callback_global_(jni, j_callback) {} void RTCStatsCollectorCallbackWrapper::OnStatsDelivered( const rtc::scoped_refptr& report) { JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedLocalRefFrame local_ref_frame(jni); - jobject j_report = ReportToJava(jni, report); + jobject j_report = NativeToJavaRtcStatsReport(jni, report); Java_RTCStatsCollectorCallback_onStatsDelivered(jni, *j_callback_global_, j_report); } -jobject RTCStatsCollectorCallbackWrapper::ReportToJava( - JNIEnv* jni, - const rtc::scoped_refptr& report) { - jobject j_stats_map = - jni->NewObject(j_linked_hash_map_class_, j_linked_hash_map_ctor_); - CHECK_EXCEPTION(jni) << "error during NewObject"; - for (const RTCStats& stats : *report) { - // Create a local reference frame for each RTCStats, since there is a - // maximum number of references that can be created in one frame. - ScopedLocalRefFrame local_ref_frame(jni); - jstring j_id = NativeToJavaString(jni, stats.id()); - jobject j_stats = StatsToJava(jni, stats); - jni->CallObjectMethod(j_stats_map, j_linked_hash_map_put_, j_id, j_stats); - CHECK_EXCEPTION(jni) << "error during CallObjectMethod"; - } - jobject j_report = - Java_RTCStatsReport_create(jni, report->timestamp_us(), j_stats_map); - return j_report; -} - -jobject RTCStatsCollectorCallbackWrapper::StatsToJava(JNIEnv* jni, - const RTCStats& stats) { - jstring j_type = NativeToJavaString(jni, stats.type()); - jstring j_id = NativeToJavaString(jni, stats.id()); - jobject j_members = - jni->NewObject(j_linked_hash_map_class_, j_linked_hash_map_ctor_); - for (const RTCStatsMemberInterface* member : stats.Members()) { - if (!member->is_defined()) { - continue; - } - // Create a local reference frame for each member as well. - ScopedLocalRefFrame local_ref_frame(jni); - jstring j_name = NativeToJavaString(jni, member->name()); - jobject j_member = MemberToJava(jni, *member); - jni->CallObjectMethod(j_members, j_linked_hash_map_put_, j_name, j_member); - CHECK_EXCEPTION(jni) << "error during CallObjectMethod"; - } - jobject j_stats = - Java_RTCStats_create(jni, stats.timestamp_us(), j_type, j_id, j_members); - CHECK_EXCEPTION(jni) << "error during NewObject"; - return j_stats; -} - } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h b/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h index d9cc6923d1..ffda94a978 100644 --- a/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h +++ b/sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h @@ -30,15 +30,7 @@ class RTCStatsCollectorCallbackWrapper : public RTCStatsCollectorCallback { const rtc::scoped_refptr& report) override; private: - // Helper functions for converting C++ RTCStatsReport to Java equivalent. - jobject ReportToJava(JNIEnv* jni, - const rtc::scoped_refptr& report); - jobject StatsToJava(JNIEnv* jni, const RTCStats& stats); - const ScopedGlobalRef j_callback_global_; - const jclass j_linked_hash_map_class_; - const jmethodID j_linked_hash_map_ctor_; - const jmethodID j_linked_hash_map_put_; }; } // namespace jni diff --git a/sdk/android/src/jni/pc/rtpsender_jni.cc b/sdk/android/src/jni/pc/rtpsender_jni.cc index 7dd34bbb1f..e179361e60 100644 --- a/sdk/android/src/jni/pc/rtpsender_jni.cc +++ b/sdk/android/src/jni/pc/rtpsender_jni.cc @@ -16,7 +16,7 @@ namespace webrtc { namespace jni { JNI_FUNCTION_DECLARATION(jboolean, - RtpSender_nativeSetTrack, + RtpSender_setNativeTrack, JNIEnv* jni, jclass, jlong j_rtp_sender_pointer, @@ -26,7 +26,7 @@ JNI_FUNCTION_DECLARATION(jboolean, } JNI_FUNCTION_DECLARATION(jlong, - RtpSender_nativeGetTrack, + RtpSender_getNativeTrack, JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) { @@ -37,7 +37,7 @@ JNI_FUNCTION_DECLARATION(jlong, } JNI_FUNCTION_DECLARATION(jlong, - RtpSender_nativeGetDtmfSender, + RtpSender_getNativeDtmfSender, JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) { @@ -48,7 +48,7 @@ JNI_FUNCTION_DECLARATION(jlong, } JNI_FUNCTION_DECLARATION(jboolean, - RtpSender_nativeSetParameters, + RtpSender_setNativeParameters, JNIEnv* jni, jclass, jlong j_rtp_sender_pointer, @@ -62,7 +62,7 @@ JNI_FUNCTION_DECLARATION(jboolean, } JNI_FUNCTION_DECLARATION(jobject, - RtpSender_nativeGetParameters, + RtpSender_getNativeParameters, JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) { @@ -73,7 +73,7 @@ JNI_FUNCTION_DECLARATION(jobject, } JNI_FUNCTION_DECLARATION(jstring, - RtpSender_nativeId, + RtpSender_getNativeId, JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) { diff --git a/sdk/android/src/jni/videoencoderfactorywrapper.cc b/sdk/android/src/jni/videoencoderfactorywrapper.cc index 255031320e..834490af47 100644 --- a/sdk/android/src/jni/videoencoderfactorywrapper.cc +++ b/sdk/android/src/jni/videoencoderfactorywrapper.cc @@ -13,6 +13,7 @@ #include "api/video_codecs/video_encoder.h" #include "common_types.h" // NOLINT(build/include) #include "rtc_base/logging.h" +#include "sdk/android/generated_video_jni/jni/VideoEncoderFactory_jni.h" #include "sdk/android/src/jni/class_loader.h" #include "sdk/android/src/jni/videocodecinfo.h" #include "sdk/android/src/jni/wrappednativecodec.h" @@ -23,15 +24,10 @@ namespace jni { VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(JNIEnv* jni, jobject encoder_factory) : encoder_factory_(jni, encoder_factory) { - jclass encoder_factory_class = jni->GetObjectClass(*encoder_factory_); - create_encoder_method_ = jni->GetMethodID( - encoder_factory_class, "createEncoder", - "(Lorg/webrtc/VideoCodecInfo;)Lorg/webrtc/VideoEncoder;"); - get_supported_codecs_method_ = - jni->GetMethodID(encoder_factory_class, "getSupportedCodecs", - "()[Lorg/webrtc/VideoCodecInfo;"); - - supported_formats_ = GetSupportedFormats(jni); + const jobjectArray j_supported_codecs = + Java_VideoEncoderFactory_getSupportedCodecs(jni, encoder_factory); + supported_formats_ = JavaToNativeVector( + jni, j_supported_codecs, &VideoCodecInfoToSdpVideoFormat); } std::unique_ptr VideoEncoderFactoryWrapper::CreateVideoEncoder( @@ -39,8 +35,8 @@ std::unique_ptr VideoEncoderFactoryWrapper::CreateVideoEncoder( JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedLocalRefFrame local_ref_frame(jni); jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format); - jobject encoder = jni->CallObjectMethod(*encoder_factory_, - create_encoder_method_, j_codec_info); + jobject encoder = Java_VideoEncoderFactory_createEncoder( + jni, *encoder_factory_, j_codec_info); return encoder != nullptr ? JavaToNativeVideoEncoder(jni, encoder) : nullptr; } @@ -50,8 +46,8 @@ VideoEncoderFactory::CodecInfo VideoEncoderFactoryWrapper::QueryVideoEncoder( ScopedLocalRefFrame local_ref_frame(jni); jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format); - jobject encoder = jni->CallObjectMethod(*encoder_factory_, - create_encoder_method_, j_codec_info); + jobject encoder = Java_VideoEncoderFactory_createEncoder( + jni, *encoder_factory_, j_codec_info); CodecInfo codec_info; // Check if this is a wrapped native software encoder implementation. @@ -60,21 +56,5 @@ VideoEncoderFactory::CodecInfo VideoEncoderFactoryWrapper::QueryVideoEncoder( return codec_info; } -std::vector VideoEncoderFactoryWrapper::GetSupportedFormats( - JNIEnv* jni) const { - const jobjectArray j_supported_codecs = static_cast( - jni->CallObjectMethod(*encoder_factory_, get_supported_codecs_method_)); - const jsize supported_codecs_count = jni->GetArrayLength(j_supported_codecs); - - std::vector supported_formats; - for (jsize i = 0; i < supported_codecs_count; i++) { - jobject j_supported_codec = - jni->GetObjectArrayElement(j_supported_codecs, i); - supported_formats.push_back( - VideoCodecInfoToSdpVideoFormat(jni, j_supported_codec)); - } - return supported_formats; -} - } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/videoencoderfactorywrapper.h b/sdk/android/src/jni/videoencoderfactorywrapper.h index 26174be292..cd7787fe9a 100644 --- a/sdk/android/src/jni/videoencoderfactorywrapper.h +++ b/sdk/android/src/jni/videoencoderfactorywrapper.h @@ -38,13 +38,7 @@ class VideoEncoderFactoryWrapper : public VideoEncoderFactory { CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; private: - std::vector GetSupportedFormats(JNIEnv* jni) const; - const ScopedGlobalRef encoder_factory_; - - jmethodID create_encoder_method_; - jmethodID get_supported_codecs_method_; - std::vector supported_formats_; };