Android: Use scoped java refs
We currently use raw jobject in our code mixed with sporadic ScopedLocalRefFrame. This CL moves every jobject into a scoped object, either local, global, or a parameter. Also, this CL uses the JNI generation script to generate declaration stubs for the Java->C++ functions so that it no longer becomes possible to mistype them without getting compilation errors. TBR=brandt@webrtc.org Bug: webrtc:8278,webrtc:6969 Change-Id: Ic7bac74a89c11180177d65041086d7db1cdfb516 Reviewed-on: https://webrtc-review.googlesource.com/34655 Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21387}
This commit is contained in:
committed by
Commit Bot
parent
ec22e3f503
commit
84d8ae5df7
@ -11,6 +11,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "sdk/android/generated_base_jni/jni/Histogram_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
@ -18,35 +19,30 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
Histogram_nativeCreateCounts,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jstring j_name,
|
||||
jint min,
|
||||
jint max,
|
||||
jint buckets) {
|
||||
static jlong JNI_Histogram_CreateCounts(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jstring>& j_name,
|
||||
jint min,
|
||||
jint max,
|
||||
jint buckets) {
|
||||
std::string name = JavaToStdString(jni, j_name);
|
||||
return jlongFromPointer(
|
||||
metrics::HistogramFactoryGetCounts(name, min, max, buckets));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
Histogram_nativeCreateEnumeration,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jstring j_name,
|
||||
jint max) {
|
||||
static jlong JNI_Histogram_CreateEnumeration(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jstring>& j_name,
|
||||
jint max) {
|
||||
std::string name = JavaToStdString(jni, j_name);
|
||||
return jlongFromPointer(metrics::HistogramFactoryGetEnumeration(name, max));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
Histogram_nativeAddSample,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong histogram,
|
||||
jint sample) {
|
||||
static void JNI_Histogram_AddSample(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong histogram,
|
||||
jint sample) {
|
||||
if (histogram) {
|
||||
HistogramAdd(reinterpret_cast<metrics::Histogram*>(histogram), sample);
|
||||
}
|
||||
|
||||
@ -130,10 +130,10 @@ class MediaCodecVideoDecoder : public VideoDecoder, public rtc::MessageHandler {
|
||||
// returns.
|
||||
std::unique_ptr<Thread>
|
||||
codec_thread_; // Thread on which to operate MediaCodec.
|
||||
ScopedGlobalRef<jobject> j_media_codec_video_decoder_;
|
||||
ScopedJavaGlobalRef<jobject> j_media_codec_video_decoder_;
|
||||
|
||||
// Global references; must be deleted in Release().
|
||||
std::vector<ScopedGlobalRef<jobject>> input_buffers_;
|
||||
std::vector<ScopedJavaGlobalRef<jobject>> input_buffers_;
|
||||
};
|
||||
|
||||
MediaCodecVideoDecoder::MediaCodecVideoDecoder(JNIEnv* jni,
|
||||
@ -225,7 +225,8 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
|
||||
|
||||
if (use_surface_) {
|
||||
surface_texture_helper_ = SurfaceTextureHelper::create(
|
||||
jni, "Decoder SurfaceTextureHelper", render_egl_context_);
|
||||
jni, "Decoder SurfaceTextureHelper",
|
||||
JavaParamRef<jobject>(render_egl_context_));
|
||||
if (!surface_texture_helper_) {
|
||||
ALOGE << "Couldn't create SurfaceTextureHelper - fallback to SW codec";
|
||||
sw_fallback_required_ = true;
|
||||
@ -233,13 +234,15 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
|
||||
}
|
||||
}
|
||||
|
||||
jobject j_video_codec_enum =
|
||||
ScopedJavaLocalRef<jobject> j_video_codec_enum =
|
||||
Java_VideoCodecType_fromNativeIndex(jni, codecType_);
|
||||
jobject j_surface_texture_helper =
|
||||
use_surface_
|
||||
? surface_texture_helper_->GetJavaSurfaceTextureHelper().obj()
|
||||
: nullptr;
|
||||
bool success = Java_MediaCodecVideoDecoder_initDecode(
|
||||
jni, *j_media_codec_video_decoder_, j_video_codec_enum, codec_.width,
|
||||
codec_.height,
|
||||
use_surface_ ? surface_texture_helper_->GetJavaSurfaceTextureHelper()
|
||||
: nullptr);
|
||||
jni, j_media_codec_video_decoder_, j_video_codec_enum, codec_.width,
|
||||
codec_.height, JavaParamRef<jobject>(j_surface_texture_helper));
|
||||
|
||||
if (CheckException(jni) || !success) {
|
||||
ALOGE << "Codec initialization error - fallback to SW codec.";
|
||||
@ -263,11 +266,13 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
|
||||
}
|
||||
ALOGD << "Maximum amount of pending frames: " << max_pending_frames_;
|
||||
|
||||
jobjectArray input_buffers = Java_MediaCodecVideoDecoder_getInputBuffers(
|
||||
jni, *j_media_codec_video_decoder_);
|
||||
input_buffers_ = JavaToNativeVector<ScopedGlobalRef<jobject>>(
|
||||
jni, input_buffers,
|
||||
[](JNIEnv* env, jobject o) { return ScopedGlobalRef<jobject>(env, o); });
|
||||
ScopedJavaLocalRef<jobjectArray> input_buffers =
|
||||
Java_MediaCodecVideoDecoder_getInputBuffers(jni,
|
||||
j_media_codec_video_decoder_);
|
||||
input_buffers_ = JavaToNativeVector<ScopedJavaGlobalRef<jobject>>(
|
||||
jni, input_buffers, [](JNIEnv* env, const JavaRef<jobject>& o) {
|
||||
return ScopedJavaGlobalRef<jobject>(env, o);
|
||||
});
|
||||
|
||||
codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this);
|
||||
|
||||
@ -287,7 +292,7 @@ int32_t MediaCodecVideoDecoder::ResetDecodeOnCodecThread() {
|
||||
rtc::MessageQueueManager::Clear(this);
|
||||
ResetVariables();
|
||||
|
||||
Java_MediaCodecVideoDecoder_reset(jni, *j_media_codec_video_decoder_,
|
||||
Java_MediaCodecVideoDecoder_reset(jni, j_media_codec_video_decoder_,
|
||||
codec_.width, codec_.height);
|
||||
|
||||
if (CheckException(jni)) {
|
||||
@ -318,7 +323,7 @@ int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() {
|
||||
frames_received_ << ". Frames decoded: " << frames_decoded_;
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
input_buffers_.clear();
|
||||
Java_MediaCodecVideoDecoder_release(jni, *j_media_codec_video_decoder_);
|
||||
Java_MediaCodecVideoDecoder_release(jni, j_media_codec_video_decoder_);
|
||||
surface_texture_helper_ = nullptr;
|
||||
inited_ = false;
|
||||
rtc::MessageQueueManager::Clear(this);
|
||||
@ -470,7 +475,7 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
|
||||
|
||||
// Get input buffer.
|
||||
int j_input_buffer_index = Java_MediaCodecVideoDecoder_dequeueInputBuffer(
|
||||
jni, *j_media_codec_video_decoder_);
|
||||
jni, j_media_codec_video_decoder_);
|
||||
if (CheckException(jni) || j_input_buffer_index < 0) {
|
||||
ALOGE << "dequeueInputBuffer error: " << j_input_buffer_index <<
|
||||
". Retry DeliverPendingOutputs.";
|
||||
@ -483,7 +488,7 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
|
||||
}
|
||||
// Try dequeue input buffer one last time.
|
||||
j_input_buffer_index = Java_MediaCodecVideoDecoder_dequeueInputBuffer(
|
||||
jni, *j_media_codec_video_decoder_);
|
||||
jni, j_media_codec_video_decoder_);
|
||||
if (CheckException(jni) || j_input_buffer_index < 0) {
|
||||
ALOGE << "dequeueInputBuffer critical error: " << j_input_buffer_index;
|
||||
return ProcessHWErrorOnCodecThread();
|
||||
@ -491,7 +496,7 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
|
||||
}
|
||||
|
||||
// Copy encoded data to Java ByteBuffer.
|
||||
jobject j_input_buffer = *input_buffers_[j_input_buffer_index];
|
||||
jobject j_input_buffer = input_buffers_[j_input_buffer_index].obj();
|
||||
uint8_t* buffer =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer));
|
||||
RTC_CHECK(buffer) << "Indirect buffer??";
|
||||
@ -534,7 +539,7 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
|
||||
|
||||
// Feed input to decoder.
|
||||
bool success = Java_MediaCodecVideoDecoder_queueInputBuffer(
|
||||
jni, *j_media_codec_video_decoder_, j_input_buffer_index,
|
||||
jni, j_media_codec_video_decoder_, j_input_buffer_index,
|
||||
inputImage._length, presentation_timestamp_us,
|
||||
static_cast<int64_t>(inputImage._timeStamp), inputImage.ntp_time_ms_);
|
||||
if (CheckException(jni) || !success) {
|
||||
@ -559,10 +564,10 @@ bool MediaCodecVideoDecoder::DeliverPendingOutputs(
|
||||
return true;
|
||||
}
|
||||
// Get decoder output.
|
||||
jobject j_decoder_output_buffer =
|
||||
ScopedJavaLocalRef<jobject> j_decoder_output_buffer =
|
||||
(use_surface_ ? &Java_MediaCodecVideoDecoder_dequeueTextureBuffer
|
||||
: &Java_MediaCodecVideoDecoder_dequeueOutputBuffer)(
|
||||
jni, *j_media_codec_video_decoder_, dequeue_timeout_ms);
|
||||
jni, j_media_codec_video_decoder_, dequeue_timeout_ms);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "dequeueOutputBuffer() error";
|
||||
return false;
|
||||
@ -574,11 +579,11 @@ bool MediaCodecVideoDecoder::DeliverPendingOutputs(
|
||||
|
||||
// Get decoded video frame properties.
|
||||
int color_format = Java_MediaCodecVideoDecoder_getColorFormat(
|
||||
jni, *j_media_codec_video_decoder_);
|
||||
jni, j_media_codec_video_decoder_);
|
||||
int width =
|
||||
Java_MediaCodecVideoDecoder_getWidth(jni, *j_media_codec_video_decoder_);
|
||||
Java_MediaCodecVideoDecoder_getWidth(jni, j_media_codec_video_decoder_);
|
||||
int height =
|
||||
Java_MediaCodecVideoDecoder_getHeight(jni, *j_media_codec_video_decoder_);
|
||||
Java_MediaCodecVideoDecoder_getHeight(jni, j_media_codec_video_decoder_);
|
||||
|
||||
rtc::scoped_refptr<VideoFrameBuffer> frame_buffer;
|
||||
int64_t presentation_timestamps_ms = 0;
|
||||
@ -601,7 +606,7 @@ bool MediaCodecVideoDecoder::DeliverPendingOutputs(
|
||||
const int texture_id =
|
||||
Java_DecodedTextureBuffer_getTextureId(jni, j_decoder_output_buffer);
|
||||
if (texture_id != 0) { // |texture_id| == 0 represents a dropped frame.
|
||||
const jfloatArray j_transform_matrix =
|
||||
ScopedJavaLocalRef<jfloatArray> j_transform_matrix =
|
||||
Java_DecodedTextureBuffer_getTransformMatrix(jni,
|
||||
j_decoder_output_buffer);
|
||||
frame_delayed_ms = Java_DecodedTextureBuffer_getFrameDelayMs(
|
||||
@ -617,9 +622,9 @@ bool MediaCodecVideoDecoder::DeliverPendingOutputs(
|
||||
// Extract data from Java ByteBuffer and create output yuv420 frame -
|
||||
// for non surface decoding only.
|
||||
int stride = Java_MediaCodecVideoDecoder_getStride(
|
||||
jni, *j_media_codec_video_decoder_);
|
||||
jni, j_media_codec_video_decoder_);
|
||||
const int slice_height = Java_MediaCodecVideoDecoder_getSliceHeight(
|
||||
jni, *j_media_codec_video_decoder_);
|
||||
jni, j_media_codec_video_decoder_);
|
||||
const int output_buffer_index =
|
||||
Java_DecodedOutputBuffer_getIndex(jni, j_decoder_output_buffer);
|
||||
const int output_buffer_offset =
|
||||
@ -648,10 +653,11 @@ bool MediaCodecVideoDecoder::DeliverPendingOutputs(
|
||||
// output byte buffer, so actual stride value need to be corrected.
|
||||
stride = output_buffer_size * 2 / (height * 3);
|
||||
}
|
||||
jobjectArray output_buffers = Java_MediaCodecVideoDecoder_getOutputBuffers(
|
||||
jni, *j_media_codec_video_decoder_);
|
||||
ScopedJavaLocalRef<jobjectArray> output_buffers =
|
||||
Java_MediaCodecVideoDecoder_getOutputBuffers(
|
||||
jni, j_media_codec_video_decoder_);
|
||||
jobject output_buffer =
|
||||
jni->GetObjectArrayElement(output_buffers, output_buffer_index);
|
||||
jni->GetObjectArrayElement(output_buffers.obj(), output_buffer_index);
|
||||
uint8_t* payload = reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(
|
||||
output_buffer));
|
||||
if (CheckException(jni)) {
|
||||
@ -714,7 +720,7 @@ bool MediaCodecVideoDecoder::DeliverPendingOutputs(
|
||||
|
||||
// Return output byte buffer back to codec.
|
||||
Java_MediaCodecVideoDecoder_returnDecodedOutputBuffer(
|
||||
jni, *j_media_codec_video_decoder_, output_buffer_index);
|
||||
jni, j_media_codec_video_decoder_, output_buffer_index);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "returnDecodedOutputBuffer error";
|
||||
return false;
|
||||
|
||||
@ -176,7 +176,7 @@ class MediaCodecVideoEncoder : public VideoEncoder {
|
||||
// frame.
|
||||
bool EncodeJavaFrame(JNIEnv* jni,
|
||||
bool key_frame,
|
||||
jobject frame,
|
||||
const JavaRef<jobject>& frame,
|
||||
int input_buffer_index);
|
||||
|
||||
// Deliver any outputs pending in the MediaCodec to our |callback_| and return
|
||||
@ -206,7 +206,7 @@ class MediaCodecVideoEncoder : public VideoEncoder {
|
||||
// State that is constant for the lifetime of this object once the ctor
|
||||
// returns.
|
||||
rtc::SequencedTaskChecker encoder_queue_checker_;
|
||||
ScopedGlobalRef<jobject> j_media_codec_video_encoder_;
|
||||
ScopedJavaGlobalRef<jobject> j_media_codec_video_encoder_;
|
||||
|
||||
// State that is valid only between InitEncode() and the next Release().
|
||||
int width_; // Frame width in pixels.
|
||||
@ -265,7 +265,7 @@ class MediaCodecVideoEncoder : public VideoEncoder {
|
||||
bool scale_;
|
||||
H264::Profile profile_;
|
||||
// Global references; must be deleted in Release().
|
||||
std::vector<ScopedGlobalRef<jobject>> input_buffers_;
|
||||
std::vector<ScopedJavaGlobalRef<jobject>> input_buffers_;
|
||||
H264BitstreamParser h264_bitstream_parser_;
|
||||
|
||||
// VP9 variables to populate codec specific structure.
|
||||
@ -521,11 +521,12 @@ int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width,
|
||||
frames_received_since_last_key_ = kMinKeyFrameInterval;
|
||||
|
||||
// We enforce no extra stride/padding in the format creation step.
|
||||
jobject j_video_codec_enum =
|
||||
ScopedJavaLocalRef<jobject> j_video_codec_enum =
|
||||
Java_VideoCodecType_fromNativeIndex(jni, codec_type);
|
||||
const bool encode_status = Java_MediaCodecVideoEncoder_initEncode(
|
||||
jni, *j_media_codec_video_encoder_, j_video_codec_enum, profile_, width,
|
||||
height, kbps, fps, (use_surface ? egl_context_ : nullptr));
|
||||
jni, j_media_codec_video_encoder_, j_video_codec_enum, profile_, width,
|
||||
height, kbps, fps,
|
||||
JavaParamRef<jobject>(use_surface ? egl_context_ : nullptr));
|
||||
if (!encode_status) {
|
||||
ALOGE << "Failed to configure encoder.";
|
||||
ProcessHWError(false /* reset_if_fallback_unavailable */);
|
||||
@ -538,8 +539,9 @@ int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width,
|
||||
}
|
||||
|
||||
if (!use_surface) {
|
||||
jobjectArray input_buffers = Java_MediaCodecVideoEncoder_getInputBuffers(
|
||||
jni, *j_media_codec_video_encoder_);
|
||||
ScopedJavaLocalRef<jobjectArray> input_buffers =
|
||||
Java_MediaCodecVideoEncoder_getInputBuffers(
|
||||
jni, j_media_codec_video_encoder_);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in get input buffers.";
|
||||
ProcessHWError(false /* reset_if_fallback_unavailable */);
|
||||
@ -552,7 +554,7 @@ int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width,
|
||||
}
|
||||
|
||||
switch (Java_MediaCodecVideoEncoder_getColorFormat(
|
||||
jni, *j_media_codec_video_encoder_)) {
|
||||
jni, j_media_codec_video_encoder_)) {
|
||||
case COLOR_FormatYUV420Planar:
|
||||
encoder_fourcc_ = libyuv::FOURCC_YU12;
|
||||
break;
|
||||
@ -569,12 +571,12 @@ int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width,
|
||||
|
||||
RTC_CHECK(input_buffers_.empty())
|
||||
<< "Unexpected double InitEncode without Release";
|
||||
input_buffers_ = JavaToNativeVector<ScopedGlobalRef<jobject>>(
|
||||
jni, input_buffers, [](JNIEnv* env, jobject o) {
|
||||
return ScopedGlobalRef<jobject>(env, o);
|
||||
input_buffers_ = JavaToNativeVector<ScopedJavaGlobalRef<jobject>>(
|
||||
jni, input_buffers, [](JNIEnv* env, const JavaRef<jobject>& o) {
|
||||
return ScopedJavaGlobalRef<jobject>(env, o);
|
||||
});
|
||||
for (const ScopedGlobalRef<jobject>& buffer : input_buffers_) {
|
||||
int64_t yuv_buffer_capacity = jni->GetDirectBufferCapacity(*buffer);
|
||||
for (const ScopedJavaGlobalRef<jobject>& buffer : input_buffers_) {
|
||||
int64_t yuv_buffer_capacity = jni->GetDirectBufferCapacity(buffer.obj());
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in get direct buffer capacity.";
|
||||
ProcessHWError(false /* reset_if_fallback_unavailable */);
|
||||
@ -689,7 +691,7 @@ int32_t MediaCodecVideoEncoder::Encode(
|
||||
int j_input_buffer_index = -1;
|
||||
if (!use_surface_) {
|
||||
j_input_buffer_index = Java_MediaCodecVideoEncoder_dequeueInputBuffer(
|
||||
jni, *j_media_codec_video_encoder_);
|
||||
jni, j_media_codec_video_encoder_);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in dequeu input buffer.";
|
||||
return ProcessHWErrorOnEncode();
|
||||
@ -833,7 +835,7 @@ bool MediaCodecVideoEncoder::EncodeByteBuffer(JNIEnv* jni,
|
||||
return false;
|
||||
}
|
||||
bool encode_status = Java_MediaCodecVideoEncoder_encodeBuffer(
|
||||
jni, *j_media_codec_video_encoder_, key_frame, input_buffer_index,
|
||||
jni, j_media_codec_video_encoder_, key_frame, input_buffer_index,
|
||||
yuv_size_, current_timestamp_us_);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in encode buffer.";
|
||||
@ -851,9 +853,8 @@ bool MediaCodecVideoEncoder::FillInputBuffer(JNIEnv* jni,
|
||||
int stride_u,
|
||||
uint8_t const* buffer_v,
|
||||
int stride_v) {
|
||||
jobject j_input_buffer = *input_buffers_[input_buffer_index];
|
||||
uint8_t* yuv_buffer =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer));
|
||||
uint8_t* yuv_buffer = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(input_buffers_[input_buffer_index].obj()));
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in get direct buffer address.";
|
||||
ProcessHWError(true /* reset_if_fallback_unavailable */);
|
||||
@ -877,10 +878,9 @@ bool MediaCodecVideoEncoder::EncodeTexture(JNIEnv* jni,
|
||||
static_cast<AndroidTextureBuffer*>(frame.video_frame_buffer().get())
|
||||
->native_handle_impl();
|
||||
|
||||
jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni);
|
||||
bool encode_status = Java_MediaCodecVideoEncoder_encodeTexture(
|
||||
jni, *j_media_codec_video_encoder_, key_frame, handle.oes_texture_id,
|
||||
sampling_matrix, current_timestamp_us_);
|
||||
jni, j_media_codec_video_encoder_, key_frame, handle.oes_texture_id,
|
||||
handle.sampling_matrix.ToJava(jni), current_timestamp_us_);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in encode texture.";
|
||||
ProcessHWError(true /* reset_if_fallback_unavailable */);
|
||||
@ -891,10 +891,10 @@ bool MediaCodecVideoEncoder::EncodeTexture(JNIEnv* jni,
|
||||
|
||||
bool MediaCodecVideoEncoder::EncodeJavaFrame(JNIEnv* jni,
|
||||
bool key_frame,
|
||||
jobject frame,
|
||||
const JavaRef<jobject>& frame,
|
||||
int input_buffer_index) {
|
||||
bool encode_status = Java_MediaCodecVideoEncoder_encodeFrame(
|
||||
jni, *j_media_codec_video_encoder_, jlongFromPointer(this), key_frame,
|
||||
jni, j_media_codec_video_encoder_, jlongFromPointer(this), key_frame,
|
||||
frame, input_buffer_index);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in encode frame.";
|
||||
@ -926,7 +926,7 @@ int32_t MediaCodecVideoEncoder::Release() {
|
||||
weak_factory_.reset(nullptr);
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
input_buffers_.clear();
|
||||
Java_MediaCodecVideoEncoder_release(jni, *j_media_codec_video_encoder_);
|
||||
Java_MediaCodecVideoEncoder_release(jni, j_media_codec_video_encoder_);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in release.";
|
||||
ProcessHWError(false /* reset_if_fallback_unavailable */);
|
||||
@ -966,8 +966,7 @@ int32_t MediaCodecVideoEncoder::SetRateAllocation(
|
||||
last_set_fps_ = frame_rate;
|
||||
}
|
||||
bool ret = Java_MediaCodecVideoEncoder_setRates(
|
||||
jni, *j_media_codec_video_encoder_, last_set_bitrate_kbps_,
|
||||
last_set_fps_);
|
||||
jni, j_media_codec_video_encoder_, last_set_bitrate_kbps_, last_set_fps_);
|
||||
if (CheckException(jni) || !ret) {
|
||||
ProcessHWError(true /* reset_if_fallback_unavailable */);
|
||||
return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_OK
|
||||
@ -980,9 +979,9 @@ bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_);
|
||||
|
||||
while (true) {
|
||||
jobject j_output_buffer_info =
|
||||
ScopedJavaLocalRef<jobject> j_output_buffer_info =
|
||||
Java_MediaCodecVideoEncoder_dequeueOutputBuffer(
|
||||
jni, *j_media_codec_video_encoder_);
|
||||
jni, j_media_codec_video_encoder_);
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in set dequeue output buffer.";
|
||||
ProcessHWError(true /* reset_if_fallback_unavailable */);
|
||||
@ -1000,7 +999,7 @@ bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) {
|
||||
}
|
||||
|
||||
// Get key and config frame flags.
|
||||
jobject j_output_buffer =
|
||||
ScopedJavaLocalRef<jobject> j_output_buffer =
|
||||
Java_OutputBufferInfo_getBuffer(jni, j_output_buffer_info);
|
||||
bool key_frame =
|
||||
Java_OutputBufferInfo_isKeyFrame(jni, j_output_buffer_info);
|
||||
@ -1022,9 +1021,9 @@ bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) {
|
||||
}
|
||||
|
||||
// Extract payload.
|
||||
size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer);
|
||||
size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer.obj());
|
||||
uint8_t* payload = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(j_output_buffer));
|
||||
jni->GetDirectBufferAddress(j_output_buffer.obj()));
|
||||
if (CheckException(jni)) {
|
||||
ALOGE << "Exception in get direct buffer address.";
|
||||
ProcessHWError(true /* reset_if_fallback_unavailable */);
|
||||
@ -1140,7 +1139,7 @@ bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) {
|
||||
|
||||
// Return output buffer back to the encoder.
|
||||
bool success = Java_MediaCodecVideoEncoder_releaseOutputBuffer(
|
||||
jni, *j_media_codec_video_encoder_, output_buffer_index);
|
||||
jni, j_media_codec_video_encoder_, output_buffer_index);
|
||||
if (CheckException(jni) || !success) {
|
||||
ProcessHWError(true /* reset_if_fallback_unavailable */);
|
||||
return false;
|
||||
@ -1345,24 +1344,23 @@ void MediaCodecVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder* encoder) {
|
||||
delete encoder;
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
MediaCodecVideoEncoder_fillInputBufferNative,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_encoder,
|
||||
jint input_buffer,
|
||||
jobject j_buffer_y,
|
||||
jint stride_y,
|
||||
jobject j_buffer_u,
|
||||
jint stride_u,
|
||||
jobject j_buffer_v,
|
||||
jint stride_v) {
|
||||
static void JNI_MediaCodecVideoEncoder_FillInputBuffer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_encoder,
|
||||
jint input_buffer,
|
||||
const JavaParamRef<jobject>& j_buffer_y,
|
||||
jint stride_y,
|
||||
const JavaParamRef<jobject>& j_buffer_u,
|
||||
jint stride_u,
|
||||
const JavaParamRef<jobject>& j_buffer_v,
|
||||
jint stride_v) {
|
||||
uint8_t* buffer_y =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_y));
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_y.obj()));
|
||||
uint8_t* buffer_u =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_u));
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_u.obj()));
|
||||
uint8_t* buffer_v =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_v));
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_v.obj()));
|
||||
|
||||
RTC_DCHECK(buffer_y) << "GetDirectBufferAddress returned null. Ensure that "
|
||||
"getDataY returns a direct ByteBuffer.";
|
||||
|
||||
@ -20,32 +20,29 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void, Metrics_enableNative, JNIEnv* jni, jclass) {
|
||||
static void JNI_Metrics_Enable(JNIEnv* jni, const JavaParamRef<jclass>&) {
|
||||
metrics::Enable();
|
||||
}
|
||||
|
||||
// Gets and clears native histograms.
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
Metrics_getAndResetNative,
|
||||
JNIEnv* jni,
|
||||
jclass) {
|
||||
jobject j_metrics = Java_Metrics_Constructor(jni);
|
||||
static ScopedJavaLocalRef<jobject> JNI_Metrics_GetAndReset(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>& jcaller) {
|
||||
ScopedJavaLocalRef<jobject> j_metrics = Java_Metrics_Constructor(jni);
|
||||
|
||||
std::map<std::string, std::unique_ptr<metrics::SampleInfo>> histograms;
|
||||
metrics::GetAndReset(&histograms);
|
||||
for (const auto& kv : histograms) {
|
||||
// Create and add samples to |HistogramInfo|.
|
||||
jobject j_info = Java_HistogramInfo_Constructor(
|
||||
ScopedJavaLocalRef<jobject> j_info = Java_HistogramInfo_Constructor(
|
||||
jni, kv.second->min, kv.second->max,
|
||||
static_cast<int>(kv.second->bucket_count));
|
||||
for (const auto& sample : kv.second->samples) {
|
||||
Java_HistogramInfo_addSample(jni, j_info, sample.first, sample.second);
|
||||
}
|
||||
// Add |HistogramInfo| to |Metrics|.
|
||||
jstring j_name = jni->NewStringUTF(kv.first.c_str());
|
||||
ScopedJavaLocalRef<jstring> j_name = NativeToJavaString(jni, kv.first);
|
||||
Java_Metrics_add(jni, j_metrics, j_name, j_info);
|
||||
jni->DeleteLocalRef(j_name);
|
||||
jni->DeleteLocalRef(j_info);
|
||||
}
|
||||
CHECK_EXCEPTION(jni);
|
||||
return j_metrics;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
#include "api/videosourceproxy.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_video_jni/jni/AndroidVideoTrackSourceObserver_jni.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoSource_jni.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
@ -38,7 +40,7 @@ AndroidVideoTrackSource* AndroidVideoTrackSourceFromJavaProxy(jlong j_proxy) {
|
||||
AndroidVideoTrackSource::AndroidVideoTrackSource(
|
||||
rtc::Thread* signaling_thread,
|
||||
JNIEnv* jni,
|
||||
jobject j_surface_texture_helper,
|
||||
const JavaRef<jobject>& j_surface_texture_helper,
|
||||
bool is_screencast)
|
||||
: AdaptedVideoTrackSource(kRequiredResolutionAlignment),
|
||||
signaling_thread_(signaling_thread),
|
||||
@ -164,12 +166,13 @@ void AndroidVideoTrackSource::OnTextureFrameCaptured(
|
||||
rotation, translated_camera_time_us));
|
||||
}
|
||||
|
||||
void AndroidVideoTrackSource::OnFrameCaptured(JNIEnv* jni,
|
||||
int width,
|
||||
int height,
|
||||
int64_t timestamp_ns,
|
||||
VideoRotation rotation,
|
||||
jobject j_video_frame_buffer) {
|
||||
void AndroidVideoTrackSource::OnFrameCaptured(
|
||||
JNIEnv* jni,
|
||||
int width,
|
||||
int height,
|
||||
int64_t timestamp_ns,
|
||||
VideoRotation rotation,
|
||||
const JavaRef<jobject>& j_video_frame_buffer) {
|
||||
RTC_DCHECK(camera_thread_checker_.CalledOnValidThread());
|
||||
|
||||
int64_t camera_time_us = timestamp_ns / rtc::kNumNanosecsPerMicrosec;
|
||||
@ -210,13 +213,11 @@ void AndroidVideoTrackSource::OnOutputFormatRequest(int width,
|
||||
video_adapter()->OnOutputFormatRequest(format);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(
|
||||
void,
|
||||
AndroidVideoTrackSourceObserver_nativeOnByteBufferFrameCaptured,
|
||||
static void JNI_AndroidVideoTrackSourceObserver_OnByteBufferFrameCaptured(
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_source,
|
||||
jbyteArray j_frame,
|
||||
const JavaParamRef<jbyteArray>& j_frame,
|
||||
jint length,
|
||||
jint width,
|
||||
jint height,
|
||||
@ -224,22 +225,20 @@ JNI_FUNCTION_DECLARATION(
|
||||
jlong timestamp) {
|
||||
AndroidVideoTrackSource* source =
|
||||
AndroidVideoTrackSourceFromJavaProxy(j_source);
|
||||
jbyte* bytes = jni->GetByteArrayElements(j_frame, nullptr);
|
||||
jbyte* bytes = jni->GetByteArrayElements(j_frame.obj(), nullptr);
|
||||
source->OnByteBufferFrameCaptured(bytes, length, width, height,
|
||||
jintToVideoRotation(rotation), timestamp);
|
||||
jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT);
|
||||
jni->ReleaseByteArrayElements(j_frame.obj(), bytes, JNI_ABORT);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(
|
||||
void,
|
||||
AndroidVideoTrackSourceObserver_nativeOnTextureFrameCaptured,
|
||||
static void JNI_AndroidVideoTrackSourceObserver_OnTextureFrameCaptured(
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_source,
|
||||
jint j_width,
|
||||
jint j_height,
|
||||
jint j_oes_texture_id,
|
||||
jfloatArray j_transform_matrix,
|
||||
const JavaParamRef<jfloatArray>& j_transform_matrix,
|
||||
jint j_rotation,
|
||||
jlong j_timestamp) {
|
||||
AndroidVideoTrackSource* source =
|
||||
@ -249,16 +248,15 @@ JNI_FUNCTION_DECLARATION(
|
||||
NativeHandleImpl(jni, j_oes_texture_id, j_transform_matrix));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
AndroidVideoTrackSourceObserver_nativeOnFrameCaptured,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_source,
|
||||
jint j_width,
|
||||
jint j_height,
|
||||
jint j_rotation,
|
||||
jlong j_timestamp_ns,
|
||||
jobject j_video_frame_buffer) {
|
||||
static void JNI_AndroidVideoTrackSourceObserver_OnFrameCaptured(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_source,
|
||||
jint j_width,
|
||||
jint j_height,
|
||||
jint j_rotation,
|
||||
jlong j_timestamp_ns,
|
||||
const JavaParamRef<jobject>& j_video_frame_buffer) {
|
||||
AndroidVideoTrackSource* source =
|
||||
AndroidVideoTrackSourceFromJavaProxy(j_source);
|
||||
source->OnFrameCaptured(jni, j_width, j_height, j_timestamp_ns,
|
||||
@ -266,12 +264,11 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
j_video_frame_buffer);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
AndroidVideoTrackSourceObserver_nativeCapturerStarted,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_source,
|
||||
jboolean j_success) {
|
||||
static void JNI_AndroidVideoTrackSourceObserver_CapturerStarted(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_source,
|
||||
jboolean j_success) {
|
||||
RTC_LOG(LS_INFO) << "AndroidVideoTrackSourceObserve_nativeCapturerStarted";
|
||||
AndroidVideoTrackSource* source =
|
||||
AndroidVideoTrackSourceFromJavaProxy(j_source);
|
||||
@ -279,25 +276,22 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
: AndroidVideoTrackSource::SourceState::kEnded);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
AndroidVideoTrackSourceObserver_nativeCapturerStopped,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_source) {
|
||||
static void JNI_AndroidVideoTrackSourceObserver_CapturerStopped(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_source) {
|
||||
RTC_LOG(LS_INFO) << "AndroidVideoTrackSourceObserve_nativeCapturerStopped";
|
||||
AndroidVideoTrackSource* source =
|
||||
AndroidVideoTrackSourceFromJavaProxy(j_source);
|
||||
source->SetState(AndroidVideoTrackSource::SourceState::kEnded);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
VideoSource_nativeAdaptOutputFormat,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_source,
|
||||
jint j_width,
|
||||
jint j_height,
|
||||
jint j_fps) {
|
||||
static void JNI_VideoSource_AdaptOutputFormat(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_source,
|
||||
jint j_width,
|
||||
jint j_height,
|
||||
jint j_fps) {
|
||||
RTC_LOG(LS_INFO) << "VideoSource_nativeAdaptOutputFormat";
|
||||
AndroidVideoTrackSource* source =
|
||||
AndroidVideoTrackSourceFromJavaProxy(j_source);
|
||||
|
||||
@ -30,7 +30,7 @@ class AndroidVideoTrackSource : public rtc::AdaptedVideoTrackSource {
|
||||
public:
|
||||
AndroidVideoTrackSource(rtc::Thread* signaling_thread,
|
||||
JNIEnv* jni,
|
||||
jobject j_surface_texture_helper,
|
||||
const JavaRef<jobject>& j_surface_texture_helper,
|
||||
bool is_screencast = false);
|
||||
|
||||
bool is_screencast() const override { return is_screencast_; }
|
||||
@ -65,7 +65,7 @@ class AndroidVideoTrackSource : public rtc::AdaptedVideoTrackSource {
|
||||
int height,
|
||||
int64_t timestamp_ns,
|
||||
VideoRotation rotation,
|
||||
jobject j_video_frame_buffer);
|
||||
const JavaRef<jobject>& j_video_frame_buffer);
|
||||
|
||||
void OnOutputFormatRequest(int width, int height, int fps);
|
||||
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/generated_base_jni/jni/WebRtcClassLoader_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
// Abort the process if |jni| has a Java exception pending. This macros uses the
|
||||
// comma operator to execute ExceptionDescribe and ExceptionClear ignoring their
|
||||
@ -30,7 +32,8 @@ namespace {
|
||||
|
||||
class ClassLoader {
|
||||
public:
|
||||
explicit ClassLoader(JNIEnv* env) {
|
||||
explicit ClassLoader(JNIEnv* env)
|
||||
: class_loader_(Java_WebRtcClassLoader_getClassLoader(env)) {
|
||||
class_loader_class_ = reinterpret_cast<jclass>(
|
||||
env->NewGlobalRef(env->FindClass("java/lang/ClassLoader")));
|
||||
CHECK_EXCEPTION(env);
|
||||
@ -38,27 +41,24 @@ class ClassLoader {
|
||||
env->GetMethodID(class_loader_class_, "loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
CHECK_EXCEPTION(env);
|
||||
class_loader_ =
|
||||
env->NewGlobalRef(Java_WebRtcClassLoader_getClassLoader(env));
|
||||
CHECK_EXCEPTION(env);
|
||||
}
|
||||
|
||||
jclass FindClass(JNIEnv* env, const char* c_name) {
|
||||
ScopedJavaLocalRef<jclass> FindClass(JNIEnv* env, const char* c_name) {
|
||||
// ClassLoader.loadClass expects a classname with components separated by
|
||||
// dots instead of the slashes that JNIEnv::FindClass expects.
|
||||
std::string name(c_name);
|
||||
std::replace(name.begin(), name.end(), '/', '.');
|
||||
jstring jstr = env->NewStringUTF(name.c_str());
|
||||
const jclass clazz = static_cast<jclass>(
|
||||
env->CallObjectMethod(class_loader_, load_class_method_, jstr));
|
||||
ScopedJavaLocalRef<jstring> j_name = NativeToJavaString(env, name);
|
||||
const jclass clazz = static_cast<jclass>(env->CallObjectMethod(
|
||||
class_loader_.obj(), load_class_method_, j_name.obj()));
|
||||
CHECK_EXCEPTION(env);
|
||||
return clazz;
|
||||
return ScopedJavaLocalRef<jclass>(env, clazz);
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedJavaGlobalRef<jobject> class_loader_;
|
||||
jclass class_loader_class_;
|
||||
jmethodID load_class_method_;
|
||||
jobject class_loader_;
|
||||
};
|
||||
|
||||
static ClassLoader* g_class_loader = nullptr;
|
||||
@ -70,11 +70,12 @@ void InitClassLoader(JNIEnv* env) {
|
||||
g_class_loader = new ClassLoader(env);
|
||||
}
|
||||
|
||||
jclass GetClass(JNIEnv* env, const char* name) {
|
||||
ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* name) {
|
||||
// The class loader will be null in the JNI code called from the ClassLoader
|
||||
// ctor when we are bootstrapping ourself.
|
||||
return (g_class_loader == nullptr) ? env->FindClass(name)
|
||||
: g_class_loader->FindClass(env, name);
|
||||
return (g_class_loader == nullptr)
|
||||
? ScopedJavaLocalRef<jclass>(env, env->FindClass(name))
|
||||
: g_class_loader->FindClass(env, name);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -32,7 +34,7 @@ void InitClassLoader(JNIEnv* env);
|
||||
// example, the fully-qualified class name for the java.lang.String class is:
|
||||
// "java/lang/String". This function will be used from the JNI generated code
|
||||
// and should rarely be used manually.
|
||||
jclass GetClass(JNIEnv* env, const char* name);
|
||||
ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* name);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -18,22 +18,28 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jobject NativeToJavaFrameType(JNIEnv* env, FrameType frame_type) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaFrameType(JNIEnv* env,
|
||||
FrameType frame_type) {
|
||||
return Java_FrameType_fromNativeIndex(env, frame_type);
|
||||
}
|
||||
|
||||
jobject NativeToJavaEncodedImage(JNIEnv* jni, const EncodedImage& image) {
|
||||
jobject buffer = jni->NewDirectByteBuffer(image._buffer, image._length);
|
||||
jobject frame_type = NativeToJavaFrameType(jni, image._frameType);
|
||||
jobject qp =
|
||||
(image.qp_ == -1) ? nullptr : NativeToJavaInteger(jni, image.qp_);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaEncodedImage(
|
||||
JNIEnv* jni,
|
||||
const EncodedImage& image) {
|
||||
ScopedJavaLocalRef<jobject> buffer =
|
||||
NewDirectByteBuffer(jni, image._buffer, image._length);
|
||||
ScopedJavaLocalRef<jobject> frame_type =
|
||||
NativeToJavaFrameType(jni, image._frameType);
|
||||
ScopedJavaLocalRef<jobject> qp;
|
||||
if (image.qp_ != -1)
|
||||
qp = NativeToJavaInteger(jni, image.qp_);
|
||||
return Java_EncodedImage_Constructor(
|
||||
jni, buffer, image._encodedWidth, image._encodedHeight,
|
||||
image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec, frame_type,
|
||||
static_cast<jint>(image.rotation_), image._completeFrame, qp);
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaFrameTypeArray(
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaFrameTypeArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<FrameType>& frame_types) {
|
||||
return NativeToJavaObjectArray(
|
||||
|
||||
@ -12,18 +12,21 @@
|
||||
#define SDK_ANDROID_SRC_JNI_ENCODEDIMAGE_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class EncodedImage;
|
||||
|
||||
namespace jni {
|
||||
|
||||
jobject NativeToJavaFrameType(JNIEnv* env, FrameType frame_type);
|
||||
jobject NativeToJavaEncodedImage(JNIEnv* jni, const EncodedImage& image);
|
||||
jobjectArray NativeToJavaFrameTypeArray(
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaFrameType(JNIEnv* env,
|
||||
FrameType frame_type);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaEncodedImage(JNIEnv* jni,
|
||||
const EncodedImage& image);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaFrameTypeArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<FrameType>& frame_types);
|
||||
|
||||
|
||||
@ -10,20 +10,18 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/h264_profile_level_id.h"
|
||||
#include "media/base/mediaconstants.h"
|
||||
#include "sdk/android/generated_video_jni/jni/HardwareVideoEncoderFactory_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
HardwareVideoEncoderFactory_isSameH264Profile,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject params1,
|
||||
jobject params2) {
|
||||
static jboolean JNI_HardwareVideoEncoderFactory_IsSameH264Profile(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& params1,
|
||||
const JavaParamRef<jobject>& params2) {
|
||||
return H264::IsSameH264Profile(JavaToStdMapStrings(jni, params1),
|
||||
JavaToStdMapStrings(jni, params2));
|
||||
}
|
||||
|
||||
@ -9,45 +9,39 @@
|
||||
*/
|
||||
|
||||
#include "rtc_base/refcount.h"
|
||||
#include "sdk/android/generated_base_jni/jni/JniCommon_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
JniCommon_nativeAddRef,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_native_ref_counted_pointer) {
|
||||
static void JNI_JniCommon_AddRef(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_native_ref_counted_pointer) {
|
||||
reinterpret_cast<rtc::RefCountInterface*>(j_native_ref_counted_pointer)
|
||||
->AddRef();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
JniCommon_nativeReleaseRef,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_native_ref_counted_pointer) {
|
||||
static void JNI_JniCommon_ReleaseRef(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_native_ref_counted_pointer) {
|
||||
reinterpret_cast<rtc::RefCountInterface*>(j_native_ref_counted_pointer)
|
||||
->Release();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
JniCommon_allocateNativeByteBuffer,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jint size) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_JniCommon_AllocateByteBuffer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jint size) {
|
||||
void* new_data = ::operator new(size);
|
||||
jobject byte_buffer = jni->NewDirectByteBuffer(new_data, size);
|
||||
return byte_buffer;
|
||||
return NewDirectByteBuffer(jni, new_data, size);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
JniCommon_freeNativeByteBuffer,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject byte_buffer) {
|
||||
void* data = jni->GetDirectBufferAddress(byte_buffer);
|
||||
static void JNI_JniCommon_FreeByteBuffer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& byte_buffer) {
|
||||
void* data = jni->GetDirectBufferAddress(byte_buffer.obj());
|
||||
::operator delete(data);
|
||||
}
|
||||
|
||||
|
||||
@ -28,22 +28,21 @@ jclass LazyGetClass(JNIEnv* env,
|
||||
rtc::AtomicOps::AcquireLoadPtr(atomic_class_id);
|
||||
if (value)
|
||||
return reinterpret_cast<jclass>(value);
|
||||
jclass clazz = static_cast<jclass>(
|
||||
env->NewGlobalRef(webrtc::jni::GetClass(env, class_name)));
|
||||
RTC_CHECK(clazz) << class_name;
|
||||
webrtc::jni::ScopedJavaGlobalRef<jclass> clazz(
|
||||
webrtc::jni::GetClass(env, class_name));
|
||||
RTC_CHECK(!clazz.is_null()) << class_name;
|
||||
base::subtle::AtomicWord null_aw = nullptr;
|
||||
base::subtle::AtomicWord cas_result = rtc::AtomicOps::CompareAndSwapPtr(
|
||||
atomic_class_id, null_aw,
|
||||
reinterpret_cast<base::subtle::AtomicWord>(clazz));
|
||||
reinterpret_cast<base::subtle::AtomicWord>(clazz.obj()));
|
||||
if (cas_result == null_aw) {
|
||||
// We sucessfully stored |clazz| in |atomic_class_id|, so we are
|
||||
// intentionally leaking the global ref since it's now stored there.
|
||||
return clazz;
|
||||
return clazz.Release();
|
||||
} else {
|
||||
// Some other thread came before us and stored a global pointer in
|
||||
// |atomic_class_id|. Relase our global ref and return the ref from the
|
||||
// other thread.
|
||||
env->DeleteGlobalRef(clazz);
|
||||
return reinterpret_cast<jclass>(cas_result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
#define CHECK_CLAZZ(env, jcaller, clazz, ...) RTC_DCHECK(clazz);
|
||||
#define CHECK_NATIVE_PTR(env, jcaller, native_ptr, method_name, ...) \
|
||||
@ -56,31 +57,9 @@ typedef void* AtomicWord;
|
||||
|
||||
namespace android {
|
||||
|
||||
// Implement JavaRef and ScopedJavaLocalRef as a shallow wrapper on top of a
|
||||
// jobject/jclass, with no scoped destruction.
|
||||
// TODO(magjed): Start using Chromium's scoped Java refs.
|
||||
template <typename T>
|
||||
class JavaRef {
|
||||
public:
|
||||
JavaRef() {}
|
||||
JavaRef(JNIEnv* env, T obj) : obj_(obj) {}
|
||||
T obj() const { return obj_; }
|
||||
|
||||
// Implicit on purpose.
|
||||
JavaRef(const T& obj) : obj_(obj) {} // NOLINT(runtime/explicit)
|
||||
operator T() const { return obj_; }
|
||||
|
||||
private:
|
||||
T obj_;
|
||||
};
|
||||
|
||||
// TODO(magjed): This looks weird, but it is safe. We don't use DeleteLocalRef
|
||||
// in WebRTC, we use ScopedLocalRefFrame instead. We should probably switch to
|
||||
// using DeleteLocalRef though.
|
||||
template <typename T>
|
||||
using ScopedJavaLocalRef = JavaRef<T>;
|
||||
template <typename T>
|
||||
using JavaParamRef = JavaRef<T>;
|
||||
using webrtc::jni::JavaRef;
|
||||
using webrtc::jni::ScopedJavaLocalRef;
|
||||
using webrtc::jni::JavaParamRef;
|
||||
|
||||
// This function will initialize |atomic_class_id| to contain a global ref to
|
||||
// the given class, and will return that ref on subsequent calls. The caller is
|
||||
|
||||
@ -150,87 +150,108 @@ jlong jlongFromPointer(void* ptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool IsNull(JNIEnv* jni, jobject obj) {
|
||||
return jni->IsSameObject(obj, nullptr);
|
||||
bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj) {
|
||||
return jni->IsSameObject(obj.obj(), nullptr);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NewDirectByteBuffer(JNIEnv* env,
|
||||
void* address,
|
||||
jlong capacity) {
|
||||
ScopedJavaLocalRef<jobject> buffer(
|
||||
env, env->NewDirectByteBuffer(address, capacity));
|
||||
CHECK_EXCEPTION(env) << "error NewDirectByteBuffer";
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Given a jstring, reinterprets it to a new native string.
|
||||
std::string JavaToStdString(JNIEnv* jni, const jstring& j_string) {
|
||||
const jbyteArray j_byte_array = Java_JniHelper_getStringBytes(jni, j_string);
|
||||
std::string JavaToStdString(JNIEnv* jni, const JavaRef<jstring>& j_string) {
|
||||
const ScopedJavaLocalRef<jbyteArray> j_byte_array =
|
||||
Java_JniHelper_getStringBytes(jni, j_string);
|
||||
|
||||
const size_t len = jni->GetArrayLength(j_byte_array);
|
||||
const size_t len = jni->GetArrayLength(j_byte_array.obj());
|
||||
CHECK_EXCEPTION(jni) << "error during GetArrayLength";
|
||||
std::string str(len, '\0');
|
||||
jni->GetByteArrayRegion(j_byte_array, 0, len,
|
||||
jni->GetByteArrayRegion(j_byte_array.obj(), 0, len,
|
||||
reinterpret_cast<jbyte*>(&str[0]));
|
||||
CHECK_EXCEPTION(jni) << "error during GetByteArrayRegion";
|
||||
return str;
|
||||
}
|
||||
|
||||
// Given a list of jstrings, reinterprets it to a new vector of native strings.
|
||||
std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni, jobject list) {
|
||||
std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni,
|
||||
const JavaRef<jobject>& list) {
|
||||
std::vector<std::string> converted_list;
|
||||
if (list != nullptr) {
|
||||
for (jobject str : Iterable(jni, list)) {
|
||||
converted_list.push_back(
|
||||
JavaToStdString(jni, reinterpret_cast<jstring>(str)));
|
||||
if (!list.is_null()) {
|
||||
for (const JavaRef<jobject>& str : Iterable(jni, list)) {
|
||||
converted_list.push_back(JavaToStdString(
|
||||
jni, JavaParamRef<jstring>(static_cast<jstring>(str.obj()))));
|
||||
}
|
||||
}
|
||||
return converted_list;
|
||||
}
|
||||
|
||||
rtc::Optional<int32_t> JavaToNativeOptionalInt(JNIEnv* jni, jobject integer) {
|
||||
rtc::Optional<int32_t> JavaToNativeOptionalInt(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& integer) {
|
||||
if (IsNull(jni, integer))
|
||||
return rtc::nullopt;
|
||||
return JNI_Integer::Java_Integer_intValue(jni, integer);
|
||||
}
|
||||
|
||||
rtc::Optional<bool> JavaToNativeOptionalBool(JNIEnv* jni, jobject boolean) {
|
||||
rtc::Optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
|
||||
const JavaRef<jobject>& boolean) {
|
||||
if (IsNull(jni, boolean))
|
||||
return rtc::nullopt;
|
||||
return JNI_Boolean::Java_Boolean_booleanValue(jni, boolean);
|
||||
}
|
||||
|
||||
int64_t JavaToNativeLong(JNIEnv* env, jobject j_long) {
|
||||
int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long) {
|
||||
return JNI_Long::Java_Long_longValue(env, j_long);
|
||||
}
|
||||
|
||||
jobject NativeToJavaBoolean(JNIEnv* env, bool b) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b) {
|
||||
return JNI_Boolean::Java_Boolean_ConstructorJLB_Z(env, b);
|
||||
}
|
||||
|
||||
jobject NativeToJavaInteger(JNIEnv* jni, int32_t i) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(JNIEnv* jni, int32_t i) {
|
||||
return JNI_Integer::Java_Integer_ConstructorJLI_I(jni, i);
|
||||
}
|
||||
|
||||
jobject NativeToJavaLong(JNIEnv* env, int64_t u) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaLong(JNIEnv* env, int64_t u) {
|
||||
return JNI_Long::Java_Long_ConstructorJLLO_J(env, u);
|
||||
}
|
||||
|
||||
jobject NativeToJavaDouble(JNIEnv* env, double d) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d) {
|
||||
return JNI_Double::Java_Double_ConstructorJLD_D(env, d);
|
||||
}
|
||||
|
||||
jstring NativeToJavaString(JNIEnv* jni, const std::string& native) {
|
||||
jstring jstr = jni->NewStringUTF(native.c_str());
|
||||
CHECK_EXCEPTION(jni) << "error during NewStringUTF";
|
||||
return jstr;
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* env, const char* str) {
|
||||
jstring j_str = env->NewStringUTF(str);
|
||||
CHECK_EXCEPTION(env) << "error during NewStringUTF";
|
||||
return ScopedJavaLocalRef<jstring>(env, j_str);
|
||||
}
|
||||
|
||||
jobject NativeToJavaInteger(JNIEnv* jni,
|
||||
const rtc::Optional<int32_t>& optional_int) {
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni,
|
||||
const std::string& str) {
|
||||
return NativeToJavaString(jni, str.c_str());
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(
|
||||
JNIEnv* jni,
|
||||
const rtc::Optional<int32_t>& optional_int) {
|
||||
return optional_int ? NativeToJavaInteger(jni, *optional_int) : nullptr;
|
||||
}
|
||||
|
||||
std::string GetJavaEnumName(JNIEnv* jni, jobject j_enum) {
|
||||
std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum) {
|
||||
return JavaToStdString(jni, JNI_Enum::Java_Enum_name(jni, j_enum));
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
|
||||
jobject j_map) {
|
||||
jobject j_entry_set = JNI_Map::Java_Map_entrySet(jni, j_map);
|
||||
std::map<std::string, std::string> JavaToStdMapStrings(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_map) {
|
||||
const JavaRef<jobject>& j_entry_set = JNI_Map::Java_Map_entrySet(jni, j_map);
|
||||
std::map<std::string, std::string> result;
|
||||
for (jobject j_entry : Iterable(jni, j_entry_set)) {
|
||||
for (const JavaRef<jobject>& j_entry : Iterable(jni, j_entry_set)) {
|
||||
result.insert(std::make_pair(
|
||||
JavaToStdString(jni, Java_JniHelper_getKey(jni, j_entry)),
|
||||
JavaToStdString(jni, Java_JniHelper_getValue(jni, j_entry))));
|
||||
@ -261,13 +282,19 @@ ScopedLocalRefFrame::~ScopedLocalRefFrame() {
|
||||
jni_->PopLocalFrame(nullptr);
|
||||
}
|
||||
|
||||
Iterable::Iterable(JNIEnv* jni, const JavaRef<jobject>& iterable)
|
||||
: jni_(jni), iterable_(jni, iterable) {}
|
||||
|
||||
Iterable::~Iterable() = default;
|
||||
|
||||
// Creates an iterator representing the end of any collection.
|
||||
Iterable::Iterator::Iterator() : iterator_(nullptr) {}
|
||||
Iterable::Iterator::Iterator() = default;
|
||||
|
||||
// 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, const JavaRef<jobject>& iterable)
|
||||
: jni_(jni) {
|
||||
iterator_ = JNI_Iterable::Java_Iterable_iterator(jni, iterable);
|
||||
RTC_CHECK(iterator_);
|
||||
RTC_CHECK(!iterator_.is_null());
|
||||
// Start at the first element in the collection.
|
||||
++(*this);
|
||||
}
|
||||
@ -280,6 +307,8 @@ Iterable::Iterator::Iterator(Iterator&& other)
|
||||
value_(std::move(other.value_)),
|
||||
thread_checker_(std::move(other.thread_checker_)){};
|
||||
|
||||
Iterable::Iterator::~Iterator() = default;
|
||||
|
||||
// Advances the iterator one step.
|
||||
Iterable::Iterator& Iterable::Iterator::operator++() {
|
||||
RTC_CHECK(thread_checker_.CalledOnValidThread());
|
||||
@ -311,7 +340,7 @@ bool Iterable::Iterator::operator==(const Iterable::Iterator& other) {
|
||||
return AtEnd() == other.AtEnd();
|
||||
}
|
||||
|
||||
jobject Iterable::Iterator::operator*() {
|
||||
ScopedJavaLocalRef<jobject>& Iterable::Iterator::operator*() {
|
||||
RTC_CHECK(!AtEnd());
|
||||
return value_;
|
||||
}
|
||||
@ -321,56 +350,63 @@ bool Iterable::Iterator::AtEnd() const {
|
||||
return jni_ == nullptr || IsNull(jni_, iterator_);
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaIntegerArray(JNIEnv* env,
|
||||
const std::vector<int32_t>& container) {
|
||||
jobject (*convert_function)(JNIEnv*, int32_t) = &NativeToJavaInteger;
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaIntegerArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int32_t>& container) {
|
||||
ScopedJavaLocalRef<jobject> (*convert_function)(JNIEnv*, int32_t) =
|
||||
&NativeToJavaInteger;
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Integer_clazz(env),
|
||||
convert_function);
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaBooleanArray(JNIEnv* env,
|
||||
const std::vector<bool>& container) {
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaBooleanArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<bool>& container) {
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Boolean_clazz(env),
|
||||
&NativeToJavaBoolean);
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaDoubleArray(JNIEnv* env,
|
||||
const std::vector<double>& container) {
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaDoubleArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<double>& container) {
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Double_clazz(env),
|
||||
&NativeToJavaDouble);
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaLongArray(JNIEnv* env,
|
||||
const std::vector<int64_t>& container) {
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaLongArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int64_t>& container) {
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Long_clazz(env),
|
||||
&NativeToJavaLong);
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaStringArray(
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaStringArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<std::string>& container) {
|
||||
ScopedJavaLocalRef<jstring> (*convert)(JNIEnv*, const std::string&) =
|
||||
&NativeToJavaString;
|
||||
return NativeToJavaObjectArray(
|
||||
env, container,
|
||||
static_cast<jclass>(Java_JniHelper_getStringClass(env).obj()),
|
||||
&NativeToJavaString);
|
||||
static_cast<jclass>(Java_JniHelper_getStringClass(env).obj()), convert);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
JavaMapBuilder::~JavaMapBuilder() = default;
|
||||
|
||||
jobject JavaMapBuilder::GetJavaMap() {
|
||||
return j_map_;
|
||||
void JavaMapBuilder::put(const JavaRef<jobject>& key,
|
||||
const JavaRef<jobject>& value) {
|
||||
JNI_Map::Java_Map_put(env_, j_map_, key, value);
|
||||
}
|
||||
|
||||
JavaListBuilder::JavaListBuilder(JNIEnv* env)
|
||||
: env_(env), j_list_(JNI_ArrayList::Java_ArrayList_ConstructorJUALI(env)) {}
|
||||
|
||||
void JavaListBuilder::add(jobject element) {
|
||||
JavaListBuilder::~JavaListBuilder() = default;
|
||||
|
||||
void JavaListBuilder::add(const JavaRef<jobject>& element) {
|
||||
JNI_ArrayList::Java_ArrayList_addZ_JUE(env_, j_list_, element);
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "rtc_base/refcount.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
// Abort the process if |jni| has a Java exception pending.
|
||||
// This macros uses the comma operator to execute ExceptionDescribe
|
||||
@ -57,34 +58,54 @@ JNIEnv* AttachCurrentThreadIfNeeded();
|
||||
jlong jlongFromPointer(void* ptr);
|
||||
|
||||
// Returns true if |obj| == null in Java.
|
||||
bool IsNull(JNIEnv* jni, jobject obj);
|
||||
bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj);
|
||||
|
||||
ScopedJavaLocalRef<jobject> NewDirectByteBuffer(JNIEnv* env,
|
||||
void* address,
|
||||
jlong capacity);
|
||||
// Given a (UTF-16) jstring return a new UTF-8 native string.
|
||||
std::string JavaToStdString(JNIEnv* jni, const jstring& j_string);
|
||||
std::string JavaToStdString(JNIEnv* jni, const JavaRef<jstring>& j_string);
|
||||
|
||||
// Deprecated. Use scoped jobjects instead.
|
||||
inline std::string JavaToStdString(JNIEnv* jni, jstring j_string) {
|
||||
return JavaToStdString(jni, JavaParamRef<jstring>(j_string));
|
||||
}
|
||||
|
||||
// Given a List of (UTF-16) jstrings
|
||||
// return a new vector of UTF-8 native strings.
|
||||
std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni, jobject list);
|
||||
std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni,
|
||||
const JavaRef<jobject>& list);
|
||||
|
||||
rtc::Optional<int32_t> JavaToNativeOptionalInt(JNIEnv* jni, jobject integer);
|
||||
rtc::Optional<bool> JavaToNativeOptionalBool(JNIEnv* jni, jobject boolean);
|
||||
int64_t JavaToNativeLong(JNIEnv* env, jobject j_long);
|
||||
rtc::Optional<int32_t> JavaToNativeOptionalInt(JNIEnv* jni,
|
||||
const JavaRef<jobject>& integer);
|
||||
rtc::Optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
|
||||
const JavaRef<jobject>& boolean);
|
||||
int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long);
|
||||
|
||||
jobject NativeToJavaBoolean(JNIEnv* env, bool b);
|
||||
jobject NativeToJavaInteger(JNIEnv* jni, int32_t i);
|
||||
jobject NativeToJavaLong(JNIEnv* env, int64_t u);
|
||||
jobject NativeToJavaDouble(JNIEnv* env, double d);
|
||||
// Given a UTF-8 encoded |native| string return a new (UTF-16) jstring.
|
||||
jstring NativeToJavaString(JNIEnv* jni, const std::string& native);
|
||||
jobject NativeToJavaInteger(JNIEnv* jni,
|
||||
const rtc::Optional<int32_t>& optional_int);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(JNIEnv* jni, int32_t i);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaLong(JNIEnv* env, int64_t u);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d);
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni, const char* str);
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni,
|
||||
const std::string& str);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(
|
||||
JNIEnv* jni,
|
||||
const rtc::Optional<int32_t>& optional_int);
|
||||
|
||||
// Parses Map<String, String> to std::map<std::string, std::string>.
|
||||
std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
|
||||
jobject j_map);
|
||||
std::map<std::string, std::string> JavaToStdMapStrings(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_map);
|
||||
|
||||
// Deprecated. Use scoped jobjects instead.
|
||||
inline std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
|
||||
jobject j_map) {
|
||||
return JavaToStdMapStrings(jni, JavaParamRef<jobject>(j_map));
|
||||
}
|
||||
|
||||
// Returns the name of a Java enum.
|
||||
std::string GetJavaEnumName(JNIEnv* jni, jobject j_enum);
|
||||
std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum);
|
||||
|
||||
jobject NewGlobalRef(JNIEnv* jni, jobject o);
|
||||
|
||||
@ -102,30 +123,6 @@ class ScopedLocalRefFrame {
|
||||
JNIEnv* jni_;
|
||||
};
|
||||
|
||||
// Scoped holder for global Java refs.
|
||||
template<class T> // T is jclass, jobject, jintArray, etc.
|
||||
class ScopedGlobalRef {
|
||||
public:
|
||||
ScopedGlobalRef(JNIEnv* jni, T obj)
|
||||
: obj_(static_cast<T>(jni->NewGlobalRef(obj))) {}
|
||||
|
||||
ScopedGlobalRef(ScopedGlobalRef&& other) : obj_(other.obj_) {
|
||||
other.obj_ = nullptr;
|
||||
}
|
||||
|
||||
~ScopedGlobalRef() {
|
||||
if (obj_) {
|
||||
DeleteGlobalRef(AttachCurrentThreadIfNeeded(), obj_);
|
||||
}
|
||||
}
|
||||
T operator*() const {
|
||||
return obj_;
|
||||
}
|
||||
private:
|
||||
T obj_;
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ScopedGlobalRef);
|
||||
};
|
||||
|
||||
// Provides a convenient way to iterate over a Java Iterable using the
|
||||
// C++ range-for loop.
|
||||
// E.g. for (jobject value : Iterable(jni, j_iterable)) { ... }
|
||||
@ -134,7 +131,8 @@ class ScopedGlobalRef {
|
||||
// Java iterator.
|
||||
class Iterable {
|
||||
public:
|
||||
Iterable(JNIEnv* jni, jobject iterable) : jni_(jni), iterable_(iterable) {}
|
||||
Iterable(JNIEnv* jni, const JavaRef<jobject>& iterable);
|
||||
~Iterable();
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
@ -142,12 +140,14 @@ class Iterable {
|
||||
Iterator();
|
||||
// Creates an iterator pointing to the beginning of the specified
|
||||
// collection.
|
||||
Iterator(JNIEnv* jni, jobject iterable);
|
||||
Iterator(JNIEnv* jni, const JavaRef<jobject>& iterable);
|
||||
|
||||
// Move constructor - necessary to be able to return iterator types from
|
||||
// functions.
|
||||
Iterator(Iterator&& other);
|
||||
|
||||
~Iterator();
|
||||
|
||||
// Move assignment should not be used.
|
||||
Iterator& operator=(Iterator&&) = delete;
|
||||
|
||||
@ -164,14 +164,14 @@ class Iterable {
|
||||
// iterators.
|
||||
bool operator==(const Iterator& other);
|
||||
bool operator!=(const Iterator& other) { return !(*this == other); }
|
||||
jobject operator*();
|
||||
ScopedJavaLocalRef<jobject>& operator*();
|
||||
|
||||
private:
|
||||
bool AtEnd() const;
|
||||
|
||||
JNIEnv* jni_ = nullptr;
|
||||
jobject iterator_ = nullptr;
|
||||
jobject value_ = nullptr;
|
||||
ScopedJavaLocalRef<jobject> iterator_;
|
||||
ScopedJavaLocalRef<jobject> value_;
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(Iterator);
|
||||
@ -182,52 +182,56 @@ class Iterable {
|
||||
|
||||
private:
|
||||
JNIEnv* jni_;
|
||||
jobject iterable_;
|
||||
ScopedJavaLocalRef<jobject> iterable_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(Iterable);
|
||||
};
|
||||
|
||||
// Helper function for converting std::vector<T> into a Java array.
|
||||
template <typename T, typename Convert>
|
||||
jobjectArray NativeToJavaObjectArray(JNIEnv* env,
|
||||
const std::vector<T>& container,
|
||||
jclass clazz,
|
||||
Convert convert) {
|
||||
jobjectArray j_container =
|
||||
env->NewObjectArray(container.size(), clazz, nullptr);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaObjectArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<T>& container,
|
||||
jclass clazz,
|
||||
Convert convert) {
|
||||
ScopedJavaLocalRef<jobjectArray> j_container(
|
||||
env, env->NewObjectArray(container.size(), clazz, nullptr));
|
||||
int i = 0;
|
||||
for (const T& element : container) {
|
||||
jobject j_element = convert(env, element);
|
||||
env->SetObjectArrayElement(j_container, i, j_element);
|
||||
// Delete local ref immediately since we might create a lot of local
|
||||
// references in this loop.
|
||||
env->DeleteLocalRef(j_element);
|
||||
env->SetObjectArrayElement(j_container.obj(), i,
|
||||
convert(env, element).obj());
|
||||
++i;
|
||||
}
|
||||
return j_container;
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaIntegerArray(JNIEnv* env,
|
||||
const std::vector<int32_t>& container);
|
||||
jobjectArray NativeToJavaBooleanArray(JNIEnv* env,
|
||||
const std::vector<bool>& container);
|
||||
jobjectArray NativeToJavaLongArray(JNIEnv* env,
|
||||
const std::vector<int64_t>& container);
|
||||
jobjectArray NativeToJavaDoubleArray(JNIEnv* env,
|
||||
const std::vector<double>& container);
|
||||
jobjectArray NativeToJavaStringArray(JNIEnv* env,
|
||||
const std::vector<std::string>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaIntegerArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int32_t>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaBooleanArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<bool>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaLongArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int64_t>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaDoubleArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<double>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaStringArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<std::string>& container);
|
||||
|
||||
template <typename T, typename Convert>
|
||||
std::vector<T> JavaToNativeVector(JNIEnv* env,
|
||||
jobjectArray j_container,
|
||||
const JavaRef<jobjectArray>& j_container,
|
||||
Convert convert) {
|
||||
std::vector<T> container;
|
||||
const size_t size = env->GetArrayLength(j_container);
|
||||
const size_t size = env->GetArrayLength(j_container.obj());
|
||||
container.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
container.emplace_back(
|
||||
convert(env, env->GetObjectArrayElement(j_container, i)));
|
||||
container.emplace_back(convert(
|
||||
env, ScopedJavaLocalRef<jobject>(
|
||||
env, env->GetObjectArrayElement(j_container.obj(), i))));
|
||||
}
|
||||
CHECK_EXCEPTION(env) << "Error during JavaToNativeVector";
|
||||
return container;
|
||||
@ -238,16 +242,19 @@ std::vector<T> JavaToNativeVector(JNIEnv* env,
|
||||
class JavaListBuilder {
|
||||
public:
|
||||
explicit JavaListBuilder(JNIEnv* env);
|
||||
void add(jobject element);
|
||||
jobject java_list() { return j_list_; }
|
||||
~JavaListBuilder();
|
||||
void add(const JavaRef<jobject>& element);
|
||||
ScopedJavaLocalRef<jobject> java_list() { return j_list_; }
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jobject j_list_;
|
||||
ScopedJavaLocalRef<jobject> j_list_;
|
||||
};
|
||||
|
||||
template <typename C, typename Convert>
|
||||
jobject NativeToJavaList(JNIEnv* env, const C& container, Convert convert) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaList(JNIEnv* env,
|
||||
const C& container,
|
||||
Convert convert) {
|
||||
JavaListBuilder builder(env);
|
||||
for (const auto& e : container)
|
||||
builder.add(convert(env, e));
|
||||
@ -259,16 +266,19 @@ jobject NativeToJavaList(JNIEnv* env, const C& container, Convert convert) {
|
||||
class JavaMapBuilder {
|
||||
public:
|
||||
explicit JavaMapBuilder(JNIEnv* env);
|
||||
void put(jobject key, jobject value);
|
||||
jobject GetJavaMap();
|
||||
~JavaMapBuilder();
|
||||
void put(const JavaRef<jobject>& key, const JavaRef<jobject>& value);
|
||||
ScopedJavaLocalRef<jobject> GetJavaMap() { return j_map_; }
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jobject j_map_;
|
||||
ScopedJavaLocalRef<jobject> j_map_;
|
||||
};
|
||||
|
||||
template <typename C, typename Convert>
|
||||
jobject NativeToJavaMap(JNIEnv* env, const C& container, Convert convert) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaMap(JNIEnv* env,
|
||||
const C& container,
|
||||
Convert convert) {
|
||||
JavaMapBuilder builder(env);
|
||||
for (const auto& e : container) {
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
|
||||
@ -15,30 +15,30 @@
|
||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/generated_video_jni/jni/NV12Buffer_jni.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_webrtc_NV12Buffer_nativeCropAndScale(JNIEnv* jni,
|
||||
jclass,
|
||||
jint crop_x,
|
||||
jint crop_y,
|
||||
jint crop_width,
|
||||
jint crop_height,
|
||||
jint scale_width,
|
||||
jint scale_height,
|
||||
jobject j_src,
|
||||
jint src_width,
|
||||
jint src_height,
|
||||
jint src_stride,
|
||||
jint src_slice_height,
|
||||
jobject j_dst_y,
|
||||
jint dst_stride_y,
|
||||
jobject j_dst_u,
|
||||
jint dst_stride_u,
|
||||
jobject j_dst_v,
|
||||
jint dst_stride_v) {
|
||||
static void JNI_NV12Buffer_CropAndScale(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jint crop_x,
|
||||
jint crop_y,
|
||||
jint crop_width,
|
||||
jint crop_height,
|
||||
jint scale_width,
|
||||
jint scale_height,
|
||||
const JavaParamRef<jobject>& j_src,
|
||||
jint src_width,
|
||||
jint src_height,
|
||||
jint src_stride,
|
||||
jint src_slice_height,
|
||||
const JavaParamRef<jobject>& j_dst_y,
|
||||
jint dst_stride_y,
|
||||
const JavaParamRef<jobject>& j_dst_u,
|
||||
jint dst_stride_u,
|
||||
const JavaParamRef<jobject>& j_dst_v,
|
||||
jint dst_stride_v) {
|
||||
const int src_stride_y = src_stride;
|
||||
const int src_stride_uv = src_stride;
|
||||
const int crop_chroma_x = crop_x / 2;
|
||||
@ -50,12 +50,15 @@ Java_org_webrtc_NV12Buffer_nativeCropAndScale(JNIEnv* jni,
|
||||
const int tmp_size = crop_chroma_height * (tmp_stride_u + tmp_stride_v);
|
||||
|
||||
uint8_t const* src_y =
|
||||
static_cast<uint8_t const*>(jni->GetDirectBufferAddress(j_src));
|
||||
static_cast<uint8_t const*>(jni->GetDirectBufferAddress(j_src.obj()));
|
||||
uint8_t const* src_uv = src_y + src_slice_height * src_stride_y;
|
||||
|
||||
uint8_t* dst_y = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y));
|
||||
uint8_t* dst_u = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u));
|
||||
uint8_t* dst_v = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v));
|
||||
uint8_t* dst_y =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y.obj()));
|
||||
uint8_t* dst_u =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u.obj()));
|
||||
uint8_t* dst_v =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v.obj()));
|
||||
|
||||
// Crop using pointer arithmetic.
|
||||
src_y += crop_x + crop_y * src_stride_y;
|
||||
|
||||
@ -16,28 +16,28 @@
|
||||
|
||||
#include "common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/generated_video_jni/jni/NV21Buffer_jni.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_webrtc_NV21Buffer_nativeCropAndScale(JNIEnv* jni,
|
||||
jclass,
|
||||
jint crop_x,
|
||||
jint crop_y,
|
||||
jint crop_width,
|
||||
jint crop_height,
|
||||
jint scale_width,
|
||||
jint scale_height,
|
||||
jbyteArray j_src,
|
||||
jint src_width,
|
||||
jint src_height,
|
||||
jobject j_dst_y,
|
||||
jint dst_stride_y,
|
||||
jobject j_dst_u,
|
||||
jint dst_stride_u,
|
||||
jobject j_dst_v,
|
||||
jint dst_stride_v) {
|
||||
static void JNI_NV21Buffer_CropAndScale(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jint crop_x,
|
||||
jint crop_y,
|
||||
jint crop_width,
|
||||
jint crop_height,
|
||||
jint scale_width,
|
||||
jint scale_height,
|
||||
const JavaParamRef<jbyteArray>& j_src,
|
||||
jint src_width,
|
||||
jint src_height,
|
||||
const JavaParamRef<jobject>& j_dst_y,
|
||||
jint dst_stride_y,
|
||||
const JavaParamRef<jobject>& j_dst_u,
|
||||
jint dst_stride_u,
|
||||
const JavaParamRef<jobject>& j_dst_v,
|
||||
jint dst_stride_v) {
|
||||
const int src_stride_y = src_width;
|
||||
const int src_stride_uv = src_width;
|
||||
const int crop_chroma_x = crop_x / 2;
|
||||
@ -49,14 +49,17 @@ Java_org_webrtc_NV21Buffer_nativeCropAndScale(JNIEnv* jni,
|
||||
const int tmp_size = crop_chroma_height * (tmp_stride_u + tmp_stride_v);
|
||||
|
||||
jboolean was_copy;
|
||||
jbyte* src_bytes = jni->GetByteArrayElements(j_src, &was_copy);
|
||||
jbyte* src_bytes = jni->GetByteArrayElements(j_src.obj(), &was_copy);
|
||||
RTC_DCHECK(!was_copy);
|
||||
uint8_t const* src_y = reinterpret_cast<uint8_t const*>(src_bytes);
|
||||
uint8_t const* src_uv = src_y + src_height * src_stride_y;
|
||||
|
||||
uint8_t* dst_y = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y));
|
||||
uint8_t* dst_u = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u));
|
||||
uint8_t* dst_v = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v));
|
||||
uint8_t* dst_y =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y.obj()));
|
||||
uint8_t* dst_u =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u.obj()));
|
||||
uint8_t* dst_v =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v.obj()));
|
||||
|
||||
// Crop using pointer arithmetic.
|
||||
src_y += crop_x + crop_y * src_stride_y;
|
||||
@ -68,7 +71,7 @@ Java_org_webrtc_NV21Buffer_nativeCropAndScale(JNIEnv* jni,
|
||||
crop_height, dst_y, dst_stride_y, dst_v, dst_stride_v,
|
||||
dst_u, dst_stride_u, scale_width, scale_height);
|
||||
|
||||
jni->ReleaseByteArrayElements(j_src, src_bytes, JNI_ABORT);
|
||||
jni->ReleaseByteArrayElements(j_src.obj(), src_bytes, JNI_ABORT);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -29,7 +29,9 @@ enum AndroidSdkVersion {
|
||||
SDK_VERSION_MARSHMALLOW = 23
|
||||
};
|
||||
|
||||
static NetworkType GetNetworkTypeFromJava(JNIEnv* jni, jobject j_network_type) {
|
||||
static NetworkType GetNetworkTypeFromJava(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_network_type) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_network_type);
|
||||
if (enum_name == "CONNECTION_UNKNOWN") {
|
||||
return NetworkType::NETWORK_UNKNOWN;
|
||||
@ -85,29 +87,32 @@ static rtc::AdapterType AdapterTypeFromNetworkType(NetworkType network_type) {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
static rtc::IPAddress JavaToNativeIpAddress(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_ip_address) {
|
||||
ScopedJavaLocalRef<jbyteArray> j_addresses =
|
||||
Java_IPAddress_getAddress(jni, j_ip_address);
|
||||
size_t address_length = jni->GetArrayLength(j_addresses.obj());
|
||||
jbyte* addr_array = jni->GetByteArrayElements(j_addresses.obj(), nullptr);
|
||||
CHECK_EXCEPTION(jni) << "Error during JavaToNativeIpAddress";
|
||||
if (address_length == 4) {
|
||||
// IP4
|
||||
struct in_addr ip4_addr;
|
||||
memcpy(&ip4_addr.s_addr, addr_array, 4);
|
||||
jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
|
||||
jni->ReleaseByteArrayElements(j_addresses.obj(), addr_array, JNI_ABORT);
|
||||
return rtc::IPAddress(ip4_addr);
|
||||
}
|
||||
// IP6
|
||||
RTC_CHECK(address_length == 16);
|
||||
struct in6_addr ip6_addr;
|
||||
memcpy(ip6_addr.s6_addr, addr_array, address_length);
|
||||
jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
|
||||
jni->ReleaseByteArrayElements(j_addresses.obj(), addr_array, JNI_ABORT);
|
||||
return rtc::IPAddress(ip6_addr);
|
||||
}
|
||||
|
||||
static NetworkInformation GetNetworkInformationFromJava(
|
||||
JNIEnv* jni,
|
||||
jobject j_network_info) {
|
||||
const JavaRef<jobject>& j_network_info) {
|
||||
NetworkInformation network_info;
|
||||
network_info.interface_name = JavaToStdString(
|
||||
jni, Java_NetworkInformation_getName(jni, j_network_info));
|
||||
@ -115,7 +120,7 @@ static NetworkInformation GetNetworkInformationFromJava(
|
||||
Java_NetworkInformation_getHandle(jni, j_network_info));
|
||||
network_info.type = GetNetworkTypeFromJava(
|
||||
jni, Java_NetworkInformation_getConnectionType(jni, j_network_info));
|
||||
jobjectArray j_ip_addresses =
|
||||
ScopedJavaLocalRef<jobjectArray> j_ip_addresses =
|
||||
Java_NetworkInformation_getIpAddresses(jni, j_network_info);
|
||||
network_info.ip_addresses = JavaToNativeVector<rtc::IPAddress>(
|
||||
jni, j_ip_addresses, &JavaToNativeIpAddress);
|
||||
@ -150,7 +155,7 @@ void AndroidNetworkMonitor::Start() {
|
||||
worker_thread()->socketserver()->set_network_binder(this);
|
||||
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_NetworkMonitor_startMonitoring(env, *j_network_monitor_,
|
||||
Java_NetworkMonitor_startMonitoring(env, j_network_monitor_,
|
||||
jlongFromPointer(this));
|
||||
}
|
||||
|
||||
@ -168,7 +173,7 @@ void AndroidNetworkMonitor::Stop() {
|
||||
}
|
||||
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_NetworkMonitor_stopMonitoring(env, *j_network_monitor_,
|
||||
Java_NetworkMonitor_stopMonitoring(env, j_network_monitor_,
|
||||
jlongFromPointer(this));
|
||||
|
||||
network_handle_by_address_.clear();
|
||||
@ -186,7 +191,7 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
// networks. This may also occur if there is no connectivity manager service.
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
const bool network_binding_supported =
|
||||
Java_NetworkMonitor_networkBindingSupported(env, *j_network_monitor_);
|
||||
Java_NetworkMonitor_networkBindingSupported(env, j_network_monitor_);
|
||||
if (!network_binding_supported) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "BindSocketToNetwork is not supported on this platform "
|
||||
@ -341,32 +346,35 @@ AndroidNetworkMonitorFactory::CreateNetworkMonitor() {
|
||||
return new AndroidNetworkMonitor(AttachCurrentThreadIfNeeded());
|
||||
}
|
||||
|
||||
void AndroidNetworkMonitor::NotifyConnectionTypeChanged(JNIEnv* env,
|
||||
jobject j_caller) {
|
||||
void AndroidNetworkMonitor::NotifyConnectionTypeChanged(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_caller) {
|
||||
OnNetworksChanged();
|
||||
}
|
||||
|
||||
void AndroidNetworkMonitor::NotifyOfActiveNetworkList(
|
||||
JNIEnv* env,
|
||||
jobject j_caller,
|
||||
jobjectArray j_network_infos) {
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobjectArray>& j_network_infos) {
|
||||
std::vector<NetworkInformation> network_infos =
|
||||
JavaToNativeVector<NetworkInformation>(env, j_network_infos,
|
||||
&GetNetworkInformationFromJava);
|
||||
SetNetworkInfos(network_infos);
|
||||
}
|
||||
|
||||
void AndroidNetworkMonitor::NotifyOfNetworkConnect(JNIEnv* env,
|
||||
jobject j_caller,
|
||||
jobject j_network_info) {
|
||||
void AndroidNetworkMonitor::NotifyOfNetworkConnect(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobject>& j_network_info) {
|
||||
NetworkInformation network_info =
|
||||
GetNetworkInformationFromJava(env, j_network_info);
|
||||
OnNetworkConnected(network_info);
|
||||
}
|
||||
|
||||
void AndroidNetworkMonitor::NotifyOfNetworkDisconnect(JNIEnv* env,
|
||||
jobject j_caller,
|
||||
jlong network_handle) {
|
||||
void AndroidNetworkMonitor::NotifyOfNetworkDisconnect(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_caller,
|
||||
jlong network_handle) {
|
||||
OnNetworkDisconnected(static_cast<NetworkHandle>(network_handle));
|
||||
}
|
||||
|
||||
|
||||
@ -69,23 +69,24 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorBase,
|
||||
// Always expected to be called on the network thread.
|
||||
void SetNetworkInfos(const std::vector<NetworkInformation>& network_infos);
|
||||
|
||||
void NotifyConnectionTypeChanged(JNIEnv* env, jobject j_caller);
|
||||
void NotifyConnectionTypeChanged(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_caller);
|
||||
void NotifyOfNetworkConnect(JNIEnv* env,
|
||||
jobject j_caller,
|
||||
jobject j_network_info);
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobject>& j_network_info);
|
||||
void NotifyOfNetworkDisconnect(JNIEnv* env,
|
||||
jobject j_caller,
|
||||
const JavaRef<jobject>& j_caller,
|
||||
jlong network_handle);
|
||||
void NotifyOfActiveNetworkList(JNIEnv* env,
|
||||
jobject j_caller,
|
||||
jobjectArray j_network_infos);
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobjectArray>& j_network_infos);
|
||||
|
||||
private:
|
||||
void OnNetworkConnected_w(const NetworkInformation& network_info);
|
||||
void OnNetworkDisconnected_w(NetworkHandle network_handle);
|
||||
|
||||
const int android_sdk_int_;
|
||||
ScopedGlobalRef<jobject> j_network_monitor_;
|
||||
ScopedJavaGlobalRef<jobject> j_network_monitor_;
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
bool started_ = false;
|
||||
std::map<std::string, rtc::AdapterType> adapter_type_by_name_;
|
||||
|
||||
@ -9,17 +9,15 @@
|
||||
*/
|
||||
|
||||
#include "api/mediastreaminterface.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/AudioTrack_jni.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
AudioTrack_nativeSetVolume,
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
jlong j_p,
|
||||
jdouble volume) {
|
||||
static void JNI_AudioTrack_SetVolume(JNIEnv*,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p,
|
||||
jdouble volume) {
|
||||
rtc::scoped_refptr<AudioSourceInterface> source(
|
||||
reinterpret_cast<AudioTrackInterface*>(j_p)->GetSource());
|
||||
source->SetVolume(volume);
|
||||
|
||||
@ -9,18 +9,18 @@
|
||||
*/
|
||||
|
||||
#include "rtc_base/logsinks.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/CallSessionFileRotatingLogSink_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
CallSessionFileRotatingLogSink_nativeAddSink,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jstring j_dirPath,
|
||||
jint j_maxFileSize,
|
||||
jint j_severity) {
|
||||
static jlong JNI_CallSessionFileRotatingLogSink_AddSink(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jstring>& j_dirPath,
|
||||
jint j_maxFileSize,
|
||||
jint j_severity) {
|
||||
std::string dir_path = JavaToStdString(jni, j_dirPath);
|
||||
rtc::CallSessionFileRotatingLogSink* sink =
|
||||
new rtc::CallSessionFileRotatingLogSink(dir_path, j_maxFileSize);
|
||||
@ -33,46 +33,46 @@ JNI_FUNCTION_DECLARATION(jlong,
|
||||
}
|
||||
rtc::LogMessage::AddLogToStream(
|
||||
sink, static_cast<rtc::LoggingSeverity>(j_severity));
|
||||
return (jlong)sink;
|
||||
return jlongFromPointer(sink);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
CallSessionFileRotatingLogSink_nativeDeleteSink,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_sink) {
|
||||
static void JNI_CallSessionFileRotatingLogSink_DeleteSink(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_sink) {
|
||||
rtc::CallSessionFileRotatingLogSink* sink =
|
||||
reinterpret_cast<rtc::CallSessionFileRotatingLogSink*>(j_sink);
|
||||
rtc::LogMessage::RemoveLogToStream(sink);
|
||||
delete sink;
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jbyteArray,
|
||||
CallSessionFileRotatingLogSink_nativeGetLogData,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jstring j_dirPath) {
|
||||
static ScopedJavaLocalRef<jbyteArray>
|
||||
JNI_CallSessionFileRotatingLogSink_GetLogData(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jstring>& j_dirPath) {
|
||||
std::string dir_path = JavaToStdString(jni, j_dirPath);
|
||||
std::unique_ptr<rtc::CallSessionFileRotatingStream> stream(
|
||||
new rtc::CallSessionFileRotatingStream(dir_path));
|
||||
if (!stream->Open()) {
|
||||
RTC_LOG_V(rtc::LoggingSeverity::LS_WARNING)
|
||||
<< "Failed to open CallSessionFileRotatingStream for path " << dir_path;
|
||||
return jni->NewByteArray(0);
|
||||
return ScopedJavaLocalRef<jbyteArray>(jni, jni->NewByteArray(0));
|
||||
}
|
||||
size_t log_size = 0;
|
||||
if (!stream->GetSize(&log_size) || log_size == 0) {
|
||||
RTC_LOG_V(rtc::LoggingSeverity::LS_WARNING)
|
||||
<< "CallSessionFileRotatingStream returns 0 size for path " << dir_path;
|
||||
return jni->NewByteArray(0);
|
||||
return ScopedJavaLocalRef<jbyteArray>(jni, jni->NewByteArray(0));
|
||||
}
|
||||
|
||||
size_t read = 0;
|
||||
std::unique_ptr<jbyte> buffer(static_cast<jbyte*>(malloc(log_size)));
|
||||
stream->ReadAll(buffer.get(), log_size, &read, nullptr);
|
||||
|
||||
jbyteArray result = jni->NewByteArray(read);
|
||||
jni->SetByteArrayRegion(result, 0, read, buffer.get());
|
||||
ScopedJavaLocalRef<jbyteArray> result =
|
||||
ScopedJavaLocalRef<jbyteArray>(jni, jni->NewByteArray(read));
|
||||
jni->SetByteArrayRegion(result.obj(), 0, read, buffer.get());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ namespace {
|
||||
// and dispatching the callback from C++ back to Java.
|
||||
class DataChannelObserverJni : public DataChannelObserver {
|
||||
public:
|
||||
DataChannelObserverJni(JNIEnv* jni, jobject j_observer);
|
||||
DataChannelObserverJni(JNIEnv* jni, const JavaRef<jobject>& j_observer);
|
||||
virtual ~DataChannelObserverJni() {}
|
||||
|
||||
void OnBufferedAmountChange(uint64_t previous_amount) override;
|
||||
@ -35,40 +35,44 @@ class DataChannelObserverJni : public DataChannelObserver {
|
||||
void OnMessage(const DataBuffer& buffer) override;
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> j_observer_global_;
|
||||
const ScopedJavaGlobalRef<jobject> j_observer_global_;
|
||||
};
|
||||
|
||||
DataChannelObserverJni::DataChannelObserverJni(JNIEnv* jni, jobject j_observer)
|
||||
DataChannelObserverJni::DataChannelObserverJni(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_observer)
|
||||
: j_observer_global_(jni, j_observer) {}
|
||||
|
||||
void DataChannelObserverJni::OnBufferedAmountChange(uint64_t previous_amount) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_Observer_onBufferedAmountChange(env, *j_observer_global_,
|
||||
Java_Observer_onBufferedAmountChange(env, j_observer_global_,
|
||||
previous_amount);
|
||||
}
|
||||
|
||||
void DataChannelObserverJni::OnStateChange() {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_Observer_onStateChange(env, *j_observer_global_);
|
||||
Java_Observer_onStateChange(env, j_observer_global_);
|
||||
}
|
||||
|
||||
void DataChannelObserverJni::OnMessage(const DataBuffer& buffer) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
jobject byte_buffer = env->NewDirectByteBuffer(
|
||||
const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
|
||||
jobject j_buffer = Java_Buffer_Constructor(env, byte_buffer, buffer.binary);
|
||||
Java_Observer_onMessage(env, *j_observer_global_, j_buffer);
|
||||
ScopedJavaLocalRef<jobject> byte_buffer = NewDirectByteBuffer(
|
||||
env, const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
|
||||
ScopedJavaLocalRef<jobject> j_buffer =
|
||||
Java_Buffer_Constructor(env, byte_buffer, buffer.binary);
|
||||
Java_Observer_onMessage(env, j_observer_global_, j_buffer);
|
||||
}
|
||||
|
||||
DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
|
||||
jlong j_d = Java_DataChannel_getNativeDataChannel(jni, j_dc);
|
||||
return reinterpret_cast<DataChannelInterface*>(j_d);
|
||||
DataChannelInterface* ExtractNativeDC(JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc) {
|
||||
return reinterpret_cast<DataChannelInterface*>(
|
||||
Java_DataChannel_getNativeDataChannel(jni, j_dc));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env, jobject j_init) {
|
||||
DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_init) {
|
||||
DataChannelInit init;
|
||||
init.ordered = Java_Init_getOrdered(env, j_init);
|
||||
init.maxRetransmitTime = Java_Init_getMaxRetransmitTimeMs(env, j_init);
|
||||
@ -79,79 +83,72 @@ DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env, jobject j_init) {
|
||||
return init;
|
||||
}
|
||||
|
||||
jobject WrapNativeDataChannel(
|
||||
ScopedJavaLocalRef<jobject> WrapNativeDataChannel(
|
||||
JNIEnv* env,
|
||||
rtc::scoped_refptr<DataChannelInterface> channel) {
|
||||
if (!channel)
|
||||
return nullptr;
|
||||
// Channel is now owned by Java object, and will be freed from there.
|
||||
return channel ? Java_DataChannel_Constructor(
|
||||
env, jlongFromPointer(channel.release()))
|
||||
: nullptr;
|
||||
return Java_DataChannel_Constructor(env, jlongFromPointer(channel.release()));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
DataChannel_registerObserverNative,
|
||||
JNIEnv* jni,
|
||||
jobject j_dc,
|
||||
jobject j_observer) {
|
||||
static jlong JNI_DataChannel_RegisterObserver(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc,
|
||||
const JavaParamRef<jobject>& j_observer) {
|
||||
auto observer = rtc::MakeUnique<DataChannelObserverJni>(jni, j_observer);
|
||||
ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
|
||||
return jlongFromPointer(observer.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
DataChannel_unregisterObserverNative,
|
||||
JNIEnv* jni,
|
||||
jobject j_dc,
|
||||
jlong native_observer) {
|
||||
static void JNI_DataChannel_UnregisterObserver(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc,
|
||||
jlong native_observer) {
|
||||
ExtractNativeDC(jni, j_dc)->UnregisterObserver();
|
||||
delete reinterpret_cast<DataChannelObserverJni*>(native_observer);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
DataChannel_label,
|
||||
JNIEnv* jni,
|
||||
jobject j_dc) {
|
||||
static ScopedJavaLocalRef<jstring> JNI_DataChannel_Label(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc) {
|
||||
return NativeToJavaString(jni, ExtractNativeDC(jni, j_dc)->label());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jint, DataChannel_id, JNIEnv* jni, jobject j_dc) {
|
||||
static jint JNI_DataChannel_Id(JNIEnv* jni, const JavaParamRef<jobject>& j_dc) {
|
||||
int id = ExtractNativeDC(jni, j_dc)->id();
|
||||
RTC_CHECK_LE(id, std::numeric_limits<int32_t>::max())
|
||||
<< "id overflowed jint!";
|
||||
return static_cast<jint>(id);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
DataChannel_state,
|
||||
JNIEnv* jni,
|
||||
jobject j_dc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_DataChannel_State(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc) {
|
||||
return Java_State_fromNativeIndex(jni, ExtractNativeDC(jni, j_dc)->state());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
DataChannel_bufferedAmount,
|
||||
JNIEnv* jni,
|
||||
jobject j_dc) {
|
||||
static jlong JNI_DataChannel_BufferedAmount(JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc) {
|
||||
uint64_t buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
|
||||
RTC_CHECK_LE(buffered_amount, std::numeric_limits<int64_t>::max())
|
||||
<< "buffered_amount overflowed jlong!";
|
||||
return static_cast<jlong>(buffered_amount);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void, DataChannel_close, JNIEnv* jni, jobject j_dc) {
|
||||
static void JNI_DataChannel_Close(JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc) {
|
||||
ExtractNativeDC(jni, j_dc)->Close();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
DataChannel_sendNative,
|
||||
JNIEnv* jni,
|
||||
jobject j_dc,
|
||||
jbyteArray data,
|
||||
jboolean binary) {
|
||||
jbyte* bytes = jni->GetByteArrayElements(data, nullptr);
|
||||
static jboolean JNI_DataChannel_Send(JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_dc,
|
||||
const JavaParamRef<jbyteArray>& data,
|
||||
jboolean binary) {
|
||||
jbyte* bytes = jni->GetByteArrayElements(data.obj(), nullptr);
|
||||
bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
|
||||
rtc::CopyOnWriteBuffer(bytes, jni->GetArrayLength(data)), binary));
|
||||
jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
|
||||
rtc::CopyOnWriteBuffer(bytes, jni->GetArrayLength(data.obj())), binary));
|
||||
jni->ReleaseByteArrayElements(data.obj(), bytes, JNI_ABORT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -14,10 +14,12 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env, jobject j_init);
|
||||
DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_init);
|
||||
|
||||
jobject WrapNativeDataChannel(JNIEnv* env,
|
||||
rtc::scoped_refptr<DataChannelInterface> channel);
|
||||
ScopedJavaLocalRef<jobject> WrapNativeDataChannel(
|
||||
JNIEnv* env,
|
||||
rtc::scoped_refptr<DataChannelInterface> channel);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -12,16 +12,15 @@
|
||||
|
||||
#include "modules/audio_processing/include/audio_processing.h"
|
||||
#include "rtc_base/scoped_ref_ptr.h"
|
||||
#include "sdk/android/generated_audio_jni/jni/DefaultAudioProcessingFactory_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(
|
||||
jlong,
|
||||
DefaultAudioProcessingFactory_nativeCreateAudioProcessing,
|
||||
static jlong JNI_DefaultAudioProcessingFactory_CreateAudioProcessing(
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_post_processor) {
|
||||
std::unique_ptr<PostProcessing> post_processor(
|
||||
reinterpret_cast<PostProcessing*>(native_post_processor));
|
||||
|
||||
@ -9,56 +9,48 @@
|
||||
*/
|
||||
|
||||
#include "api/dtmfsenderinterface.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/DtmfSender_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
DtmfSender_nativeCanInsertDtmf,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
static jboolean JNI_DtmfSender_CanInsertDtmf(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
return reinterpret_cast<DtmfSenderInterface*>(j_dtmf_sender_pointer)
|
||||
->CanInsertDtmf();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
DtmfSender_nativeInsertDtmf,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_dtmf_sender_pointer,
|
||||
jstring tones,
|
||||
jint duration,
|
||||
jint inter_tone_gap) {
|
||||
static jboolean JNI_DtmfSender_InsertDtmf(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_dtmf_sender_pointer,
|
||||
const JavaParamRef<jstring>& tones,
|
||||
jint duration,
|
||||
jint inter_tone_gap) {
|
||||
return reinterpret_cast<DtmfSenderInterface*>(j_dtmf_sender_pointer)
|
||||
->InsertDtmf(JavaToStdString(jni, tones), duration, inter_tone_gap);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
DtmfSender_nativeTones,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
static ScopedJavaLocalRef<jstring> JNI_DtmfSender_Tones(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
return NativeToJavaString(
|
||||
jni,
|
||||
reinterpret_cast<DtmfSenderInterface*>(j_dtmf_sender_pointer)->tones());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jint,
|
||||
DtmfSender_nativeDuration,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
static jint JNI_DtmfSender_Duration(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
return reinterpret_cast<DtmfSenderInterface*>(j_dtmf_sender_pointer)
|
||||
->duration();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jint,
|
||||
DtmfSender_nativeInterToneGap,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
static jint JNI_DtmfSender_InterToneGap(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_dtmf_sender_pointer) {
|
||||
return reinterpret_cast<DtmfSenderInterface*>(j_dtmf_sender_pointer)
|
||||
->inter_tone_gap();
|
||||
}
|
||||
|
||||
@ -21,11 +21,12 @@ namespace jni {
|
||||
|
||||
namespace {
|
||||
|
||||
jobject CreateJavaIceCandidate(JNIEnv* env,
|
||||
const std::string& sdp_mid,
|
||||
int sdp_mline_index,
|
||||
const std::string& sdp,
|
||||
const std::string server_url) {
|
||||
ScopedJavaLocalRef<jobject> CreateJavaIceCandidate(
|
||||
JNIEnv* env,
|
||||
const std::string& sdp_mid,
|
||||
int sdp_mline_index,
|
||||
const std::string& sdp,
|
||||
const std::string server_url) {
|
||||
return Java_IceCandidate_Constructor(
|
||||
env, NativeToJavaString(env, sdp_mid), sdp_mline_index,
|
||||
NativeToJavaString(env, sdp), NativeToJavaString(env, server_url));
|
||||
@ -33,7 +34,8 @@ jobject CreateJavaIceCandidate(JNIEnv* env,
|
||||
|
||||
} // namespace
|
||||
|
||||
cricket::Candidate JavaToNativeCandidate(JNIEnv* jni, jobject j_candidate) {
|
||||
cricket::Candidate JavaToNativeCandidate(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_candidate) {
|
||||
std::string sdp_mid =
|
||||
JavaToStdString(jni, Java_IceCandidate_getSdpMid(jni, j_candidate));
|
||||
std::string sdp =
|
||||
@ -45,8 +47,9 @@ cricket::Candidate JavaToNativeCandidate(JNIEnv* jni, jobject j_candidate) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
jobject NativeToJavaCandidate(JNIEnv* env,
|
||||
const cricket::Candidate& candidate) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaCandidate(
|
||||
JNIEnv* env,
|
||||
const cricket::Candidate& candidate) {
|
||||
std::string sdp = SdpSerializeCandidate(candidate);
|
||||
RTC_CHECK(!sdp.empty()) << "got an empty ICE candidate";
|
||||
// sdp_mline_index is not used, pass an invalid value -1.
|
||||
@ -55,8 +58,9 @@ jobject NativeToJavaCandidate(JNIEnv* env,
|
||||
"" /* server_url */);
|
||||
}
|
||||
|
||||
jobject NativeToJavaIceCandidate(JNIEnv* env,
|
||||
const IceCandidateInterface& candidate) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaIceCandidate(
|
||||
JNIEnv* env,
|
||||
const IceCandidateInterface& candidate) {
|
||||
std::string sdp;
|
||||
RTC_CHECK(candidate.ToString(&sdp)) << "got so far: " << sdp;
|
||||
return CreateJavaIceCandidate(env, candidate.sdp_mid(),
|
||||
@ -64,7 +68,7 @@ jobject NativeToJavaIceCandidate(JNIEnv* env,
|
||||
candidate.candidate().url());
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaCandidateArray(
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaCandidateArray(
|
||||
JNIEnv* jni,
|
||||
const std::vector<cricket::Candidate>& candidates) {
|
||||
return NativeToJavaObjectArray(jni, candidates,
|
||||
@ -74,7 +78,7 @@ jobjectArray NativeToJavaCandidateArray(
|
||||
|
||||
PeerConnectionInterface::IceTransportsType JavaToNativeIceTransportsType(
|
||||
JNIEnv* jni,
|
||||
jobject j_ice_transports_type) {
|
||||
const JavaRef<jobject>& j_ice_transports_type) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_ice_transports_type);
|
||||
|
||||
if (enum_name == "ALL")
|
||||
@ -95,7 +99,7 @@ PeerConnectionInterface::IceTransportsType JavaToNativeIceTransportsType(
|
||||
|
||||
PeerConnectionInterface::BundlePolicy JavaToNativeBundlePolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_bundle_policy) {
|
||||
const JavaRef<jobject>& j_bundle_policy) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_bundle_policy);
|
||||
|
||||
if (enum_name == "BALANCED")
|
||||
@ -113,7 +117,7 @@ PeerConnectionInterface::BundlePolicy JavaToNativeBundlePolicy(
|
||||
|
||||
PeerConnectionInterface::RtcpMuxPolicy JavaToNativeRtcpMuxPolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_rtcp_mux_policy) {
|
||||
const JavaRef<jobject>& j_rtcp_mux_policy) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_rtcp_mux_policy);
|
||||
|
||||
if (enum_name == "NEGOTIATE")
|
||||
@ -128,7 +132,7 @@ PeerConnectionInterface::RtcpMuxPolicy JavaToNativeRtcpMuxPolicy(
|
||||
|
||||
PeerConnectionInterface::TcpCandidatePolicy JavaToNativeTcpCandidatePolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_tcp_candidate_policy) {
|
||||
const JavaRef<jobject>& j_tcp_candidate_policy) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_tcp_candidate_policy);
|
||||
|
||||
if (enum_name == "ENABLED")
|
||||
@ -142,8 +146,9 @@ PeerConnectionInterface::TcpCandidatePolicy JavaToNativeTcpCandidatePolicy(
|
||||
}
|
||||
|
||||
PeerConnectionInterface::CandidateNetworkPolicy
|
||||
JavaToNativeCandidateNetworkPolicy(JNIEnv* jni,
|
||||
jobject j_candidate_network_policy) {
|
||||
JavaToNativeCandidateNetworkPolicy(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_candidate_network_policy) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_candidate_network_policy);
|
||||
|
||||
if (enum_name == "ALL")
|
||||
@ -157,7 +162,8 @@ JavaToNativeCandidateNetworkPolicy(JNIEnv* jni,
|
||||
return PeerConnectionInterface::kCandidateNetworkPolicyAll;
|
||||
}
|
||||
|
||||
rtc::KeyType JavaToNativeKeyType(JNIEnv* jni, jobject j_key_type) {
|
||||
rtc::KeyType JavaToNativeKeyType(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_key_type) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_key_type);
|
||||
|
||||
if (enum_name == "RSA")
|
||||
@ -170,7 +176,9 @@ rtc::KeyType JavaToNativeKeyType(JNIEnv* jni, jobject j_key_type) {
|
||||
}
|
||||
|
||||
PeerConnectionInterface::ContinualGatheringPolicy
|
||||
JavaToNativeContinualGatheringPolicy(JNIEnv* jni, jobject j_gathering_policy) {
|
||||
JavaToNativeContinualGatheringPolicy(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_gathering_policy) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_gathering_policy);
|
||||
if (enum_name == "GATHER_ONCE")
|
||||
return PeerConnectionInterface::GATHER_ONCE;
|
||||
@ -185,7 +193,7 @@ JavaToNativeContinualGatheringPolicy(JNIEnv* jni, jobject j_gathering_policy) {
|
||||
|
||||
PeerConnectionInterface::TlsCertPolicy JavaToNativeTlsCertPolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_ice_server_tls_cert_policy) {
|
||||
const JavaRef<jobject>& j_ice_server_tls_cert_policy) {
|
||||
std::string enum_name = GetJavaEnumName(jni, j_ice_server_tls_cert_policy);
|
||||
|
||||
if (enum_name == "TLS_CERT_POLICY_SECURE")
|
||||
|
||||
@ -24,14 +24,18 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
cricket::Candidate JavaToNativeCandidate(JNIEnv* jni, jobject j_candidate);
|
||||
cricket::Candidate JavaToNativeCandidate(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_candidate);
|
||||
|
||||
jobject NativeToJavaCandidate(JNIEnv* env, const cricket::Candidate& candidate);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaCandidate(
|
||||
JNIEnv* env,
|
||||
const cricket::Candidate& candidate);
|
||||
|
||||
jobject NativeToJavaIceCandidate(JNIEnv* env,
|
||||
const IceCandidateInterface& candidate);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaIceCandidate(
|
||||
JNIEnv* env,
|
||||
const IceCandidateInterface& candidate);
|
||||
|
||||
jobjectArray NativeToJavaCandidateArray(
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaCandidateArray(
|
||||
JNIEnv* jni,
|
||||
const std::vector<cricket::Candidate>& candidates);
|
||||
|
||||
@ -40,32 +44,36 @@ jobjectArray NativeToJavaCandidateArray(
|
||||
*****************************************************/
|
||||
PeerConnectionInterface::IceTransportsType JavaToNativeIceTransportsType(
|
||||
JNIEnv* jni,
|
||||
jobject j_ice_transports_type);
|
||||
const JavaRef<jobject>& j_ice_transports_type);
|
||||
|
||||
PeerConnectionInterface::BundlePolicy JavaToNativeBundlePolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_bundle_policy);
|
||||
const JavaRef<jobject>& j_bundle_policy);
|
||||
|
||||
PeerConnectionInterface::RtcpMuxPolicy JavaToNativeRtcpMuxPolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_rtcp_mux_policy);
|
||||
const JavaRef<jobject>& j_rtcp_mux_policy);
|
||||
|
||||
PeerConnectionInterface::TcpCandidatePolicy JavaToNativeTcpCandidatePolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_tcp_candidate_policy);
|
||||
const JavaRef<jobject>& j_tcp_candidate_policy);
|
||||
|
||||
PeerConnectionInterface::CandidateNetworkPolicy
|
||||
JavaToNativeCandidateNetworkPolicy(JNIEnv* jni,
|
||||
jobject j_candidate_network_policy);
|
||||
JavaToNativeCandidateNetworkPolicy(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_candidate_network_policy);
|
||||
|
||||
rtc::KeyType JavaToNativeKeyType(JNIEnv* jni, jobject j_key_type);
|
||||
rtc::KeyType JavaToNativeKeyType(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_key_type);
|
||||
|
||||
PeerConnectionInterface::ContinualGatheringPolicy
|
||||
JavaToNativeContinualGatheringPolicy(JNIEnv* jni, jobject j_gathering_policy);
|
||||
JavaToNativeContinualGatheringPolicy(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_gathering_policy);
|
||||
|
||||
PeerConnectionInterface::TlsCertPolicy JavaToNativeTlsCertPolicy(
|
||||
JNIEnv* jni,
|
||||
jobject j_ice_server_tls_cert_policy);
|
||||
const JavaRef<jobject>& j_ice_server_tls_cert_policy);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -48,8 +48,8 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
jint j_severity,
|
||||
jstring j_tag,
|
||||
jstring j_message) {
|
||||
std::string message = JavaToStdString(jni, j_message);
|
||||
std::string tag = JavaToStdString(jni, j_tag);
|
||||
std::string message = JavaToStdString(jni, JavaParamRef<jstring>(j_message));
|
||||
std::string tag = JavaToStdString(jni, JavaParamRef<jstring>(j_tag));
|
||||
RTC_LOG_TAG(static_cast<rtc::LoggingSeverity>(j_severity), tag) << message;
|
||||
}
|
||||
|
||||
|
||||
@ -22,13 +22,12 @@ namespace {
|
||||
// Helper for translating a List<Pair<String, String>> to a Constraints.
|
||||
MediaConstraintsInterface::Constraints PopulateConstraintsFromJavaPairList(
|
||||
JNIEnv* env,
|
||||
jobject j_list) {
|
||||
const JavaRef<jobject>& j_list) {
|
||||
MediaConstraintsInterface::Constraints constraints;
|
||||
for (jobject entry : Iterable(env, j_list)) {
|
||||
jstring j_key = Java_KeyValuePair_getKey(env, entry);
|
||||
jstring j_value = Java_KeyValuePair_getValue(env, entry);
|
||||
constraints.emplace_back(JavaToStdString(env, j_key),
|
||||
JavaToStdString(env, j_value));
|
||||
for (const JavaRef<jobject>& entry : Iterable(env, j_list)) {
|
||||
constraints.emplace_back(
|
||||
JavaToStdString(env, Java_KeyValuePair_getKey(env, entry)),
|
||||
JavaToStdString(env, Java_KeyValuePair_getValue(env, entry)));
|
||||
}
|
||||
return constraints;
|
||||
}
|
||||
@ -37,7 +36,7 @@ MediaConstraintsInterface::Constraints PopulateConstraintsFromJavaPairList(
|
||||
// the constructor returns the Java object is no longer needed.
|
||||
class MediaConstraintsJni : public MediaConstraintsInterface {
|
||||
public:
|
||||
MediaConstraintsJni(JNIEnv* env, jobject j_constraints)
|
||||
MediaConstraintsJni(JNIEnv* env, const JavaRef<jobject>& j_constraints)
|
||||
: mandatory_(PopulateConstraintsFromJavaPairList(
|
||||
env,
|
||||
Java_MediaConstraints_getMandatory(env, j_constraints))),
|
||||
@ -59,7 +58,7 @@ class MediaConstraintsJni : public MediaConstraintsInterface {
|
||||
|
||||
std::unique_ptr<MediaConstraintsInterface> JavaToNativeMediaConstraints(
|
||||
JNIEnv* env,
|
||||
jobject j_constraints) {
|
||||
const JavaRef<jobject>& j_constraints) {
|
||||
return rtc::MakeUnique<MediaConstraintsJni>(env, j_constraints);
|
||||
}
|
||||
|
||||
|
||||
@ -15,13 +15,14 @@
|
||||
#include <memory>
|
||||
|
||||
#include "api/mediaconstraintsinterface.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
std::unique_ptr<MediaConstraintsInterface> JavaToNativeMediaConstraints(
|
||||
JNIEnv* env,
|
||||
jobject j_constraints);
|
||||
const JavaRef<jobject>& j_constraints);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -10,16 +10,12 @@
|
||||
|
||||
#include "api/mediastreaminterface.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/MediaSource_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
MediaSource_getNativeState,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static ScopedJavaLocalRef<jobject>
|
||||
JNI_MediaSource_GetState(JNIEnv* jni, const JavaParamRef<jclass>&, jlong j_p) {
|
||||
return Java_State_fromNativeIndex(
|
||||
jni, reinterpret_cast<MediaSourceInterface*>(j_p)->state());
|
||||
}
|
||||
|
||||
@ -27,12 +27,12 @@ JavaMediaStream::JavaMediaStream(
|
||||
observer_(rtc::MakeUnique<MediaStreamObserver>(media_stream)) {
|
||||
for (rtc::scoped_refptr<AudioTrackInterface> track :
|
||||
media_stream->GetAudioTracks()) {
|
||||
Java_MediaStream_addNativeAudioTrack(env, *j_media_stream_,
|
||||
Java_MediaStream_addNativeAudioTrack(env, j_media_stream_,
|
||||
jlongFromPointer(track.release()));
|
||||
}
|
||||
for (rtc::scoped_refptr<VideoTrackInterface> track :
|
||||
media_stream->GetVideoTracks()) {
|
||||
Java_MediaStream_addNativeVideoTrack(env, *j_media_stream_,
|
||||
Java_MediaStream_addNativeVideoTrack(env, j_media_stream_,
|
||||
jlongFromPointer(track.release()));
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ JavaMediaStream::~JavaMediaStream() {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
// Remove the observer first, so it doesn't react to events during deletion.
|
||||
observer_ = nullptr;
|
||||
Java_MediaStream_dispose(env, *j_media_stream_);
|
||||
Java_MediaStream_dispose(env, j_media_stream_);
|
||||
}
|
||||
|
||||
void JavaMediaStream::OnAudioTrackAddedToStream(AudioTrackInterface* track,
|
||||
@ -64,7 +64,7 @@ void JavaMediaStream::OnAudioTrackAddedToStream(AudioTrackInterface* track,
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
track->AddRef();
|
||||
Java_MediaStream_addNativeAudioTrack(env, *j_media_stream_,
|
||||
Java_MediaStream_addNativeAudioTrack(env, j_media_stream_,
|
||||
jlongFromPointer(track));
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ void JavaMediaStream::OnVideoTrackAddedToStream(VideoTrackInterface* track,
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
track->AddRef();
|
||||
Java_MediaStream_addNativeVideoTrack(env, *j_media_stream_,
|
||||
Java_MediaStream_addNativeVideoTrack(env, j_media_stream_,
|
||||
jlongFromPointer(track));
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ void JavaMediaStream::OnAudioTrackRemovedFromStream(
|
||||
MediaStreamInterface* stream) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_MediaStream_removeAudioTrack(env, *j_media_stream_,
|
||||
Java_MediaStream_removeAudioTrack(env, j_media_stream_,
|
||||
jlongFromPointer(track));
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ void JavaMediaStream::OnVideoTrackRemovedFromStream(
|
||||
MediaStreamInterface* stream) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_MediaStream_removeVideoTrack(env, *j_media_stream_,
|
||||
Java_MediaStream_removeVideoTrack(env, j_media_stream_,
|
||||
jlongFromPointer(track));
|
||||
}
|
||||
|
||||
@ -99,51 +99,42 @@ jclass GetMediaStreamClass(JNIEnv* env) {
|
||||
return org_webrtc_MediaStream_clazz(env);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
MediaStream_addAudioTrackToNativeStream,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong pointer,
|
||||
jlong j_audio_track_pointer) {
|
||||
static jboolean JNI_MediaStream_AddAudioTrackToNativeStream(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong pointer,
|
||||
jlong j_audio_track_pointer) {
|
||||
return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
|
||||
reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
MediaStream_addVideoTrackToNativeStream,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong pointer,
|
||||
jlong j_video_track_pointer) {
|
||||
static jboolean JNI_MediaStream_AddVideoTrackToNativeStream(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong pointer,
|
||||
jlong j_video_track_pointer) {
|
||||
return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
|
||||
reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
MediaStream_removeNativeAudioTrack,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong pointer,
|
||||
jlong j_audio_track_pointer) {
|
||||
static jboolean JNI_MediaStream_RemoveAudioTrack(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong pointer,
|
||||
jlong j_audio_track_pointer) {
|
||||
return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
|
||||
reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
MediaStream_removeNativeVideoTrack,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong pointer,
|
||||
jlong j_video_track_pointer) {
|
||||
static jboolean JNI_MediaStream_RemoveVideoTrack(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong pointer,
|
||||
jlong j_video_track_pointer) {
|
||||
return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
|
||||
reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
MediaStream_getNativeLabel,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static ScopedJavaLocalRef<jstring>
|
||||
JNI_MediaStream_GetLabel(JNIEnv* jni, const JavaParamRef<jclass>&, jlong j_p) {
|
||||
return NativeToJavaString(
|
||||
jni, reinterpret_cast<MediaStreamInterface*>(j_p)->label());
|
||||
}
|
||||
|
||||
@ -28,7 +28,9 @@ class JavaMediaStream : public sigslot::has_slots<> {
|
||||
rtc::scoped_refptr<MediaStreamInterface> media_stream);
|
||||
~JavaMediaStream();
|
||||
|
||||
jobject j_media_stream() { return *j_media_stream_; }
|
||||
const ScopedJavaGlobalRef<jobject>& j_media_stream() {
|
||||
return j_media_stream_;
|
||||
}
|
||||
|
||||
private:
|
||||
void OnAudioTrackAddedToStream(AudioTrackInterface* track,
|
||||
@ -40,7 +42,7 @@ class JavaMediaStream : public sigslot::has_slots<> {
|
||||
void OnVideoTrackRemovedFromStream(VideoTrackInterface* track,
|
||||
MediaStreamInterface* stream);
|
||||
|
||||
ScopedGlobalRef<jobject> j_media_stream_;
|
||||
ScopedJavaGlobalRef<jobject> j_media_stream_;
|
||||
std::unique_ptr<MediaStreamObserver> observer_;
|
||||
};
|
||||
|
||||
|
||||
@ -17,56 +17,52 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jobject NativeToJavaMediaType(JNIEnv* jni, cricket::MediaType media_type) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaMediaType(
|
||||
JNIEnv* jni,
|
||||
cricket::MediaType media_type) {
|
||||
return Java_MediaType_fromNativeIndex(jni, media_type);
|
||||
}
|
||||
|
||||
cricket::MediaType JavaToNativeMediaType(JNIEnv* jni, jobject j_media_type) {
|
||||
cricket::MediaType JavaToNativeMediaType(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_media_type) {
|
||||
return static_cast<cricket::MediaType>(
|
||||
Java_MediaType_getNative(jni, j_media_type));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
MediaStreamTrack_getNativeId,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static ScopedJavaLocalRef<jstring> JNI_MediaStreamTrack_GetId(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
return NativeToJavaString(
|
||||
jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->id());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
MediaStreamTrack_getNativeKind,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static ScopedJavaLocalRef<jstring> JNI_MediaStreamTrack_GetKind(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
return NativeToJavaString(
|
||||
jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->kind());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
MediaStreamTrack_getNativeEnabled,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static jboolean JNI_MediaStreamTrack_GetEnabled(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->enabled();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
MediaStreamTrack_getNativeState,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_MediaStreamTrack_GetState(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
return Java_State_fromNativeIndex(
|
||||
jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->state());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
MediaStreamTrack_setNativeEnabled,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_p,
|
||||
jboolean enabled) {
|
||||
static jboolean JNI_MediaStreamTrack_SetEnabled(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p,
|
||||
jboolean enabled) {
|
||||
return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->set_enabled(
|
||||
enabled);
|
||||
}
|
||||
|
||||
@ -14,12 +14,16 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/mediatypes.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jobject NativeToJavaMediaType(JNIEnv* jni, cricket::MediaType media_type);
|
||||
cricket::MediaType JavaToNativeMediaType(JNIEnv* jni, jobject j_media_type);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaMediaType(
|
||||
JNIEnv* jni,
|
||||
cricket::MediaType media_type);
|
||||
cricket::MediaType JavaToNativeMediaType(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_media_type);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -13,13 +13,30 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
VideoEncoderFactory* CreateVideoEncoderFactory(JNIEnv* jni,
|
||||
jobject j_encoder_factory) {
|
||||
VideoEncoderFactory* CreateVideoEncoderFactory(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_encoder_factory) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VideoDecoderFactory* CreateVideoDecoderFactory(JNIEnv* jni,
|
||||
jobject j_decoder_factory) {
|
||||
VideoDecoderFactory* CreateVideoDecoderFactory(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_decoder_factory) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SetEglContext(JNIEnv* env,
|
||||
cricket::WebRtcVideoEncoderFactory* encoder_factory,
|
||||
const JavaRef<jobject>& egl_context) {}
|
||||
void SetEglContext(JNIEnv* env,
|
||||
cricket::WebRtcVideoDecoderFactory* decoder_factory,
|
||||
const JavaRef<jobject>& egl_context) {}
|
||||
|
||||
void* CreateVideoSource(JNIEnv* env,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
const JavaParamRef<jobject>& j_surface_texture_helper,
|
||||
jboolean is_screencast) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -56,27 +56,32 @@ namespace jni {
|
||||
|
||||
namespace {
|
||||
|
||||
PeerConnectionInterface* ExtractNativePC(JNIEnv* jni, jobject j_pc) {
|
||||
PeerConnectionInterface* ExtractNativePC(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_pc) {
|
||||
return reinterpret_cast<PeerConnectionInterface*>(
|
||||
Java_PeerConnection_getNativePeerConnection(jni, j_pc));
|
||||
}
|
||||
|
||||
PeerConnectionInterface::IceServers JavaToNativeIceServers(
|
||||
JNIEnv* jni,
|
||||
jobject j_ice_servers) {
|
||||
const JavaRef<jobject>& j_ice_servers) {
|
||||
PeerConnectionInterface::IceServers ice_servers;
|
||||
for (jobject j_ice_server : Iterable(jni, j_ice_servers)) {
|
||||
jobject j_ice_server_tls_cert_policy =
|
||||
for (const JavaRef<jobject>& j_ice_server : Iterable(jni, j_ice_servers)) {
|
||||
ScopedJavaLocalRef<jobject> j_ice_server_tls_cert_policy =
|
||||
Java_IceServer_getTlsCertPolicy(jni, j_ice_server);
|
||||
jobject urls = Java_IceServer_getUrls(jni, j_ice_server);
|
||||
jstring username = Java_IceServer_getUsername(jni, j_ice_server);
|
||||
jstring password = Java_IceServer_getPassword(jni, j_ice_server);
|
||||
ScopedJavaLocalRef<jobject> urls =
|
||||
Java_IceServer_getUrls(jni, j_ice_server);
|
||||
ScopedJavaLocalRef<jstring> username =
|
||||
Java_IceServer_getUsername(jni, j_ice_server);
|
||||
ScopedJavaLocalRef<jstring> password =
|
||||
Java_IceServer_getPassword(jni, j_ice_server);
|
||||
PeerConnectionInterface::TlsCertPolicy tls_cert_policy =
|
||||
JavaToNativeTlsCertPolicy(jni, j_ice_server_tls_cert_policy);
|
||||
jstring hostname = Java_IceServer_getHostname(jni, j_ice_server);
|
||||
jobject tls_alpn_protocols =
|
||||
ScopedJavaLocalRef<jstring> hostname =
|
||||
Java_IceServer_getHostname(jni, j_ice_server);
|
||||
ScopedJavaLocalRef<jobject> tls_alpn_protocols =
|
||||
Java_IceServer_getTlsAlpnProtocols(jni, j_ice_server);
|
||||
jobject tls_elliptic_curves =
|
||||
ScopedJavaLocalRef<jobject> tls_elliptic_curves =
|
||||
Java_IceServer_getTlsEllipticCurves(jni, j_ice_server);
|
||||
PeerConnectionInterface::IceServer server;
|
||||
server.urls = JavaToStdVectorStrings(jni, urls);
|
||||
@ -96,23 +101,23 @@ PeerConnectionInterface::IceServers JavaToNativeIceServers(
|
||||
|
||||
void JavaToNativeRTCConfiguration(
|
||||
JNIEnv* jni,
|
||||
jobject j_rtc_config,
|
||||
const JavaRef<jobject>& j_rtc_config,
|
||||
PeerConnectionInterface::RTCConfiguration* rtc_config) {
|
||||
jobject j_ice_transports_type =
|
||||
ScopedJavaLocalRef<jobject> j_ice_transports_type =
|
||||
Java_RTCConfiguration_getIceTransportsType(jni, j_rtc_config);
|
||||
jobject j_bundle_policy =
|
||||
ScopedJavaLocalRef<jobject> j_bundle_policy =
|
||||
Java_RTCConfiguration_getBundlePolicy(jni, j_rtc_config);
|
||||
jobject j_rtcp_mux_policy =
|
||||
ScopedJavaLocalRef<jobject> j_rtcp_mux_policy =
|
||||
Java_RTCConfiguration_getRtcpMuxPolicy(jni, j_rtc_config);
|
||||
jobject j_tcp_candidate_policy =
|
||||
ScopedJavaLocalRef<jobject> j_tcp_candidate_policy =
|
||||
Java_RTCConfiguration_getTcpCandidatePolicy(jni, j_rtc_config);
|
||||
jobject j_candidate_network_policy =
|
||||
ScopedJavaLocalRef<jobject> j_candidate_network_policy =
|
||||
Java_RTCConfiguration_getCandidateNetworkPolicy(jni, j_rtc_config);
|
||||
jobject j_ice_servers =
|
||||
ScopedJavaLocalRef<jobject> j_ice_servers =
|
||||
Java_RTCConfiguration_getIceServers(jni, j_rtc_config);
|
||||
jobject j_continual_gathering_policy =
|
||||
ScopedJavaLocalRef<jobject> j_continual_gathering_policy =
|
||||
Java_RTCConfiguration_getContinualGatheringPolicy(jni, j_rtc_config);
|
||||
jobject j_turn_customizer =
|
||||
ScopedJavaLocalRef<jobject> j_turn_customizer =
|
||||
Java_RTCConfiguration_getTurnCustomizer(jni, j_rtc_config);
|
||||
|
||||
rtc_config->type = JavaToNativeIceTransportsType(jni, j_ice_transports_type);
|
||||
@ -143,7 +148,7 @@ void JavaToNativeRTCConfiguration(
|
||||
rtc_config->presume_writable_when_fully_relayed =
|
||||
Java_RTCConfiguration_getPresumeWritableWhenFullyRelayed(jni,
|
||||
j_rtc_config);
|
||||
jobject j_ice_check_min_interval =
|
||||
ScopedJavaLocalRef<jobject> j_ice_check_min_interval =
|
||||
Java_RTCConfiguration_getIceCheckMinInterval(jni, j_rtc_config);
|
||||
rtc_config->ice_check_min_interval =
|
||||
JavaToNativeOptionalInt(jni, j_ice_check_min_interval);
|
||||
@ -151,7 +156,7 @@ void JavaToNativeRTCConfiguration(
|
||||
Java_RTCConfiguration_getDisableIPv6OnWifi(jni, j_rtc_config);
|
||||
rtc_config->max_ipv6_networks =
|
||||
Java_RTCConfiguration_getMaxIPv6Networks(jni, j_rtc_config);
|
||||
jobject j_ice_regather_interval_range =
|
||||
ScopedJavaLocalRef<jobject> j_ice_regather_interval_range =
|
||||
Java_RTCConfiguration_getIceRegatherIntervalRange(jni, j_rtc_config);
|
||||
if (!IsNull(jni, j_ice_regather_interval_range)) {
|
||||
int min = Java_IntervalRange_getMin(jni, j_ice_regather_interval_range);
|
||||
@ -179,13 +184,15 @@ void JavaToNativeRTCConfiguration(
|
||||
jni, Java_RTCConfiguration_getEnableDtlsSrtp(jni, j_rtc_config));
|
||||
}
|
||||
|
||||
rtc::KeyType GetRtcConfigKeyType(JNIEnv* env, jobject j_rtc_config) {
|
||||
rtc::KeyType GetRtcConfigKeyType(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_rtc_config) {
|
||||
return JavaToNativeKeyType(
|
||||
env, Java_RTCConfiguration_getKeyType(env, j_rtc_config));
|
||||
}
|
||||
|
||||
PeerConnectionObserverJni::PeerConnectionObserverJni(JNIEnv* jni,
|
||||
jobject j_observer)
|
||||
PeerConnectionObserverJni::PeerConnectionObserverJni(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_observer)
|
||||
: j_observer_global_(jni, j_observer) {}
|
||||
|
||||
PeerConnectionObserverJni::~PeerConnectionObserverJni() = default;
|
||||
@ -193,70 +200,62 @@ PeerConnectionObserverJni::~PeerConnectionObserverJni() = default;
|
||||
void PeerConnectionObserverJni::OnIceCandidate(
|
||||
const IceCandidateInterface* candidate) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onIceCandidate(env, *j_observer_global_,
|
||||
Java_Observer_onIceCandidate(env, j_observer_global_,
|
||||
NativeToJavaIceCandidate(env, *candidate));
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnIceCandidatesRemoved(
|
||||
const std::vector<cricket::Candidate>& candidates) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onIceCandidatesRemoved(
|
||||
env, *j_observer_global_, NativeToJavaCandidateArray(env, candidates));
|
||||
env, j_observer_global_, NativeToJavaCandidateArray(env, candidates));
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnSignalingChange(
|
||||
PeerConnectionInterface::SignalingState new_state) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onSignalingChange(
|
||||
env, *j_observer_global_,
|
||||
env, j_observer_global_,
|
||||
Java_SignalingState_fromNativeIndex(env, new_state));
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnIceConnectionChange(
|
||||
PeerConnectionInterface::IceConnectionState new_state) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onIceConnectionChange(
|
||||
env, *j_observer_global_,
|
||||
env, j_observer_global_,
|
||||
Java_IceConnectionState_fromNativeIndex(env, new_state));
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnIceConnectionReceivingChange(bool receiving) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onIceConnectionReceivingChange(env, *j_observer_global_,
|
||||
Java_Observer_onIceConnectionReceivingChange(env, j_observer_global_,
|
||||
receiving);
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnIceGatheringChange(
|
||||
PeerConnectionInterface::IceGatheringState new_state) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onIceGatheringChange(
|
||||
env, *j_observer_global_,
|
||||
env, j_observer_global_,
|
||||
Java_IceGatheringState_fromNativeIndex(env, new_state));
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnAddStream(
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
jobject j_stream = GetOrCreateJavaStream(env, stream).j_media_stream();
|
||||
Java_Observer_onAddStream(env, *j_observer_global_, j_stream);
|
||||
|
||||
Java_Observer_onAddStream(
|
||||
env, j_observer_global_,
|
||||
GetOrCreateJavaStream(env, stream).j_media_stream());
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnRemoveStream(
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream);
|
||||
RTC_CHECK(it != remote_streams_.end())
|
||||
<< "unexpected stream: " << std::hex << stream;
|
||||
Java_Observer_onRemoveStream(env, *j_observer_global_,
|
||||
Java_Observer_onRemoveStream(env, j_observer_global_,
|
||||
it->second.j_media_stream());
|
||||
remote_streams_.erase(it);
|
||||
}
|
||||
@ -264,26 +263,24 @@ void PeerConnectionObserverJni::OnRemoveStream(
|
||||
void PeerConnectionObserverJni::OnDataChannel(
|
||||
rtc::scoped_refptr<DataChannelInterface> channel) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onDataChannel(env, *j_observer_global_,
|
||||
Java_Observer_onDataChannel(env, j_observer_global_,
|
||||
WrapNativeDataChannel(env, channel));
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnRenegotiationNeeded() {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_Observer_onRenegotiationNeeded(env, *j_observer_global_);
|
||||
Java_Observer_onRenegotiationNeeded(env, j_observer_global_);
|
||||
}
|
||||
|
||||
void PeerConnectionObserverJni::OnAddTrack(
|
||||
rtc::scoped_refptr<RtpReceiverInterface> receiver,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
jobject j_rtp_receiver = NativeToJavaRtpReceiver(env, receiver);
|
||||
ScopedJavaLocalRef<jobject> j_rtp_receiver =
|
||||
NativeToJavaRtpReceiver(env, receiver);
|
||||
rtp_receivers_.emplace_back(env, j_rtp_receiver);
|
||||
|
||||
Java_Observer_onAddTrack(env, *j_observer_global_, j_rtp_receiver,
|
||||
Java_Observer_onAddTrack(env, j_observer_global_, j_rtp_receiver,
|
||||
NativeToJavaMediaStreamArray(env, streams));
|
||||
}
|
||||
|
||||
@ -309,61 +306,55 @@ JavaMediaStream& PeerConnectionObserverJni::GetOrCreateJavaStream(
|
||||
return it->second;
|
||||
}
|
||||
|
||||
jobjectArray PeerConnectionObserverJni::NativeToJavaMediaStreamArray(
|
||||
ScopedJavaLocalRef<jobjectArray>
|
||||
PeerConnectionObserverJni::NativeToJavaMediaStreamArray(
|
||||
JNIEnv* jni,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
|
||||
jobjectArray java_streams =
|
||||
jni->NewObjectArray(streams.size(), GetMediaStreamClass(jni), nullptr);
|
||||
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
|
||||
for (size_t i = 0; i < streams.size(); ++i) {
|
||||
jobject j_stream = GetOrCreateJavaStream(jni, streams[i]).j_media_stream();
|
||||
jni->SetObjectArrayElement(java_streams, i, j_stream);
|
||||
}
|
||||
return java_streams;
|
||||
return NativeToJavaObjectArray(
|
||||
jni, streams, GetMediaStreamClass(jni),
|
||||
[this](JNIEnv* env, rtc::scoped_refptr<MediaStreamInterface> stream)
|
||||
-> const ScopedJavaGlobalRef<jobject>& {
|
||||
return GetOrCreateJavaStream(env, stream).j_media_stream();
|
||||
});
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
PeerConnection_createNativePeerConnectionObserver,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_observer) {
|
||||
static jlong JNI_PeerConnection_CreatePeerConnectionObserver(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_observer) {
|
||||
return jlongFromPointer(new PeerConnectionObserverJni(jni, j_observer));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_freeNativePeerConnectionObserver,
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static void JNI_PeerConnection_FreePeerConnectionObserver(
|
||||
JNIEnv*,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
PeerConnectionObserverJni* p =
|
||||
reinterpret_cast<PeerConnectionObserverJni*>(j_p);
|
||||
delete p;
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_getLocalDescription,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetLocalDescription(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
const SessionDescriptionInterface* sdp =
|
||||
ExtractNativePC(jni, j_pc)->local_description();
|
||||
return sdp ? NativeToJavaSessionDescription(jni, sdp) : nullptr;
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_getRemoteDescription,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetRemoteDescription(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
const SessionDescriptionInterface* sdp =
|
||||
ExtractNativePC(jni, j_pc)->remote_description();
|
||||
return sdp ? NativeToJavaSessionDescription(jni, sdp) : nullptr;
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_createDataChannel,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jstring j_label,
|
||||
jobject j_init) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_CreateDataChannel(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jstring>& j_label,
|
||||
const JavaParamRef<jobject>& j_init) {
|
||||
DataChannelInit init = JavaToNativeDataChannelInit(jni, j_init);
|
||||
rtc::scoped_refptr<DataChannelInterface> channel(
|
||||
ExtractNativePC(jni, j_pc)->CreateDataChannel(
|
||||
@ -371,12 +362,11 @@ JNI_FUNCTION_DECLARATION(jobject,
|
||||
return WrapNativeDataChannel(jni, channel);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_createOffer,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_observer,
|
||||
jobject j_constraints) {
|
||||
static void JNI_PeerConnection_CreateOffer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_observer,
|
||||
const JavaParamRef<jobject>& j_constraints) {
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints =
|
||||
JavaToNativeMediaConstraints(jni, j_constraints);
|
||||
rtc::scoped_refptr<CreateSdpObserverJni> observer(
|
||||
@ -385,12 +375,11 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
ExtractNativePC(jni, j_pc)->CreateOffer(observer, observer->constraints());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_createAnswer,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_observer,
|
||||
jobject j_constraints) {
|
||||
static void JNI_PeerConnection_CreateAnswer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_observer,
|
||||
const JavaParamRef<jobject>& j_constraints) {
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints =
|
||||
JavaToNativeMediaConstraints(jni, j_constraints);
|
||||
rtc::scoped_refptr<CreateSdpObserverJni> observer(
|
||||
@ -399,52 +388,47 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
ExtractNativePC(jni, j_pc)->CreateAnswer(observer, observer->constraints());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_setLocalDescription,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_observer,
|
||||
jobject j_sdp) {
|
||||
static void JNI_PeerConnection_SetLocalDescription(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_observer,
|
||||
const JavaParamRef<jobject>& j_sdp) {
|
||||
rtc::scoped_refptr<SetSdpObserverJni> observer(
|
||||
new rtc::RefCountedObject<SetSdpObserverJni>(jni, j_observer, nullptr));
|
||||
ExtractNativePC(jni, j_pc)->SetLocalDescription(
|
||||
observer, JavaToNativeSessionDescription(jni, j_sdp).release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_setRemoteDescription,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_observer,
|
||||
jobject j_sdp) {
|
||||
static void JNI_PeerConnection_SetRemoteDescription(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_observer,
|
||||
const JavaParamRef<jobject>& j_sdp) {
|
||||
rtc::scoped_refptr<SetSdpObserverJni> observer(
|
||||
new rtc::RefCountedObject<SetSdpObserverJni>(jni, j_observer, nullptr));
|
||||
ExtractNativePC(jni, j_pc)->SetRemoteDescription(
|
||||
observer, JavaToNativeSessionDescription(jni, j_sdp).release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_setAudioPlayout,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jboolean playout) {
|
||||
static void JNI_PeerConnection_SetAudioPlayout(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
jboolean playout) {
|
||||
ExtractNativePC(jni, j_pc)->SetAudioPlayout(playout);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_setAudioRecording,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jboolean recording) {
|
||||
static void JNI_PeerConnection_SetAudioRecording(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
jboolean recording) {
|
||||
ExtractNativePC(jni, j_pc)->SetAudioRecording(recording);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
PeerConnection_setNativeConfiguration,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_rtc_config,
|
||||
jlong native_observer) {
|
||||
static jboolean JNI_PeerConnection_SetConfiguration(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_rtc_config,
|
||||
jlong native_observer) {
|
||||
// Need to merge constraints into RTCConfiguration again, which are stored
|
||||
// in the observer object.
|
||||
PeerConnectionObserverJni* observer =
|
||||
@ -458,13 +442,12 @@ JNI_FUNCTION_DECLARATION(jboolean,
|
||||
return ExtractNativePC(jni, j_pc)->SetConfiguration(rtc_config);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
PeerConnection_addNativeIceCandidate,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jstring j_sdp_mid,
|
||||
jint j_sdp_mline_index,
|
||||
jstring j_candidate_sdp) {
|
||||
static jboolean JNI_PeerConnection_AddIceCandidate(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jstring>& j_sdp_mid,
|
||||
jint j_sdp_mline_index,
|
||||
const JavaParamRef<jstring>& j_candidate_sdp) {
|
||||
std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
|
||||
std::string sdp = JavaToStdString(jni, j_candidate_sdp);
|
||||
std::unique_ptr<IceCandidateInterface> candidate(
|
||||
@ -472,41 +455,37 @@ JNI_FUNCTION_DECLARATION(jboolean,
|
||||
return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
PeerConnection_removeNativeIceCandidates,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobjectArray j_candidates) {
|
||||
static jboolean JNI_PeerConnection_RemoveIceCandidates(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobjectArray>& j_candidates) {
|
||||
std::vector<cricket::Candidate> candidates =
|
||||
JavaToNativeVector<cricket::Candidate>(jni, j_candidates,
|
||||
&JavaToNativeCandidate);
|
||||
return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
PeerConnection_addNativeLocalStream,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jlong native_stream) {
|
||||
static jboolean JNI_PeerConnection_AddLocalStream(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
jlong native_stream) {
|
||||
return ExtractNativePC(jni, j_pc)->AddStream(
|
||||
reinterpret_cast<MediaStreamInterface*>(native_stream));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_removeNativeLocalStream,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jlong native_stream) {
|
||||
static void JNI_PeerConnection_RemoveLocalStream(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
jlong native_stream) {
|
||||
ExtractNativePC(jni, j_pc)->RemoveStream(
|
||||
reinterpret_cast<MediaStreamInterface*>(native_stream));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_createNativeSender,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jstring j_kind,
|
||||
jstring j_stream_id) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_CreateSender(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jstring>& j_kind,
|
||||
const JavaParamRef<jstring>& j_stream_id) {
|
||||
std::string kind = JavaToStdString(jni, j_kind);
|
||||
std::string stream_id = JavaToStdString(jni, j_stream_id);
|
||||
rtc::scoped_refptr<RtpSenderInterface> sender =
|
||||
@ -514,28 +493,25 @@ JNI_FUNCTION_DECLARATION(jobject,
|
||||
return NativeToJavaRtpSender(jni, sender);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_getNativeSenders,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetSenders(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetSenders(),
|
||||
&NativeToJavaRtpSender);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_getNativeReceivers,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetReceivers(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetReceivers(),
|
||||
&NativeToJavaRtpReceiver);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(bool,
|
||||
PeerConnection_oldGetNativeStats,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_observer,
|
||||
jlong native_track) {
|
||||
static jboolean JNI_PeerConnection_OldGetStats(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_observer,
|
||||
jlong native_track) {
|
||||
rtc::scoped_refptr<StatsObserverJni> observer(
|
||||
new rtc::RefCountedObject<StatsObserverJni>(jni, j_observer));
|
||||
return ExtractNativePC(jni, j_pc)->GetStats(
|
||||
@ -543,24 +519,22 @@ JNI_FUNCTION_DECLARATION(bool,
|
||||
PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_newGetNativeStats,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_callback) {
|
||||
static void JNI_PeerConnection_NewGetStats(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_callback) {
|
||||
rtc::scoped_refptr<RTCStatsCollectorCallbackWrapper> callback(
|
||||
new rtc::RefCountedObject<RTCStatsCollectorCallbackWrapper>(jni,
|
||||
j_callback));
|
||||
ExtractNativePC(jni, j_pc)->GetStats(callback);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
PeerConnection_setBitrate,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
jobject j_min,
|
||||
jobject j_current,
|
||||
jobject j_max) {
|
||||
static jboolean JNI_PeerConnection_SetBitrate(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
const JavaParamRef<jobject>& j_min,
|
||||
const JavaParamRef<jobject>& j_current,
|
||||
const JavaParamRef<jobject>& j_max) {
|
||||
PeerConnectionInterface::BitrateParameters params;
|
||||
params.min_bitrate_bps = JavaToNativeOptionalInt(jni, j_min);
|
||||
params.current_bitrate_bps = JavaToNativeOptionalInt(jni, j_current);
|
||||
@ -568,51 +542,44 @@ JNI_FUNCTION_DECLARATION(jboolean,
|
||||
return ExtractNativePC(jni, j_pc)->SetBitrate(params).ok();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(bool,
|
||||
PeerConnection_startNativeRtcEventLog,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc,
|
||||
int file_descriptor,
|
||||
int max_size_bytes) {
|
||||
static jboolean JNI_PeerConnection_StartRtcEventLog(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc,
|
||||
int file_descriptor,
|
||||
int max_size_bytes) {
|
||||
return ExtractNativePC(jni, j_pc)->StartRtcEventLog(file_descriptor,
|
||||
max_size_bytes);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_stopNativeRtcEventLog,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc) {
|
||||
static void JNI_PeerConnection_StopRtcEventLog(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
ExtractNativePC(jni, j_pc)->StopRtcEventLog();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_signalingState,
|
||||
JNIEnv* env,
|
||||
jobject j_pc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_SignalingState(
|
||||
JNIEnv* env,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
return Java_SignalingState_fromNativeIndex(
|
||||
env, ExtractNativePC(env, j_pc)->signaling_state());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_iceConnectionState,
|
||||
JNIEnv* env,
|
||||
jobject j_pc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_IceConnectionState(
|
||||
JNIEnv* env,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
return Java_IceConnectionState_fromNativeIndex(
|
||||
env, ExtractNativePC(env, j_pc)->ice_connection_state());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
PeerConnection_iceGatheringState,
|
||||
JNIEnv* env,
|
||||
jobject j_pc) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_IceGatheringState(
|
||||
JNIEnv* env,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
return Java_IceGatheringState_fromNativeIndex(
|
||||
env, ExtractNativePC(env, j_pc)->ice_gathering_state());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnection_close,
|
||||
JNIEnv* jni,
|
||||
jobject j_pc) {
|
||||
static void JNI_PeerConnection_Close(JNIEnv* jni,
|
||||
const JavaParamRef<jobject>& j_pc) {
|
||||
ExtractNativePC(jni, j_pc)->Close();
|
||||
}
|
||||
|
||||
|
||||
@ -27,17 +27,18 @@ namespace jni {
|
||||
|
||||
void JavaToNativeRTCConfiguration(
|
||||
JNIEnv* jni,
|
||||
jobject j_rtc_config,
|
||||
const JavaRef<jobject>& j_rtc_config,
|
||||
PeerConnectionInterface::RTCConfiguration* rtc_config);
|
||||
|
||||
rtc::KeyType GetRtcConfigKeyType(JNIEnv* env, jobject j_rtc_config);
|
||||
rtc::KeyType GetRtcConfigKeyType(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_rtc_config);
|
||||
|
||||
// Adapter between the C++ PeerConnectionObserver interface and the Java
|
||||
// PeerConnection.Observer interface. Wraps an instance of the Java interface
|
||||
// and dispatches C++ callbacks to Java.
|
||||
class PeerConnectionObserverJni : public PeerConnectionObserver {
|
||||
public:
|
||||
PeerConnectionObserverJni(JNIEnv* jni, jobject j_observer);
|
||||
PeerConnectionObserverJni(JNIEnv* jni, const JavaRef<jobject>& j_observer);
|
||||
virtual ~PeerConnectionObserverJni();
|
||||
|
||||
// Implementation of PeerConnectionObserver interface, which propagates
|
||||
@ -76,11 +77,11 @@ class PeerConnectionObserverJni : public PeerConnectionObserver {
|
||||
const rtc::scoped_refptr<MediaStreamInterface>& stream);
|
||||
|
||||
// Converts array of streams, creating or re-using Java streams as necessary.
|
||||
jobjectArray NativeToJavaMediaStreamArray(
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaMediaStreamArray(
|
||||
JNIEnv* jni,
|
||||
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams);
|
||||
|
||||
const ScopedGlobalRef<jobject> j_observer_global_;
|
||||
const ScopedJavaGlobalRef<jobject> j_observer_global_;
|
||||
|
||||
// C++ -> Java remote streams.
|
||||
NativeToJavaStreamsMap remote_streams_;
|
||||
|
||||
@ -45,7 +45,8 @@ namespace jni {
|
||||
|
||||
namespace {
|
||||
PeerConnectionFactoryInterface::Options
|
||||
JavaToNativePeerConnectionFactoryOptions(JNIEnv* jni, jobject options) {
|
||||
JavaToNativePeerConnectionFactoryOptions(JNIEnv* jni,
|
||||
const JavaRef<jobject>& options) {
|
||||
int network_ignore_mask = Java_Options_getNetworkIgnoreMask(jni, options);
|
||||
bool disable_encryption = Java_Options_getDisableEncryption(jni, options);
|
||||
bool disable_network_monitor =
|
||||
@ -93,12 +94,11 @@ void PeerConnectionFactorySignalingThreadReady() {
|
||||
Java_PeerConnectionFactory_onSignalingThreadReady(env);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_initializeNativeAndroidGlobals,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject context,
|
||||
jboolean video_hw_acceleration) {
|
||||
static void JNI_PeerConnectionFactory_InitializeAndroidGlobals(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& context,
|
||||
jboolean video_hw_acceleration) {
|
||||
video_hw_acceleration_enabled = video_hw_acceleration;
|
||||
if (!factory_static_initialized) {
|
||||
JVM::Initialize(GetJVM());
|
||||
@ -106,75 +106,71 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
}
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_initializeFieldTrials,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jstring j_trials_init_string) {
|
||||
static void JNI_PeerConnectionFactory_InitializeFieldTrials(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jstring>& j_trials_init_string) {
|
||||
field_trials_init_string = NULL;
|
||||
if (j_trials_init_string != NULL) {
|
||||
if (!j_trials_init_string.is_null()) {
|
||||
const char* init_string =
|
||||
jni->GetStringUTFChars(j_trials_init_string, NULL);
|
||||
int init_string_length = jni->GetStringUTFLength(j_trials_init_string);
|
||||
jni->GetStringUTFChars(j_trials_init_string.obj(), NULL);
|
||||
int init_string_length =
|
||||
jni->GetStringUTFLength(j_trials_init_string.obj());
|
||||
field_trials_init_string = new char[init_string_length + 1];
|
||||
rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string);
|
||||
jni->ReleaseStringUTFChars(j_trials_init_string, init_string);
|
||||
jni->ReleaseStringUTFChars(j_trials_init_string.obj(), init_string);
|
||||
RTC_LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string;
|
||||
}
|
||||
field_trial::InitFieldTrialsFromString(field_trials_init_string);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_initializeNativeInternalTracer,
|
||||
JNIEnv* jni,
|
||||
jclass) {
|
||||
static void JNI_PeerConnectionFactory_InitializeInternalTracer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&) {
|
||||
rtc::tracing::SetupInternalTracer();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
PeerConnectionFactory_findNativeFieldTrialsFullName,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jstring j_name) {
|
||||
static ScopedJavaLocalRef<jstring>
|
||||
JNI_PeerConnectionFactory_FindFieldTrialsFullName(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jstring>& j_name) {
|
||||
return NativeToJavaString(
|
||||
jni, field_trial::FindFullName(JavaToStdString(jni, j_name)));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
PeerConnectionFactory_startInternalTracingCapture,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jstring j_event_tracing_filename) {
|
||||
if (!j_event_tracing_filename)
|
||||
static jboolean JNI_PeerConnectionFactory_StartInternalTracingCapture(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jstring>& j_event_tracing_filename) {
|
||||
if (j_event_tracing_filename.is_null())
|
||||
return false;
|
||||
|
||||
const char* init_string =
|
||||
jni->GetStringUTFChars(j_event_tracing_filename, NULL);
|
||||
jni->GetStringUTFChars(j_event_tracing_filename.obj(), NULL);
|
||||
RTC_LOG(LS_INFO) << "Starting internal tracing to: " << init_string;
|
||||
bool ret = rtc::tracing::StartInternalCapture(init_string);
|
||||
jni->ReleaseStringUTFChars(j_event_tracing_filename, init_string);
|
||||
jni->ReleaseStringUTFChars(j_event_tracing_filename.obj(), init_string);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_stopInternalTracingCapture,
|
||||
JNIEnv* jni,
|
||||
jclass) {
|
||||
static void JNI_PeerConnectionFactory_StopInternalTracingCapture(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&) {
|
||||
rtc::tracing::StopInternalCapture();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_shutdownNativeInternalTracer,
|
||||
JNIEnv* jni,
|
||||
jclass) {
|
||||
static void JNI_PeerConnectionFactory_ShutdownInternalTracer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&) {
|
||||
rtc::tracing::ShutdownInternalTracer();
|
||||
}
|
||||
|
||||
jlong CreatePeerConnectionFactoryForJava(
|
||||
JNIEnv* jni,
|
||||
jobject joptions,
|
||||
jobject jencoder_factory,
|
||||
jobject jdecoder_factory,
|
||||
const JavaParamRef<jobject>& joptions,
|
||||
const JavaParamRef<jobject>& jencoder_factory,
|
||||
const JavaParamRef<jobject>& jdecoder_factory,
|
||||
rtc::scoped_refptr<AudioProcessing> audio_processor) {
|
||||
// talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
|
||||
// ThreadManager only WrapCurrentThread()s the thread where it is first
|
||||
@ -201,7 +197,7 @@ jlong CreatePeerConnectionFactoryForJava(
|
||||
auto audio_decoder_factory = CreateAudioDecoderFactory();
|
||||
|
||||
PeerConnectionFactoryInterface::Options options;
|
||||
bool has_options = joptions != NULL;
|
||||
bool has_options = !joptions.is_null();
|
||||
if (has_options) {
|
||||
options = JavaToNativePeerConnectionFactoryOptions(jni, joptions);
|
||||
}
|
||||
@ -222,7 +218,7 @@ jlong CreatePeerConnectionFactoryForJava(
|
||||
cricket::WebRtcVideoEncoderFactory* legacy_video_encoder_factory = nullptr;
|
||||
cricket::WebRtcVideoDecoderFactory* legacy_video_decoder_factory = nullptr;
|
||||
std::unique_ptr<cricket::MediaEngineInterface> media_engine;
|
||||
if (jencoder_factory == nullptr && jdecoder_factory == nullptr) {
|
||||
if (jencoder_factory.is_null() && jdecoder_factory.is_null()) {
|
||||
// This uses the legacy API, which automatically uses the internal SW
|
||||
// codecs in WebRTC.
|
||||
if (video_hw_acceleration_enabled) {
|
||||
@ -236,7 +232,7 @@ jlong CreatePeerConnectionFactoryForJava(
|
||||
} else {
|
||||
// This uses the new API, does not automatically include software codecs.
|
||||
std::unique_ptr<VideoEncoderFactory> video_encoder_factory = nullptr;
|
||||
if (jencoder_factory == nullptr) {
|
||||
if (jencoder_factory.is_null()) {
|
||||
legacy_video_encoder_factory = CreateLegacyVideoEncoderFactory();
|
||||
video_encoder_factory = std::unique_ptr<VideoEncoderFactory>(
|
||||
WrapLegacyVideoEncoderFactory(legacy_video_encoder_factory));
|
||||
@ -246,7 +242,7 @@ jlong CreatePeerConnectionFactoryForJava(
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoDecoderFactory> video_decoder_factory = nullptr;
|
||||
if (jdecoder_factory == nullptr) {
|
||||
if (jdecoder_factory.is_null()) {
|
||||
legacy_video_decoder_factory = CreateLegacyVideoDecoderFactory();
|
||||
video_decoder_factory = std::unique_ptr<VideoDecoderFactory>(
|
||||
WrapLegacyVideoDecoderFactory(legacy_video_decoder_factory));
|
||||
@ -282,27 +278,24 @@ jlong CreatePeerConnectionFactoryForJava(
|
||||
return jlongFromPointer(owned_factory);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(
|
||||
jlong,
|
||||
PeerConnectionFactory_createNativePeerConnectionFactory,
|
||||
static jlong JNI_PeerConnectionFactory_CreatePeerConnectionFactory(
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject joptions,
|
||||
jobject jencoder_factory,
|
||||
jobject jdecoder_factory) {
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& joptions,
|
||||
const JavaParamRef<jobject>& jencoder_factory,
|
||||
const JavaParamRef<jobject>& jdecoder_factory) {
|
||||
return CreatePeerConnectionFactoryForJava(jni, joptions, jencoder_factory,
|
||||
jdecoder_factory,
|
||||
CreateAudioProcessing());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(
|
||||
jlong,
|
||||
PeerConnectionFactory_createNativePeerConnectionFactoryWithAudioProcessing,
|
||||
static jlong
|
||||
JNI_PeerConnectionFactory_CreatePeerConnectionFactoryWithAudioProcessing(
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject joptions,
|
||||
jobject jencoder_factory,
|
||||
jobject jdecoder_factory,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& joptions,
|
||||
const JavaParamRef<jobject>& jencoder_factory,
|
||||
const JavaParamRef<jobject>& jdecoder_factory,
|
||||
jlong native_audio_processor) {
|
||||
rtc::scoped_refptr<AudioProcessing> audio_processor =
|
||||
reinterpret_cast<AudioProcessing*>(native_audio_processor);
|
||||
@ -311,11 +304,9 @@ JNI_FUNCTION_DECLARATION(
|
||||
jdecoder_factory, audio_processor);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_freeNativeFactory,
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static void JNI_PeerConnectionFactory_FreeFactory(JNIEnv*,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
|
||||
if (field_trials_init_string) {
|
||||
field_trial::InitFieldTrialsFromString(NULL);
|
||||
@ -324,35 +315,32 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
}
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_invokeNativeThreadsCallbacks,
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static void JNI_PeerConnectionFactory_InvokeThreadsCallbacks(
|
||||
JNIEnv*,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
OwnedFactoryAndThreads* factory =
|
||||
reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
|
||||
factory->InvokeJavaCallbacksOnFactoryThreads();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
PeerConnectionFactory_createNativeLocalMediaStream,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory,
|
||||
jstring label) {
|
||||
static jlong JNI_PeerConnectionFactory_CreateLocalMediaStream(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory,
|
||||
const JavaParamRef<jstring>& label) {
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
||||
factoryFromJava(native_factory));
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream(
|
||||
factory->CreateLocalMediaStream(JavaToStdString(jni, label)));
|
||||
return (jlong)stream.release();
|
||||
return jlongFromPointer(stream.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
PeerConnectionFactory_createNativeAudioSource,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory,
|
||||
jobject j_constraints) {
|
||||
static jlong JNI_PeerConnectionFactory_CreateAudioSource(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory,
|
||||
const JavaParamRef<jobject>& j_constraints) {
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints =
|
||||
JavaToNativeMediaConstraints(jni, j_constraints);
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
||||
@ -361,52 +349,47 @@ JNI_FUNCTION_DECLARATION(jlong,
|
||||
CopyConstraintsIntoAudioOptions(constraints.get(), &options);
|
||||
rtc::scoped_refptr<AudioSourceInterface> source(
|
||||
factory->CreateAudioSource(options));
|
||||
return (jlong)source.release();
|
||||
return jlongFromPointer(source.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
PeerConnectionFactory_createNativeAudioTrack,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory,
|
||||
jstring id,
|
||||
jlong native_source) {
|
||||
jlong JNI_PeerConnectionFactory_CreateAudioTrack(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory,
|
||||
const JavaParamRef<jstring>& id,
|
||||
jlong native_source) {
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
||||
factoryFromJava(native_factory));
|
||||
rtc::scoped_refptr<AudioTrackInterface> track(factory->CreateAudioTrack(
|
||||
JavaToStdString(jni, id),
|
||||
reinterpret_cast<AudioSourceInterface*>(native_source)));
|
||||
return (jlong)track.release();
|
||||
return jlongFromPointer(track.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
PeerConnectionFactory_startNativeAecDump,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory,
|
||||
jint file,
|
||||
jint filesize_limit_bytes) {
|
||||
static jboolean JNI_PeerConnectionFactory_StartAecDump(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory,
|
||||
jint file,
|
||||
jint filesize_limit_bytes) {
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
||||
factoryFromJava(native_factory));
|
||||
return factory->StartAecDump(file, filesize_limit_bytes);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_stopNativeAecDump,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory) {
|
||||
static void JNI_PeerConnectionFactory_StopAecDump(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory) {
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
||||
factoryFromJava(native_factory));
|
||||
factory->StopAecDump();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
PeerConnectionFactory_setNativeOptions,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory,
|
||||
jobject options) {
|
||||
static void JNI_PeerConnectionFactory_SetOptions(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jobject>&,
|
||||
jlong native_factory,
|
||||
const JavaParamRef<jobject>& options) {
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
||||
factoryFromJava(native_factory));
|
||||
PeerConnectionFactoryInterface::Options options_to_set =
|
||||
@ -424,14 +407,13 @@ JNI_FUNCTION_DECLARATION(void,
|
||||
}
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
PeerConnectionFactory_createNativePeerConnection,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong factory,
|
||||
jobject j_rtc_config,
|
||||
jobject j_constraints,
|
||||
jlong observer_p) {
|
||||
static jlong JNI_PeerConnectionFactory_CreatePeerConnection(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong factory,
|
||||
const JavaParamRef<jobject>& j_rtc_config,
|
||||
const JavaParamRef<jobject>& j_constraints,
|
||||
jlong observer_p) {
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
|
||||
reinterpret_cast<PeerConnectionFactoryInterface*>(
|
||||
factoryFromJava(factory)));
|
||||
@ -456,7 +438,7 @@ JNI_FUNCTION_DECLARATION(jlong,
|
||||
|
||||
PeerConnectionObserverJni* observer =
|
||||
reinterpret_cast<PeerConnectionObserverJni*>(observer_p);
|
||||
if (j_constraints != nullptr) {
|
||||
if (!j_constraints.is_null()) {
|
||||
observer->SetConstraints(JavaToNativeMediaConstraints(jni, j_constraints));
|
||||
CopyConstraintsIntoRtcConfiguration(observer->constraints(), &rtc_config);
|
||||
}
|
||||
@ -465,13 +447,12 @@ JNI_FUNCTION_DECLARATION(jlong,
|
||||
return jlongFromPointer(pc.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
PeerConnectionFactory_createNativeVideoSource,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory,
|
||||
jobject j_surface_texture_helper,
|
||||
jboolean is_screencast) {
|
||||
static jlong JNI_PeerConnectionFactory_CreateVideoSource(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory,
|
||||
const JavaParamRef<jobject>& j_surface_texture_helper,
|
||||
jboolean is_screencast) {
|
||||
OwnedFactoryAndThreads* factory =
|
||||
reinterpret_cast<OwnedFactoryAndThreads*>(native_factory);
|
||||
return jlongFromPointer(CreateVideoSource(
|
||||
@ -479,13 +460,12 @@ JNI_FUNCTION_DECLARATION(jlong,
|
||||
j_surface_texture_helper, is_screencast));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
PeerConnectionFactory_createNativeVideoTrack,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong native_factory,
|
||||
jstring id,
|
||||
jlong native_source) {
|
||||
static jlong JNI_PeerConnectionFactory_CreateVideoTrack(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory,
|
||||
const JavaParamRef<jstring>& id,
|
||||
jlong native_source) {
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
||||
factoryFromJava(native_factory));
|
||||
rtc::scoped_refptr<VideoTrackInterface> track(factory->CreateVideoTrack(
|
||||
@ -494,14 +474,12 @@ JNI_FUNCTION_DECLARATION(jlong,
|
||||
return jlongFromPointer(track.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(
|
||||
void,
|
||||
PeerConnectionFactory_setNativeVideoHwAccelerationOptions,
|
||||
static void JNI_PeerConnectionFactory_SetVideoHwAccelerationOptions(
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong native_factory,
|
||||
jobject local_egl_context,
|
||||
jobject remote_egl_context) {
|
||||
const JavaParamRef<jobject>& local_egl_context,
|
||||
const JavaParamRef<jobject>& remote_egl_context) {
|
||||
OwnedFactoryAndThreads* owned_factory =
|
||||
reinterpret_cast<OwnedFactoryAndThreads*>(native_factory);
|
||||
SetEglContext(jni, owned_factory->legacy_encoder_factory(),
|
||||
|
||||
@ -24,19 +24,21 @@ namespace jni {
|
||||
|
||||
namespace {
|
||||
|
||||
jobject NativeToJavaBigInteger(JNIEnv* env, uint64_t u) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaBigInteger(JNIEnv* env, uint64_t u) {
|
||||
return JNI_BigInteger::Java_BigInteger_ConstructorJMBI_JLS(
|
||||
env, NativeToJavaString(env, rtc::ToString(u)));
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaBigIntegerArray(
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaBigIntegerArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<uint64_t>& container) {
|
||||
return NativeToJavaObjectArray(
|
||||
env, container, java_math_BigInteger_clazz(env), &NativeToJavaBigInteger);
|
||||
}
|
||||
|
||||
jobject MemberToJava(JNIEnv* env, const RTCStatsMemberInterface& member) {
|
||||
ScopedJavaLocalRef<jobject> MemberToJava(
|
||||
JNIEnv* env,
|
||||
const RTCStatsMemberInterface& member) {
|
||||
switch (member.type()) {
|
||||
case RTCStatsMemberInterface::kBool:
|
||||
return NativeToJavaBoolean(env, *member.cast_to<RTCStatsMember<bool>>());
|
||||
@ -96,12 +98,12 @@ jobject MemberToJava(JNIEnv* env, const RTCStatsMemberInterface& member) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
jobject NativeToJavaRtcStats(JNIEnv* env, const RTCStats& stats) {
|
||||
ScopedJavaLocalRef<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));
|
||||
}
|
||||
@ -110,10 +112,10 @@ jobject NativeToJavaRtcStats(JNIEnv* env, const RTCStats& stats) {
|
||||
NativeToJavaString(env, stats.id()), builder.GetJavaMap());
|
||||
}
|
||||
|
||||
jobject NativeToJavaRtcStatsReport(
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtcStatsReport(
|
||||
JNIEnv* env,
|
||||
const rtc::scoped_refptr<const RTCStatsReport>& report) {
|
||||
jobject j_stats_map =
|
||||
ScopedJavaLocalRef<jobject> j_stats_map =
|
||||
NativeToJavaMap(env, *report, [](JNIEnv* env, const RTCStats& stats) {
|
||||
return std::make_pair(NativeToJavaString(env, stats.id()),
|
||||
NativeToJavaRtcStats(env, stats));
|
||||
@ -125,16 +127,14 @@ jobject NativeToJavaRtcStatsReport(
|
||||
|
||||
RTCStatsCollectorCallbackWrapper::RTCStatsCollectorCallbackWrapper(
|
||||
JNIEnv* jni,
|
||||
jobject j_callback)
|
||||
const JavaRef<jobject>& j_callback)
|
||||
: 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 = NativeToJavaRtcStatsReport(jni, report);
|
||||
Java_RTCStatsCollectorCallback_onStatsDelivered(jni, *j_callback_global_,
|
||||
j_report);
|
||||
Java_RTCStatsCollectorCallback_onStatsDelivered(
|
||||
jni, j_callback_global_, NativeToJavaRtcStatsReport(jni, report));
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -24,13 +24,14 @@ namespace jni {
|
||||
// Java.
|
||||
class RTCStatsCollectorCallbackWrapper : public RTCStatsCollectorCallback {
|
||||
public:
|
||||
RTCStatsCollectorCallbackWrapper(JNIEnv* jni, jobject j_callback);
|
||||
RTCStatsCollectorCallbackWrapper(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_callback);
|
||||
|
||||
void OnStatsDelivered(
|
||||
const rtc::scoped_refptr<const RTCStatsReport>& report) override;
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> j_callback_global_;
|
||||
const ScopedJavaGlobalRef<jobject> j_callback_global_;
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -19,7 +19,7 @@ namespace jni {
|
||||
|
||||
namespace {
|
||||
|
||||
jobject NativeToJavaRtpEncodingParameter(
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtpEncodingParameter(
|
||||
JNIEnv* env,
|
||||
const RtpEncodingParameters& encoding) {
|
||||
return Java_Encoding_Constructor(
|
||||
@ -27,8 +27,9 @@ jobject NativeToJavaRtpEncodingParameter(
|
||||
encoding.ssrc ? NativeToJavaLong(env, *encoding.ssrc) : nullptr);
|
||||
}
|
||||
|
||||
jobject NativeToJavaRtpCodecParameter(JNIEnv* env,
|
||||
const RtpCodecParameters& codec) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtpCodecParameter(
|
||||
JNIEnv* env,
|
||||
const RtpCodecParameters& codec) {
|
||||
return Java_Codec_Constructor(env, codec.payload_type,
|
||||
NativeToJavaString(env, codec.name),
|
||||
NativeToJavaMediaType(env, codec.kind),
|
||||
@ -38,26 +39,31 @@ jobject NativeToJavaRtpCodecParameter(JNIEnv* env,
|
||||
|
||||
} // namespace
|
||||
|
||||
RtpParameters JavaToNativeRtpParameters(JNIEnv* jni, jobject j_parameters) {
|
||||
RtpParameters JavaToNativeRtpParameters(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_parameters) {
|
||||
RtpParameters parameters;
|
||||
|
||||
// Convert encodings.
|
||||
jobject j_encodings = Java_RtpParameters_getEncodings(jni, j_parameters);
|
||||
for (jobject j_encoding_parameters : Iterable(jni, j_encodings)) {
|
||||
ScopedJavaLocalRef<jobject> j_encodings =
|
||||
Java_RtpParameters_getEncodings(jni, j_parameters);
|
||||
for (const JavaRef<jobject>& j_encoding_parameters :
|
||||
Iterable(jni, j_encodings)) {
|
||||
RtpEncodingParameters encoding;
|
||||
encoding.active = Java_Encoding_getActive(jni, j_encoding_parameters);
|
||||
jobject j_bitrate =
|
||||
ScopedJavaLocalRef<jobject> j_bitrate =
|
||||
Java_Encoding_getMaxBitrateBps(jni, j_encoding_parameters);
|
||||
encoding.max_bitrate_bps = JavaToNativeOptionalInt(jni, j_bitrate);
|
||||
jobject j_ssrc = Java_Encoding_getSsrc(jni, j_encoding_parameters);
|
||||
ScopedJavaLocalRef<jobject> j_ssrc =
|
||||
Java_Encoding_getSsrc(jni, j_encoding_parameters);
|
||||
if (!IsNull(jni, j_ssrc))
|
||||
encoding.ssrc = JavaToNativeLong(jni, j_ssrc);
|
||||
parameters.encodings.push_back(encoding);
|
||||
}
|
||||
|
||||
// Convert codecs.
|
||||
jobject j_codecs = Java_RtpParameters_getCodecs(jni, j_parameters);
|
||||
for (jobject j_codec : Iterable(jni, j_codecs)) {
|
||||
ScopedJavaLocalRef<jobject> j_codecs =
|
||||
Java_RtpParameters_getCodecs(jni, j_parameters);
|
||||
for (const JavaRef<jobject>& j_codec : Iterable(jni, j_codecs)) {
|
||||
RtpCodecParameters codec;
|
||||
codec.payload_type = Java_Codec_getPayloadType(jni, j_codec);
|
||||
codec.name = JavaToStdString(jni, Java_Codec_getName(jni, j_codec));
|
||||
@ -71,8 +77,9 @@ RtpParameters JavaToNativeRtpParameters(JNIEnv* jni, jobject j_parameters) {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
jobject NativeToJavaRtpParameters(JNIEnv* env,
|
||||
const RtpParameters& parameters) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtpParameters(
|
||||
JNIEnv* env,
|
||||
const RtpParameters& parameters) {
|
||||
return Java_RtpParameters_Constructor(
|
||||
env,
|
||||
NativeToJavaList(env, parameters.encodings,
|
||||
|
||||
@ -14,12 +14,16 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/rtpparameters.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
RtpParameters JavaToNativeRtpParameters(JNIEnv* jni, jobject j_parameters);
|
||||
jobject NativeToJavaRtpParameters(JNIEnv* jni, const RtpParameters& parameters);
|
||||
RtpParameters JavaToNativeRtpParameters(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_parameters);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtpParameters(
|
||||
JNIEnv* jni,
|
||||
const RtpParameters& parameters);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -25,24 +25,24 @@ namespace {
|
||||
// dispatches C++ callbacks to Java.
|
||||
class RtpReceiverObserverJni : public RtpReceiverObserverInterface {
|
||||
public:
|
||||
RtpReceiverObserverJni(JNIEnv* env, jobject j_observer)
|
||||
RtpReceiverObserverJni(JNIEnv* env, const JavaRef<jobject>& j_observer)
|
||||
: j_observer_global_(env, j_observer) {}
|
||||
|
||||
~RtpReceiverObserverJni() override = default;
|
||||
|
||||
void OnFirstPacketReceived(cricket::MediaType media_type) override {
|
||||
JNIEnv* const env = AttachCurrentThreadIfNeeded();
|
||||
Java_Observer_onFirstPacketReceived(env, *j_observer_global_,
|
||||
Java_Observer_onFirstPacketReceived(env, j_observer_global_,
|
||||
NativeToJavaMediaType(env, media_type));
|
||||
}
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> j_observer_global_;
|
||||
const ScopedJavaGlobalRef<jobject> j_observer_global_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
jobject NativeToJavaRtpReceiver(
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtpReceiver(
|
||||
JNIEnv* env,
|
||||
rtc::scoped_refptr<RtpReceiverInterface> receiver) {
|
||||
// Receiver is now owned by Java object, and will be freed from there.
|
||||
@ -50,68 +50,62 @@ jobject NativeToJavaRtpReceiver(
|
||||
jlongFromPointer(receiver.release()));
|
||||
}
|
||||
|
||||
JavaRtpReceiverGlobalOwner::JavaRtpReceiverGlobalOwner(JNIEnv* env,
|
||||
jobject j_receiver)
|
||||
JavaRtpReceiverGlobalOwner::JavaRtpReceiverGlobalOwner(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_receiver)
|
||||
: j_receiver_(env, j_receiver) {}
|
||||
|
||||
JavaRtpReceiverGlobalOwner::JavaRtpReceiverGlobalOwner(
|
||||
JavaRtpReceiverGlobalOwner&& other) = default;
|
||||
|
||||
JavaRtpReceiverGlobalOwner::~JavaRtpReceiverGlobalOwner() {
|
||||
if (*j_receiver_)
|
||||
Java_RtpReceiver_dispose(AttachCurrentThreadIfNeeded(), *j_receiver_);
|
||||
if (j_receiver_.obj())
|
||||
Java_RtpReceiver_dispose(AttachCurrentThreadIfNeeded(), j_receiver_);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
RtpReceiver_getNativeTrack,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_receiver_pointer,
|
||||
jlong j_track_pointer) {
|
||||
static jlong JNI_RtpReceiver_GetTrack(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_receiver_pointer) {
|
||||
return jlongFromPointer(
|
||||
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)
|
||||
->track()
|
||||
.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
RtpReceiver_setNativeParameters,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_receiver_pointer,
|
||||
jobject j_parameters) {
|
||||
static jboolean JNI_RtpReceiver_SetParameters(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_receiver_pointer,
|
||||
const JavaParamRef<jobject>& j_parameters) {
|
||||
RtpParameters parameters = JavaToNativeRtpParameters(jni, j_parameters);
|
||||
return reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)
|
||||
->SetParameters(parameters);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
RtpReceiver_getNativeParameters,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_receiver_pointer) {
|
||||
static ScopedJavaLocalRef<jobject> JNI_RtpReceiver_GetParameters(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_receiver_pointer) {
|
||||
RtpParameters parameters =
|
||||
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)
|
||||
->GetParameters();
|
||||
return NativeToJavaRtpParameters(jni, parameters);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
RtpReceiver_getNativeId,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_receiver_pointer) {
|
||||
static ScopedJavaLocalRef<jstring> JNI_RtpReceiver_GetId(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_receiver_pointer) {
|
||||
return NativeToJavaString(
|
||||
jni,
|
||||
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)->id());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
RtpReceiver_setNativeObserver,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_receiver_pointer,
|
||||
jobject j_observer) {
|
||||
static jlong JNI_RtpReceiver_SetObserver(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_receiver_pointer,
|
||||
const JavaParamRef<jobject>& j_observer) {
|
||||
RtpReceiverObserverJni* rtpReceiverObserver =
|
||||
new RtpReceiverObserverJni(jni, j_observer);
|
||||
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)
|
||||
@ -119,12 +113,10 @@ JNI_FUNCTION_DECLARATION(jlong,
|
||||
return jlongFromPointer(rtpReceiverObserver);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
RtpReceiver_unsetNativeObserver,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_receiver_pointer,
|
||||
jlong j_observer_pointer) {
|
||||
static void JNI_RtpReceiver_UnsetObserver(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_receiver_pointer,
|
||||
jlong j_observer_pointer) {
|
||||
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)
|
||||
->SetObserver(nullptr);
|
||||
RtpReceiverObserverJni* observer =
|
||||
|
||||
@ -14,12 +14,12 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/rtpreceiverinterface.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jobject NativeToJavaRtpReceiver(
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtpReceiver(
|
||||
JNIEnv* env,
|
||||
rtc::scoped_refptr<RtpReceiverInterface> receiver);
|
||||
|
||||
@ -27,12 +27,12 @@ jobject NativeToJavaRtpReceiver(
|
||||
// reference. Will call dispose() in the dtor.
|
||||
class JavaRtpReceiverGlobalOwner {
|
||||
public:
|
||||
JavaRtpReceiverGlobalOwner(JNIEnv* env, jobject j_receiver);
|
||||
JavaRtpReceiverGlobalOwner(JNIEnv* env, const JavaRef<jobject>& j_receiver);
|
||||
JavaRtpReceiverGlobalOwner(JavaRtpReceiverGlobalOwner&& other);
|
||||
~JavaRtpReceiverGlobalOwner();
|
||||
|
||||
private:
|
||||
ScopedGlobalRef<jobject> j_receiver_;
|
||||
ScopedJavaGlobalRef<jobject> j_receiver_;
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -17,8 +17,9 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jobject NativeToJavaRtpSender(JNIEnv* env,
|
||||
rtc::scoped_refptr<RtpSenderInterface> sender) {
|
||||
ScopedJavaLocalRef<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
|
||||
@ -26,44 +27,37 @@ jobject NativeToJavaRtpSender(JNIEnv* env,
|
||||
return Java_RtpSender_Constructor(env, jlongFromPointer(sender.release()));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
RtpSender_setNativeTrack,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_sender_pointer,
|
||||
jlong j_track_pointer) {
|
||||
static jboolean JNI_RtpSender_SetTrack(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_sender_pointer,
|
||||
jlong j_track_pointer) {
|
||||
return reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
||||
->SetTrack(reinterpret_cast<MediaStreamTrackInterface*>(j_track_pointer));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
RtpSender_getNativeTrack,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
jlong JNI_RtpSender_GetTrack(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
return jlongFromPointer(
|
||||
reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
||||
->track()
|
||||
.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
RtpSender_getNativeDtmfSender,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
jlong JNI_RtpSender_GetDtmfSender(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
return jlongFromPointer(
|
||||
reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
||||
->GetDtmfSender()
|
||||
.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
RtpSender_setNativeParameters,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_sender_pointer,
|
||||
jobject j_parameters) {
|
||||
jboolean JNI_RtpSender_SetParameters(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_sender_pointer,
|
||||
const JavaParamRef<jobject>& j_parameters) {
|
||||
if (IsNull(jni, j_parameters)) {
|
||||
return false;
|
||||
}
|
||||
@ -72,22 +66,19 @@ JNI_FUNCTION_DECLARATION(jboolean,
|
||||
->SetParameters(parameters);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jobject,
|
||||
RtpSender_getNativeParameters,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
ScopedJavaLocalRef<jobject> JNI_RtpSender_GetParameters(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
RtpParameters parameters =
|
||||
reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
||||
->GetParameters();
|
||||
return NativeToJavaRtpParameters(jni, parameters);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jstring,
|
||||
RtpSender_getNativeId,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
ScopedJavaLocalRef<jstring> JNI_RtpSender_GetId(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_rtp_sender_pointer) {
|
||||
return NativeToJavaString(
|
||||
jni, reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)->id());
|
||||
}
|
||||
|
||||
@ -14,12 +14,14 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/rtpsenderinterface.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jobject NativeToJavaRtpSender(JNIEnv* env,
|
||||
rtc::scoped_refptr<RtpSenderInterface> sender);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaRtpSender(
|
||||
JNIEnv* env,
|
||||
rtc::scoped_refptr<RtpSenderInterface> sender);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -21,15 +21,14 @@ namespace jni {
|
||||
|
||||
CreateSdpObserverJni::CreateSdpObserverJni(
|
||||
JNIEnv* env,
|
||||
jobject j_observer,
|
||||
const JavaRef<jobject>& j_observer,
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints)
|
||||
: j_observer_global_(env, j_observer),
|
||||
constraints_(std::move(constraints)) {}
|
||||
|
||||
void CreateSdpObserverJni::OnSuccess(SessionDescriptionInterface* desc) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
Java_SdpObserver_onCreateSuccess(env, *j_observer_global_,
|
||||
Java_SdpObserver_onCreateSuccess(env, j_observer_global_,
|
||||
NativeToJavaSessionDescription(env, desc));
|
||||
// OnSuccess transfers ownership of the description (there's a TODO to make
|
||||
// it use unique_ptr...).
|
||||
@ -38,25 +37,25 @@ void CreateSdpObserverJni::OnSuccess(SessionDescriptionInterface* desc) {
|
||||
|
||||
void CreateSdpObserverJni::OnFailure(const std::string& error) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_SdpObserver_onCreateFailure(env, *j_observer_global_,
|
||||
Java_SdpObserver_onCreateFailure(env, j_observer_global_,
|
||||
NativeToJavaString(env, error));
|
||||
}
|
||||
|
||||
SetSdpObserverJni::SetSdpObserverJni(
|
||||
JNIEnv* env,
|
||||
jobject j_observer,
|
||||
const JavaRef<jobject>& j_observer,
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints)
|
||||
: j_observer_global_(env, j_observer),
|
||||
constraints_(std::move(constraints)) {}
|
||||
|
||||
void SetSdpObserverJni::OnSuccess() {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_SdpObserver_onSetSuccess(env, *j_observer_global_);
|
||||
Java_SdpObserver_onSetSuccess(env, j_observer_global_);
|
||||
}
|
||||
|
||||
void SetSdpObserverJni::OnFailure(const std::string& error) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_SdpObserver_onSetFailure(env, *j_observer_global_,
|
||||
Java_SdpObserver_onSetFailure(env, j_observer_global_,
|
||||
NativeToJavaString(env, error));
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ namespace jni {
|
||||
class CreateSdpObserverJni : public CreateSessionDescriptionObserver {
|
||||
public:
|
||||
CreateSdpObserverJni(JNIEnv* env,
|
||||
jobject j_observer,
|
||||
const JavaRef<jobject>& j_observer,
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints);
|
||||
|
||||
MediaConstraintsInterface* constraints() { return constraints_.get(); }
|
||||
@ -33,14 +33,14 @@ class CreateSdpObserverJni : public CreateSessionDescriptionObserver {
|
||||
void OnFailure(const std::string& error) override;
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> j_observer_global_;
|
||||
const ScopedJavaGlobalRef<jobject> j_observer_global_;
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints_;
|
||||
};
|
||||
|
||||
class SetSdpObserverJni : public SetSessionDescriptionObserver {
|
||||
public:
|
||||
SetSdpObserverJni(JNIEnv* env,
|
||||
jobject j_observer,
|
||||
const JavaRef<jobject>& j_observer,
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints);
|
||||
|
||||
MediaConstraintsInterface* constraints() { return constraints_.get(); }
|
||||
@ -49,7 +49,7 @@ class SetSdpObserverJni : public SetSessionDescriptionObserver {
|
||||
void OnFailure(const std::string& error) override;
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> j_observer_global_;
|
||||
const ScopedJavaGlobalRef<jobject> j_observer_global_;
|
||||
std::unique_ptr<MediaConstraintsInterface> constraints_;
|
||||
};
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ namespace jni {
|
||||
|
||||
std::unique_ptr<SessionDescriptionInterface> JavaToNativeSessionDescription(
|
||||
JNIEnv* jni,
|
||||
jobject j_sdp) {
|
||||
const JavaRef<jobject>& j_sdp) {
|
||||
std::string std_type = JavaToStdString(
|
||||
jni, Java_SessionDescription_getTypeInCanonicalForm(jni, j_sdp));
|
||||
std::string std_description =
|
||||
@ -34,18 +34,15 @@ std::unique_ptr<SessionDescriptionInterface> JavaToNativeSessionDescription(
|
||||
return CreateSessionDescription(*sdp_type_maybe, std_description);
|
||||
}
|
||||
|
||||
jobject NativeToJavaSessionDescription(
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaSessionDescription(
|
||||
JNIEnv* jni,
|
||||
const SessionDescriptionInterface* desc) {
|
||||
std::string sdp;
|
||||
RTC_CHECK(desc->ToString(&sdp)) << "got so far: " << sdp;
|
||||
jstring j_description = NativeToJavaString(jni, sdp);
|
||||
jobject j_type =
|
||||
Java_Type_fromCanonicalForm(jni, NativeToJavaString(jni, desc->type()));
|
||||
jobject j_sdp =
|
||||
Java_SessionDescription_Constructor(jni, j_type, j_description);
|
||||
CHECK_EXCEPTION(jni) << "error during NewObject";
|
||||
return j_sdp;
|
||||
return Java_SessionDescription_Constructor(
|
||||
jni,
|
||||
Java_Type_fromCanonicalForm(jni, NativeToJavaString(jni, desc->type())),
|
||||
NativeToJavaString(jni, sdp));
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -15,16 +15,18 @@
|
||||
#include <memory>
|
||||
|
||||
#include "api/jsep.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
std::unique_ptr<SessionDescriptionInterface> JavaToNativeSessionDescription(
|
||||
JNIEnv* jni,
|
||||
jobject j_sdp);
|
||||
const JavaRef<jobject>& j_sdp);
|
||||
|
||||
jobject NativeToJavaSessionDescription(JNIEnv* jni,
|
||||
const SessionDescriptionInterface* desc);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaSessionDescription(
|
||||
JNIEnv* jni,
|
||||
const SessionDescriptionInterface* desc);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -21,20 +21,17 @@ namespace jni {
|
||||
|
||||
namespace {
|
||||
|
||||
jobject NativeToJavaStatsReportValue(
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaStatsReportValue(
|
||||
JNIEnv* env,
|
||||
const rtc::scoped_refptr<StatsReport::Value>& value_ptr) {
|
||||
// Should we use the '.name' enum value here instead of converting the
|
||||
// name to a string?
|
||||
jstring j_name = NativeToJavaString(env, value_ptr->display_name());
|
||||
jstring j_value = NativeToJavaString(env, value_ptr->ToString());
|
||||
jobject ret = Java_Value_Constructor(env, j_name, j_value);
|
||||
env->DeleteLocalRef(j_name);
|
||||
env->DeleteLocalRef(j_value);
|
||||
return ret;
|
||||
return Java_Value_Constructor(
|
||||
env, NativeToJavaString(env, value_ptr->display_name()),
|
||||
NativeToJavaString(env, value_ptr->ToString()));
|
||||
}
|
||||
|
||||
jobjectArray NativeToJavaStatsReportValueArray(
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaStatsReportValueArray(
|
||||
JNIEnv* env,
|
||||
const StatsReport::Values& value_map) {
|
||||
// Ignore the keys and make an array out of the values.
|
||||
@ -46,33 +43,28 @@ jobjectArray NativeToJavaStatsReportValueArray(
|
||||
&NativeToJavaStatsReportValue);
|
||||
}
|
||||
|
||||
jobject NativeToJavaStatsReport(JNIEnv* env, const StatsReport& report) {
|
||||
jstring j_id = NativeToJavaString(env, report.id()->ToString());
|
||||
jstring j_type = NativeToJavaString(env, report.TypeToString());
|
||||
jobjectArray j_values =
|
||||
NativeToJavaStatsReportValueArray(env, report.values());
|
||||
jobject ret = Java_StatsReport_Constructor(env, j_id, j_type,
|
||||
report.timestamp(), j_values);
|
||||
env->DeleteLocalRef(j_values);
|
||||
env->DeleteLocalRef(j_type);
|
||||
env->DeleteLocalRef(j_id);
|
||||
return ret;
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaStatsReport(JNIEnv* env,
|
||||
const StatsReport& report) {
|
||||
return Java_StatsReport_Constructor(
|
||||
env, NativeToJavaString(env, report.id()->ToString()),
|
||||
NativeToJavaString(env, report.TypeToString()), report.timestamp(),
|
||||
NativeToJavaStatsReportValueArray(env, report.values()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
StatsObserverJni::StatsObserverJni(JNIEnv* jni, jobject j_observer)
|
||||
StatsObserverJni::StatsObserverJni(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_observer)
|
||||
: j_observer_global_(jni, j_observer) {}
|
||||
|
||||
void StatsObserverJni::OnComplete(const StatsReports& reports) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
jobjectArray j_reports =
|
||||
ScopedJavaLocalRef<jobjectArray> j_reports =
|
||||
NativeToJavaObjectArray(env, reports, org_webrtc_StatsReport_clazz(env),
|
||||
[](JNIEnv* env, const StatsReport* report) {
|
||||
return NativeToJavaStatsReport(env, *report);
|
||||
});
|
||||
Java_StatsObserver_onComplete(env, *j_observer_global_, j_reports);
|
||||
env->DeleteLocalRef(j_reports);
|
||||
Java_StatsObserver_onComplete(env, j_observer_global_, j_reports);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -21,12 +21,12 @@ namespace jni {
|
||||
// dispatching the callback from C++ back to Java.
|
||||
class StatsObserverJni : public StatsObserver {
|
||||
public:
|
||||
StatsObserverJni(JNIEnv* jni, jobject j_observer);
|
||||
StatsObserverJni(JNIEnv* jni, const JavaRef<jobject>& j_observer);
|
||||
|
||||
void OnComplete(const StatsReports& reports) override;
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> j_observer_global_;
|
||||
const ScopedJavaGlobalRef<jobject> j_observer_global_;
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -15,19 +15,19 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
TurnCustomizer* GetNativeTurnCustomizer(JNIEnv* env,
|
||||
jobject j_turn_customizer) {
|
||||
TurnCustomizer* GetNativeTurnCustomizer(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_turn_customizer) {
|
||||
if (IsNull(env, j_turn_customizer))
|
||||
return nullptr;
|
||||
return reinterpret_cast<webrtc::TurnCustomizer*>(
|
||||
Java_TurnCustomizer_getNativeTurnCustomizer(env, j_turn_customizer));
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
TurnCustomizer_freeNativeTurnCustomizer,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_turn_customizer_pointer) {
|
||||
static void JNI_TurnCustomizer_FreeTurnCustomizer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_turn_customizer_pointer) {
|
||||
delete reinterpret_cast<TurnCustomizer*>(j_turn_customizer_pointer);
|
||||
}
|
||||
|
||||
|
||||
@ -12,11 +12,14 @@
|
||||
#define SDK_ANDROID_SRC_JNI_PC_TURNCUSTOMIZER_H_
|
||||
|
||||
#include "api/turncustomizer.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
TurnCustomizer* GetNativeTurnCustomizer(JNIEnv* env, jobject j_turn_customizer);
|
||||
TurnCustomizer* GetNativeTurnCustomizer(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_turn_customizer);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -32,38 +32,40 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
VideoEncoderFactory* CreateVideoEncoderFactory(JNIEnv* jni,
|
||||
jobject j_encoder_factory) {
|
||||
VideoEncoderFactory* CreateVideoEncoderFactory(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_encoder_factory) {
|
||||
return new VideoEncoderFactoryWrapper(jni, j_encoder_factory);
|
||||
}
|
||||
|
||||
VideoDecoderFactory* CreateVideoDecoderFactory(JNIEnv* jni,
|
||||
jobject j_decoder_factory) {
|
||||
VideoDecoderFactory* CreateVideoDecoderFactory(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_decoder_factory) {
|
||||
return new VideoDecoderFactoryWrapper(jni, j_decoder_factory);
|
||||
}
|
||||
|
||||
void SetEglContext(JNIEnv* env,
|
||||
cricket::WebRtcVideoEncoderFactory* encoder_factory,
|
||||
jobject egl_context) {
|
||||
const JavaRef<jobject>& egl_context) {
|
||||
if (encoder_factory) {
|
||||
MediaCodecVideoEncoderFactory* media_codec_factory =
|
||||
static_cast<MediaCodecVideoEncoderFactory*>(encoder_factory);
|
||||
if (media_codec_factory && Java_Context_isEgl14Context(env, egl_context)) {
|
||||
RTC_LOG(LS_INFO) << "Set EGL context for HW encoding.";
|
||||
media_codec_factory->SetEGLContext(env, egl_context);
|
||||
media_codec_factory->SetEGLContext(env, egl_context.obj());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetEglContext(JNIEnv* env,
|
||||
cricket::WebRtcVideoDecoderFactory* decoder_factory,
|
||||
jobject egl_context) {
|
||||
const JavaRef<jobject>& egl_context) {
|
||||
if (decoder_factory) {
|
||||
MediaCodecVideoDecoderFactory* media_codec_factory =
|
||||
static_cast<MediaCodecVideoDecoderFactory*>(decoder_factory);
|
||||
if (media_codec_factory) {
|
||||
RTC_LOG(LS_INFO) << "Set EGL context for HW decoding.";
|
||||
media_codec_factory->SetEGLContext(env, egl_context);
|
||||
media_codec_factory->SetEGLContext(env, egl_context.obj());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -71,7 +73,7 @@ void SetEglContext(JNIEnv* env,
|
||||
void* CreateVideoSource(JNIEnv* env,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
jobject j_surface_texture_helper,
|
||||
const JavaParamRef<jobject>& j_surface_texture_helper,
|
||||
jboolean is_screencast) {
|
||||
rtc::scoped_refptr<AndroidVideoTrackSource> source(
|
||||
new rtc::RefCountedObject<AndroidVideoTrackSource>(
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
#include "rtc_base/scoped_ref_ptr.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace cricket {
|
||||
class WebRtcVideoEncoderFactory;
|
||||
@ -31,23 +32,25 @@ namespace jni {
|
||||
|
||||
class SurfaceTextureHelper;
|
||||
|
||||
VideoEncoderFactory* CreateVideoEncoderFactory(JNIEnv* jni,
|
||||
jobject j_encoder_factory);
|
||||
VideoEncoderFactory* CreateVideoEncoderFactory(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_encoder_factory);
|
||||
|
||||
VideoDecoderFactory* CreateVideoDecoderFactory(JNIEnv* jni,
|
||||
jobject j_decoder_factory);
|
||||
VideoDecoderFactory* CreateVideoDecoderFactory(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_decoder_factory);
|
||||
|
||||
void SetEglContext(JNIEnv* env,
|
||||
cricket::WebRtcVideoEncoderFactory* encoder_factory,
|
||||
jobject egl_context);
|
||||
const JavaRef<jobject>& egl_context);
|
||||
void SetEglContext(JNIEnv* env,
|
||||
cricket::WebRtcVideoDecoderFactory* decoder_factory,
|
||||
jobject egl_context);
|
||||
const JavaRef<jobject>& egl_context);
|
||||
|
||||
void* CreateVideoSource(JNIEnv* env,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
jobject j_surface_texture_helper,
|
||||
const JavaParamRef<jobject>& j_surface_texture_helper,
|
||||
jboolean is_screencast);
|
||||
|
||||
cricket::WebRtcVideoEncoderFactory* CreateLegacyVideoEncoderFactory();
|
||||
|
||||
205
sdk/android/src/jni/scoped_java_ref.h
Normal file
205
sdk/android/src/jni/scoped_java_ref.h
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Originally these classes are from Chromium.
|
||||
// https://cs.chromium.org/chromium/src/base/android/scoped_java_ref.h.
|
||||
|
||||
#ifndef SDK_ANDROID_SRC_JNI_SCOPED_JAVA_REF_H_
|
||||
#define SDK_ANDROID_SRC_JNI_SCOPED_JAVA_REF_H_
|
||||
|
||||
#include <jni.h>
|
||||
#include <utility>
|
||||
|
||||
#include "rtc_base/constructormagic.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNIEnv* AttachCurrentThreadIfNeeded();
|
||||
|
||||
// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
|
||||
// for allowing functions to accept a reference without having to mandate
|
||||
// whether it is a local or global type.
|
||||
template <typename T>
|
||||
class JavaRef;
|
||||
|
||||
// Template specialization of JavaRef, which acts as the base class for all
|
||||
// other JavaRef<> template types. This allows you to e.g. pass JavaRef<jstring>
|
||||
// into a function taking const JavaRef<jobject>&.
|
||||
template <>
|
||||
class JavaRef<jobject> {
|
||||
public:
|
||||
jobject obj() const { return obj_; }
|
||||
bool is_null() const {
|
||||
// This is not valid for weak references. For weak references you need to
|
||||
// use env->IsSameObject(objc_, nullptr), but that should be avoided anyway
|
||||
// since it does not prevent the object from being freed immediately
|
||||
// thereafter. Consequently, programmers should not use this check on weak
|
||||
// references anyway and should first make a ScopedJavaLocalRef or
|
||||
// ScopedJavaGlobalRef before checking if it is null.
|
||||
return obj_ == nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
JavaRef() : obj_(nullptr) {}
|
||||
explicit JavaRef(jobject obj) : obj_(obj) {}
|
||||
jobject obj_;
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JavaRef);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JavaRef : public JavaRef<jobject> {
|
||||
public:
|
||||
T obj() const { return static_cast<T>(obj_); }
|
||||
|
||||
protected:
|
||||
JavaRef() : JavaRef<jobject>(nullptr) {}
|
||||
explicit JavaRef(T obj) : JavaRef<jobject>(obj) {}
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JavaRef);
|
||||
};
|
||||
|
||||
// Holds a local reference to a JNI method parameter.
|
||||
// Method parameters should not be deleted, and so this class exists purely to
|
||||
// wrap them as a JavaRef<T> in the JNI binding generator. Do not create
|
||||
// instances manually.
|
||||
template <typename T>
|
||||
class JavaParamRef : public JavaRef<T> {
|
||||
public:
|
||||
// Assumes that |obj| is a parameter passed to a JNI method from Java.
|
||||
// Does not assume ownership as parameters should not be deleted.
|
||||
explicit JavaParamRef(T obj) : JavaRef<T>(obj) {}
|
||||
JavaParamRef(JNIEnv*, T obj) : JavaRef<T>(obj) {}
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JavaParamRef);
|
||||
};
|
||||
|
||||
// Holds a local reference to a Java object. The local reference is scoped
|
||||
// to the lifetime of this object.
|
||||
// Instances of this class may hold onto any JNIEnv passed into it until
|
||||
// destroyed. Therefore, since a JNIEnv is only suitable for use on a single
|
||||
// thread, objects of this class must be created, used, and destroyed, on a
|
||||
// single thread.
|
||||
// Therefore, this class should only be used as a stack-based object and from a
|
||||
// single thread. If you wish to have the reference outlive the current
|
||||
// callstack (e.g. as a class member) or you wish to pass it across threads,
|
||||
// use a ScopedJavaGlobalRef instead.
|
||||
template <typename T>
|
||||
class ScopedJavaLocalRef : public JavaRef<T> {
|
||||
public:
|
||||
ScopedJavaLocalRef() = default;
|
||||
ScopedJavaLocalRef(std::nullptr_t) {} // NOLINT(runtime/explicit)
|
||||
|
||||
ScopedJavaLocalRef(JNIEnv* env, const JavaRef<T>& other) : env_(env) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
// Allow constructing e.g. ScopedJavaLocalRef<jobject> from
|
||||
// ScopedJavaLocalRef<jstring>.
|
||||
template <typename G>
|
||||
ScopedJavaLocalRef(ScopedJavaLocalRef<G>&& other) : env_(other.env()) {
|
||||
Reset(other.Release(), OwnershipPolicy::ADOPT);
|
||||
}
|
||||
ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
|
||||
// Assumes that |obj| is a reference to a Java object and takes
|
||||
// ownership of this reference. This should preferably not be used
|
||||
// outside of JNI helper functions.
|
||||
ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(obj), env_(env) {}
|
||||
|
||||
~ScopedJavaLocalRef() {
|
||||
if (obj_ != nullptr)
|
||||
env_->DeleteLocalRef(obj_);
|
||||
}
|
||||
|
||||
void operator=(const ScopedJavaLocalRef& other) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
void operator=(ScopedJavaLocalRef&& other) {
|
||||
Reset(other.Release(), OwnershipPolicy::ADOPT);
|
||||
}
|
||||
|
||||
// Releases the reference to the caller. The caller *must* delete the
|
||||
// reference when it is done with it. Note that calling a Java method
|
||||
// is *not* a transfer of ownership and Release() should not be used.
|
||||
T Release() {
|
||||
T obj = static_cast<T>(obj_);
|
||||
obj_ = nullptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
JNIEnv* env() const { return env_; }
|
||||
|
||||
private:
|
||||
using JavaRef<T>::obj_;
|
||||
|
||||
enum OwnershipPolicy {
|
||||
// The scoped object takes ownership of an object by taking over an existing
|
||||
// ownership claim.
|
||||
ADOPT,
|
||||
// The scoped object will retain the the object and any initial ownership is
|
||||
// not changed.
|
||||
RETAIN
|
||||
};
|
||||
|
||||
void Reset(T obj, OwnershipPolicy policy) {
|
||||
if (obj_ != nullptr)
|
||||
env_->DeleteLocalRef(obj_);
|
||||
obj_ = (obj != nullptr && policy == OwnershipPolicy::RETAIN)
|
||||
? env_->NewLocalRef(obj)
|
||||
: obj;
|
||||
}
|
||||
|
||||
JNIEnv* const env_ = AttachCurrentThreadIfNeeded();
|
||||
};
|
||||
|
||||
// Holds a global reference to a Java object. The global reference is scoped
|
||||
// to the lifetime of this object. This class does not hold onto any JNIEnv*
|
||||
// passed to it, hence it is safe to use across threads (within the constraints
|
||||
// imposed by the underlying Java object that it references).
|
||||
template <typename T>
|
||||
class ScopedJavaGlobalRef : public JavaRef<T> {
|
||||
public:
|
||||
using JavaRef<T>::obj_;
|
||||
|
||||
ScopedJavaGlobalRef(JNIEnv* env, const JavaRef<T>& other)
|
||||
: JavaRef<T>(static_cast<T>(env->NewGlobalRef(other.obj()))) {}
|
||||
explicit ScopedJavaGlobalRef(const ScopedJavaLocalRef<T>& other)
|
||||
: ScopedJavaGlobalRef(other.env(), other) {}
|
||||
ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other)
|
||||
: JavaRef<T>(other.Release()) {}
|
||||
|
||||
~ScopedJavaGlobalRef() {
|
||||
if (obj_ != nullptr)
|
||||
AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
|
||||
}
|
||||
|
||||
// Releases the reference to the caller. The caller *must* delete the
|
||||
// reference when it is done with it. Note that calling a Java method
|
||||
// is *not* a transfer of ownership and Release() should not be used.
|
||||
T Release() {
|
||||
T obj = static_cast<T>(obj_);
|
||||
obj_ = nullptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ScopedJavaGlobalRef);
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SDK_ANDROID_SRC_JNI_SCOPED_JAVA_REF_H_
|
||||
@ -18,13 +18,14 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
void SurfaceTextureHelperTextureToYUV(JNIEnv* env,
|
||||
jobject j_surface_texture_helper,
|
||||
jobject buffer,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
const NativeHandleImpl& native_handle) {
|
||||
void SurfaceTextureHelperTextureToYUV(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_surface_texture_helper,
|
||||
const JavaRef<jobject>& buffer,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
const NativeHandleImpl& native_handle) {
|
||||
Java_SurfaceTextureHelper_textureToYUV(
|
||||
env, j_surface_texture_helper, buffer, width, height, stride,
|
||||
native_handle.oes_texture_id, native_handle.sampling_matrix.ToJava(env));
|
||||
@ -33,34 +34,35 @@ void SurfaceTextureHelperTextureToYUV(JNIEnv* env,
|
||||
rtc::scoped_refptr<SurfaceTextureHelper> SurfaceTextureHelper::create(
|
||||
JNIEnv* jni,
|
||||
const char* thread_name,
|
||||
jobject j_egl_context) {
|
||||
jobject j_surface_texture_helper = Java_SurfaceTextureHelper_create(
|
||||
jni, NativeToJavaString(jni, thread_name), j_egl_context);
|
||||
CHECK_EXCEPTION(jni)
|
||||
<< "error during initialization of Java SurfaceTextureHelper";
|
||||
const JavaRef<jobject>& j_egl_context) {
|
||||
ScopedJavaLocalRef<jobject> j_surface_texture_helper =
|
||||
Java_SurfaceTextureHelper_create(
|
||||
jni, NativeToJavaString(jni, thread_name), j_egl_context);
|
||||
if (IsNull(jni, j_surface_texture_helper))
|
||||
return nullptr;
|
||||
return new rtc::RefCountedObject<SurfaceTextureHelper>(
|
||||
jni, j_surface_texture_helper);
|
||||
}
|
||||
|
||||
SurfaceTextureHelper::SurfaceTextureHelper(JNIEnv* jni,
|
||||
jobject j_surface_texture_helper)
|
||||
SurfaceTextureHelper::SurfaceTextureHelper(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_surface_texture_helper)
|
||||
: j_surface_texture_helper_(jni, j_surface_texture_helper) {}
|
||||
|
||||
SurfaceTextureHelper::~SurfaceTextureHelper() {
|
||||
RTC_LOG(LS_INFO) << "SurfaceTextureHelper dtor";
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
Java_SurfaceTextureHelper_dispose(jni, *j_surface_texture_helper_);
|
||||
Java_SurfaceTextureHelper_dispose(jni, j_surface_texture_helper_);
|
||||
}
|
||||
|
||||
jobject SurfaceTextureHelper::GetJavaSurfaceTextureHelper() const {
|
||||
return *j_surface_texture_helper_;
|
||||
const ScopedJavaGlobalRef<jobject>&
|
||||
SurfaceTextureHelper::GetJavaSurfaceTextureHelper() const {
|
||||
return j_surface_texture_helper_;
|
||||
}
|
||||
|
||||
void SurfaceTextureHelper::ReturnTextureFrame() const {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
Java_SurfaceTextureHelper_returnTextureFrame(jni, *j_surface_texture_helper_);
|
||||
Java_SurfaceTextureHelper_returnTextureFrame(jni, j_surface_texture_helper_);
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<VideoFrameBuffer> SurfaceTextureHelper::CreateTextureFrame(
|
||||
|
||||
@ -43,10 +43,12 @@ struct NativeHandleImpl;
|
||||
class SurfaceTextureHelper : public rtc::RefCountInterface {
|
||||
public:
|
||||
// Might return null if creating the Java SurfaceTextureHelper fails.
|
||||
static rtc::scoped_refptr<SurfaceTextureHelper>
|
||||
create(JNIEnv* jni, const char* thread_name, jobject j_egl_context);
|
||||
static rtc::scoped_refptr<SurfaceTextureHelper> create(
|
||||
JNIEnv* jni,
|
||||
const char* thread_name,
|
||||
const JavaRef<jobject>& j_egl_context);
|
||||
|
||||
jobject GetJavaSurfaceTextureHelper() const;
|
||||
const ScopedJavaGlobalRef<jobject>& GetJavaSurfaceTextureHelper() const;
|
||||
|
||||
rtc::scoped_refptr<VideoFrameBuffer> CreateTextureFrame(
|
||||
int width,
|
||||
@ -58,19 +60,21 @@ class SurfaceTextureHelper : public rtc::RefCountInterface {
|
||||
|
||||
protected:
|
||||
~SurfaceTextureHelper();
|
||||
SurfaceTextureHelper(JNIEnv* jni, jobject j_surface_texture_helper);
|
||||
SurfaceTextureHelper(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_surface_texture_helper);
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> j_surface_texture_helper_;
|
||||
const ScopedJavaGlobalRef<jobject> j_surface_texture_helper_;
|
||||
};
|
||||
|
||||
void SurfaceTextureHelperTextureToYUV(JNIEnv* env,
|
||||
jobject j_surface_texture_helper,
|
||||
jobject buffer,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
const NativeHandleImpl& native_handle);
|
||||
void SurfaceTextureHelperTextureToYUV(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_surface_texture_helper,
|
||||
const JavaRef<jobject>& buffer,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
const NativeHandleImpl& native_handle);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -23,16 +23,15 @@ namespace jni {
|
||||
// instance.
|
||||
class JavaVideoRendererWrapper : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
public:
|
||||
JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
|
||||
JavaVideoRendererWrapper(JNIEnv* jni, const JavaRef<jobject>& j_callbacks)
|
||||
: j_callbacks_(jni, j_callbacks) {}
|
||||
|
||||
virtual ~JavaVideoRendererWrapper() {}
|
||||
|
||||
void OnFrame(const VideoFrame& video_frame) override {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
|
||||
jobject j_frame;
|
||||
ScopedJavaLocalRef<jobject> j_frame;
|
||||
if (video_frame.video_frame_buffer()->type() ==
|
||||
VideoFrameBuffer::Type::kNative) {
|
||||
AndroidVideoFrameBuffer* android_buffer =
|
||||
@ -53,7 +52,7 @@ class JavaVideoRendererWrapper : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
}
|
||||
// |j_callbacks_| is responsible for releasing |j_frame| with
|
||||
// VideoRenderer.renderFrameDone().
|
||||
Java_Callbacks_renderFrame(env, *j_callbacks_, j_frame);
|
||||
Java_Callbacks_renderFrame(env, j_callbacks_, j_frame);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -65,7 +64,8 @@ class JavaVideoRendererWrapper : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
}
|
||||
|
||||
// Return a VideoRenderer.I420Frame referring to the data in |frame|.
|
||||
jobject FromWrappedJavaBuffer(JNIEnv* env, const VideoFrame& frame) {
|
||||
ScopedJavaLocalRef<jobject> FromWrappedJavaBuffer(JNIEnv* env,
|
||||
const VideoFrame& frame) {
|
||||
return Java_I420Frame_Constructor(
|
||||
env, frame.rotation(),
|
||||
static_cast<AndroidVideoBuffer*>(frame.video_frame_buffer().get())
|
||||
@ -74,19 +74,20 @@ class JavaVideoRendererWrapper : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
}
|
||||
|
||||
// Return a VideoRenderer.I420Frame referring to the data in |frame|.
|
||||
jobject ToJavaI420Frame(JNIEnv* env, const VideoFrame& frame) {
|
||||
ScopedJavaLocalRef<jobject> ToJavaI420Frame(JNIEnv* env,
|
||||
const VideoFrame& frame) {
|
||||
rtc::scoped_refptr<I420BufferInterface> i420_buffer =
|
||||
frame.video_frame_buffer()->ToI420();
|
||||
jobject y_buffer = env->NewDirectByteBuffer(
|
||||
const_cast<uint8_t*>(i420_buffer->DataY()),
|
||||
i420_buffer->StrideY() * i420_buffer->height());
|
||||
ScopedJavaLocalRef<jobject> y_buffer =
|
||||
NewDirectByteBuffer(env, const_cast<uint8_t*>(i420_buffer->DataY()),
|
||||
i420_buffer->StrideY() * i420_buffer->height());
|
||||
size_t chroma_height = i420_buffer->ChromaHeight();
|
||||
jobject u_buffer =
|
||||
env->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataU()),
|
||||
i420_buffer->StrideU() * chroma_height);
|
||||
jobject v_buffer =
|
||||
env->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataV()),
|
||||
i420_buffer->StrideV() * chroma_height);
|
||||
ScopedJavaLocalRef<jobject> u_buffer =
|
||||
NewDirectByteBuffer(env, const_cast<uint8_t*>(i420_buffer->DataU()),
|
||||
i420_buffer->StrideU() * chroma_height);
|
||||
ScopedJavaLocalRef<jobject> v_buffer =
|
||||
NewDirectByteBuffer(env, const_cast<uint8_t*>(i420_buffer->DataV()),
|
||||
i420_buffer->StrideV() * chroma_height);
|
||||
return Java_I420Frame_createI420Frame(
|
||||
env, frame.width(), frame.height(), static_cast<int>(frame.rotation()),
|
||||
i420_buffer->StrideY(), y_buffer, i420_buffer->StrideU(), u_buffer,
|
||||
@ -94,68 +95,63 @@ class JavaVideoRendererWrapper : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
}
|
||||
|
||||
// Return a VideoRenderer.I420Frame referring texture object in |frame|.
|
||||
jobject ToJavaTextureFrame(JNIEnv* env, const VideoFrame& frame) {
|
||||
ScopedJavaLocalRef<jobject> ToJavaTextureFrame(JNIEnv* env,
|
||||
const VideoFrame& frame) {
|
||||
NativeHandleImpl handle =
|
||||
static_cast<AndroidTextureBuffer*>(frame.video_frame_buffer().get())
|
||||
->native_handle_impl();
|
||||
jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(env);
|
||||
|
||||
return Java_I420Frame_createTextureFrame(
|
||||
env, frame.width(), frame.height(), static_cast<int>(frame.rotation()),
|
||||
handle.oes_texture_id, sampling_matrix, javaShallowCopy(frame));
|
||||
handle.oes_texture_id, handle.sampling_matrix.ToJava(env),
|
||||
javaShallowCopy(frame));
|
||||
}
|
||||
|
||||
ScopedGlobalRef<jobject> j_callbacks_;
|
||||
ScopedJavaGlobalRef<jobject> j_callbacks_;
|
||||
};
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
VideoRenderer_freeWrappedVideoRenderer,
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
jlong j_p) {
|
||||
static void JNI_VideoRenderer_FreeWrappedVideoRenderer(
|
||||
JNIEnv*,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_p) {
|
||||
delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
VideoRenderer_releaseNativeFrame,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_frame_ptr) {
|
||||
static void JNI_VideoRenderer_ReleaseFrame(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_frame_ptr) {
|
||||
delete reinterpret_cast<const VideoFrame*>(j_frame_ptr);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
VideoRenderer_createNativeVideoRenderer,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_callbacks) {
|
||||
static jlong JNI_VideoRenderer_CreateVideoRenderer(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_callbacks) {
|
||||
std::unique_ptr<JavaVideoRendererWrapper> renderer(
|
||||
new JavaVideoRendererWrapper(jni, j_callbacks));
|
||||
return jlongFromPointer(renderer.release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
VideoRenderer_copyPlaneNative,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_src_buffer,
|
||||
jint width,
|
||||
jint height,
|
||||
jint src_stride,
|
||||
jobject j_dst_buffer,
|
||||
jint dst_stride) {
|
||||
size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer);
|
||||
size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
|
||||
static void JNI_VideoRenderer_CopyPlane(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_src_buffer,
|
||||
jint width,
|
||||
jint height,
|
||||
jint src_stride,
|
||||
const JavaParamRef<jobject>& j_dst_buffer,
|
||||
jint dst_stride) {
|
||||
size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer.obj());
|
||||
size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer.obj());
|
||||
RTC_CHECK(src_stride >= width) << "Wrong source stride " << src_stride;
|
||||
RTC_CHECK(dst_stride >= width) << "Wrong destination stride " << dst_stride;
|
||||
RTC_CHECK(src_size >= src_stride * height)
|
||||
<< "Insufficient source buffer capacity " << src_size;
|
||||
RTC_CHECK(dst_size >= dst_stride * height)
|
||||
<< "Insufficient destination buffer capacity " << dst_size;
|
||||
uint8_t* src =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer));
|
||||
uint8_t* dst =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
|
||||
uint8_t* src = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(j_src_buffer.obj()));
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(j_dst_buffer.obj()));
|
||||
if (src_stride == dst_stride) {
|
||||
memcpy(dst, src, src_stride * height);
|
||||
} else {
|
||||
|
||||
@ -16,15 +16,17 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni, jobject j_info) {
|
||||
SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_info) {
|
||||
return SdpVideoFormat(
|
||||
JavaToStdString(jni, Java_VideoCodecInfo_getName(jni, j_info)),
|
||||
JavaToStdMapStrings(jni, Java_VideoCodecInfo_getParams(jni, j_info)));
|
||||
}
|
||||
|
||||
jobject SdpVideoFormatToVideoCodecInfo(JNIEnv* jni,
|
||||
const SdpVideoFormat& format) {
|
||||
jobject j_params = NativeToJavaMap(
|
||||
ScopedJavaLocalRef<jobject> SdpVideoFormatToVideoCodecInfo(
|
||||
JNIEnv* jni,
|
||||
const SdpVideoFormat& format) {
|
||||
ScopedJavaLocalRef<jobject> j_params = NativeToJavaMap(
|
||||
jni, format.parameters,
|
||||
[](JNIEnv* env, const std::pair<std::string, std::string>& entry) {
|
||||
return std::make_pair(NativeToJavaString(env, entry.first),
|
||||
|
||||
@ -14,13 +14,16 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/video_codecs/sdp_video_format.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni, jobject info);
|
||||
jobject SdpVideoFormatToVideoCodecInfo(JNIEnv* jni,
|
||||
const SdpVideoFormat& format);
|
||||
SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni,
|
||||
const JavaRef<jobject>& info);
|
||||
ScopedJavaLocalRef<jobject> SdpVideoFormatToVideoCodecInfo(
|
||||
JNIEnv* jni,
|
||||
const SdpVideoFormat& format);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -15,8 +15,9 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
int32_t JavaToNativeVideoCodecStatus(JNIEnv* env,
|
||||
jobject j_video_codec_status) {
|
||||
int32_t JavaToNativeVideoCodecStatus(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_video_codec_status) {
|
||||
return Java_VideoCodecStatus_getNumber(env, j_video_codec_status);
|
||||
}
|
||||
|
||||
|
||||
@ -14,9 +14,13 @@
|
||||
#include <jni.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
int32_t JavaToNativeVideoCodecStatus(JNIEnv* env, jobject j_video_codec_status);
|
||||
int32_t JavaToNativeVideoCodecStatus(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_video_codec_status);
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -20,17 +20,19 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
VideoDecoderFactoryWrapper::VideoDecoderFactoryWrapper(JNIEnv* jni,
|
||||
jobject decoder_factory)
|
||||
VideoDecoderFactoryWrapper::VideoDecoderFactoryWrapper(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& decoder_factory)
|
||||
: decoder_factory_(jni, decoder_factory) {}
|
||||
|
||||
std::unique_ptr<VideoDecoder> VideoDecoderFactoryWrapper::CreateVideoDecoder(
|
||||
const SdpVideoFormat& format) {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
jobject decoder = Java_VideoDecoderFactory_createDecoder(
|
||||
jni, *decoder_factory_, NativeToJavaString(jni, format.name));
|
||||
return decoder != nullptr ? JavaToNativeVideoDecoder(jni, decoder) : nullptr;
|
||||
ScopedJavaLocalRef<jobject> decoder = Java_VideoDecoderFactory_createDecoder(
|
||||
jni, decoder_factory_, NativeToJavaString(jni, format.name));
|
||||
if (!decoder.obj())
|
||||
return nullptr;
|
||||
return JavaToNativeVideoDecoder(jni, decoder);
|
||||
}
|
||||
|
||||
std::vector<SdpVideoFormat> VideoDecoderFactoryWrapper::GetSupportedFormats()
|
||||
|
||||
@ -23,14 +23,15 @@ namespace jni {
|
||||
// JNI and wraps the decoder inside VideoDecoderWrapper.
|
||||
class VideoDecoderFactoryWrapper : public VideoDecoderFactory {
|
||||
public:
|
||||
VideoDecoderFactoryWrapper(JNIEnv* jni, jobject decoder_factory);
|
||||
VideoDecoderFactoryWrapper(JNIEnv* jni,
|
||||
const JavaRef<jobject>& decoder_factory);
|
||||
|
||||
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
|
||||
std::unique_ptr<VideoDecoder> CreateVideoDecoder(
|
||||
const SdpVideoFormat& format) override;
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> decoder_factory_;
|
||||
const ScopedJavaGlobalRef<jobject> decoder_factory_;
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -11,18 +11,18 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "media/engine/videodecodersoftwarefallbackwrapper.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoDecoderFallback_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/wrappednativecodec.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
VideoDecoderFallback_createNativeDecoder,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_fallback_decoder,
|
||||
jobject j_primary_decoder) {
|
||||
static jlong JNI_VideoDecoderFallback_CreateDecoder(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_fallback_decoder,
|
||||
const JavaParamRef<jobject>& j_primary_decoder) {
|
||||
std::unique_ptr<VideoDecoder> fallback_decoder =
|
||||
JavaToNativeVideoDecoder(jni, j_fallback_decoder);
|
||||
std::unique_ptr<VideoDecoder> primary_decoder =
|
||||
|
||||
@ -35,7 +35,8 @@ inline rtc::Optional<Dst> cast_optional(const rtc::Optional<Src>& value) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder)
|
||||
VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni,
|
||||
const JavaRef<jobject>& decoder)
|
||||
: decoder_(jni, decoder) {
|
||||
initialized_ = false;
|
||||
// QP parsing starts enabled and we disable it if the decoder provides frames.
|
||||
@ -48,22 +49,21 @@ VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder)
|
||||
int32_t VideoDecoderWrapper::InitDecode(const VideoCodec* codec_settings,
|
||||
int32_t number_of_cores) {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
|
||||
codec_settings_ = *codec_settings;
|
||||
number_of_cores_ = number_of_cores;
|
||||
return InitDecodeInternal(jni);
|
||||
}
|
||||
|
||||
int32_t VideoDecoderWrapper::InitDecodeInternal(JNIEnv* jni) {
|
||||
jobject settings = Java_Settings_Constructor(
|
||||
ScopedJavaLocalRef<jobject> settings = Java_Settings_Constructor(
|
||||
jni, number_of_cores_, codec_settings_.width, codec_settings_.height);
|
||||
|
||||
jobject callback = Java_VideoDecoderWrapper_createDecoderCallback(
|
||||
jni, jlongFromPointer(this));
|
||||
ScopedJavaLocalRef<jobject> callback =
|
||||
Java_VideoDecoderWrapper_createDecoderCallback(jni,
|
||||
jlongFromPointer(this));
|
||||
|
||||
jobject ret =
|
||||
Java_VideoDecoder_initDecode(jni, *decoder_, settings, callback);
|
||||
ScopedJavaLocalRef<jobject> ret =
|
||||
Java_VideoDecoder_initDecode(jni, decoder_, settings, callback);
|
||||
if (JavaToNativeVideoCodecStatus(jni, ret) == WEBRTC_VIDEO_CODEC_OK) {
|
||||
initialized_ = true;
|
||||
}
|
||||
@ -86,9 +86,6 @@ int32_t VideoDecoderWrapper::Decode(
|
||||
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
|
||||
}
|
||||
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
|
||||
// Make a mutable copy so we can modify the timestamp.
|
||||
EncodedImage input_image(image_param);
|
||||
// We use RTP timestamp for capture time because capture_time_ms_ is always 0.
|
||||
@ -104,9 +101,13 @@ int32_t VideoDecoderWrapper::Decode(
|
||||
qp_parsing_enabled_ ? ParseQP(input_image) : rtc::nullopt;
|
||||
frame_extra_infos_.push_back(frame_extra_info);
|
||||
|
||||
jobject jinput_image = NativeToJavaEncodedImage(jni, input_image);
|
||||
jobject ret = Java_VideoDecoder_decode(jni, *decoder_, jinput_image, nullptr);
|
||||
return HandleReturnCode(jni, ret);
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
ScopedJavaLocalRef<jobject> jinput_image =
|
||||
NativeToJavaEncodedImage(env, input_image);
|
||||
ScopedJavaLocalRef<jobject> decode_info;
|
||||
ScopedJavaLocalRef<jobject> ret =
|
||||
Java_VideoDecoder_decode(env, decoder_, jinput_image, decode_info);
|
||||
return HandleReturnCode(env, ret);
|
||||
}
|
||||
|
||||
int32_t VideoDecoderWrapper::RegisterDecodeCompleteCallback(
|
||||
@ -117,8 +118,7 @@ int32_t VideoDecoderWrapper::RegisterDecodeCompleteCallback(
|
||||
|
||||
int32_t VideoDecoderWrapper::Release() {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
jobject ret = Java_VideoDecoder_release(jni, *decoder_);
|
||||
ScopedJavaLocalRef<jobject> ret = Java_VideoDecoder_release(jni, decoder_);
|
||||
frame_extra_infos_.clear();
|
||||
initialized_ = false;
|
||||
return HandleReturnCode(jni, ret);
|
||||
@ -126,18 +126,19 @@ int32_t VideoDecoderWrapper::Release() {
|
||||
|
||||
bool VideoDecoderWrapper::PrefersLateDecoding() const {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
return Java_VideoDecoder_getPrefersLateDecoding(jni, *decoder_);
|
||||
return Java_VideoDecoder_getPrefersLateDecoding(jni, decoder_);
|
||||
}
|
||||
|
||||
const char* VideoDecoderWrapper::ImplementationName() const {
|
||||
return implementation_name_.c_str();
|
||||
}
|
||||
|
||||
void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* env,
|
||||
jobject j_caller,
|
||||
jobject j_frame,
|
||||
jobject j_decode_time_ms,
|
||||
jobject j_qp) {
|
||||
void VideoDecoderWrapper::OnDecodedFrame(
|
||||
JNIEnv* env,
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobject>& j_frame,
|
||||
const JavaRef<jobject>& j_decode_time_ms,
|
||||
const JavaRef<jobject>& j_qp) {
|
||||
const uint64_t timestamp_ns = GetJavaVideoFrameTimestampNs(env, j_frame);
|
||||
|
||||
FrameExtraInfo frame_extra_info;
|
||||
@ -170,7 +171,8 @@ void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* env,
|
||||
decoder_qp ? decoder_qp : frame_extra_info.qp);
|
||||
}
|
||||
|
||||
int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) {
|
||||
int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni,
|
||||
const JavaRef<jobject>& code) {
|
||||
int32_t value = JavaToNativeVideoCodecStatus(jni, code);
|
||||
if (value < 0) { // Any errors are represented by negative values.
|
||||
// Reset the codec.
|
||||
|
||||
@ -24,7 +24,7 @@ namespace jni {
|
||||
// Wraps a Java decoder and delegates all calls to it.
|
||||
class VideoDecoderWrapper : public VideoDecoder {
|
||||
public:
|
||||
VideoDecoderWrapper(JNIEnv* jni, jobject decoder);
|
||||
VideoDecoderWrapper(JNIEnv* jni, const JavaRef<jobject>& decoder);
|
||||
|
||||
int32_t InitDecode(const VideoCodec* codec_settings,
|
||||
int32_t number_of_cores) override;
|
||||
@ -49,10 +49,10 @@ class VideoDecoderWrapper : public VideoDecoder {
|
||||
|
||||
// Wraps the frame to a AndroidVideoBuffer and passes it to the callback.
|
||||
void OnDecodedFrame(JNIEnv* env,
|
||||
jobject j_caller,
|
||||
jobject j_frame,
|
||||
jobject j_decode_time_ms,
|
||||
jobject j_qp);
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobject>& j_frame,
|
||||
const JavaRef<jobject>& j_decode_time_ms,
|
||||
const JavaRef<jobject>& j_qp);
|
||||
|
||||
private:
|
||||
struct FrameExtraInfo {
|
||||
@ -67,7 +67,7 @@ class VideoDecoderWrapper : public VideoDecoder {
|
||||
|
||||
// Takes Java VideoCodecStatus, handles it and returns WEBRTC_VIDEO_CODEC_*
|
||||
// status code.
|
||||
int32_t HandleReturnCode(JNIEnv* jni, jobject code);
|
||||
int32_t HandleReturnCode(JNIEnv* jni, const JavaRef<jobject>& code);
|
||||
|
||||
rtc::Optional<uint8_t> ParseQP(const EncodedImage& input_image);
|
||||
|
||||
@ -82,7 +82,7 @@ class VideoDecoderWrapper : public VideoDecoder {
|
||||
|
||||
DecodedImageCallback* callback_;
|
||||
|
||||
const ScopedGlobalRef<jobject> decoder_;
|
||||
const ScopedJavaGlobalRef<jobject> decoder_;
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -21,10 +21,11 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(JNIEnv* jni,
|
||||
jobject encoder_factory)
|
||||
VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& encoder_factory)
|
||||
: encoder_factory_(jni, encoder_factory) {
|
||||
const jobjectArray j_supported_codecs =
|
||||
const ScopedJavaLocalRef<jobjectArray> j_supported_codecs =
|
||||
Java_VideoEncoderFactory_getSupportedCodecs(jni, encoder_factory);
|
||||
supported_formats_ = JavaToNativeVector<SdpVideoFormat>(
|
||||
jni, j_supported_codecs, &VideoCodecInfoToSdpVideoFormat);
|
||||
@ -33,21 +34,22 @@ VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(JNIEnv* jni,
|
||||
std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder(
|
||||
const SdpVideoFormat& format) {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format);
|
||||
jobject encoder = Java_VideoEncoderFactory_createEncoder(
|
||||
jni, *encoder_factory_, j_codec_info);
|
||||
return encoder != nullptr ? JavaToNativeVideoEncoder(jni, encoder) : nullptr;
|
||||
ScopedJavaLocalRef<jobject> j_codec_info =
|
||||
SdpVideoFormatToVideoCodecInfo(jni, format);
|
||||
ScopedJavaLocalRef<jobject> encoder = Java_VideoEncoderFactory_createEncoder(
|
||||
jni, encoder_factory_, j_codec_info);
|
||||
if (!encoder.obj())
|
||||
return nullptr;
|
||||
return JavaToNativeVideoEncoder(jni, encoder);
|
||||
}
|
||||
|
||||
VideoEncoderFactory::CodecInfo VideoEncoderFactoryWrapper::QueryVideoEncoder(
|
||||
const SdpVideoFormat& format) const {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
|
||||
jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format);
|
||||
jobject encoder = Java_VideoEncoderFactory_createEncoder(
|
||||
jni, *encoder_factory_, j_codec_info);
|
||||
ScopedJavaLocalRef<jobject> j_codec_info =
|
||||
SdpVideoFormatToVideoCodecInfo(jni, format);
|
||||
ScopedJavaLocalRef<jobject> encoder = Java_VideoEncoderFactory_createEncoder(
|
||||
jni, encoder_factory_, j_codec_info);
|
||||
|
||||
CodecInfo codec_info;
|
||||
// Check if this is a wrapped native software encoder implementation.
|
||||
|
||||
@ -25,7 +25,8 @@ namespace jni {
|
||||
// JNI and wraps the encoder inside VideoEncoderWrapper.
|
||||
class VideoEncoderFactoryWrapper : public VideoEncoderFactory {
|
||||
public:
|
||||
VideoEncoderFactoryWrapper(JNIEnv* jni, jobject encoder_factory);
|
||||
VideoEncoderFactoryWrapper(JNIEnv* jni,
|
||||
const JavaRef<jobject>& encoder_factory);
|
||||
|
||||
std::unique_ptr<VideoEncoder> CreateVideoEncoder(
|
||||
const SdpVideoFormat& format) override;
|
||||
@ -38,7 +39,7 @@ class VideoEncoderFactoryWrapper : public VideoEncoderFactory {
|
||||
CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
|
||||
|
||||
private:
|
||||
const ScopedGlobalRef<jobject> encoder_factory_;
|
||||
const ScopedJavaGlobalRef<jobject> encoder_factory_;
|
||||
std::vector<SdpVideoFormat> supported_formats_;
|
||||
};
|
||||
|
||||
|
||||
@ -11,18 +11,18 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "media/engine/videoencodersoftwarefallbackwrapper.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoEncoderFallback_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/wrappednativecodec.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
VideoEncoderFallback_createNativeEncoder,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_fallback_encoder,
|
||||
jobject j_primary_encoder) {
|
||||
static jlong JNI_VideoEncoderFallback_CreateEncoder(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_fallback_encoder,
|
||||
const JavaParamRef<jobject>& j_primary_encoder) {
|
||||
std::unique_ptr<VideoEncoder> fallback_encoder =
|
||||
JavaToNativeVideoEncoder(jni, j_fallback_encoder);
|
||||
std::unique_ptr<VideoEncoder> primary_encoder =
|
||||
|
||||
@ -32,9 +32,9 @@ namespace jni {
|
||||
|
||||
static const int kMaxJavaEncoderResets = 3;
|
||||
|
||||
VideoEncoderWrapper::VideoEncoderWrapper(JNIEnv* jni, jobject j_encoder)
|
||||
: encoder_(jni, j_encoder),
|
||||
int_array_class_(jni, jni->FindClass("[I")) {
|
||||
VideoEncoderWrapper::VideoEncoderWrapper(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_encoder)
|
||||
: encoder_(jni, j_encoder), int_array_class_(GetClass(jni, "[I")) {
|
||||
implementation_name_ = GetImplementationName(jni);
|
||||
|
||||
initialized_ = false;
|
||||
@ -49,7 +49,6 @@ int32_t VideoEncoderWrapper::InitEncode(const VideoCodec* codec_settings,
|
||||
int32_t number_of_cores,
|
||||
size_t max_payload_size) {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
|
||||
number_of_cores_ = number_of_cores;
|
||||
codec_settings_ = *codec_settings;
|
||||
@ -72,16 +71,17 @@ int32_t VideoEncoderWrapper::InitEncodeInternal(JNIEnv* jni) {
|
||||
automatic_resize_on = true;
|
||||
}
|
||||
|
||||
jobject settings = Java_Settings_Constructor(
|
||||
ScopedJavaLocalRef<jobject> settings = Java_Settings_Constructor(
|
||||
jni, number_of_cores_, codec_settings_.width, codec_settings_.height,
|
||||
codec_settings_.startBitrate, codec_settings_.maxFramerate,
|
||||
automatic_resize_on);
|
||||
|
||||
jobject callback = Java_VideoEncoderWrapper_createEncoderCallback(
|
||||
jni, jlongFromPointer(this));
|
||||
ScopedJavaLocalRef<jobject> callback =
|
||||
Java_VideoEncoderWrapper_createEncoderCallback(jni,
|
||||
jlongFromPointer(this));
|
||||
|
||||
jobject ret =
|
||||
Java_VideoEncoder_initEncode(jni, *encoder_, settings, callback);
|
||||
ScopedJavaLocalRef<jobject> ret =
|
||||
Java_VideoEncoder_initEncode(jni, encoder_, settings, callback);
|
||||
|
||||
if (JavaToNativeVideoCodecStatus(jni, ret) == WEBRTC_VIDEO_CODEC_OK) {
|
||||
initialized_ = true;
|
||||
@ -98,8 +98,7 @@ int32_t VideoEncoderWrapper::RegisterEncodeCompleteCallback(
|
||||
|
||||
int32_t VideoEncoderWrapper::Release() {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
jobject ret = Java_VideoEncoder_release(jni, *encoder_);
|
||||
ScopedJavaLocalRef<jobject> ret = Java_VideoEncoder_release(jni, encoder_);
|
||||
frame_extra_infos_.clear();
|
||||
initialized_ = false;
|
||||
encoder_queue_ = nullptr;
|
||||
@ -116,28 +115,28 @@ int32_t VideoEncoderWrapper::Encode(
|
||||
}
|
||||
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
|
||||
// Construct encode info.
|
||||
jobjectArray j_frame_types = NativeToJavaFrameTypeArray(jni, *frame_types);
|
||||
jobject encode_info = Java_EncodeInfo_Constructor(jni, j_frame_types);
|
||||
ScopedJavaLocalRef<jobjectArray> j_frame_types =
|
||||
NativeToJavaFrameTypeArray(jni, *frame_types);
|
||||
ScopedJavaLocalRef<jobject> encode_info =
|
||||
Java_EncodeInfo_Constructor(jni, j_frame_types);
|
||||
|
||||
FrameExtraInfo info;
|
||||
info.capture_time_ns = frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec;
|
||||
info.timestamp_rtp = frame.timestamp();
|
||||
frame_extra_infos_.push_back(info);
|
||||
|
||||
jobject ret = Java_VideoEncoder_encode(
|
||||
jni, *encoder_, NativeToJavaFrame(jni, frame), encode_info);
|
||||
ScopedJavaLocalRef<jobject> ret = Java_VideoEncoder_encode(
|
||||
jni, encoder_, NativeToJavaFrame(jni, frame), encode_info);
|
||||
return HandleReturnCode(jni, ret);
|
||||
}
|
||||
|
||||
int32_t VideoEncoderWrapper::SetChannelParameters(uint32_t packet_loss,
|
||||
int64_t rtt) {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
jobject ret = Java_VideoEncoder_setChannelParameters(
|
||||
jni, *encoder_, (jshort)packet_loss, (jlong)rtt);
|
||||
ScopedJavaLocalRef<jobject> ret = Java_VideoEncoder_setChannelParameters(
|
||||
jni, encoder_, (jshort)packet_loss, (jlong)rtt);
|
||||
return HandleReturnCode(jni, ret);
|
||||
}
|
||||
|
||||
@ -145,20 +144,19 @@ int32_t VideoEncoderWrapper::SetRateAllocation(
|
||||
const BitrateAllocation& allocation,
|
||||
uint32_t framerate) {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
|
||||
jobject j_bitrate_allocation = ToJavaBitrateAllocation(jni, allocation);
|
||||
jobject ret = Java_VideoEncoder_setRateAllocation(
|
||||
jni, *encoder_, j_bitrate_allocation, (jint)framerate);
|
||||
ScopedJavaLocalRef<jobject> j_bitrate_allocation =
|
||||
ToJavaBitrateAllocation(jni, allocation);
|
||||
ScopedJavaLocalRef<jobject> ret = Java_VideoEncoder_setRateAllocation(
|
||||
jni, encoder_, j_bitrate_allocation, (jint)framerate);
|
||||
return HandleReturnCode(jni, ret);
|
||||
}
|
||||
|
||||
VideoEncoderWrapper::ScalingSettings VideoEncoderWrapper::GetScalingSettings()
|
||||
const {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
jobject j_scaling_settings =
|
||||
Java_VideoEncoder_getScalingSettings(jni, *encoder_);
|
||||
ScopedJavaLocalRef<jobject> j_scaling_settings =
|
||||
Java_VideoEncoder_getScalingSettings(jni, encoder_);
|
||||
bool isOn =
|
||||
Java_VideoEncoderWrapper_getScalingSettingsOn(jni, j_scaling_settings);
|
||||
|
||||
@ -178,18 +176,18 @@ const char* VideoEncoderWrapper::ImplementationName() const {
|
||||
}
|
||||
|
||||
void VideoEncoderWrapper::OnEncodedFrame(JNIEnv* jni,
|
||||
jobject j_caller,
|
||||
jobject j_buffer,
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobject>& j_buffer,
|
||||
jint encoded_width,
|
||||
jint encoded_height,
|
||||
jlong capture_time_ns,
|
||||
jint frame_type,
|
||||
jint rotation,
|
||||
jboolean complete_frame,
|
||||
jobject j_qp) {
|
||||
const JavaRef<jobject>& j_qp) {
|
||||
const uint8_t* buffer =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer));
|
||||
const size_t buffer_size = jni->GetDirectBufferCapacity(j_buffer);
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer.obj()));
|
||||
const size_t buffer_size = jni->GetDirectBufferCapacity(j_buffer.obj());
|
||||
|
||||
std::vector<uint8_t> buffer_copy(buffer_size);
|
||||
memcpy(buffer_copy.data(), buffer, buffer_size);
|
||||
@ -236,7 +234,8 @@ void VideoEncoderWrapper::OnEncodedFrame(JNIEnv* jni,
|
||||
});
|
||||
}
|
||||
|
||||
int32_t VideoEncoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) {
|
||||
int32_t VideoEncoderWrapper::HandleReturnCode(JNIEnv* jni,
|
||||
const JavaRef<jobject>& code) {
|
||||
int32_t value = JavaToNativeVideoCodecStatus(jni, code);
|
||||
if (value < 0) { // Any errors are represented by negative values.
|
||||
// Try resetting the codec.
|
||||
@ -358,31 +357,33 @@ CodecSpecificInfo VideoEncoderWrapper::ParseCodecSpecificInfo(
|
||||
return info;
|
||||
}
|
||||
|
||||
jobject VideoEncoderWrapper::ToJavaBitrateAllocation(
|
||||
ScopedJavaLocalRef<jobject> VideoEncoderWrapper::ToJavaBitrateAllocation(
|
||||
JNIEnv* jni,
|
||||
const BitrateAllocation& allocation) {
|
||||
jobjectArray j_allocation_array = jni->NewObjectArray(
|
||||
kMaxSpatialLayers, *int_array_class_, nullptr /* initial */);
|
||||
ScopedJavaLocalRef<jobjectArray> j_allocation_array(
|
||||
jni, jni->NewObjectArray(kMaxSpatialLayers, int_array_class_.obj(),
|
||||
nullptr /* initial */));
|
||||
for (int spatial_i = 0; spatial_i < kMaxSpatialLayers; ++spatial_i) {
|
||||
jintArray j_array_spatial_layer = jni->NewIntArray(kMaxTemporalStreams);
|
||||
jint* array_spatial_layer =
|
||||
jni->GetIntArrayElements(j_array_spatial_layer, nullptr /* isCopy */);
|
||||
ScopedJavaLocalRef<jintArray> j_array_spatial_layer(
|
||||
jni, jni->NewIntArray(kMaxTemporalStreams));
|
||||
jint* array_spatial_layer = jni->GetIntArrayElements(
|
||||
j_array_spatial_layer.obj(), nullptr /* isCopy */);
|
||||
for (int temporal_i = 0; temporal_i < kMaxTemporalStreams; ++temporal_i) {
|
||||
array_spatial_layer[temporal_i] =
|
||||
allocation.GetBitrate(spatial_i, temporal_i);
|
||||
}
|
||||
jni->ReleaseIntArrayElements(j_array_spatial_layer, array_spatial_layer,
|
||||
JNI_COMMIT);
|
||||
jni->ReleaseIntArrayElements(j_array_spatial_layer.obj(),
|
||||
array_spatial_layer, JNI_COMMIT);
|
||||
|
||||
jni->SetObjectArrayElement(j_allocation_array, spatial_i,
|
||||
j_array_spatial_layer);
|
||||
jni->SetObjectArrayElement(j_allocation_array.obj(), spatial_i,
|
||||
j_array_spatial_layer.obj());
|
||||
}
|
||||
return Java_BitrateAllocation_Constructor(jni, j_allocation_array);
|
||||
}
|
||||
|
||||
std::string VideoEncoderWrapper::GetImplementationName(JNIEnv* jni) const {
|
||||
jstring jname = Java_VideoEncoder_getImplementationName(jni, *encoder_);
|
||||
return JavaToStdString(jni, jname);
|
||||
return JavaToStdString(
|
||||
jni, Java_VideoEncoder_getImplementationName(jni, encoder_));
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -29,7 +29,7 @@ namespace jni {
|
||||
// Wraps a Java encoder and delegates all calls to it.
|
||||
class VideoEncoderWrapper : public VideoEncoder {
|
||||
public:
|
||||
VideoEncoderWrapper(JNIEnv* jni, jobject j_encoder);
|
||||
VideoEncoderWrapper(JNIEnv* jni, const JavaRef<jobject>& j_encoder);
|
||||
|
||||
int32_t InitEncode(const VideoCodec* codec_settings,
|
||||
int32_t number_of_cores,
|
||||
@ -55,15 +55,15 @@ class VideoEncoderWrapper : public VideoEncoder {
|
||||
|
||||
// Should only be called by JNI.
|
||||
void OnEncodedFrame(JNIEnv* jni,
|
||||
jobject j_caller,
|
||||
jobject j_buffer,
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobject>& j_buffer,
|
||||
jint encoded_width,
|
||||
jint encoded_height,
|
||||
jlong capture_time_ms,
|
||||
jint frame_type,
|
||||
jint rotation,
|
||||
jboolean complete_frame,
|
||||
jobject j_qp);
|
||||
const JavaRef<jobject>& j_qp);
|
||||
|
||||
const char* ImplementationName() const override;
|
||||
|
||||
@ -78,18 +78,19 @@ class VideoEncoderWrapper : public VideoEncoder {
|
||||
|
||||
// Takes Java VideoCodecStatus, handles it and returns WEBRTC_VIDEO_CODEC_*
|
||||
// status code.
|
||||
int32_t HandleReturnCode(JNIEnv* jni, jobject code);
|
||||
int32_t HandleReturnCode(JNIEnv* jni, const JavaRef<jobject>& code);
|
||||
|
||||
RTPFragmentationHeader ParseFragmentationHeader(
|
||||
const std::vector<uint8_t>& buffer);
|
||||
int ParseQp(const std::vector<uint8_t>& buffer);
|
||||
CodecSpecificInfo ParseCodecSpecificInfo(const EncodedImage& frame);
|
||||
jobject ToJavaBitrateAllocation(JNIEnv* jni,
|
||||
const BitrateAllocation& allocation);
|
||||
ScopedJavaLocalRef<jobject> ToJavaBitrateAllocation(
|
||||
JNIEnv* jni,
|
||||
const BitrateAllocation& allocation);
|
||||
std::string GetImplementationName(JNIEnv* jni) const;
|
||||
|
||||
const ScopedGlobalRef<jobject> encoder_;
|
||||
const ScopedGlobalRef<jclass> int_array_class_;
|
||||
const ScopedJavaGlobalRef<jobject> encoder_;
|
||||
const ScopedJavaGlobalRef<jclass> int_array_class_;
|
||||
|
||||
std::string implementation_name_;
|
||||
|
||||
|
||||
@ -12,42 +12,44 @@
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoFileRenderer_jni.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_webrtc_VideoFileRenderer_nativeI420Scale(JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_src_buffer_y,
|
||||
jint j_src_stride_y,
|
||||
jobject j_src_buffer_u,
|
||||
jint j_src_stride_u,
|
||||
jobject j_src_buffer_v,
|
||||
jint j_src_stride_v,
|
||||
jint width,
|
||||
jint height,
|
||||
jbyteArray j_dst_buffer,
|
||||
jint dstWidth,
|
||||
jint dstHeight) {
|
||||
size_t src_size_y = jni->GetDirectBufferCapacity(j_src_buffer_y);
|
||||
size_t src_size_u = jni->GetDirectBufferCapacity(j_src_buffer_u);
|
||||
size_t src_size_v = jni->GetDirectBufferCapacity(j_src_buffer_v);
|
||||
size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
|
||||
static void JNI_VideoFileRenderer_I420Scale(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_src_buffer_y,
|
||||
jint j_src_stride_y,
|
||||
const JavaParamRef<jobject>& j_src_buffer_u,
|
||||
jint j_src_stride_u,
|
||||
const JavaParamRef<jobject>& j_src_buffer_v,
|
||||
jint j_src_stride_v,
|
||||
jint width,
|
||||
jint height,
|
||||
const JavaParamRef<jobject>& j_dst_buffer,
|
||||
jint dstWidth,
|
||||
jint dstHeight) {
|
||||
size_t src_size_y = jni->GetDirectBufferCapacity(j_src_buffer_y.obj());
|
||||
size_t src_size_u = jni->GetDirectBufferCapacity(j_src_buffer_u.obj());
|
||||
size_t src_size_v = jni->GetDirectBufferCapacity(j_src_buffer_v.obj());
|
||||
size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer.obj());
|
||||
int dst_stride = dstWidth;
|
||||
RTC_CHECK_GE(src_size_y, j_src_stride_y * height);
|
||||
RTC_CHECK_GE(src_size_u, j_src_stride_u * height / 4);
|
||||
RTC_CHECK_GE(src_size_v, j_src_stride_v * height / 4);
|
||||
RTC_CHECK_GE(dst_size, dst_stride * dstHeight * 3 / 2);
|
||||
uint8_t* src_y =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer_y));
|
||||
uint8_t* src_u =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer_u));
|
||||
uint8_t* src_v =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer_v));
|
||||
uint8_t* dst =
|
||||
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
|
||||
uint8_t* src_y = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(j_src_buffer_y.obj()));
|
||||
uint8_t* src_u = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(j_src_buffer_u.obj()));
|
||||
uint8_t* src_v = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(j_src_buffer_v.obj()));
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(
|
||||
jni->GetDirectBufferAddress(j_dst_buffer.obj()));
|
||||
|
||||
uint8_t* dst_y = dst;
|
||||
size_t dst_stride_y = dst_stride;
|
||||
|
||||
@ -36,8 +36,11 @@ class AndroidVideoI420Buffer : public I420BufferInterface {
|
||||
// Adopts and takes ownership of the Java VideoFrame.Buffer. I.e. retain()
|
||||
// will not be called, but release() will be called when the returned
|
||||
// AndroidVideoBuffer is destroyed.
|
||||
static rtc::scoped_refptr<AndroidVideoI420Buffer>
|
||||
Adopt(JNIEnv* jni, int width, int height, jobject j_video_frame_buffer);
|
||||
static rtc::scoped_refptr<AndroidVideoI420Buffer> Adopt(
|
||||
JNIEnv* jni,
|
||||
int width,
|
||||
int height,
|
||||
const JavaRef<jobject>& j_video_frame_buffer);
|
||||
|
||||
protected:
|
||||
// Should not be called directly. Adopts the buffer. Use Adopt() instead for
|
||||
@ -45,7 +48,7 @@ class AndroidVideoI420Buffer : public I420BufferInterface {
|
||||
AndroidVideoI420Buffer(JNIEnv* jni,
|
||||
int width,
|
||||
int height,
|
||||
jobject j_video_frame_buffer);
|
||||
const JavaRef<jobject>& j_video_frame_buffer);
|
||||
~AndroidVideoI420Buffer();
|
||||
|
||||
private:
|
||||
@ -63,7 +66,7 @@ class AndroidVideoI420Buffer : public I420BufferInterface {
|
||||
const int width_;
|
||||
const int height_;
|
||||
// Holds a VideoFrame.I420Buffer.
|
||||
const ScopedGlobalRef<jobject> j_video_frame_buffer_;
|
||||
const ScopedJavaGlobalRef<jobject> j_video_frame_buffer_;
|
||||
|
||||
const uint8_t* data_y_;
|
||||
const uint8_t* data_u_;
|
||||
@ -77,25 +80,32 @@ rtc::scoped_refptr<AndroidVideoI420Buffer> AndroidVideoI420Buffer::Adopt(
|
||||
JNIEnv* jni,
|
||||
int width,
|
||||
int height,
|
||||
jobject j_video_frame_buffer) {
|
||||
const JavaRef<jobject>& j_video_frame_buffer) {
|
||||
return new rtc::RefCountedObject<AndroidVideoI420Buffer>(
|
||||
jni, width, height, j_video_frame_buffer);
|
||||
}
|
||||
|
||||
AndroidVideoI420Buffer::AndroidVideoI420Buffer(JNIEnv* jni,
|
||||
int width,
|
||||
int height,
|
||||
jobject j_video_frame_buffer)
|
||||
AndroidVideoI420Buffer::AndroidVideoI420Buffer(
|
||||
JNIEnv* jni,
|
||||
int width,
|
||||
int height,
|
||||
const JavaRef<jobject>& j_video_frame_buffer)
|
||||
: width_(width),
|
||||
height_(height),
|
||||
j_video_frame_buffer_(jni, j_video_frame_buffer) {
|
||||
jobject j_data_y = Java_I420Buffer_getDataY(jni, j_video_frame_buffer);
|
||||
jobject j_data_u = Java_I420Buffer_getDataU(jni, j_video_frame_buffer);
|
||||
jobject j_data_v = Java_I420Buffer_getDataV(jni, j_video_frame_buffer);
|
||||
ScopedJavaLocalRef<jobject> j_data_y =
|
||||
Java_I420Buffer_getDataY(jni, j_video_frame_buffer);
|
||||
ScopedJavaLocalRef<jobject> j_data_u =
|
||||
Java_I420Buffer_getDataU(jni, j_video_frame_buffer);
|
||||
ScopedJavaLocalRef<jobject> j_data_v =
|
||||
Java_I420Buffer_getDataV(jni, j_video_frame_buffer);
|
||||
|
||||
data_y_ = static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_y));
|
||||
data_u_ = static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_u));
|
||||
data_v_ = static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_v));
|
||||
data_y_ =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_y.obj()));
|
||||
data_u_ =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_u.obj()));
|
||||
data_v_ =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_v.obj()));
|
||||
|
||||
stride_y_ = Java_I420Buffer_getStrideY(jni, j_video_frame_buffer);
|
||||
stride_u_ = Java_I420Buffer_getStrideU(jni, j_video_frame_buffer);
|
||||
@ -104,27 +114,28 @@ AndroidVideoI420Buffer::AndroidVideoI420Buffer(JNIEnv* jni,
|
||||
|
||||
AndroidVideoI420Buffer::~AndroidVideoI420Buffer() {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
Java_Buffer_release(jni, *j_video_frame_buffer_);
|
||||
Java_Buffer_release(jni, j_video_frame_buffer_);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni, jobject j_video_frame) {
|
||||
int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_video_frame) {
|
||||
return Java_VideoFrame_getTimestampNs(jni, j_video_frame);
|
||||
}
|
||||
|
||||
Matrix::Matrix(JNIEnv* jni, jfloatArray a) {
|
||||
RTC_CHECK_EQ(16, jni->GetArrayLength(a));
|
||||
jfloat* ptr = jni->GetFloatArrayElements(a, nullptr);
|
||||
Matrix::Matrix(JNIEnv* jni, const JavaRef<jfloatArray>& a) {
|
||||
RTC_CHECK_EQ(16, jni->GetArrayLength(a.obj()));
|
||||
jfloat* ptr = jni->GetFloatArrayElements(a.obj(), nullptr);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
elem_[i] = ptr[i];
|
||||
}
|
||||
jni->ReleaseFloatArrayElements(a, ptr, 0);
|
||||
jni->ReleaseFloatArrayElements(a.obj(), ptr, 0);
|
||||
}
|
||||
|
||||
jfloatArray Matrix::ToJava(JNIEnv* jni) const {
|
||||
jfloatArray matrix = jni->NewFloatArray(16);
|
||||
jni->SetFloatArrayRegion(matrix, 0, 16, elem_);
|
||||
ScopedJavaLocalRef<jfloatArray> Matrix::ToJava(JNIEnv* jni) const {
|
||||
ScopedJavaLocalRef<jfloatArray> matrix(jni, jni->NewFloatArray(16));
|
||||
jni->SetFloatArrayRegion(matrix.obj(), 0, 16, elem_);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
@ -200,9 +211,10 @@ static const int kBufferAlignment = 64;
|
||||
NativeHandleImpl::NativeHandleImpl(int id, const Matrix& matrix)
|
||||
: oes_texture_id(id), sampling_matrix(matrix) {}
|
||||
|
||||
NativeHandleImpl::NativeHandleImpl(JNIEnv* jni,
|
||||
jint j_oes_texture_id,
|
||||
jfloatArray j_transform_matrix)
|
||||
NativeHandleImpl::NativeHandleImpl(
|
||||
JNIEnv* jni,
|
||||
jint j_oes_texture_id,
|
||||
const JavaRef<jfloatArray>& j_transform_matrix)
|
||||
: oes_texture_id(j_oes_texture_id),
|
||||
sampling_matrix(jni, j_transform_matrix) {}
|
||||
|
||||
@ -262,11 +274,11 @@ rtc::scoped_refptr<I420BufferInterface> AndroidTextureBuffer::ToI420() {
|
||||
rtc::Bind(&AlignedFree, yuv_data.release()));
|
||||
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
|
||||
// TODO(sakal): This call to a deperecated method will be removed when
|
||||
// AndroidTextureBuffer is removed.
|
||||
jobject byte_buffer = jni->NewDirectByteBuffer(y_data, size);
|
||||
ScopedJavaLocalRef<jobject> byte_buffer =
|
||||
NewDirectByteBuffer(jni, y_data, size);
|
||||
SurfaceTextureHelperTextureToYUV(
|
||||
jni, surface_texture_helper_->GetJavaSurfaceTextureHelper(), byte_buffer,
|
||||
width(), height(), stride, native_handle_);
|
||||
@ -275,31 +287,33 @@ rtc::scoped_refptr<I420BufferInterface> AndroidTextureBuffer::ToI420() {
|
||||
|
||||
rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBuffer::Adopt(
|
||||
JNIEnv* jni,
|
||||
jobject j_video_frame_buffer) {
|
||||
const JavaRef<jobject>& j_video_frame_buffer) {
|
||||
return new rtc::RefCountedObject<AndroidVideoBuffer>(jni,
|
||||
j_video_frame_buffer);
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBuffer::Create(
|
||||
JNIEnv* jni,
|
||||
jobject j_video_frame_buffer) {
|
||||
const JavaRef<jobject>& j_video_frame_buffer) {
|
||||
Java_Buffer_retain(jni, j_video_frame_buffer);
|
||||
return Adopt(jni, j_video_frame_buffer);
|
||||
}
|
||||
|
||||
AndroidVideoBuffer::AndroidVideoBuffer(JNIEnv* jni,
|
||||
jobject j_video_frame_buffer)
|
||||
AndroidVideoBuffer::AndroidVideoBuffer(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_video_frame_buffer)
|
||||
: width_(Java_Buffer_getWidth(jni, j_video_frame_buffer)),
|
||||
height_(Java_Buffer_getHeight(jni, j_video_frame_buffer)),
|
||||
j_video_frame_buffer_(jni, j_video_frame_buffer) {}
|
||||
|
||||
AndroidVideoBuffer::~AndroidVideoBuffer() {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
Java_Buffer_release(jni, *j_video_frame_buffer_);
|
||||
Java_Buffer_release(jni, j_video_frame_buffer_);
|
||||
}
|
||||
|
||||
jobject AndroidVideoBuffer::video_frame_buffer() const {
|
||||
return *j_video_frame_buffer_;
|
||||
const ScopedJavaGlobalRef<jobject>& AndroidVideoBuffer::video_frame_buffer()
|
||||
const {
|
||||
return j_video_frame_buffer_;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBuffer::CropAndScale(
|
||||
@ -310,9 +324,9 @@ rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBuffer::CropAndScale(
|
||||
int crop_height,
|
||||
int scale_width,
|
||||
int scale_height) {
|
||||
return Adopt(jni, Java_Buffer_cropAndScale(
|
||||
jni, *j_video_frame_buffer_, crop_x, crop_y, crop_width,
|
||||
crop_height, scale_width, scale_height));
|
||||
return Adopt(jni, Java_Buffer_cropAndScale(jni, j_video_frame_buffer_, crop_x,
|
||||
crop_y, crop_width, crop_height,
|
||||
scale_width, scale_height));
|
||||
}
|
||||
|
||||
VideoFrameBuffer::Type AndroidVideoBuffer::type() const {
|
||||
@ -329,8 +343,8 @@ int AndroidVideoBuffer::height() const {
|
||||
|
||||
rtc::scoped_refptr<I420BufferInterface> AndroidVideoBuffer::ToI420() {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
jobject j_i420_buffer = Java_Buffer_toI420(jni, *j_video_frame_buffer_);
|
||||
ScopedJavaLocalRef<jobject> j_i420_buffer =
|
||||
Java_Buffer_toI420(jni, j_video_frame_buffer_);
|
||||
|
||||
// We don't need to retain the buffer because toI420 returns a new object that
|
||||
// we are assumed to take the ownership of.
|
||||
@ -338,9 +352,10 @@ rtc::scoped_refptr<I420BufferInterface> AndroidVideoBuffer::ToI420() {
|
||||
}
|
||||
|
||||
VideoFrame JavaToNativeFrame(JNIEnv* jni,
|
||||
jobject j_video_frame,
|
||||
const JavaRef<jobject>& j_video_frame,
|
||||
uint32_t timestamp_rtp) {
|
||||
jobject j_video_frame_buffer = Java_VideoFrame_getBuffer(jni, j_video_frame);
|
||||
ScopedJavaLocalRef<jobject> j_video_frame_buffer =
|
||||
Java_VideoFrame_getBuffer(jni, j_video_frame);
|
||||
int rotation = Java_VideoFrame_getRotation(jni, j_video_frame);
|
||||
int64_t timestamp_ns = Java_VideoFrame_getTimestampNs(jni, j_video_frame);
|
||||
rtc::scoped_refptr<AndroidVideoBuffer> buffer =
|
||||
@ -360,7 +375,8 @@ static bool IsJavaVideoBuffer(rtc::scoped_refptr<VideoFrameBuffer> buffer) {
|
||||
AndroidVideoFrameBuffer::AndroidType::kJavaBuffer;
|
||||
}
|
||||
|
||||
jobject NativeToJavaFrame(JNIEnv* jni, const VideoFrame& frame) {
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaFrame(JNIEnv* jni,
|
||||
const VideoFrame& frame) {
|
||||
rtc::scoped_refptr<VideoFrameBuffer> buffer = frame.video_frame_buffer();
|
||||
|
||||
if (IsJavaVideoBuffer(buffer)) {
|
||||
@ -386,36 +402,39 @@ jobject NativeToJavaFrame(JNIEnv* jni, const VideoFrame& frame) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_webrtc_VideoFrame_cropAndScaleI420Native(JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_src_y,
|
||||
jint src_stride_y,
|
||||
jobject j_src_u,
|
||||
jint src_stride_u,
|
||||
jobject j_src_v,
|
||||
jint src_stride_v,
|
||||
jint crop_x,
|
||||
jint crop_y,
|
||||
jint crop_width,
|
||||
jint crop_height,
|
||||
jobject j_dst_y,
|
||||
jint dst_stride_y,
|
||||
jobject j_dst_u,
|
||||
jint dst_stride_u,
|
||||
jobject j_dst_v,
|
||||
jint dst_stride_v,
|
||||
jint scale_width,
|
||||
jint scale_height) {
|
||||
static void JNI_VideoFrame_CropAndScaleI420(
|
||||
JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_src_y,
|
||||
jint src_stride_y,
|
||||
const JavaParamRef<jobject>& j_src_u,
|
||||
jint src_stride_u,
|
||||
const JavaParamRef<jobject>& j_src_v,
|
||||
jint src_stride_v,
|
||||
jint crop_x,
|
||||
jint crop_y,
|
||||
jint crop_width,
|
||||
jint crop_height,
|
||||
const JavaParamRef<jobject>& j_dst_y,
|
||||
jint dst_stride_y,
|
||||
const JavaParamRef<jobject>& j_dst_u,
|
||||
jint dst_stride_u,
|
||||
const JavaParamRef<jobject>& j_dst_v,
|
||||
jint dst_stride_v,
|
||||
jint scale_width,
|
||||
jint scale_height) {
|
||||
uint8_t const* src_y =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_y));
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_y.obj()));
|
||||
uint8_t const* src_u =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_u));
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_u.obj()));
|
||||
uint8_t const* src_v =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_v));
|
||||
uint8_t* dst_y = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y));
|
||||
uint8_t* dst_u = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u));
|
||||
uint8_t* dst_v = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v));
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_v.obj()));
|
||||
uint8_t* dst_y =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y.obj()));
|
||||
uint8_t* dst_u =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u.obj()));
|
||||
uint8_t* dst_v =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v.obj()));
|
||||
|
||||
// Perform cropping using pointer arithmetic.
|
||||
src_y += crop_x + crop_y * src_stride_y;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "api/video/video_rotation.h"
|
||||
#include "rtc_base/callback.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/surfacetexturehelper.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
@ -28,11 +29,12 @@ class SurfaceTextureHelper;
|
||||
// in-place.
|
||||
class Matrix {
|
||||
public:
|
||||
Matrix(JNIEnv* jni, jfloatArray a);
|
||||
Matrix(JNIEnv* jni, const JavaRef<jfloatArray>& a);
|
||||
|
||||
static Matrix fromAndroidGraphicsMatrix(JNIEnv* jni, jobject j_matrix);
|
||||
static Matrix fromAndroidGraphicsMatrix(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_matrix);
|
||||
|
||||
jfloatArray ToJava(JNIEnv* jni) const;
|
||||
ScopedJavaLocalRef<jfloatArray> ToJava(JNIEnv* jni) const;
|
||||
|
||||
// Crop arguments are relative to original size.
|
||||
void Crop(float cropped_width,
|
||||
@ -53,7 +55,7 @@ class Matrix {
|
||||
struct NativeHandleImpl {
|
||||
NativeHandleImpl(JNIEnv* jni,
|
||||
jint j_oes_texture_id,
|
||||
jfloatArray j_transform_matrix);
|
||||
const JavaRef<jfloatArray>& j_transform_matrix);
|
||||
|
||||
NativeHandleImpl(int id, const Matrix& matrix);
|
||||
|
||||
@ -103,18 +105,18 @@ class AndroidVideoBuffer : public AndroidVideoFrameBuffer {
|
||||
// Creates a native VideoFrameBuffer from a Java VideoFrame.Buffer.
|
||||
static rtc::scoped_refptr<AndroidVideoBuffer> Create(
|
||||
JNIEnv* jni,
|
||||
jobject j_video_frame_buffer);
|
||||
const JavaRef<jobject>& j_video_frame_buffer);
|
||||
|
||||
// Similar to the Create() above, but adopts and takes ownership of the Java
|
||||
// VideoFrame.Buffer. I.e. retain() will not be called, but release() will be
|
||||
// called when the returned AndroidVideoBuffer is destroyed.
|
||||
static rtc::scoped_refptr<AndroidVideoBuffer> Adopt(
|
||||
JNIEnv* jni,
|
||||
jobject j_video_frame_buffer);
|
||||
const JavaRef<jobject>& j_video_frame_buffer);
|
||||
|
||||
~AndroidVideoBuffer() override;
|
||||
|
||||
jobject video_frame_buffer() const;
|
||||
const ScopedJavaGlobalRef<jobject>& video_frame_buffer() const;
|
||||
|
||||
// Crops a region defined by |crop_x|, |crop_y|, |crop_width| and
|
||||
// |crop_height|. Scales it to size |scale_width| x |scale_height|.
|
||||
@ -129,7 +131,7 @@ class AndroidVideoBuffer : public AndroidVideoFrameBuffer {
|
||||
protected:
|
||||
// Should not be called directly. Adopts the Java VideoFrame.Buffer. Use
|
||||
// Create() or Adopt() instead for clarity.
|
||||
AndroidVideoBuffer(JNIEnv* jni, jobject j_video_frame_buffer);
|
||||
AndroidVideoBuffer(JNIEnv* jni, const JavaRef<jobject>& j_video_frame_buffer);
|
||||
|
||||
private:
|
||||
Type type() const override;
|
||||
@ -143,16 +145,18 @@ class AndroidVideoBuffer : public AndroidVideoFrameBuffer {
|
||||
const int width_;
|
||||
const int height_;
|
||||
// Holds a VideoFrame.Buffer.
|
||||
const ScopedGlobalRef<jobject> j_video_frame_buffer_;
|
||||
const ScopedJavaGlobalRef<jobject> j_video_frame_buffer_;
|
||||
};
|
||||
|
||||
VideoFrame JavaToNativeFrame(JNIEnv* jni,
|
||||
jobject j_video_frame,
|
||||
const JavaRef<jobject>& j_video_frame,
|
||||
uint32_t timestamp_rtp);
|
||||
|
||||
jobject NativeToJavaFrame(JNIEnv* jni, const VideoFrame& frame);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaFrame(JNIEnv* jni,
|
||||
const VideoFrame& frame);
|
||||
|
||||
int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni, jobject j_video_frame);
|
||||
int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_video_frame);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "api/mediastreaminterface.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoSink_jni.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoTrack_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/videoframe.h"
|
||||
|
||||
@ -23,56 +24,53 @@ namespace {
|
||||
|
||||
class VideoSinkWrapper : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
public:
|
||||
VideoSinkWrapper(JNIEnv* jni, jobject j_sink);
|
||||
VideoSinkWrapper(JNIEnv* jni, const JavaRef<jobject>& j_sink);
|
||||
~VideoSinkWrapper() override {}
|
||||
|
||||
private:
|
||||
void OnFrame(const VideoFrame& frame) override;
|
||||
|
||||
const ScopedGlobalRef<jobject> j_sink_;
|
||||
const ScopedJavaGlobalRef<jobject> j_sink_;
|
||||
};
|
||||
|
||||
VideoSinkWrapper::VideoSinkWrapper(JNIEnv* jni, jobject j_sink)
|
||||
VideoSinkWrapper::VideoSinkWrapper(JNIEnv* jni, const JavaRef<jobject>& j_sink)
|
||||
: j_sink_(jni, j_sink) {}
|
||||
|
||||
void VideoSinkWrapper::OnFrame(const VideoFrame& frame) {
|
||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
Java_VideoSink_onFrame(jni, *j_sink_, NativeToJavaFrame(jni, frame));
|
||||
Java_VideoSink_onFrame(jni, j_sink_, NativeToJavaFrame(jni, frame));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_webrtc_VideoTrack_nativeAddSink(JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_native_track,
|
||||
jlong j_native_sink) {
|
||||
static void JNI_VideoTrack_AddSink(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_native_track,
|
||||
jlong j_native_sink) {
|
||||
reinterpret_cast<VideoTrackInterface*>(j_native_track)
|
||||
->AddOrUpdateSink(
|
||||
reinterpret_cast<rtc::VideoSinkInterface<VideoFrame>*>(j_native_sink),
|
||||
rtc::VideoSinkWants());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_webrtc_VideoTrack_nativeRemoveSink(JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_native_track,
|
||||
jlong j_native_sink) {
|
||||
static void JNI_VideoTrack_RemoveSink(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_native_track,
|
||||
jlong j_native_sink) {
|
||||
reinterpret_cast<VideoTrackInterface*>(j_native_track)
|
||||
->RemoveSink(reinterpret_cast<rtc::VideoSinkInterface<VideoFrame>*>(
|
||||
j_native_sink));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_org_webrtc_VideoTrack_nativeWrapSink(JNIEnv* jni, jclass, jobject sink) {
|
||||
static jlong JNI_VideoTrack_WrapSink(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& sink) {
|
||||
return jlongFromPointer(new VideoSinkWrapper(jni, sink));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_webrtc_VideoTrack_nativeFreeSink(JNIEnv* jni,
|
||||
jclass,
|
||||
jlong j_native_sink) {
|
||||
static void JNI_VideoTrack_FreeSink(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
jlong j_native_sink) {
|
||||
delete reinterpret_cast<rtc::VideoSinkInterface<VideoFrame>*>(j_native_sink);
|
||||
}
|
||||
|
||||
|
||||
@ -11,22 +11,20 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "modules/video_coding/codecs/vp8/include/vp8.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VP8Decoder_jni.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VP8Encoder_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
VP8Encoder_createNativeEncoder,
|
||||
JNIEnv* jni,
|
||||
jobject) {
|
||||
static jlong JNI_VP8Encoder_CreateEncoder(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&) {
|
||||
return jlongFromPointer(VP8Encoder::Create().release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
VP8Decoder_createNativeDecoder,
|
||||
JNIEnv* jni,
|
||||
jobject) {
|
||||
static jlong JNI_VP8Decoder_CreateDecoder(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&) {
|
||||
return jlongFromPointer(VP8Decoder::Create().release());
|
||||
}
|
||||
|
||||
|
||||
@ -11,36 +11,30 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "modules/video_coding/codecs/vp9/include/vp9.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VP9Decoder_jni.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VP9Encoder_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
VP9Encoder_createNativeEncoder,
|
||||
JNIEnv* jni,
|
||||
jobject) {
|
||||
static jlong JNI_VP9Encoder_CreateEncoder(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>& w) {
|
||||
return jlongFromPointer(VP9Encoder::Create().release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
VP9Encoder_isSupported,
|
||||
JNIEnv* jni,
|
||||
jclass) {
|
||||
static jboolean JNI_VP9Encoder_IsSupported(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&) {
|
||||
return VP9Encoder::IsSupported();
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jlong,
|
||||
VP9Decoder_createNativeDecoder,
|
||||
JNIEnv* jni,
|
||||
jobject) {
|
||||
static jlong JNI_VP9Decoder_CreateDecoder(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>& w) {
|
||||
return jlongFromPointer(VP9Decoder::Create().release());
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(jboolean,
|
||||
VP9Decoder_isSupported,
|
||||
JNIEnv* jni,
|
||||
jclass) {
|
||||
static jboolean JNI_VP9Decoder_IsSupported(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&) {
|
||||
return VP9Decoder::IsSupported();
|
||||
}
|
||||
|
||||
|
||||
@ -17,26 +17,23 @@ namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
// TODO(magjed): Write a test for this function.
|
||||
jobject WrapI420Buffer(
|
||||
ScopedJavaLocalRef<jobject> WrapI420Buffer(
|
||||
JNIEnv* jni,
|
||||
const rtc::scoped_refptr<I420BufferInterface>& i420_buffer) {
|
||||
jobject y_buffer =
|
||||
jni->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataY()),
|
||||
i420_buffer->StrideY() * i420_buffer->height());
|
||||
jobject u_buffer = jni->NewDirectByteBuffer(
|
||||
const_cast<uint8_t*>(i420_buffer->DataU()),
|
||||
i420_buffer->StrideU() * i420_buffer->ChromaHeight());
|
||||
jobject v_buffer = jni->NewDirectByteBuffer(
|
||||
const_cast<uint8_t*>(i420_buffer->DataV()),
|
||||
i420_buffer->StrideV() * i420_buffer->ChromaHeight());
|
||||
ScopedJavaLocalRef<jobject> y_buffer =
|
||||
NewDirectByteBuffer(jni, const_cast<uint8_t*>(i420_buffer->DataY()),
|
||||
i420_buffer->StrideY() * i420_buffer->height());
|
||||
ScopedJavaLocalRef<jobject> u_buffer =
|
||||
NewDirectByteBuffer(jni, const_cast<uint8_t*>(i420_buffer->DataU()),
|
||||
i420_buffer->StrideU() * i420_buffer->ChromaHeight());
|
||||
ScopedJavaLocalRef<jobject> v_buffer =
|
||||
NewDirectByteBuffer(jni, const_cast<uint8_t*>(i420_buffer->DataV()),
|
||||
i420_buffer->StrideV() * i420_buffer->ChromaHeight());
|
||||
|
||||
jobject j_wrapped_native_i420_buffer =
|
||||
Java_WrappedNativeI420Buffer_Constructor(
|
||||
jni, i420_buffer->width(), i420_buffer->height(), y_buffer,
|
||||
i420_buffer->StrideY(), u_buffer, i420_buffer->StrideU(), v_buffer,
|
||||
i420_buffer->StrideV(), jlongFromPointer(i420_buffer.get()));
|
||||
|
||||
return j_wrapped_native_i420_buffer;
|
||||
return Java_WrappedNativeI420Buffer_Constructor(
|
||||
jni, i420_buffer->width(), i420_buffer->height(), y_buffer,
|
||||
i420_buffer->StrideY(), u_buffer, i420_buffer->StrideU(), v_buffer,
|
||||
i420_buffer->StrideV(), jlongFromPointer(i420_buffer.get()));
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
@ -14,13 +14,14 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/video/video_frame_buffer.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
// This function wraps the C++ I420 buffer and returns a Java
|
||||
// VideoFrame.I420Buffer as a jobject.
|
||||
jobject WrapI420Buffer(
|
||||
ScopedJavaLocalRef<jobject> WrapI420Buffer(
|
||||
JNIEnv* jni,
|
||||
const rtc::scoped_refptr<I420BufferInterface>& i420_buffer);
|
||||
|
||||
|
||||
@ -20,8 +20,9 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(JNIEnv* jni,
|
||||
jobject j_decoder) {
|
||||
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_decoder) {
|
||||
VideoDecoder* decoder;
|
||||
if (Java_WrappedNativeVideoDecoder_isInstanceOf(jni, j_decoder)) {
|
||||
jlong native_decoder =
|
||||
@ -34,8 +35,9 @@ std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(JNIEnv* jni,
|
||||
return std::unique_ptr<VideoDecoder>(decoder);
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoEncoder> JavaToNativeVideoEncoder(JNIEnv* jni,
|
||||
jobject j_encoder) {
|
||||
std::unique_ptr<VideoEncoder> JavaToNativeVideoEncoder(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_encoder) {
|
||||
VideoEncoder* encoder;
|
||||
if (Java_WrappedNativeVideoEncoder_isInstanceOf(jni, j_encoder)) {
|
||||
jlong native_encoder =
|
||||
@ -48,7 +50,7 @@ std::unique_ptr<VideoEncoder> JavaToNativeVideoEncoder(JNIEnv* jni,
|
||||
return std::unique_ptr<VideoEncoder>(encoder);
|
||||
}
|
||||
|
||||
bool IsWrappedSoftwareEncoder(JNIEnv* jni, jobject j_encoder) {
|
||||
bool IsWrappedSoftwareEncoder(JNIEnv* jni, const JavaRef<jobject>& j_encoder) {
|
||||
return Java_WrappedNativeVideoEncoder_isWrappedSoftwareEncoder(jni,
|
||||
j_encoder);
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
#include "api/video_codecs/video_decoder.h"
|
||||
#include "api/video_codecs/video_encoder.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
@ -23,16 +24,18 @@ namespace jni {
|
||||
/* If the j_decoder is a wrapped native decoder, unwrap it. If it is not,
|
||||
* wrap it in a VideoDecoderWrapper.
|
||||
*/
|
||||
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(JNIEnv* jni,
|
||||
jobject j_decoder);
|
||||
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_decoder);
|
||||
|
||||
/* If the j_encoder is a wrapped native encoder, unwrap it. If it is not,
|
||||
* wrap it in a VideoEncoderWrapper.
|
||||
*/
|
||||
std::unique_ptr<VideoEncoder> JavaToNativeVideoEncoder(JNIEnv* jni,
|
||||
jobject j_encoder);
|
||||
std::unique_ptr<VideoEncoder> JavaToNativeVideoEncoder(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_encoder);
|
||||
|
||||
bool IsWrappedSoftwareEncoder(JNIEnv* jni, jobject j_encoder);
|
||||
bool IsWrappedSoftwareEncoder(JNIEnv* jni, const JavaRef<jobject>& j_encoder);
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -10,70 +10,71 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "sdk/android/generated_video_jni/jni/YuvHelper_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "third_party/libyuv/include/libyuv/convert.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
YuvHelper_I420Copy,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_src_y,
|
||||
jint src_stride_y,
|
||||
jobject j_src_u,
|
||||
jint src_stride_u,
|
||||
jobject j_src_v,
|
||||
jint src_stride_v,
|
||||
jobject j_dst_y,
|
||||
jint dst_stride_y,
|
||||
jobject j_dst_u,
|
||||
jint dst_stride_u,
|
||||
jobject j_dst_v,
|
||||
jint dst_stride_v,
|
||||
jint width,
|
||||
jint height) {
|
||||
void JNI_YuvHelper_I420Copy(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_src_y,
|
||||
jint src_stride_y,
|
||||
const JavaParamRef<jobject>& j_src_u,
|
||||
jint src_stride_u,
|
||||
const JavaParamRef<jobject>& j_src_v,
|
||||
jint src_stride_v,
|
||||
const JavaParamRef<jobject>& j_dst_y,
|
||||
jint dst_stride_y,
|
||||
const JavaParamRef<jobject>& j_dst_u,
|
||||
jint dst_stride_u,
|
||||
const JavaParamRef<jobject>& j_dst_v,
|
||||
jint dst_stride_v,
|
||||
jint width,
|
||||
jint height) {
|
||||
const uint8_t* src_y =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_y));
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_y.obj()));
|
||||
const uint8_t* src_u =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_u));
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_u.obj()));
|
||||
const uint8_t* src_v =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_v));
|
||||
uint8_t* dst_y = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y));
|
||||
uint8_t* dst_u = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u));
|
||||
uint8_t* dst_v = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v));
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_v.obj()));
|
||||
uint8_t* dst_y =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y.obj()));
|
||||
uint8_t* dst_u =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_u.obj()));
|
||||
uint8_t* dst_v =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_v.obj()));
|
||||
|
||||
libyuv::I420Copy(src_y, src_stride_y, src_u, src_stride_u, src_v,
|
||||
src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v, width, height);
|
||||
}
|
||||
|
||||
JNI_FUNCTION_DECLARATION(void,
|
||||
YuvHelper_I420ToNV12,
|
||||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject j_src_y,
|
||||
jint src_stride_y,
|
||||
jobject j_src_u,
|
||||
jint src_stride_u,
|
||||
jobject j_src_v,
|
||||
jint src_stride_v,
|
||||
jobject j_dst_y,
|
||||
jint dst_stride_y,
|
||||
jobject j_dst_uv,
|
||||
jint dst_stride_uv,
|
||||
jint width,
|
||||
jint height) {
|
||||
static void JNI_YuvHelper_I420ToNV12(JNIEnv* jni,
|
||||
const JavaParamRef<jclass>&,
|
||||
const JavaParamRef<jobject>& j_src_y,
|
||||
jint src_stride_y,
|
||||
const JavaParamRef<jobject>& j_src_u,
|
||||
jint src_stride_u,
|
||||
const JavaParamRef<jobject>& j_src_v,
|
||||
jint src_stride_v,
|
||||
const JavaParamRef<jobject>& j_dst_y,
|
||||
jint dst_stride_y,
|
||||
const JavaParamRef<jobject>& j_dst_uv,
|
||||
jint dst_stride_uv,
|
||||
jint width,
|
||||
jint height) {
|
||||
const uint8_t* src_y =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_y));
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_y.obj()));
|
||||
const uint8_t* src_u =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_u));
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_u.obj()));
|
||||
const uint8_t* src_v =
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_v));
|
||||
uint8_t* dst_y = static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y));
|
||||
static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_src_v.obj()));
|
||||
uint8_t* dst_y =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_y.obj()));
|
||||
uint8_t* dst_uv =
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_uv));
|
||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_uv.obj()));
|
||||
|
||||
libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v,
|
||||
src_stride_v, dst_y, dst_stride_y, dst_uv, dst_stride_uv,
|
||||
|
||||
Reference in New Issue
Block a user