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:
Magnus Jedvert
2017-12-20 15:12:10 +01:00
committed by Commit Bot
parent ec22e3f503
commit 84d8ae5df7
128 changed files with 2324 additions and 1958 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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.";

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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);

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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));
}

View File

@ -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_;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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));

View File

@ -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();
}

View File

@ -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")

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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());
}

View File

@ -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());
}

View File

@ -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_;
};

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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_;

View File

@ -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(),

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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 =

View File

@ -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

View File

@ -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());
}

View File

@ -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

View File

@ -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));
}

View File

@ -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_;
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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>(

View File

@ -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();

View 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_

View File

@ -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(

View File

@ -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

View File

@ -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 {

View File

@ -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),

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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 =

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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_;
};

View File

@ -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 =

View File

@ -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

View File

@ -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_;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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();
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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,