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:

committed by
Commit Bot

parent
e51f785043
commit
3863153267
@ -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",
|
||||
]
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -15,10 +15,16 @@
|
||||
#include <unistd.h>
|
||||
#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/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<jobjectArray>(
|
||||
@ -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<jstring>(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<std::string, std::string> 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<std::string, std::string> 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<jstring>(jni->CallObjectMethod(j_entry, get_key_method));
|
||||
jstring j_value =
|
||||
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;
|
||||
@ -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
|
||||
|
@ -116,10 +116,6 @@ jstring NativeToJavaString(JNIEnv* jni, const std::string& native);
|
||||
jobject NativeToJavaInteger(JNIEnv* jni,
|
||||
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|;
|
||||
// |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<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 webrtc
|
||||
|
||||
|
@ -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<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(
|
||||
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<rtc::IPAddress>(
|
||||
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<NetworkInformation> 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<NetworkInformation> network_infos =
|
||||
JavaToNativeVector<NetworkInformation>(env, j_network_infos,
|
||||
&GetNetworkInformationFromJava);
|
||||
SetNetworkInfos(network_infos);
|
||||
}
|
||||
|
||||
|
@ -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,8 +49,9 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
|
||||
JNIEnv* jni,
|
||||
namespace {
|
||||
|
||||
rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(JNIEnv* jni,
|
||||
jobject j_pc) {
|
||||
jfieldID native_pc_id =
|
||||
GetFieldID(jni, GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
|
||||
@ -58,6 +60,17 @@ static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
|
||||
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,
|
||||
PeerConnection_freeObserver,
|
||||
JNIEnv*,
|
||||
@ -203,12 +216,9 @@ JNI_FUNCTION_DECLARATION(jboolean,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobjectArray j_candidates) {
|
||||
std::vector<cricket::Candidate> 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<cricket::Candidate> candidates =
|
||||
JavaToNativeVector<cricket::Candidate>(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, "<init>", "(J)V");
|
||||
|
||||
std::string kind = JavaToStdString(jni, j_kind);
|
||||
std::string stream_id = JavaToStdString(jni, j_stream_id);
|
||||
rtc::scoped_refptr<RtpSenderInterface> 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, "<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;
|
||||
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, "<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;
|
||||
return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetReceivers(),
|
||||
&NativeToJavaRtpReceiver);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(bool,
|
||||
|
@ -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<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
|
||||
|
||||
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_, "<init>", "()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<const RTCStatsReport>& 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<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 webrtc
|
||||
|
@ -30,15 +30,7 @@ class RTCStatsCollectorCallbackWrapper : public RTCStatsCollectorCallback {
|
||||
const rtc::scoped_refptr<const RTCStatsReport>& report) override;
|
||||
|
||||
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 jclass j_linked_hash_map_class_;
|
||||
const jmethodID j_linked_hash_map_ctor_;
|
||||
const jmethodID j_linked_hash_map_put_;
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
|
@ -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) {
|
||||
|
@ -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<SdpVideoFormat>(
|
||||
jni, j_supported_codecs, &VideoCodecInfoToSdpVideoFormat);
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder(
|
||||
@ -39,8 +35,8 @@ std::unique_ptr<VideoEncoder> 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<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 webrtc
|
||||
|
@ -38,13 +38,7 @@ class VideoEncoderFactoryWrapper : public VideoEncoderFactory {
|
||||
CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
|
||||
|
||||
private:
|
||||
std::vector<SdpVideoFormat> GetSupportedFormats(JNIEnv* jni) const;
|
||||
|
||||
const ScopedGlobalRef<jobject> encoder_factory_;
|
||||
|
||||
jmethodID create_encoder_method_;
|
||||
jmethodID get_supported_codecs_method_;
|
||||
|
||||
std::vector<SdpVideoFormat> supported_formats_;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user