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

@ -65,23 +65,6 @@ class AttachThreadScoped {
JNIEnv* env_;
};
// Scoped holder for global Java refs.
template<class T> // T is jclass, jobject, jintArray, etc.
class ScopedGlobalRef {
public:
ScopedGlobalRef(JNIEnv* jni, T obj)
: jni_(jni), obj_(static_cast<T>(NewGlobalRef(jni, obj))) {}
~ScopedGlobalRef() {
DeleteGlobalRef(jni_, obj_);
}
T operator*() const {
return obj_;
}
private:
JNIEnv* jni_;
T obj_;
};
} // namespace webrtc
#endif // MODULES_UTILITY_INCLUDE_HELPERS_ANDROID_H_

View File

@ -290,15 +290,15 @@ void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() {
if (config_.hw_encoder) {
#if defined(WEBRTC_ANDROID)
JNIEnv* env = jni::AttachCurrentThreadIfNeeded();
jni::ScopedLocalRefFrame local_ref_frame(env);
jclass factory_class =
webrtc::jni::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
jni::ScopedJavaLocalRef<jclass> factory_class =
jni::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
jmethodID factory_constructor = env->GetMethodID(
factory_class, "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
jobject factory_object = env->NewObject(
factory_class, factory_constructor, nullptr /* shared_context */,
false /* enable_intel_vp8_encoder */,
true /* enable_h264_high_profile */);
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
jni::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor,
nullptr /* shared_context */,
false /* enable_intel_vp8_encoder */,
true /* enable_h264_high_profile */));
encoder_factory = rtc::MakeUnique<webrtc::jni::VideoEncoderFactoryWrapper>(
env, factory_object);
#elif defined(WEBRTC_IOS)
@ -316,13 +316,13 @@ void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() {
if (config_.hw_decoder) {
#if defined(WEBRTC_ANDROID)
JNIEnv* env = jni::AttachCurrentThreadIfNeeded();
jni::ScopedLocalRefFrame local_ref_frame(env);
jclass factory_class =
webrtc::jni::GetClass(env, "org/webrtc/HardwareVideoDecoderFactory");
jni::ScopedJavaLocalRef<jclass> factory_class =
jni::GetClass(env, "org/webrtc/HardwareVideoDecoderFactory");
jmethodID factory_constructor = env->GetMethodID(
factory_class, "<init>", "(Lorg/webrtc/EglBase$Context;)V");
jobject factory_object = env->NewObject(factory_class, factory_constructor,
nullptr /* shared_context */);
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;)V");
jni::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor,
nullptr /* shared_context */));
decoder_factory = rtc::MakeUnique<webrtc::jni::VideoDecoderFactoryWrapper>(
env, factory_object);
#elif defined(WEBRTC_IOS)

View File

@ -35,6 +35,8 @@ config("libjingle_peerconnection_jni_warnings_config") {
generate_jni("generated_base_jni") {
sources = [
"src/java/org/webrtc/Histogram.java",
"src/java/org/webrtc/JniCommon.java",
"src/java/org/webrtc/JniHelper.java",
"src/java/org/webrtc/WebRtcClassLoader.java",
]
@ -74,6 +76,7 @@ rtc_source_set("base_jni") {
"src/jni/pc/audio.h",
"src/jni/pc/media.h",
"src/jni/pc/video.h",
"src/jni/scoped_java_ref.h",
]
deps = [
@ -96,6 +99,14 @@ rtc_source_set("base_jni") {
}
}
generate_jni("generated_audio_jni") {
sources = [
"api/org/webrtc/DefaultAudioProcessingFactory.java",
]
jni_package = ""
jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h"
}
rtc_static_library("audio_jni") {
sources = [
"src/jni/pc/audio.cc",
@ -104,6 +115,7 @@ rtc_static_library("audio_jni") {
deps = [
":base_jni",
":generated_audio_jni",
"../../api/audio_codecs:builtin_audio_decoder_factory",
"../../api/audio_codecs:builtin_audio_encoder_factory",
"../../modules/audio_processing:audio_processing",
@ -125,6 +137,7 @@ rtc_static_library("null_audio_jni") {
generate_jni("generated_video_jni") {
sources = [
"api/org/webrtc/EncodedImage.java",
"api/org/webrtc/HardwareVideoEncoderFactory.java",
"api/org/webrtc/MediaCodecVideoDecoder.java",
"api/org/webrtc/MediaCodecVideoEncoder.java",
"api/org/webrtc/SurfaceTextureHelper.java",
@ -132,12 +145,25 @@ generate_jni("generated_video_jni") {
"api/org/webrtc/VideoCodecStatus.java",
"api/org/webrtc/VideoDecoder.java",
"api/org/webrtc/VideoDecoderFactory.java",
"api/org/webrtc/VideoDecoderFallback.java",
"api/org/webrtc/VideoEncoder.java",
"api/org/webrtc/VideoEncoderFactory.java",
"api/org/webrtc/VideoEncoderFallback.java",
"api/org/webrtc/VideoFileRenderer.java",
"api/org/webrtc/VideoFrame.java",
"api/org/webrtc/VideoRenderer.java",
"api/org/webrtc/VideoSink.java",
"api/org/webrtc/VideoSource.java",
"api/org/webrtc/VideoTrack.java",
"api/org/webrtc/YuvHelper.java",
"src/java/org/webrtc/AndroidVideoTrackSourceObserver.java",
"src/java/org/webrtc/EglBase14.java",
"src/java/org/webrtc/NV12Buffer.java",
"src/java/org/webrtc/NV21Buffer.java",
"src/java/org/webrtc/VP8Decoder.java",
"src/java/org/webrtc/VP8Encoder.java",
"src/java/org/webrtc/VP9Decoder.java",
"src/java/org/webrtc/VP9Encoder.java",
"src/java/org/webrtc/VideoDecoderWrapper.java",
"src/java/org/webrtc/VideoEncoderWrapper.java",
"src/java/org/webrtc/WrappedNativeI420Buffer.java",
@ -297,7 +323,10 @@ rtc_static_library("null_media_jni") {
generate_jni("generated_peerconnection_jni") {
sources = [
"api/org/webrtc/AudioTrack.java",
"api/org/webrtc/CallSessionFileRotatingLogSink.java",
"api/org/webrtc/DataChannel.java",
"api/org/webrtc/DtmfSender.java",
"api/org/webrtc/IceCandidate.java",
"api/org/webrtc/MediaConstraints.java",
"api/org/webrtc/MediaSource.java",
@ -637,6 +666,7 @@ rtc_android_library("libjingle_peerconnection_java") {
"src/java/org/webrtc/BitrateAdjuster.java",
"src/java/org/webrtc/CalledByNative.java",
"src/java/org/webrtc/CalledByNativeUnchecked.java",
"src/java/org/webrtc/JNINamespace.java",
"src/java/org/webrtc/Camera1Session.java",
"src/java/org/webrtc/Camera2Session.java",
"src/java/org/webrtc/CameraCapturer.java",

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** Java wrapper for a C++ AudioTrackInterface */
@JNINamespace("webrtc::jni")
public class AudioTrack extends MediaStreamTrack {
public AudioTrack(long nativeTrack) {
super(nativeTrack);
@ -23,5 +24,5 @@ public class AudioTrack extends MediaStreamTrack {
nativeSetVolume(super.nativeTrack, volume);
}
private static native void nativeSetVolume(long nativeTrack, double volume);
private static native void nativeSetVolume(long track, double volume);
}

View File

@ -10,6 +10,7 @@
package org.webrtc;
@JNINamespace("webrtc::jni")
public class CallSessionFileRotatingLogSink {
private long nativeSink;
@ -30,6 +31,6 @@ public class CallSessionFileRotatingLogSink {
}
private static native long nativeAddSink(String dirPath, int maxFileSize, int severity);
private static native void nativeDeleteSink(long nativeSink);
private static native void nativeDeleteSink(long sink);
private static native byte[] nativeGetLogData(String dirPath);
}

View File

@ -13,6 +13,7 @@ package org.webrtc;
import java.nio.ByteBuffer;
/** Java wrapper for a C++ DataChannelInterface. */
@JNINamespace("webrtc::jni")
public class DataChannel {
/** Java wrapper for WebIDL RTCDataChannel. */
public static class Init {
@ -113,33 +114,41 @@ public class DataChannel {
/** Register |observer|, replacing any previously-registered observer. */
public void registerObserver(Observer observer) {
if (nativeObserver != 0) {
unregisterObserverNative(nativeObserver);
nativeUnregisterObserver(nativeObserver);
}
nativeObserver = registerObserverNative(observer);
nativeObserver = nativeRegisterObserver(observer);
}
private native long registerObserverNative(Observer observer);
/** Unregister the (only) observer. */
public void unregisterObserver() {
unregisterObserverNative(nativeObserver);
nativeUnregisterObserver(nativeObserver);
}
private native void unregisterObserverNative(long nativeObserver);
public native String label();
public String label() {
return nativeLabel();
}
public native int id();
public int id() {
return nativeId();
}
public native State state();
public State state() {
return nativeState();
}
/**
* Return the number of bytes of application data (UTF-8 text and binary data)
* that have been queued using SendBuffer but have not yet been transmitted
* to the network.
*/
public native long bufferedAmount();
public long bufferedAmount() {
return nativeBufferedAmount();
}
/** Close the channel. */
public native void close();
public void close() {
nativeClose();
}
/** Send |data| to the remote peer; return success. */
public boolean send(Buffer buffer) {
@ -147,9 +156,8 @@ public class DataChannel {
// ByteBuffer is direct and/or is backed by an array.
byte[] data = new byte[buffer.data.remaining()];
buffer.data.get(data);
return sendNative(data, buffer.binary);
return nativeSend(data, buffer.binary);
}
private native boolean sendNative(byte[] data, boolean binary);
/** Dispose of native resources attached to this channel. */
public void dispose() {
@ -160,4 +168,13 @@ public class DataChannel {
long getNativeDataChannel() {
return nativeDataChannel;
}
private native long nativeRegisterObserver(Observer observer);
private native void nativeUnregisterObserver(long observer);
private native String nativeLabel();
private native int nativeId();
private native State nativeState();
private native long nativeBufferedAmount();
private native void nativeClose();
private native boolean nativeSend(byte[] data, boolean binary);
};

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** Factory for instantiating the default webrtc::AudioProcessing implementation. */
@JNINamespace("webrtc::jni")
public class DefaultAudioProcessingFactory implements AudioProcessingFactory {
public DefaultAudioProcessingFactory() {
this(null /* postProcessingFactory */);
@ -43,5 +44,5 @@ public class DefaultAudioProcessingFactory implements AudioProcessingFactory {
private PostProcessingFactory postProcessingFactory;
private static native long nativeCreateAudioProcessing(long nativePostProcessor);
private static native long nativeCreateAudioProcessing(long postProcessor);
}

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** Java wrapper for a C++ DtmfSenderInterface. */
@JNINamespace("webrtc::jni")
public class DtmfSender {
final long nativeDtmfSender;
@ -74,10 +75,10 @@ public class DtmfSender {
JniCommon.nativeReleaseRef(nativeDtmfSender);
}
private static native boolean nativeCanInsertDtmf(long nativeDtmfSender);
private static native boolean nativeCanInsertDtmf(long dtmfSender);
private static native boolean nativeInsertDtmf(
long nativeDtmfSender, String tones, int duration, int interToneGap);
private static native String nativeTones(long nativeDtmfSender);
private static native int nativeDuration(long nativeDtmfSender);
private static native int nativeInterToneGap(long nativeDtmfSender);
long dtmfSender, String tones, int duration, int interToneGap);
private static native String nativeTones(long dtmfSender);
private static native int nativeDuration(long dtmfSender);
private static native int nativeInterToneGap(long dtmfSender);
};

View File

@ -25,6 +25,7 @@ import java.util.Map;
/** Factory for android hardware video encoders. */
@SuppressWarnings("deprecation") // API 16 requires the use of deprecated methods.
@JNINamespace("webrtc::jni")
public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
private static final String TAG = "HardwareVideoEncoderFactory";
@ -94,9 +95,10 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
MediaCodecUtils.ENCODER_COLOR_FORMATS, info.getCapabilitiesForType(mime));
if (type == VideoCodecType.H264) {
boolean isHighProfile = isSameH264Profile(input.params, getCodecProperties(type, true))
boolean isHighProfile = nativeIsSameH264Profile(input.params, getCodecProperties(type, true))
&& isH264HighProfileSupported(info);
boolean isBaselineProfile = isSameH264Profile(input.params, getCodecProperties(type, false));
boolean isBaselineProfile =
nativeIsSameH264Profile(input.params, getCodecProperties(type, false));
if (!isHighProfile && !isBaselineProfile) {
return null;
@ -281,6 +283,6 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
}
}
private static native boolean isSameH264Profile(
private static native boolean nativeIsSameH264Profile(
Map<String, String> params1, Map<String, String> params2);
}

View File

@ -36,6 +36,7 @@ import org.webrtc.VideoFrame;
// This class is an implementation detail of the Java PeerConnection API.
@TargetApi(19)
@SuppressWarnings("deprecation")
@JNINamespace("webrtc::jni")
public class MediaCodecVideoEncoder {
// This class is constructed, operated, and destroyed by its C++ incarnation,
// so the class and its methods have non-public visibility. The API this
@ -658,7 +659,7 @@ public class MediaCodecVideoEncoder {
if (dataV.capacity() < strideV * chromaHeight) {
throw new RuntimeException("V-plane buffer size too small.");
}
fillInputBufferNative(
nativeFillInputBuffer(
nativeEncoder, bufferIndex, dataY, strideY, dataU, strideU, dataV, strideV);
i420Buffer.release();
// I420 consists of one full-resolution and two half-resolution planes.
@ -993,6 +994,6 @@ public class MediaCodecVideoEncoder {
}
/** Fills an inputBuffer with the given index with data from the byte buffers. */
private static native void fillInputBufferNative(long nativeEncoder, int inputBuffer,
ByteBuffer dataY, int strideY, ByteBuffer dataU, int strideU, ByteBuffer dataV, int strideV);
private static native void nativeFillInputBuffer(long encoder, int inputBuffer, ByteBuffer dataY,
int strideY, ByteBuffer dataU, int strideU, ByteBuffer dataV, int strideV);
}

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** Java wrapper for a C++ MediaSourceInterface. */
@JNINamespace("webrtc::jni")
public class MediaSource {
/** Tracks MediaSourceInterface.SourceState */
public enum State {
@ -32,12 +33,12 @@ public class MediaSource {
}
public State state() {
return getNativeState(nativeSource);
return nativeGetState(nativeSource);
}
public void dispose() {
JniCommon.nativeReleaseRef(nativeSource);
}
private static native State getNativeState(long pointer);
private static native State nativeGetState(long pointer);
}

View File

@ -15,6 +15,7 @@ import java.util.List;
import java.util.Iterator;
/** Java wrapper for a C++ MediaStreamInterface. */
@JNINamespace("webrtc::jni")
public class MediaStream {
private static final String TAG = "MediaStream";
@ -30,7 +31,7 @@ public class MediaStream {
}
public boolean addTrack(AudioTrack track) {
if (addAudioTrackToNativeStream(nativeStream, track.nativeTrack)) {
if (nativeAddAudioTrackToNativeStream(nativeStream, track.nativeTrack)) {
audioTracks.add(track);
return true;
}
@ -38,7 +39,7 @@ public class MediaStream {
}
public boolean addTrack(VideoTrack track) {
if (addVideoTrackToNativeStream(nativeStream, track.nativeTrack)) {
if (nativeAddVideoTrackToNativeStream(nativeStream, track.nativeTrack)) {
videoTracks.add(track);
return true;
}
@ -49,7 +50,7 @@ public class MediaStream {
// is called. If video track need to be preserved after MediaStream is destroyed it
// should be added to MediaStream using addPreservedTrack() call.
public boolean addPreservedTrack(VideoTrack track) {
if (addVideoTrackToNativeStream(nativeStream, track.nativeTrack)) {
if (nativeAddVideoTrackToNativeStream(nativeStream, track.nativeTrack)) {
preservedVideoTracks.add(track);
return true;
}
@ -58,13 +59,13 @@ public class MediaStream {
public boolean removeTrack(AudioTrack track) {
audioTracks.remove(track);
return removeNativeAudioTrack(nativeStream, track.nativeTrack);
return nativeRemoveAudioTrack(nativeStream, track.nativeTrack);
}
public boolean removeTrack(VideoTrack track) {
videoTracks.remove(track);
preservedVideoTracks.remove(track);
return removeNativeVideoTrack(nativeStream, track.nativeTrack);
return nativeRemoveVideoTrack(nativeStream, track.nativeTrack);
}
@CalledByNative
@ -88,7 +89,7 @@ public class MediaStream {
}
public String label() {
return getNativeLabel(nativeStream);
return nativeGetLabel(nativeStream);
}
@Override
@ -130,15 +131,11 @@ public class MediaStream {
Logging.e(TAG, "Couldn't not find track");
}
private static native boolean addAudioTrackToNativeStream(
long nativeStream, long nativeAudioTrack);
private static native boolean addVideoTrackToNativeStream(
long nativeStream, long nativeVideoTrack);
private static native boolean removeNativeAudioTrack(long nativeStream, long nativeAudioTrack);
private static native boolean removeNativeVideoTrack(long nativeStream, long nativeVideoTrack);
private static native String getNativeLabel(long nativeStream);
private static native boolean nativeAddAudioTrackToNativeStream(
long stream, long nativeAudioTrack);
private static native boolean nativeAddVideoTrackToNativeStream(
long stream, long nativeVideoTrack);
private static native boolean nativeRemoveAudioTrack(long stream, long nativeAudioTrack);
private static native boolean nativeRemoveVideoTrack(long stream, long nativeVideoTrack);
private static native String nativeGetLabel(long stream);
}

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** Java wrapper for a C++ MediaStreamTrackInterface. */
@JNINamespace("webrtc::jni")
public class MediaStreamTrack {
/** Tracks MediaStreamTrackInterface.TrackState */
public enum State {
@ -57,36 +58,32 @@ public class MediaStreamTrack {
}
public String id() {
return getNativeId(nativeTrack);
return nativeGetId(nativeTrack);
}
public String kind() {
return getNativeKind(nativeTrack);
return nativeGetKind(nativeTrack);
}
public boolean enabled() {
return getNativeEnabled(nativeTrack);
return nativeGetEnabled(nativeTrack);
}
public boolean setEnabled(boolean enable) {
return setNativeEnabled(nativeTrack, enable);
return nativeSetEnabled(nativeTrack, enable);
}
public State state() {
return getNativeState(nativeTrack);
return nativeGetState(nativeTrack);
}
public void dispose() {
JniCommon.nativeReleaseRef(nativeTrack);
}
private static native String getNativeId(long nativeTrack);
private static native String getNativeKind(long nativeTrack);
private static native boolean getNativeEnabled(long nativeTrack);
private static native boolean setNativeEnabled(long nativeTrack, boolean enabled);
private static native State getNativeState(long nativeTrack);
private static native String nativeGetId(long track);
private static native String nativeGetKind(long track);
private static native boolean nativeGetEnabled(long track);
private static native boolean nativeSetEnabled(long track, boolean enabled);
private static native State nativeGetState(long track);
}

View File

@ -28,7 +28,7 @@ import java.util.Map;
// Most histograms are not updated frequently (e.g. most video metrics are an
// average over the call and recorded when a stream is removed).
// The metrics can for example be retrieved when a peer connection is closed.
@JNINamespace("webrtc::jni")
public class Metrics {
private static final String TAG = "Metrics";
@ -69,14 +69,14 @@ public class Metrics {
// Enables gathering of metrics (which can be fetched with getAndReset()).
// Must be called before PeerConnectionFactory is created.
public static void enable() {
enableNative();
nativeEnable();
}
// Gets and clears native histograms.
public static Metrics getAndReset() {
return getAndResetNative();
return nativeGetAndReset();
}
private static native void enableNative();
private static native Metrics getAndResetNative();
private static native void nativeEnable();
private static native Metrics nativeGetAndReset();
}

View File

@ -20,6 +20,7 @@ import java.util.List;
* JS APIs: http://dev.w3.org/2011/webrtc/editor/webrtc.html and
* http://www.w3.org/TR/mediacapture-streams/
*/
@JNINamespace("webrtc::jni")
public class PeerConnection {
/** Tracks PeerConnectionInterface::IceGatheringState */
public enum IceGatheringState {
@ -565,46 +566,64 @@ public class PeerConnection {
}
// JsepInterface.
public native SessionDescription getLocalDescription();
public SessionDescription getLocalDescription() {
return nativeGetLocalDescription();
}
public native SessionDescription getRemoteDescription();
public SessionDescription getRemoteDescription() {
return nativeGetRemoteDescription();
}
public native DataChannel createDataChannel(String label, DataChannel.Init init);
public DataChannel createDataChannel(String label, DataChannel.Init init) {
return nativeCreateDataChannel(label, init);
}
public native void createOffer(SdpObserver observer, MediaConstraints constraints);
public void createOffer(SdpObserver observer, MediaConstraints constraints) {
nativeCreateOffer(observer, constraints);
}
public native void createAnswer(SdpObserver observer, MediaConstraints constraints);
public void createAnswer(SdpObserver observer, MediaConstraints constraints) {
nativeCreateAnswer(observer, constraints);
}
public native void setLocalDescription(SdpObserver observer, SessionDescription sdp);
public void setLocalDescription(SdpObserver observer, SessionDescription sdp) {
nativeSetLocalDescription(observer, sdp);
}
public native void setRemoteDescription(SdpObserver observer, SessionDescription sdp);
public void setRemoteDescription(SdpObserver observer, SessionDescription sdp) {
nativeSetRemoteDescription(observer, sdp);
}
// True if remote audio should be played out. Defaults to true.
// Note that even if playout is enabled, streams will only be played out if
// the appropriate SDP is also applied. The main purpose of this API is to
// be able to control the exact time when audio playout starts.
public native void setAudioPlayout(boolean playout);
public void setAudioPlayout(boolean playout) {
nativeSetAudioPlayout(playout);
}
// True if local audio shall be recorded. Defaults to true.
// Note that even if recording is enabled, streams will only be recorded if
// the appropriate SDP is also applied. The main purpose of this API is to
// be able to control the exact time when audio recording starts.
public native void setAudioRecording(boolean recording);
public void setAudioRecording(boolean recording) {
nativeSetAudioRecording(recording);
}
public boolean setConfiguration(RTCConfiguration config) {
return setNativeConfiguration(config, nativeObserver);
return nativeSetConfiguration(config, nativeObserver);
}
public boolean addIceCandidate(IceCandidate candidate) {
return addNativeIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp);
return nativeAddIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp);
}
public boolean removeIceCandidates(final IceCandidate[] candidates) {
return removeNativeIceCandidates(candidates);
return nativeRemoveIceCandidates(candidates);
}
public boolean addStream(MediaStream stream) {
boolean ret = addNativeLocalStream(stream.nativeStream);
boolean ret = nativeAddLocalStream(stream.nativeStream);
if (!ret) {
return false;
}
@ -613,7 +632,7 @@ public class PeerConnection {
}
public void removeStream(MediaStream stream) {
removeNativeLocalStream(stream.nativeStream);
nativeRemoveLocalStream(stream.nativeStream);
localStreams.remove(stream);
}
@ -655,7 +674,7 @@ public class PeerConnection {
* @return A new RtpSender object if successful, or null otherwise.
*/
public RtpSender createSender(String kind, String stream_id) {
RtpSender new_sender = createNativeSender(kind, stream_id);
RtpSender new_sender = nativeCreateSender(kind, stream_id);
if (new_sender != null) {
senders.add(new_sender);
}
@ -668,7 +687,7 @@ public class PeerConnection {
for (RtpSender sender : senders) {
sender.dispose();
}
senders = getNativeSenders();
senders = nativeGetSenders();
return Collections.unmodifiableList(senders);
}
@ -676,25 +695,27 @@ public class PeerConnection {
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
receivers = getNativeReceivers();
receivers = nativeGetReceivers();
return Collections.unmodifiableList(receivers);
}
// Older, non-standard implementation of getStats.
@Deprecated
public boolean getStats(StatsObserver observer, MediaStreamTrack track) {
return oldGetNativeStats(observer, (track == null) ? 0 : track.nativeTrack);
return nativeOldGetStats(observer, (track == null) ? 0 : track.nativeTrack);
}
// Gets stats using the new stats collection API, see webrtc/api/stats/. These
// will replace old stats collection API when the new API has matured enough.
public void getStats(RTCStatsCollectorCallback callback) {
newGetNativeStats(callback);
nativeNewGetStats(callback);
}
// Limits the bandwidth allocated for all RTP streams sent by this
// PeerConnection. Pass null to leave a value unchanged.
public native boolean setBitrate(Integer min, Integer current, Integer max);
public boolean setBitrate(Integer min, Integer current, Integer max) {
return nativeSetBitrate(min, current, max);
}
// Starts recording an RTC event log. Ownership of the file is transfered to
// the native code. If an RTC event log is already being recorded, it will be
@ -702,24 +723,32 @@ public class PeerConnection {
// continue until the stopRtcEventLog function is called. The max_size_bytes
// argument is ignored, it is added for future use.
public boolean startRtcEventLog(int file_descriptor, int max_size_bytes) {
return startNativeRtcEventLog(file_descriptor, max_size_bytes);
return nativeStartRtcEventLog(file_descriptor, max_size_bytes);
}
// Stops recording an RTC event log. If no RTC event log is currently being
// recorded, this call will have no effect.
public void stopRtcEventLog() {
stopNativeRtcEventLog();
nativeStopRtcEventLog();
}
// TODO(fischman): add support for DTMF-related methods once that API
// stabilizes.
public native SignalingState signalingState();
public SignalingState signalingState() {
return nativeSignalingState();
}
public native IceConnectionState iceConnectionState();
public IceConnectionState iceConnectionState() {
return nativeIceConnectionState();
}
public native IceGatheringState iceGatheringState();
public IceGatheringState iceGatheringState() {
return nativeIceGatheringState();
}
public native void close();
public void close() {
nativeClose();
}
/**
* Free native resources associated with this PeerConnection instance.
@ -740,7 +769,7 @@ public class PeerConnection {
public void dispose() {
close();
for (MediaStream stream : localStreams) {
removeNativeLocalStream(stream.nativeStream);
nativeRemoveLocalStream(stream.nativeStream);
stream.dispose();
}
localStreams.clear();
@ -754,7 +783,7 @@ public class PeerConnection {
receivers.clear();
JniCommon.nativeReleaseRef(nativePeerConnection);
if (nativeObserver != 0) {
freeNativePeerConnectionObserver(nativeObserver);
nativeFreePeerConnectionObserver(nativeObserver);
}
}
@ -763,31 +792,41 @@ public class PeerConnection {
return nativePeerConnection;
}
public static native long createNativePeerConnectionObserver(Observer observer);
public static native void freeNativePeerConnectionObserver(long nativeObserver);
public static long createNativePeerConnectionObserver(Observer observer) {
return nativeCreatePeerConnectionObserver(observer);
}
private native boolean setNativeConfiguration(RTCConfiguration config, long nativeObserver);
public static void freeNativePeerConnectionObserver(long observer) {
nativeFreePeerConnectionObserver(observer);
}
private native boolean addNativeIceCandidate(
private native SessionDescription nativeGetLocalDescription();
private native SessionDescription nativeGetRemoteDescription();
private native DataChannel nativeCreateDataChannel(String label, DataChannel.Init init);
private native void nativeCreateOffer(SdpObserver observer, MediaConstraints constraints);
private native void nativeCreateAnswer(SdpObserver observer, MediaConstraints constraints);
private native void nativeSetLocalDescription(SdpObserver observer, SessionDescription sdp);
private native void nativeSetRemoteDescription(SdpObserver observer, SessionDescription sdp);
private native void nativeSetAudioPlayout(boolean playout);
private native void nativeSetAudioRecording(boolean recording);
private native boolean nativeSetBitrate(Integer min, Integer current, Integer max);
private native SignalingState nativeSignalingState();
private native IceConnectionState nativeIceConnectionState();
private native IceGatheringState nativeIceGatheringState();
private native void nativeClose();
private static native long nativeCreatePeerConnectionObserver(Observer observer);
private static native void nativeFreePeerConnectionObserver(long observer);
private native boolean nativeSetConfiguration(RTCConfiguration config, long nativeObserver);
private native boolean nativeAddIceCandidate(
String sdpMid, int sdpMLineIndex, String iceCandidateSdp);
private native boolean removeNativeIceCandidates(final IceCandidate[] candidates);
private native boolean addNativeLocalStream(long nativeStream);
private native void removeNativeLocalStream(long nativeStream);
private native boolean oldGetNativeStats(StatsObserver observer, long nativeTrack);
private native void newGetNativeStats(RTCStatsCollectorCallback callback);
private native RtpSender createNativeSender(String kind, String stream_id);
private native List<RtpSender> getNativeSenders();
private native List<RtpReceiver> getNativeReceivers();
private native boolean startNativeRtcEventLog(int file_descriptor, int max_size_bytes);
private native void stopNativeRtcEventLog();
private native boolean nativeRemoveIceCandidates(final IceCandidate[] candidates);
private native boolean nativeAddLocalStream(long stream);
private native void nativeRemoveLocalStream(long stream);
private native boolean nativeOldGetStats(StatsObserver observer, long nativeTrack);
private native void nativeNewGetStats(RTCStatsCollectorCallback callback);
private native RtpSender nativeCreateSender(String kind, String stream_id);
private native List<RtpSender> nativeGetSenders();
private native List<RtpReceiver> nativeGetReceivers();
private native boolean nativeStartRtcEventLog(int file_descriptor, int max_size_bytes);
private native void nativeStopRtcEventLog();
}

View File

@ -17,6 +17,7 @@ import java.util.List;
* Java wrapper for a C++ PeerConnectionFactoryInterface. Main entry point to
* the PeerConnection API for clients.
*/
@JNINamespace("webrtc::jni")
public class PeerConnectionFactory {
public static final String TRIAL_ENABLED = "Enabled";
public static final String VIDEO_FRAME_EMIT_TRIAL = "VideoFrameEmit";
@ -129,7 +130,7 @@ public class PeerConnectionFactory {
public static void initialize(InitializationOptions options) {
ContextUtils.initialize(options.applicationContext);
NativeLibrary.initialize(options.nativeLibraryLoader);
initializeNativeAndroidGlobals(options.applicationContext, options.enableVideoHwAcceleration);
nativeInitializeAndroidGlobals(options.applicationContext, options.enableVideoHwAcceleration);
initializeFieldTrials(options.fieldTrials);
if (options.enableInternalTracer && !internalTracerInitialized) {
initializeInternalTracer();
@ -144,25 +145,24 @@ public class PeerConnectionFactory {
}
}
// Must be called at least once before creating a PeerConnectionFactory
// (for example, at application startup time).
private static native void initializeNativeAndroidGlobals(
Context context, boolean videoHwAcceleration);
private static void initializeInternalTracer() {
internalTracerInitialized = true;
initializeNativeInternalTracer();
nativeInitializeInternalTracer();
}
public static void shutdownInternalTracer() {
internalTracerInitialized = false;
shutdownNativeInternalTracer();
nativeShutdownInternalTracer();
}
// Field trial initialization. Must be called before PeerConnectionFactory
// is created.
// Deprecated, use PeerConnectionFactory.initialize instead.
@Deprecated public static native void initializeFieldTrials(String fieldTrialsInitString);
@Deprecated
public static void initializeFieldTrials(String fieldTrialsInitString) {
nativeInitializeFieldTrials(fieldTrialsInitString);
}
// Wrapper of webrtc::field_trial::FindFullName. Develop the feature with default behaviour off.
// Example usage:
// if (PeerConnectionFactory.fieldTrialsFindFullName("WebRTCExperiment").equals("Enabled")) {
@ -171,19 +171,16 @@ public class PeerConnectionFactory {
// method2();
// }
public static String fieldTrialsFindFullName(String name) {
return NativeLibrary.isLoaded() ? findNativeFieldTrialsFullName(name) : "";
return NativeLibrary.isLoaded() ? nativeFindFieldTrialsFullName(name) : "";
}
private static native String findNativeFieldTrialsFullName(String name);
// Internal tracing initialization. Must be called before PeerConnectionFactory is created to
// prevent racing with tracing code.
// Deprecated, use PeerConnectionFactory.initialize instead.
private static native void initializeNativeInternalTracer();
// Internal tracing shutdown, called to prevent resource leaks. Must be called after
// PeerConnectionFactory is gone to prevent races with code performing tracing.
private static native void shutdownNativeInternalTracer();
// Start/stop internal capturing of internal tracing.
public static native boolean startInternalTracingCapture(String tracing_filename);
public static native void stopInternalTracingCapture();
public static boolean startInternalTracingCapture(String tracingFilename) {
return nativeStartInternalTracingCapture(tracingFilename);
}
public static void stopInternalTracingCapture() {
nativeStopInternalTracingCapture();
}
@Deprecated
public PeerConnectionFactory() {
@ -199,7 +196,7 @@ public class PeerConnectionFactory {
public PeerConnectionFactory(
Options options, VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory) {
checkInitializeHasBeenCalled();
nativeFactory = createNativePeerConnectionFactory(options, encoderFactory, decoderFactory);
nativeFactory = nativeCreatePeerConnectionFactory(options, encoderFactory, decoderFactory);
if (nativeFactory == 0) {
throw new RuntimeException("Failed to initialize PeerConnectionFactory!");
}
@ -212,7 +209,7 @@ public class PeerConnectionFactory {
throw new NullPointerException(
"PeerConnectionFactory constructor does not accept a null AudioProcessingFactory.");
}
nativeFactory = createNativePeerConnectionFactoryWithAudioProcessing(
nativeFactory = nativeCreatePeerConnectionFactoryWithAudioProcessing(
options, encoderFactory, decoderFactory, audioProcessingFactory.createNative());
if (nativeFactory == 0) {
throw new RuntimeException("Failed to initialize PeerConnectionFactory!");
@ -231,7 +228,7 @@ public class PeerConnectionFactory {
return null;
}
long nativePeerConnection =
createNativePeerConnection(nativeFactory, rtcConfig, constraints, nativeObserver);
nativeCreatePeerConnection(nativeFactory, rtcConfig, constraints, nativeObserver);
if (nativePeerConnection == 0) {
return null;
}
@ -261,7 +258,7 @@ public class PeerConnectionFactory {
}
public MediaStream createLocalMediaStream(String label) {
return new MediaStream(createNativeLocalMediaStream(nativeFactory, label));
return new MediaStream(nativeCreateLocalMediaStream(nativeFactory, label));
}
public VideoSource createVideoSource(VideoCapturer capturer) {
@ -270,7 +267,7 @@ public class PeerConnectionFactory {
final SurfaceTextureHelper surfaceTextureHelper =
SurfaceTextureHelper.create(VIDEO_CAPTURER_THREAD_NAME, eglContext);
long nativeAndroidVideoTrackSource =
createNativeVideoSource(nativeFactory, surfaceTextureHelper, capturer.isScreencast());
nativeCreateVideoSource(nativeFactory, surfaceTextureHelper, capturer.isScreencast());
VideoCapturer.CapturerObserver capturerObserver =
new AndroidVideoTrackSourceObserver(nativeAndroidVideoTrackSource);
capturer.initialize(
@ -279,33 +276,33 @@ public class PeerConnectionFactory {
}
public VideoTrack createVideoTrack(String id, VideoSource source) {
return new VideoTrack(createNativeVideoTrack(nativeFactory, id, source.nativeSource));
return new VideoTrack(nativeCreateVideoTrack(nativeFactory, id, source.nativeSource));
}
public AudioSource createAudioSource(MediaConstraints constraints) {
return new AudioSource(createNativeAudioSource(nativeFactory, constraints));
return new AudioSource(nativeCreateAudioSource(nativeFactory, constraints));
}
public AudioTrack createAudioTrack(String id, AudioSource source) {
return new AudioTrack(createNativeAudioTrack(nativeFactory, id, source.nativeSource));
return new AudioTrack(nativeCreateAudioTrack(nativeFactory, id, source.nativeSource));
}
// Starts recording an AEC dump. Ownership of the file is transfered to the
// native code. If an AEC dump is already in progress, it will be stopped and
// a new one will start using the provided file.
public boolean startAecDump(int file_descriptor, int filesize_limit_bytes) {
return startNativeAecDump(nativeFactory, file_descriptor, filesize_limit_bytes);
return nativeStartAecDump(nativeFactory, file_descriptor, filesize_limit_bytes);
}
// Stops recording an AEC dump. If no AEC dump is currently being recorded,
// this call will have no effect.
public void stopAecDump() {
stopNativeAecDump(nativeFactory);
nativeStopAecDump(nativeFactory);
}
@Deprecated
public void setOptions(Options options) {
setNativeOptions(nativeFactory, options);
nativeSetOptions(nativeFactory, options);
}
/** Set the EGL context used by HW Video encoding and decoding.
@ -326,12 +323,12 @@ public class PeerConnectionFactory {
}
localEglbase = EglBase.create(localEglContext);
remoteEglbase = EglBase.create(remoteEglContext);
setNativeVideoHwAccelerationOptions(
nativeSetVideoHwAccelerationOptions(
nativeFactory, localEglbase.getEglBaseContext(), remoteEglbase.getEglBaseContext());
}
public void dispose() {
freeNativeFactory(nativeFactory);
nativeFreeFactory(nativeFactory);
networkThread = null;
workerThread = null;
signalingThread = null;
@ -342,7 +339,7 @@ public class PeerConnectionFactory {
}
public void threadsCallbacks() {
invokeNativeThreadsCallbacks(nativeFactory);
nativeInvokeThreadsCallbacks(nativeFactory);
}
private static void printStackTrace(Thread thread, String threadName) {
@ -381,46 +378,41 @@ public class PeerConnectionFactory {
Logging.d(TAG, "onSignalingThreadReady");
}
private static native long createNativePeerConnectionFactory(
// Must be called at least once before creating a PeerConnectionFactory
// (for example, at application startup time).
private static native void nativeInitializeAndroidGlobals(
Context context, boolean videoHwAcceleration);
private static native void nativeInitializeFieldTrials(String fieldTrialsInitString);
private static native String nativeFindFieldTrialsFullName(String name);
// Internal tracing initialization. Must be called before PeerConnectionFactory is created to
// prevent racing with tracing code.
// Deprecated, use PeerConnectionFactory.initialize instead.
private static native void nativeInitializeInternalTracer();
// Internal tracing shutdown, called to prevent resource leaks. Must be called after
// PeerConnectionFactory is gone to prevent races with code performing tracing.
private static native void nativeShutdownInternalTracer();
private static native boolean nativeStartInternalTracingCapture(String tracingFilename);
private static native void nativeStopInternalTracingCapture();
private static native long nativeCreatePeerConnectionFactory(
Options options, VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory);
private static native long createNativePeerConnectionFactoryWithAudioProcessing(Options options,
private static native long nativeCreatePeerConnectionFactoryWithAudioProcessing(Options options,
VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory,
long nativeAudioProcessor);
private static native long createNativePeerConnection(long nativeFactory,
private static native long nativeCreatePeerConnection(long factory,
PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver);
private static native long createNativeLocalMediaStream(long nativeFactory, String label);
private static native long createNativeVideoSource(
long nativeFactory, SurfaceTextureHelper surfaceTextureHelper, boolean is_screencast);
private static native long createNativeVideoTrack(
long nativeFactory, String id, long nativeVideoSource);
private static native long createNativeAudioSource(
long nativeFactory, MediaConstraints constraints);
private static native long createNativeAudioTrack(
long nativeFactory, String id, long nativeSource);
private static native boolean startNativeAecDump(
long nativeFactory, int file_descriptor, int filesize_limit_bytes);
private static native void stopNativeAecDump(long nativeFactory);
@Deprecated
public void nativeSetOptions(long nativeFactory, Options options) {
setNativeOptions(nativeFactory, options);
}
private native void setNativeOptions(long nativeFactory, Options options);
private static native void setNativeVideoHwAccelerationOptions(
long nativeFactory, Object localEGLContext, Object remoteEGLContext);
private static native void invokeNativeThreadsCallbacks(long nativeFactory);
private static native void freeNativeFactory(long nativeFactory);
private static native long nativeCreateLocalMediaStream(long factory, String label);
private static native long nativeCreateVideoSource(
long factory, SurfaceTextureHelper surfaceTextureHelper, boolean is_screencast);
private static native long nativeCreateVideoTrack(
long factory, String id, long nativeVideoSource);
private static native long nativeCreateAudioSource(long factory, MediaConstraints constraints);
private static native long nativeCreateAudioTrack(long factory, String id, long nativeSource);
private static native boolean nativeStartAecDump(
long factory, int file_descriptor, int filesize_limit_bytes);
private static native void nativeStopAecDump(long factory);
@Deprecated public native void nativeSetOptions(long factory, Options options);
private static native void nativeSetVideoHwAccelerationOptions(
long factory, Object localEGLContext, Object remoteEGLContext);
private static native void nativeInvokeThreadsCallbacks(long factory);
private static native void nativeFreeFactory(long factory);
}

View File

@ -13,6 +13,7 @@ package org.webrtc;
import org.webrtc.MediaStreamTrack;
/** Java wrapper for a C++ RtpReceiverInterface. */
@JNINamespace("webrtc::jni")
public class RtpReceiver {
/** Java wrapper for a C++ RtpReceiverObserverInterface*/
public static interface Observer {
@ -29,7 +30,7 @@ public class RtpReceiver {
@CalledByNative
public RtpReceiver(long nativeRtpReceiver) {
this.nativeRtpReceiver = nativeRtpReceiver;
long track = getNativeTrack(nativeRtpReceiver);
long track = nativeGetTrack(nativeRtpReceiver);
// We can assume that an RtpReceiver always has an associated track.
cachedTrack = new MediaStreamTrack(track);
}
@ -39,22 +40,22 @@ public class RtpReceiver {
}
public boolean setParameters(RtpParameters parameters) {
return parameters == null ? false : setNativeParameters(nativeRtpReceiver, parameters);
return parameters == null ? false : nativeSetParameters(nativeRtpReceiver, parameters);
}
public RtpParameters getParameters() {
return getNativeParameters(nativeRtpReceiver);
return nativeGetParameters(nativeRtpReceiver);
}
public String id() {
return getNativeId(nativeRtpReceiver);
return nativeGetId(nativeRtpReceiver);
}
@CalledByNative
public void dispose() {
cachedTrack.dispose();
if (nativeObserver != 0) {
unsetNativeObserver(nativeRtpReceiver, nativeObserver);
nativeUnsetObserver(nativeRtpReceiver, nativeObserver);
nativeObserver = 0;
}
JniCommon.nativeReleaseRef(nativeRtpReceiver);
@ -63,23 +64,17 @@ public class RtpReceiver {
public void SetObserver(Observer observer) {
// Unset the existing one before setting a new one.
if (nativeObserver != 0) {
unsetNativeObserver(nativeRtpReceiver, nativeObserver);
nativeUnsetObserver(nativeRtpReceiver, nativeObserver);
}
nativeObserver = setNativeObserver(nativeRtpReceiver, observer);
nativeObserver = nativeSetObserver(nativeRtpReceiver, observer);
}
// This should increment the reference count of the track.
// Will be released in dispose().
private static native long getNativeTrack(long nativeRtpReceiver);
private static native boolean setNativeParameters(
long nativeRtpReceiver, RtpParameters parameters);
private static native RtpParameters getNativeParameters(long nativeRtpReceiver);
private static native String getNativeId(long nativeRtpReceiver);
private static native long setNativeObserver(long nativeRtpReceiver, Observer observer);
private static native void unsetNativeObserver(long nativeRtpReceiver, long nativeObserver);
private static native long nativeGetTrack(long rtpReceiver);
private static native boolean nativeSetParameters(long rtpReceiver, RtpParameters parameters);
private static native RtpParameters nativeGetParameters(long rtpReceiver);
private static native String nativeGetId(long rtpReceiver);
private static native long nativeSetObserver(long rtpReceiver, Observer observer);
private static native void nativeUnsetObserver(long rtpReceiver, long nativeObserver);
};

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** Java wrapper for a C++ RtpSenderInterface. */
@JNINamespace("webrtc::jni")
public class RtpSender {
final long nativeRtpSender;
@ -22,11 +23,11 @@ public class RtpSender {
@CalledByNative
public RtpSender(long nativeRtpSender) {
this.nativeRtpSender = nativeRtpSender;
long track = getNativeTrack(nativeRtpSender);
long track = nativeGetTrack(nativeRtpSender);
// It may be possible for an RtpSender to be created without a track.
cachedTrack = (track != 0) ? new MediaStreamTrack(track) : null;
long nativeDtmfSender = getNativeDtmfSender(nativeRtpSender);
long nativeDtmfSender = nativeGetDtmfSender(nativeRtpSender);
dtmfSender = (nativeDtmfSender != 0) ? new DtmfSender(nativeDtmfSender) : null;
}
@ -45,7 +46,7 @@ public class RtpSender {
* @return true on success and false on failure.
*/
public boolean setTrack(MediaStreamTrack track, boolean takeOwnership) {
if (!setNativeTrack(nativeRtpSender, (track == null) ? 0 : track.nativeTrack)) {
if (!nativeSetTrack(nativeRtpSender, (track == null) ? 0 : track.nativeTrack)) {
return false;
}
if (cachedTrack != null && ownsTrack) {
@ -61,15 +62,15 @@ public class RtpSender {
}
public boolean setParameters(RtpParameters parameters) {
return setNativeParameters(nativeRtpSender, parameters);
return nativeSetParameters(nativeRtpSender, parameters);
}
public RtpParameters getParameters() {
return getNativeParameters(nativeRtpSender);
return nativeGetParameters(nativeRtpSender);
}
public String id() {
return getNativeId(nativeRtpSender);
return nativeGetId(nativeRtpSender);
}
public DtmfSender dtmf() {
@ -86,19 +87,19 @@ public class RtpSender {
JniCommon.nativeReleaseRef(nativeRtpSender);
}
private static native boolean setNativeTrack(long nativeRtpSender, long nativeTrack);
private static native boolean nativeSetTrack(long rtpSender, long nativeTrack);
// This should increment the reference count of the track.
// Will be released in dispose() or setTrack().
private static native long getNativeTrack(long nativeRtpSender);
private static native long nativeGetTrack(long rtpSender);
// This should increment the reference count of the DTMF sender.
// Will be released in dispose().
private static native long getNativeDtmfSender(long nativeRtpSender);
private static native long nativeGetDtmfSender(long rtpSender);
private static native boolean setNativeParameters(long nativeRtpSender, RtpParameters parameters);
private static native boolean nativeSetParameters(long rtpSender, RtpParameters parameters);
private static native RtpParameters getNativeParameters(long nativeRtpSender);
private static native RtpParameters nativeGetParameters(long rtpSender);
private static native String getNativeId(long nativeRtpSender);
private static native String nativeGetId(long rtpSender);
};

View File

@ -16,7 +16,7 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
if (codecType.equalsIgnoreCase("VP8")) {
return new VP8Decoder();
}
if (codecType.equalsIgnoreCase("VP9") && VP9Decoder.isSupported()) {
if (codecType.equalsIgnoreCase("VP9") && VP9Decoder.nativeIsSupported()) {
return new VP9Decoder();
}

View File

@ -20,7 +20,7 @@ public class SoftwareVideoEncoderFactory implements VideoEncoderFactory {
if (info.name.equalsIgnoreCase("VP8")) {
return new VP8Encoder();
}
if (info.name.equalsIgnoreCase("VP9") && VP9Encoder.isSupported()) {
if (info.name.equalsIgnoreCase("VP9") && VP9Encoder.nativeIsSupported()) {
return new VP9Encoder();
}
@ -36,7 +36,7 @@ public class SoftwareVideoEncoderFactory implements VideoEncoderFactory {
List<VideoCodecInfo> codecs = new ArrayList<VideoCodecInfo>();
codecs.add(new VideoCodecInfo("VP8", new HashMap<>()));
if (VP9Encoder.isSupported()) {
if (VP9Encoder.nativeIsSupported()) {
codecs.add(new VideoCodecInfo("VP9", new HashMap<>()));
}

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** Java wrapper for a C++ TurnCustomizer. */
@JNINamespace("webrtc::jni")
public class TurnCustomizer {
final long nativeTurnCustomizer;
@ -19,10 +20,10 @@ public class TurnCustomizer {
}
public void dispose() {
freeNativeTurnCustomizer(nativeTurnCustomizer);
nativeFreeTurnCustomizer(nativeTurnCustomizer);
}
private static native void freeNativeTurnCustomizer(long nativeTurnCustomizer);
private static native void nativeFreeTurnCustomizer(long turnCustomizer);
@CalledByNative
long getNativeTurnCustomizer() {

View File

@ -13,6 +13,7 @@ package org.webrtc;
/**
* A combined video decoder that falls back on a secondary decoder if the primary decoder fails.
*/
@JNINamespace("webrtc::jni")
public class VideoDecoderFallback extends WrappedNativeVideoDecoder {
private final VideoDecoder fallback;
private final VideoDecoder primary;
@ -24,8 +25,8 @@ public class VideoDecoderFallback extends WrappedNativeVideoDecoder {
@Override
long createNativeDecoder() {
return createNativeDecoder(fallback, primary);
return nativeCreateDecoder(fallback, primary);
}
private static native long createNativeDecoder(VideoDecoder fallback, VideoDecoder primary);
private static native long nativeCreateDecoder(VideoDecoder fallback, VideoDecoder primary);
}

View File

@ -13,6 +13,7 @@ package org.webrtc;
/**
* A combined video encoder that falls back on a secondary encoder if the primary encoder fails.
*/
@JNINamespace("webrtc::jni")
public class VideoEncoderFallback extends WrappedNativeVideoEncoder {
private final VideoEncoder fallback;
private final VideoEncoder primary;
@ -24,7 +25,7 @@ public class VideoEncoderFallback extends WrappedNativeVideoEncoder {
@Override
long createNativeEncoder() {
return createNativeEncoder(fallback, primary);
return nativeCreateEncoder(fallback, primary);
}
@Override
@ -32,5 +33,5 @@ public class VideoEncoderFallback extends WrappedNativeVideoEncoder {
return isWrappedSoftwareEncoder(primary);
}
private static native long createNativeEncoder(VideoEncoder fallback, VideoEncoder primary);
private static native long nativeCreateEncoder(VideoEncoder fallback, VideoEncoder primary);
}

View File

@ -22,6 +22,7 @@ import java.util.concurrent.CountDownLatch;
/**
* Can be used to save the video frames to file.
*/
@JNINamespace("webrtc::jni")
public class VideoFileRenderer implements VideoRenderer.Callbacks {
private static final String TAG = "VideoFileRenderer";
@ -94,7 +95,7 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
final float[] texMatrix = RendererCommon.multiplyMatrices(rotatedSamplingMatrix, layoutMatrix);
try {
ByteBuffer buffer = JniCommon.allocateNativeByteBuffer(outputFrameSize);
ByteBuffer buffer = JniCommon.nativeAllocateByteBuffer(outputFrameSize);
if (!frame.yuvFrame) {
yuvConverter.convert(outputFrameBuffer, outputFileWidth, outputFileHeight, outputFileWidth,
frame.textureId, texMatrix);
@ -153,7 +154,7 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
videoOutFile.write(data);
JniCommon.freeNativeByteBuffer(buffer);
JniCommon.nativeFreeByteBuffer(buffer);
}
videoOutFile.close();
Logging.d(TAG, "Video written to disk as " + outputFileName + ". Number frames are "

View File

@ -25,6 +25,7 @@ import java.nio.ByteBuffer;
* format and serves as a fallback for video sinks that can only handle I420, e.g. the internal
* WebRTC software encoders.
*/
@JNINamespace("webrtc::jni")
public class VideoFrame {
public interface Buffer {
/**
@ -199,7 +200,7 @@ public class VideoFrame {
}
JavaI420Buffer newBuffer = JavaI420Buffer.allocate(scaleWidth, scaleHeight);
cropAndScaleI420Native(buffer.getDataY(), buffer.getStrideY(), buffer.getDataU(),
nativeCropAndScaleI420(buffer.getDataY(), buffer.getStrideY(), buffer.getDataU(),
buffer.getStrideU(), buffer.getDataV(), buffer.getStrideV(), cropX, cropY, cropWidth,
cropHeight, newBuffer.getDataY(), newBuffer.getStrideY(), newBuffer.getDataU(),
newBuffer.getStrideU(), newBuffer.getDataV(), newBuffer.getStrideV(), scaleWidth,
@ -207,7 +208,7 @@ public class VideoFrame {
return newBuffer;
}
private static native void cropAndScaleI420Native(ByteBuffer srcY, int srcStrideY,
private static native void nativeCropAndScaleI420(ByteBuffer srcY, int srcStrideY,
ByteBuffer srcU, int srcStrideU, ByteBuffer srcV, int srcStrideV, int cropX, int cropY,
int cropWidth, int cropHeight, ByteBuffer dstY, int dstStrideY, ByteBuffer dstU,
int dstStrideU, ByteBuffer dstV, int dstStrideV, int scaleWidth, int scaleHeight);

View File

@ -95,7 +95,7 @@ public class VideoFrameDrawer {
// Input is packed already.
packedByteBuffer = planes[i];
} else {
VideoRenderer.copyPlaneNative(
VideoRenderer.nativeCopyPlane(
planes[i], planeWidths[i], planeHeights[i], strides[i], copyBuffer, planeWidths[i]);
packedByteBuffer = copyBuffer;
}

View File

@ -19,6 +19,7 @@ import org.webrtc.VideoFrame;
* class also provides a createGui() method for creating a GUI-rendering window
* on various platforms.
*/
@JNINamespace("webrtc::jni")
public class VideoRenderer {
/**
* Java version of webrtc::VideoFrame. Frames are only constructed from native code and test
@ -194,7 +195,7 @@ public class VideoRenderer {
}
// Helper native function to do a video frame plane copying.
static native void copyPlaneNative(
static native void nativeCopyPlane(
ByteBuffer src, int width, int height, int srcStride, ByteBuffer dst, int dstStride);
/** The real meat of VideoSinkInterface. */
@ -213,7 +214,7 @@ public class VideoRenderer {
frame.yuvPlanes = null;
frame.textureId = 0;
if (frame.nativeFramePointer != 0) {
releaseNativeFrame(frame.nativeFramePointer);
nativeReleaseFrame(frame.nativeFramePointer);
frame.nativeFramePointer = 0;
}
}
@ -221,7 +222,7 @@ public class VideoRenderer {
long nativeVideoRenderer;
public VideoRenderer(Callbacks callbacks) {
nativeVideoRenderer = createNativeVideoRenderer(callbacks);
nativeVideoRenderer = nativeCreateVideoRenderer(callbacks);
}
public void dispose() {
@ -230,11 +231,11 @@ public class VideoRenderer {
return;
}
freeWrappedVideoRenderer(nativeVideoRenderer);
nativeFreeWrappedVideoRenderer(nativeVideoRenderer);
nativeVideoRenderer = 0;
}
private static native long createNativeVideoRenderer(Callbacks callbacks);
private static native void freeWrappedVideoRenderer(long nativeVideoRenderer);
private static native void releaseNativeFrame(long nativeFramePointer);
private static native long nativeCreateVideoRenderer(Callbacks callbacks);
private static native void nativeFreeWrappedVideoRenderer(long videoRenderer);
private static native void nativeReleaseFrame(long framePointer);
}

View File

@ -13,6 +13,7 @@ package org.webrtc;
/**
* Java wrapper of native AndroidVideoTrackSource.
*/
@JNINamespace("webrtc::jni")
public class VideoSource extends MediaSource {
public VideoSource(long nativeSource) {
super(nativeSource);
@ -28,6 +29,5 @@ public class VideoSource extends MediaSource {
nativeAdaptOutputFormat(nativeSource, width, height, fps);
}
private static native void nativeAdaptOutputFormat(
long nativeSource, int width, int height, int fps);
private static native void nativeAdaptOutputFormat(long source, int width, int height, int fps);
}

View File

@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.List;
/** Java version of VideoTrackInterface. */
@JNINamespace("webrtc::jni")
public class VideoTrack extends MediaStreamTrack {
private final List<VideoRenderer> renderers = new ArrayList<>();
private final IdentityHashMap<VideoSink, Long> sinks = new IdentityHashMap<VideoSink, Long>();
@ -78,9 +79,8 @@ public class VideoTrack extends MediaStreamTrack {
super.dispose();
}
private static native void nativeAddSink(long nativeTrack, long nativeSink);
private static native void nativeRemoveSink(long nativeTrack, long nativeSink);
private static native void nativeAddSink(long track, long nativeSink);
private static native void nativeRemoveSink(long track, long nativeSink);
private static native long nativeWrapSink(VideoSink sink);
private static native void nativeFreeSink(long nativeSink);
private static native void nativeFreeSink(long sink);
}

View File

@ -141,7 +141,7 @@ public class YuvConverter {
// extra row, but now other code does not have to deal with v stride * v height exceeding the
// buffer's capacity.
final int size = stride * (height + uvHeight + 1);
ByteBuffer buffer = JniCommon.allocateNativeByteBuffer(size);
ByteBuffer buffer = JniCommon.nativeAllocateByteBuffer(size);
convert(buffer, width, height, stride, textureBuffer.getTextureId(),
RendererCommon.convertMatrixFromAndroidGraphicsMatrix(textureBuffer.getTransformMatrix()),
textureBuffer.getType());
@ -165,7 +165,7 @@ public class YuvConverter {
// SurfaceTextureHelper uses the same stride for Y, U, and V data.
return JavaI420Buffer.wrap(width, height, dataY, stride, dataU, stride, dataV, stride,
() -> { JniCommon.freeNativeByteBuffer(buffer); });
() -> { JniCommon.nativeFreeByteBuffer(buffer); });
}
/** Deprecated, use convert(TextureBuffer). */

View File

@ -13,6 +13,7 @@ package org.webrtc;
import java.nio.ByteBuffer;
/** Wraps libyuv methods to Java. All passed byte buffers must be direct byte buffers. */
@JNINamespace("webrtc::jni")
public class YuvHelper {
/** Helper method for copying I420 to tightly packed destination buffer. */
public static void I420Copy(ByteBuffer srcY, int srcStrideY, ByteBuffer srcU, int srcStrideU,
@ -37,8 +38,8 @@ public class YuvHelper {
dst.position(startV);
final ByteBuffer dstV = dst.slice();
I420Copy(srcY, srcStrideY, srcU, srcStrideU, srcV, srcStrideV, dstY, width, dstU, chromaWidth,
dstV, chromaWidth, width, height);
nativeI420Copy(srcY, srcStrideY, srcU, srcStrideU, srcV, srcStrideV, dstY, width, dstU,
chromaWidth, dstV, chromaWidth, width, height);
}
/** Helper method for copying I420 to tightly packed NV12 destination buffer. */
@ -61,14 +62,28 @@ public class YuvHelper {
dst.position(startUV);
final ByteBuffer dstUV = dst.slice();
I420ToNV12(srcY, srcStrideY, srcU, srcStrideU, srcV, srcStrideV, dstY, width, dstUV,
nativeI420ToNV12(srcY, srcStrideY, srcU, srcStrideU, srcV, srcStrideV, dstY, width, dstUV,
chromaWidth * 2, width, height);
}
public static native void I420Copy(ByteBuffer srcY, int srcStrideY, ByteBuffer srcU,
public static void I420Copy(ByteBuffer srcY, int srcStrideY, ByteBuffer srcU, int srcStrideU,
ByteBuffer srcV, int srcStrideV, ByteBuffer dstY, int dstStrideY, ByteBuffer dstU,
int dstStrideU, ByteBuffer dstV, int dstStrideV, int width, int height) {
nativeI420Copy(srcY, srcStrideY, srcU, srcStrideU, srcV, srcStrideV, dstY, dstStrideY, dstU,
dstStrideU, dstV, dstStrideV, width, height);
}
public static void I420ToNV12(ByteBuffer srcY, int srcStrideY, ByteBuffer srcU, int srcStrideU,
ByteBuffer srcV, int srcStrideV, ByteBuffer dstY, int dstStrideY, ByteBuffer dstUV,
int dstStrideUV, int width, int height) {
nativeI420ToNV12(srcY, srcStrideY, srcU, srcStrideU, srcV, srcStrideV, dstY, dstStrideY, dstUV,
dstStrideUV, width, height);
}
private static native void nativeI420Copy(ByteBuffer srcY, int srcStrideY, ByteBuffer srcU,
int srcStrideU, ByteBuffer srcV, int srcStrideV, ByteBuffer dstY, int dstStrideY,
ByteBuffer dstU, int dstStrideU, ByteBuffer dstV, int dstStrideV, int width, int height);
public static native void I420ToNV12(ByteBuffer srcY, int srcStrideY, ByteBuffer srcU,
private static native void nativeI420ToNV12(ByteBuffer srcY, int srcStrideY, ByteBuffer srcU,
int srcStrideU, ByteBuffer srcV, int srcStrideV, ByteBuffer dstY, int dstStrideY,
ByteBuffer dstUV, int dstStrideUV, int width, int height);
}

View File

@ -11,6 +11,7 @@
package org.webrtc;
/** An implementation of CapturerObserver that forwards all calls from Java to the C layer. */
@JNINamespace("webrtc::jni")
class AndroidVideoTrackSourceObserver implements VideoCapturer.CapturerObserver {
// Pointer to VideoTrackSourceProxy proxying AndroidVideoTrackSource.
private final long nativeSource;
@ -49,12 +50,12 @@ class AndroidVideoTrackSourceObserver implements VideoCapturer.CapturerObserver
frame.getRotation(), frame.getTimestampNs(), frame.getBuffer());
}
private native void nativeCapturerStarted(long nativeSource, boolean success);
private native void nativeCapturerStopped(long nativeSource);
private native void nativeOnByteBufferFrameCaptured(long nativeSource, byte[] data, int length,
int width, int height, int rotation, long timeStamp);
private native void nativeOnTextureFrameCaptured(long nativeSource, int width, int height,
private static native void nativeCapturerStarted(long source, boolean success);
private static native void nativeCapturerStopped(long source);
private static native void nativeOnByteBufferFrameCaptured(
long source, byte[] data, int length, int width, int height, int rotation, long timeStamp);
private static native void nativeOnTextureFrameCaptured(long source, int width, int height,
int oesTextureId, float[] transformMatrix, int rotation, long timestamp);
private native void nativeOnFrameCaptured(long nativeSource, int width, int height, int rotation,
long timestampNs, VideoFrame.Buffer frame);
private static native void nativeOnFrameCaptured(
long source, int width, int height, int rotation, long timestampNs, VideoFrame.Buffer frame);
}

View File

@ -19,6 +19,7 @@ package org.webrtc;
* Histogram.createCounts("WebRTC.Video.SomeMetric", 1, 10000, 50);
* someMetricHistogram.addSample(someVariable);
*/
@JNINamespace("webrtc::jni")
class Histogram {
private final long handle;

View File

@ -0,0 +1,26 @@
/*
* 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.
*/
package org.webrtc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @JNINamespace is used by the JNI generator to create the necessary JNI
* bindings and expose this method to native code using the specified namespace.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JNINamespace {
public String value();
}

View File

@ -13,11 +13,12 @@ package org.webrtc;
import java.nio.ByteBuffer;
/** Class with static JNI helper functions that are used in many places. */
@JNINamespace("webrtc::jni")
class JniCommon {
/** Functions to increment/decrement an rtc::RefCountInterface pointer. */
static native void nativeAddRef(long nativeRefCountedPointer);
static native void nativeReleaseRef(long nativeRefCountedPointer);
static native void nativeAddRef(long refCountedPointer);
static native void nativeReleaseRef(long refCountedPointer);
public static native ByteBuffer allocateNativeByteBuffer(int size);
public static native void freeNativeByteBuffer(ByteBuffer buffer);
public static native ByteBuffer nativeAllocateByteBuffer(int size);
public static native void nativeFreeByteBuffer(ByteBuffer buffer);
}

View File

@ -12,6 +12,7 @@ package org.webrtc;
import java.nio.ByteBuffer;
@JNINamespace("webrtc::jni")
public class NV12Buffer implements VideoFrame.Buffer {
private final int width;
private final int height;

View File

@ -12,6 +12,7 @@ package org.webrtc;
import java.nio.ByteBuffer;
@JNINamespace("webrtc::jni")
public class NV21Buffer implements VideoFrame.Buffer {
private final byte[] data;
private final int width;

View File

@ -10,6 +10,12 @@
package org.webrtc;
@JNINamespace("webrtc::jni")
class VP8Decoder extends WrappedNativeVideoDecoder {
@Override native long createNativeDecoder();
@Override
long createNativeDecoder() {
return nativeCreateDecoder();
}
static native long nativeCreateDecoder();
}

View File

@ -10,8 +10,14 @@
package org.webrtc;
@JNINamespace("webrtc::jni")
class VP8Encoder extends WrappedNativeVideoEncoder {
@Override native long createNativeEncoder();
@Override
long createNativeEncoder() {
return nativeCreateEncoder();
}
static native long nativeCreateEncoder();
@Override
boolean isSoftwareEncoder() {

View File

@ -10,8 +10,14 @@
package org.webrtc;
@JNINamespace("webrtc::jni")
class VP9Decoder extends WrappedNativeVideoDecoder {
@Override native long createNativeDecoder();
@Override
long createNativeDecoder() {
return nativeCreateDecoder();
}
static native boolean isSupported();
static native long nativeCreateDecoder();
static native boolean nativeIsSupported();
}

View File

@ -10,13 +10,19 @@
package org.webrtc;
@JNINamespace("webrtc::jni")
class VP9Encoder extends WrappedNativeVideoEncoder {
@Override native long createNativeEncoder();
@Override
long createNativeEncoder() {
return nativeCreateEncoder();
}
static native long nativeCreateEncoder();
@Override
boolean isSoftwareEncoder() {
return true;
}
static native boolean isSupported();
static native boolean nativeIsSupported();
}

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_

Some files were not shown because too many files have changed in this diff Show More