Android: Generate JNI code for jni_helper, RtpSender, and VideoEncoderFactory

Bug: webrtc:8278
Change-Id: I6111e562cc5a8fe6c595fcb8dfd5202d46a08806
Reviewed-on: https://webrtc-review.googlesource.com/28622
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21140}
This commit is contained in:
Magnus Jedvert
2017-12-07 14:07:20 +01:00
committed by Commit Bot
parent e51f785043
commit 3863153267
12 changed files with 198 additions and 262 deletions

View File

@ -46,9 +46,14 @@ generate_jar_jni("generated_external_classes_jni") {
"java/lang/Integer.class", "java/lang/Integer.class",
"java/lang/Double.class", "java/lang/Double.class",
"java/lang/Long.class", "java/lang/Long.class",
"java/lang/Iterable.class",
"java/util/Iterator.class",
"java/lang/Boolean.class", "java/lang/Boolean.class",
"java/math/BigInteger.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_package = ""
jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h" 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/VideoCodecStatus.java",
"api/org/webrtc/VideoDecoder.java", "api/org/webrtc/VideoDecoder.java",
"api/org/webrtc/VideoEncoder.java", "api/org/webrtc/VideoEncoder.java",
"api/org/webrtc/VideoEncoderFactory.java",
"api/org/webrtc/VideoFrame.java", "api/org/webrtc/VideoFrame.java",
"api/org/webrtc/VideoSink.java", "api/org/webrtc/VideoSink.java",
"src/java/org/webrtc/VideoDecoderWrapper.java", "src/java/org/webrtc/VideoDecoderWrapper.java",
@ -295,6 +301,7 @@ generate_jni("generated_peerconnection_jni") {
"api/org/webrtc/RTCStatsCollectorCallback.java", "api/org/webrtc/RTCStatsCollectorCallback.java",
"api/org/webrtc/RTCStatsReport.java", "api/org/webrtc/RTCStatsReport.java",
"api/org/webrtc/RtpReceiver.java", "api/org/webrtc/RtpReceiver.java",
"api/org/webrtc/RtpSender.java",
"api/org/webrtc/StatsObserver.java", "api/org/webrtc/StatsObserver.java",
"api/org/webrtc/StatsReport.java", "api/org/webrtc/StatsReport.java",
] ]

View File

@ -19,13 +19,14 @@ public class RtpSender {
private final DtmfSender dtmfSender; private final DtmfSender dtmfSender;
@CalledByNative
public RtpSender(long nativeRtpSender) { public RtpSender(long nativeRtpSender) {
this.nativeRtpSender = 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. // It may be possible for an RtpSender to be created without a track.
cachedTrack = (track != 0) ? new MediaStreamTrack(track) : null; cachedTrack = (track != 0) ? new MediaStreamTrack(track) : null;
long nativeDtmfSender = nativeGetDtmfSender(nativeRtpSender); long nativeDtmfSender = getNativeDtmfSender(nativeRtpSender);
dtmfSender = (nativeDtmfSender != 0) ? new DtmfSender(nativeDtmfSender) : null; dtmfSender = (nativeDtmfSender != 0) ? new DtmfSender(nativeDtmfSender) : null;
} }
@ -44,7 +45,7 @@ public class RtpSender {
* @return true on success and false on failure. * @return true on success and false on failure.
*/ */
public boolean setTrack(MediaStreamTrack track, boolean takeOwnership) { 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; return false;
} }
if (cachedTrack != null && ownsTrack) { if (cachedTrack != null && ownsTrack) {
@ -60,15 +61,15 @@ public class RtpSender {
} }
public boolean setParameters(RtpParameters parameters) { public boolean setParameters(RtpParameters parameters) {
return nativeSetParameters(nativeRtpSender, parameters); return setNativeParameters(nativeRtpSender, parameters);
} }
public RtpParameters getParameters() { public RtpParameters getParameters() {
return nativeGetParameters(nativeRtpSender); return getNativeParameters(nativeRtpSender);
} }
public String id() { public String id() {
return nativeId(nativeRtpSender); return getNativeId(nativeRtpSender);
} }
public DtmfSender dtmf() { public DtmfSender dtmf() {
@ -85,19 +86,19 @@ public class RtpSender {
JniCommon.nativeReleaseRef(nativeRtpSender); 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. // This should increment the reference count of the track.
// Will be released in dispose() or setTrack(). // 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. // This should increment the reference count of the DTMF sender.
// Will be released in dispose(). // 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);
}; };

View File

@ -13,11 +13,11 @@ package org.webrtc;
/** Factory for creating VideoEncoders. */ /** Factory for creating VideoEncoders. */
public interface VideoEncoderFactory { public interface VideoEncoderFactory {
/** Creates an encoder for the given video codec. */ /** 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 * Enumerates the list of supported video codecs. This method will only be called once and the
* result will be cached. * result will be cached.
*/ */
public VideoCodecInfo[] getSupportedCodecs(); @CalledByNative VideoCodecInfo[] getSupportedCodecs();
} }

View File

@ -15,10 +15,16 @@
#include <unistd.h> #include <unistd.h>
#include <vector> #include <vector>
#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/Boolean_jni.h"
#include "sdk/android/generated_external_classes_jni/jni/Double_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/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/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/class_loader.h"
#include "sdk/android/src/jni/classreferenceholder.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 jclass string_class = GetObjectClass(jni, j_string);
const jmethodID get_bytes = const jmethodID get_bytes =
GetMethodID(jni, string_class, "getBytes", "(Ljava/lang/String;)[B"); GetMethodID(jni, string_class, "getBytes", "(Ljava/lang/String;)[B");
const jstring charset_name = jni->NewStringUTF("ISO-8859-1"); const jbyteArray j_byte_array = (jbyteArray)jni->CallObjectMethod(
CHECK_EXCEPTION(jni) << "error during NewStringUTF"; j_string, get_bytes, NativeToJavaString(jni, "ISO-8859-1"));
const jbyteArray j_byte_array =
(jbyteArray)jni->CallObjectMethod(j_string, get_bytes, charset_name);
CHECK_EXCEPTION(jni) << "error during CallObjectMethod"; CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
const size_t len = jni->GetArrayLength(j_byte_array); 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|; // Return the (singleton) Java Enum object corresponding to |index|;
jobject JavaEnumFromIndex(JNIEnv* jni, jclass state_class, static jobject JavaEnumFromIndex(JNIEnv* jni,
const std::string& state_class_name, int index) { jclass state_class,
const std::string& state_class_name,
int index) {
jmethodID state_values_id = GetStaticMethodID( jmethodID state_values_id = GetStaticMethodID(
jni, state_class, "values", ("()[L" + state_class_name + ";").c_str()); jni, state_class, "values", ("()[L" + state_class_name + ";").c_str());
jobjectArray state_values = static_cast<jobjectArray>( jobjectArray state_values = static_cast<jobjectArray>(
@ -326,45 +333,26 @@ jobject JavaEnumFromIndexAndClassName(JNIEnv* jni,
} }
std::string GetJavaEnumName(JNIEnv* jni, jobject j_enum) { std::string GetJavaEnumName(JNIEnv* jni, jobject j_enum) {
jclass enum_class = GetClass(jni, "java/lang/Enum"); return JavaToStdString(jni, JNI_Enum::Java_Enum_name(jni, j_enum));
jmethodID nameMethod =
GetMethodID(jni, enum_class, "name", "()Ljava/lang/String;");
jstring name =
reinterpret_cast<jstring>(jni->CallObjectMethod(j_enum, nameMethod));
CHECK_EXCEPTION(jni);
return JavaToStdString(jni, name);
} }
std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni, std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
jobject j_map) { jobject j_map) {
jclass map_class = jni->FindClass("java/util/Map"); jobject j_entry_set = JNI_Map::Java_Map_entrySet(jni, j_map);
jclass set_class = jni->FindClass("java/util/Set");
jclass iterator_class = jni->FindClass("java/util/Iterator");
jclass entry_class = jni->FindClass("java/util/Map$Entry"); 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 = jmethodID get_key_method =
jni->GetMethodID(entry_class, "getKey", "()Ljava/lang/Object;"); jni->GetMethodID(entry_class, "getKey", "()Ljava/lang/Object;");
jmethodID get_value_method = jmethodID get_value_method =
jni->GetMethodID(entry_class, "getValue", "()Ljava/lang/Object;"); 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<std::string, std::string> result; std::map<std::string, std::string> result;
while (jni->CallBooleanMethod(j_iterator, has_next_method)) { for (jobject j_entry : Iterable(jni, j_entry_set)) {
jobject j_entry = jni->CallObjectMethod(j_iterator, next_method);
jstring j_key = jstring j_key =
static_cast<jstring>(jni->CallObjectMethod(j_entry, get_key_method)); static_cast<jstring>(jni->CallObjectMethod(j_entry, get_key_method));
jstring j_value = jstring j_value =
static_cast<jstring>(jni->CallObjectMethod(j_entry, get_value_method)); static_cast<jstring>(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; return result;
@ -397,18 +385,8 @@ Iterable::Iterator::Iterator() : iterator_(nullptr) {}
// Creates an iterator pointing to the beginning of the specified collection. // Creates an iterator pointing to the beginning of the specified collection.
Iterable::Iterator::Iterator(JNIEnv* jni, jobject iterable) : jni_(jni) { Iterable::Iterator::Iterator(JNIEnv* jni, jobject iterable) : jni_(jni) {
jclass j_class = GetObjectClass(jni, iterable); iterator_ = JNI_Iterable::Java_Iterable_iterator(jni, iterable);
jmethodID iterator_id = RTC_CHECK(iterator_);
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");
// Start at the first element in the collection. // Start at the first element in the collection.
++(*this); ++(*this);
} }
@ -419,8 +397,6 @@ Iterable::Iterator::Iterator(Iterator&& other)
: jni_(std::move(other.jni_)), : jni_(std::move(other.jni_)),
iterator_(std::move(other.iterator_)), iterator_(std::move(other.iterator_)),
value_(std::move(other.value_)), 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_)){}; thread_checker_(std::move(other.thread_checker_)){};
// Advances the iterator one step. // Advances the iterator one step.
@ -430,22 +406,19 @@ Iterable::Iterator& Iterable::Iterator::operator++() {
// Can't move past the end. // Can't move past the end.
return *this; return *this;
} }
bool has_next = jni_->CallBooleanMethod(iterator_, has_next_id_); bool has_next = JNI_Iterator::Java_Iterator_hasNext(jni_, iterator_);
CHECK_EXCEPTION(jni_) << "error during CallBooleanMethod";
if (!has_next) { if (!has_next) {
iterator_ = nullptr; iterator_ = nullptr;
value_ = nullptr; value_ = nullptr;
return *this; return *this;
} }
value_ = jni_->CallObjectMethod(iterator_, next_id_); value_ = JNI_Iterator::Java_Iterator_next(jni_, iterator_);
CHECK_EXCEPTION(jni_) << "error during CallObjectMethod";
return *this; return *this;
} }
void Iterable::Iterator::Remove() { void Iterable::Iterator::Remove() {
jni_->CallVoidMethod(iterator_, remove_id_); JNI_Iterator::Java_Iterator_remove(jni_, iterator_);
CHECK_EXCEPTION(jni_) << "error during CallVoidMethod";
} }
// Provides a way to compare the iterator with itself and with the end 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); 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 jni
} // namespace webrtc } // namespace webrtc

View File

@ -116,10 +116,6 @@ jstring NativeToJavaString(JNIEnv* jni, const std::string& native);
jobject NativeToJavaInteger(JNIEnv* jni, jobject NativeToJavaInteger(JNIEnv* jni,
const rtc::Optional<int32_t>& optional_int); const rtc::Optional<int32_t>& 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|; // Return the (singleton) Java Enum object corresponding to |index|;
// |state_class_fragment| is something like "MediaSource$State". // |state_class_fragment| is something like "MediaSource$State".
jobject JavaEnumFromIndexAndClassName(JNIEnv* jni, jobject JavaEnumFromIndexAndClassName(JNIEnv* jni,
@ -219,9 +215,6 @@ class Iterable {
JNIEnv* jni_ = nullptr; JNIEnv* jni_ = nullptr;
jobject iterator_ = nullptr; jobject iterator_ = nullptr;
jobject value_ = nullptr; jobject value_ = nullptr;
jmethodID has_next_id_ = nullptr;
jmethodID next_id_ = nullptr;
jmethodID remove_id_ = nullptr;
rtc::ThreadChecker thread_checker_; rtc::ThreadChecker thread_checker_;
RTC_DISALLOW_COPY_AND_ASSIGN(Iterator); RTC_DISALLOW_COPY_AND_ASSIGN(Iterator);
@ -268,6 +261,66 @@ jobjectArray NativeToJavaDoubleArray(JNIEnv* env,
jobjectArray NativeToJavaStringArray(JNIEnv* env, jobjectArray NativeToJavaStringArray(JNIEnv* env,
const std::vector<std::string>& container); const std::vector<std::string>& container);
template <typename T, typename Convert>
std::vector<T> JavaToNativeVector(JNIEnv* env,
jobjectArray j_container,
Convert convert) {
std::vector<T> 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 <typename C, typename Convert>
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 <typename C, typename Convert>
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 jni
} // namespace webrtc } // namespace webrtc

View File

@ -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); jbyteArray j_addresses = Java_IPAddress_getAddress(jni, j_ip_address);
size_t address_length = jni->GetArrayLength(j_addresses); size_t address_length = jni->GetArrayLength(j_addresses);
jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr); jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr);
CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava"; CHECK_EXCEPTION(jni) << "Error during JavaToNativeIpAddress";
if (address_length == 4) { if (address_length == 4) {
// IP4 // IP4
struct in_addr ip4_addr; struct in_addr ip4_addr;
@ -105,20 +105,6 @@ static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) {
return rtc::IPAddress(ip6_addr); return rtc::IPAddress(ip6_addr);
} }
static void GetIPAddressesFromJava(JNIEnv* jni,
jobjectArray j_ip_addresses,
std::vector<rtc::IPAddress>* 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( static NetworkInformation GetNetworkInformationFromJava(
JNIEnv* jni, JNIEnv* jni,
jobject j_network_info) { jobject j_network_info) {
@ -131,7 +117,8 @@ static NetworkInformation GetNetworkInformationFromJava(
jni, Java_NetworkInformation_getConnectionType(jni, j_network_info)); jni, Java_NetworkInformation_getConnectionType(jni, j_network_info));
jobjectArray j_ip_addresses = jobjectArray j_ip_addresses =
Java_NetworkInformation_getIpAddresses(jni, j_network_info); Java_NetworkInformation_getIpAddresses(jni, j_network_info);
GetIPAddressesFromJava(jni, j_ip_addresses, &network_info.ip_addresses); network_info.ip_addresses = JavaToNativeVector<rtc::IPAddress>(
jni, j_ip_addresses, &JavaToNativeIpAddress);
return network_info; return network_info;
} }
@ -363,13 +350,9 @@ void AndroidNetworkMonitor::NotifyOfActiveNetworkList(
JNIEnv* env, JNIEnv* env,
jobject j_caller, jobject j_caller,
jobjectArray j_network_infos) { jobjectArray j_network_infos) {
std::vector<NetworkInformation> network_infos; std::vector<NetworkInformation> network_infos =
size_t num_networks = env->GetArrayLength(j_network_infos); JavaToNativeVector<NetworkInformation>(env, j_network_infos,
for (size_t i = 0; i < num_networks; ++i) { &GetNetworkInformationFromJava);
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));
}
SetNetworkInfos(network_infos); SetNetworkInfos(network_infos);
} }

View File

@ -35,6 +35,7 @@
#include "api/rtpsenderinterface.h" #include "api/rtpsenderinterface.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.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/classreferenceholder.h"
#include "sdk/android/src/jni/jni_helpers.h" #include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/pc/datachannel.h" #include "sdk/android/src/jni/pc/datachannel.h"
@ -48,9 +49,10 @@
namespace webrtc { namespace webrtc {
namespace jni { namespace jni {
static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC( namespace {
JNIEnv* jni,
jobject j_pc) { rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(JNIEnv* jni,
jobject j_pc) {
jfieldID native_pc_id = jfieldID native_pc_id =
GetFieldID(jni, GetObjectClass(jni, j_pc), "nativePeerConnection", "J"); GetFieldID(jni, GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
jlong j_p = GetLongField(jni, j_pc, native_pc_id); jlong j_p = GetLongField(jni, j_pc, native_pc_id);
@ -58,6 +60,17 @@ static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
reinterpret_cast<PeerConnectionInterface*>(j_p)); reinterpret_cast<PeerConnectionInterface*>(j_p));
} }
jobject NativeToJavaRtpSender(JNIEnv* env,
rtc::scoped_refptr<RtpSenderInterface> 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, JNI_FUNCTION_DECLARATION(void,
PeerConnection_freeObserver, PeerConnection_freeObserver,
JNIEnv*, JNIEnv*,
@ -203,12 +216,9 @@ JNI_FUNCTION_DECLARATION(jboolean,
JNIEnv* jni, JNIEnv* jni,
jobject j_pc, jobject j_pc,
jobjectArray j_candidates) { jobjectArray j_candidates) {
std::vector<cricket::Candidate> candidates; std::vector<cricket::Candidate> candidates =
size_t num_candidates = jni->GetArrayLength(j_candidates); JavaToNativeVector<cricket::Candidate>(jni, j_candidates,
for (size_t i = 0; i < num_candidates; ++i) { &JavaToNativeCandidate);
jobject j_candidate = jni->GetObjectArrayElement(j_candidates, i);
candidates.push_back(JavaToNativeCandidate(jni, j_candidate));
}
return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates); return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates);
} }
@ -236,77 +246,27 @@ JNI_FUNCTION_DECLARATION(jobject,
jobject j_pc, jobject j_pc,
jstring j_kind, jstring j_kind,
jstring j_stream_id) { 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, "<init>", "(J)V");
std::string kind = JavaToStdString(jni, j_kind); std::string kind = JavaToStdString(jni, j_kind);
std::string stream_id = JavaToStdString(jni, j_stream_id); std::string stream_id = JavaToStdString(jni, j_stream_id);
rtc::scoped_refptr<RtpSenderInterface> sender = rtc::scoped_refptr<RtpSenderInterface> sender =
ExtractNativePC(jni, j_pc)->CreateSender(kind, stream_id); ExtractNativePC(jni, j_pc)->CreateSender(kind, stream_id);
if (!sender.get()) { return NativeToJavaRtpSender(jni, sender);
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;
} }
JNI_FUNCTION_DECLARATION(jobject, JNI_FUNCTION_DECLARATION(jobject,
PeerConnection_getNativeSenders, PeerConnection_getNativeSenders,
JNIEnv* jni, JNIEnv* jni,
jobject j_pc) { jobject j_pc) {
jclass j_array_list_class = FindClass(jni, "java/util/ArrayList"); return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetSenders(),
jmethodID j_array_list_ctor = &NativeToJavaRtpSender);
GetMethodID(jni, j_array_list_class, "<init>", "()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, "<init>", "(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;
} }
JNI_FUNCTION_DECLARATION(jobject, JNI_FUNCTION_DECLARATION(jobject,
PeerConnection_getNativeReceivers, PeerConnection_getNativeReceivers,
JNIEnv* jni, JNIEnv* jni,
jobject j_pc) { jobject j_pc) {
jclass j_array_list_class = FindClass(jni, "java/util/ArrayList"); return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetReceivers(),
jmethodID j_array_list_ctor = &NativeToJavaRtpReceiver);
GetMethodID(jni, j_array_list_class, "<init>", "()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;
} }
JNI_FUNCTION_DECLARATION(bool, JNI_FUNCTION_DECLARATION(bool,

View File

@ -97,72 +97,46 @@ jobject MemberToJava(JNIEnv* env, const RTCStatsMemberInterface& member) {
return nullptr; 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<const RTCStatsReport>& report) {
jobject j_stats_map =
NativeToJavaMap(env, *report, [](JNIEnv* env, const RTCStats& stats) {
return std::pair<jobject, jobject>(NativeToJavaString(env, stats.id()),
NativeToJavaRtcStats(env, stats));
});
return Java_RTCStatsReport_create(env, report->timestamp_us(), j_stats_map);
}
} // namespace } // namespace
RTCStatsCollectorCallbackWrapper::RTCStatsCollectorCallbackWrapper( RTCStatsCollectorCallbackWrapper::RTCStatsCollectorCallbackWrapper(
JNIEnv* jni, JNIEnv* jni,
jobject j_callback) jobject j_callback)
: j_callback_global_(jni, 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_, "<init>", "()V")),
j_linked_hash_map_put_(GetMethodID(
jni,
j_linked_hash_map_class_,
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) {}
void RTCStatsCollectorCallbackWrapper::OnStatsDelivered( void RTCStatsCollectorCallbackWrapper::OnStatsDelivered(
const rtc::scoped_refptr<const RTCStatsReport>& report) { const rtc::scoped_refptr<const RTCStatsReport>& report) {
JNIEnv* jni = AttachCurrentThreadIfNeeded(); JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni); ScopedLocalRefFrame local_ref_frame(jni);
jobject j_report = ReportToJava(jni, report); jobject j_report = NativeToJavaRtcStatsReport(jni, report);
Java_RTCStatsCollectorCallback_onStatsDelivered(jni, *j_callback_global_, Java_RTCStatsCollectorCallback_onStatsDelivered(jni, *j_callback_global_,
j_report); j_report);
} }
jobject RTCStatsCollectorCallbackWrapper::ReportToJava(
JNIEnv* jni,
const rtc::scoped_refptr<const RTCStatsReport>& 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 jni
} // namespace webrtc } // namespace webrtc

View File

@ -30,15 +30,7 @@ class RTCStatsCollectorCallbackWrapper : public RTCStatsCollectorCallback {
const rtc::scoped_refptr<const RTCStatsReport>& report) override; const rtc::scoped_refptr<const RTCStatsReport>& report) override;
private: private:
// Helper functions for converting C++ RTCStatsReport to Java equivalent.
jobject ReportToJava(JNIEnv* jni,
const rtc::scoped_refptr<const RTCStatsReport>& report);
jobject StatsToJava(JNIEnv* jni, const RTCStats& stats);
const ScopedGlobalRef<jobject> j_callback_global_; const ScopedGlobalRef<jobject> 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 } // namespace jni

View File

@ -16,7 +16,7 @@ namespace webrtc {
namespace jni { namespace jni {
JNI_FUNCTION_DECLARATION(jboolean, JNI_FUNCTION_DECLARATION(jboolean,
RtpSender_nativeSetTrack, RtpSender_setNativeTrack,
JNIEnv* jni, JNIEnv* jni,
jclass, jclass,
jlong j_rtp_sender_pointer, jlong j_rtp_sender_pointer,
@ -26,7 +26,7 @@ JNI_FUNCTION_DECLARATION(jboolean,
} }
JNI_FUNCTION_DECLARATION(jlong, JNI_FUNCTION_DECLARATION(jlong,
RtpSender_nativeGetTrack, RtpSender_getNativeTrack,
JNIEnv* jni, JNIEnv* jni,
jclass, jclass,
jlong j_rtp_sender_pointer) { jlong j_rtp_sender_pointer) {
@ -37,7 +37,7 @@ JNI_FUNCTION_DECLARATION(jlong,
} }
JNI_FUNCTION_DECLARATION(jlong, JNI_FUNCTION_DECLARATION(jlong,
RtpSender_nativeGetDtmfSender, RtpSender_getNativeDtmfSender,
JNIEnv* jni, JNIEnv* jni,
jclass, jclass,
jlong j_rtp_sender_pointer) { jlong j_rtp_sender_pointer) {
@ -48,7 +48,7 @@ JNI_FUNCTION_DECLARATION(jlong,
} }
JNI_FUNCTION_DECLARATION(jboolean, JNI_FUNCTION_DECLARATION(jboolean,
RtpSender_nativeSetParameters, RtpSender_setNativeParameters,
JNIEnv* jni, JNIEnv* jni,
jclass, jclass,
jlong j_rtp_sender_pointer, jlong j_rtp_sender_pointer,
@ -62,7 +62,7 @@ JNI_FUNCTION_DECLARATION(jboolean,
} }
JNI_FUNCTION_DECLARATION(jobject, JNI_FUNCTION_DECLARATION(jobject,
RtpSender_nativeGetParameters, RtpSender_getNativeParameters,
JNIEnv* jni, JNIEnv* jni,
jclass, jclass,
jlong j_rtp_sender_pointer) { jlong j_rtp_sender_pointer) {
@ -73,7 +73,7 @@ JNI_FUNCTION_DECLARATION(jobject,
} }
JNI_FUNCTION_DECLARATION(jstring, JNI_FUNCTION_DECLARATION(jstring,
RtpSender_nativeId, RtpSender_getNativeId,
JNIEnv* jni, JNIEnv* jni,
jclass, jclass,
jlong j_rtp_sender_pointer) { jlong j_rtp_sender_pointer) {

View File

@ -13,6 +13,7 @@
#include "api/video_codecs/video_encoder.h" #include "api/video_codecs/video_encoder.h"
#include "common_types.h" // NOLINT(build/include) #include "common_types.h" // NOLINT(build/include)
#include "rtc_base/logging.h" #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/class_loader.h"
#include "sdk/android/src/jni/videocodecinfo.h" #include "sdk/android/src/jni/videocodecinfo.h"
#include "sdk/android/src/jni/wrappednativecodec.h" #include "sdk/android/src/jni/wrappednativecodec.h"
@ -23,15 +24,10 @@ namespace jni {
VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(JNIEnv* jni, VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(JNIEnv* jni,
jobject encoder_factory) jobject encoder_factory)
: encoder_factory_(jni, encoder_factory) { : encoder_factory_(jni, encoder_factory) {
jclass encoder_factory_class = jni->GetObjectClass(*encoder_factory_); const jobjectArray j_supported_codecs =
create_encoder_method_ = jni->GetMethodID( Java_VideoEncoderFactory_getSupportedCodecs(jni, encoder_factory);
encoder_factory_class, "createEncoder", supported_formats_ = JavaToNativeVector<SdpVideoFormat>(
"(Lorg/webrtc/VideoCodecInfo;)Lorg/webrtc/VideoEncoder;"); jni, j_supported_codecs, &VideoCodecInfoToSdpVideoFormat);
get_supported_codecs_method_ =
jni->GetMethodID(encoder_factory_class, "getSupportedCodecs",
"()[Lorg/webrtc/VideoCodecInfo;");
supported_formats_ = GetSupportedFormats(jni);
} }
std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder( std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder(
@ -39,8 +35,8 @@ std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder(
JNIEnv* jni = AttachCurrentThreadIfNeeded(); JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni); ScopedLocalRefFrame local_ref_frame(jni);
jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format); jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format);
jobject encoder = jni->CallObjectMethod(*encoder_factory_, jobject encoder = Java_VideoEncoderFactory_createEncoder(
create_encoder_method_, j_codec_info); jni, *encoder_factory_, j_codec_info);
return encoder != nullptr ? JavaToNativeVideoEncoder(jni, encoder) : nullptr; return encoder != nullptr ? JavaToNativeVideoEncoder(jni, encoder) : nullptr;
} }
@ -50,8 +46,8 @@ VideoEncoderFactory::CodecInfo VideoEncoderFactoryWrapper::QueryVideoEncoder(
ScopedLocalRefFrame local_ref_frame(jni); ScopedLocalRefFrame local_ref_frame(jni);
jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format); jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format);
jobject encoder = jni->CallObjectMethod(*encoder_factory_, jobject encoder = Java_VideoEncoderFactory_createEncoder(
create_encoder_method_, j_codec_info); jni, *encoder_factory_, j_codec_info);
CodecInfo codec_info; CodecInfo codec_info;
// Check if this is a wrapped native software encoder implementation. // Check if this is a wrapped native software encoder implementation.
@ -60,21 +56,5 @@ VideoEncoderFactory::CodecInfo VideoEncoderFactoryWrapper::QueryVideoEncoder(
return codec_info; return codec_info;
} }
std::vector<SdpVideoFormat> VideoEncoderFactoryWrapper::GetSupportedFormats(
JNIEnv* jni) const {
const jobjectArray j_supported_codecs = static_cast<jobjectArray>(
jni->CallObjectMethod(*encoder_factory_, get_supported_codecs_method_));
const jsize supported_codecs_count = jni->GetArrayLength(j_supported_codecs);
std::vector<SdpVideoFormat> 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 jni
} // namespace webrtc } // namespace webrtc

View File

@ -38,13 +38,7 @@ class VideoEncoderFactoryWrapper : public VideoEncoderFactory {
CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
private: private:
std::vector<SdpVideoFormat> GetSupportedFormats(JNIEnv* jni) const;
const ScopedGlobalRef<jobject> encoder_factory_; const ScopedGlobalRef<jobject> encoder_factory_;
jmethodID create_encoder_method_;
jmethodID get_supported_codecs_method_;
std::vector<SdpVideoFormat> supported_formats_; std::vector<SdpVideoFormat> supported_formats_;
}; };