From 07b1fad76bc637009724f31331b6a0380afb4506 Mon Sep 17 00:00:00 2001 From: Alex Andres Date: Thu, 22 Oct 2026 07:58:22 +0200 Subject: [PATCH 1/2] fix: catch C++ exceptions at every JNI entry point that converts or allocates 86 entry points let a C++ exception, such as a JavaWrappedException from a conversion helper, cross the JNI boundary, which aborts the VM; they now rethrow it as a Java exception like the others. --- .../src/main/cpp/src/JNI_AudioConverter.cpp | 29 +- .../main/cpp/src/JNI_AudioDeviceModule.cpp | 29 +- .../cpp/src/JNI_AudioDeviceModuleBase.cpp | 206 ++++++----- .../src/main/cpp/src/JNI_AudioProcessing.cpp | 11 +- .../src/main/cpp/src/JNI_AudioResampler.cpp | 58 +-- .../src/main/cpp/src/JNI_AudioTrack.cpp | 24 +- .../main/cpp/src/JNI_CustomAudioSource.cpp | 53 ++- .../main/cpp/src/JNI_CustomVideoSource.cpp | 13 +- .../src/main/cpp/src/JNI_DesktopCapturer.cpp | 45 ++- webrtc-jni/src/main/cpp/src/JNI_Logging.cpp | 42 ++- .../src/main/cpp/src/JNI_MediaSource.cpp | 12 +- .../src/main/cpp/src/JNI_MediaStream.cpp | 12 +- .../src/main/cpp/src/JNI_MediaStreamTrack.cpp | 37 +- .../src/main/cpp/src/JNI_NativeI420Buffer.cpp | 37 +- .../cpp/src/JNI_PeerConnectionFactory.cpp | 136 ++++--- .../src/main/cpp/src/JNI_RTCDataChannel.cpp | 87 +++-- .../src/main/cpp/src/JNI_RTCDtlsTransport.cpp | 79 ++-- .../src/main/cpp/src/JNI_RTCDtmfSender.cpp | 59 +-- .../main/cpp/src/JNI_RTCPeerConnection.cpp | 339 +++++++++++------- .../src/main/cpp/src/JNI_RTCRtpReceiver.cpp | 82 +++-- .../src/main/cpp/src/JNI_RTCRtpSender.cpp | 92 +++-- .../main/cpp/src/JNI_RTCRtpTransceiver.cpp | 113 ++++-- webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp | 9 +- .../main/cpp/src/JNI_VideoBufferConverter.cpp | 101 +++--- .../src/main/cpp/src/JNI_VideoCapture.cpp | 36 +- .../main/cpp/src/JNI_VideoDeviceSource.cpp | 29 +- .../src/main/cpp/src/JNI_VideoTrack.cpp | 24 +- 27 files changed, 1142 insertions(+), 652 deletions(-) diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp index 47e1a336e..9ab11b28b 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp @@ -22,24 +22,29 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_convertInternal (JNIEnv * env, jobject caller, jbyteArray src, jint nSrcSamples, jbyteArray dst, jint nDstSamples) { - jni::AudioConverter * converter = GetHandle(env, caller); - CHECK_HANDLE(converter); + try { + jni::AudioConverter * converter = GetHandle(env, caller); + CHECK_HANDLE(converter); - jboolean isDstCopy = JNI_FALSE; + jboolean isDstCopy = JNI_FALSE; - jbyte * srcPtr = env->GetByteArrayElements(src, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(dst, &isDstCopy); + jbyte * srcPtr = env->GetByteArrayElements(src, nullptr); + jbyte * dstPtr = env->GetByteArrayElements(dst, &isDstCopy); - converter->convert(reinterpret_cast(srcPtr), nSrcSamples, reinterpret_cast(dstPtr), nDstSamples); + converter->convert(reinterpret_cast(srcPtr), nSrcSamples, reinterpret_cast(dstPtr), nDstSamples); - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dst); + if (isDstCopy == JNI_TRUE) { + jsize dstLength = env->GetArrayLength(dst); - env->SetByteArrayRegion(dst, 0, dstLength, dstPtr); - } + env->SetByteArrayRegion(dst, 0, dstLength, dstPtr); + } - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dst, dstPtr, JNI_ABORT); + env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); + env->ReleaseByteArrayElements(dst, dstPtr, JNI_ABORT); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_dispose diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp index 2528d2520..5373f1313 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp @@ -28,20 +28,25 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_initialize (JNIEnv * env, jobject caller, jobject jAudioLayer) { - jni::WebRTCContext * context = static_cast(javaContext); - auto audioLayer = jni::JavaEnums::toNative(env, jAudioLayer); + try { + jni::WebRTCContext * context = static_cast(javaContext); + auto audioLayer = jni::JavaEnums::toNative(env, jAudioLayer); - webrtc::scoped_refptr audioModule = webrtc::CreateAudioDeviceModule(context->webrtcEnv, audioLayer); + webrtc::scoped_refptr audioModule = webrtc::CreateAudioDeviceModule(context->webrtcEnv, audioLayer); - if (!audioModule) { - env->Throw(jni::JavaError(env, "Create AudioDeviceModule failed")); - return; - } + if (!audioModule) { + env->Throw(jni::JavaError(env, "Create AudioDeviceModule failed")); + return; + } - if (audioModule->Init() != 0) { - env->Throw(jni::JavaError(env, "Initialize AudioDeviceModule failed")); - return; - } + if (audioModule->Init() != 0) { + env->Throw(jni::JavaError(env, "Initialize AudioDeviceModule failed")); + return; + } - SetHandle(env, caller, audioModule.release()); + SetHandle(env, caller, audioModule.release()); + } + catch (...) { + ThrowCxxJavaException(env); + } } diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp index 38b825676..a2aedc57a 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp @@ -108,120 +108,142 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getPlayoutDevices (JNIEnv* env, jobject caller) { - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, nullptr); + try { + webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); + CHECK_HANDLEV(audioModule, nullptr); - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; + char name[webrtc::kAdmMaxDeviceNameSize]; + char guid[webrtc::kAdmMaxGuidSize]; - int16_t deviceCount = audioModule->PlayoutDevices(); + int16_t deviceCount = audioModule->PlayoutDevices(); - jni::JavaArrayList deviceList(env, deviceCount); + jni::JavaArrayList deviceList(env, deviceCount); - for (int i = 0; i < deviceCount; ++i) { - if (audioModule->PlayoutDeviceName(i, name, guid) == 0) { - auto device = std::make_shared(name, guid); - device -> directionType = jni::avdev::AudioDeviceDirectionType::adtRender; + for (int i = 0; i < deviceCount; ++i) { + if (audioModule->PlayoutDeviceName(i, name, guid) == 0) { + auto device = std::make_shared(name, guid); + device -> directionType = jni::avdev::AudioDeviceDirectionType::adtRender; - deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); + deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); + } } - } - return deviceList.listObject().release(); + return deviceList.listObject().release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getRecordingDevices (JNIEnv * env, jobject caller) { - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, nullptr); + try { + webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); + CHECK_HANDLEV(audioModule, nullptr); - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; + char name[webrtc::kAdmMaxDeviceNameSize]; + char guid[webrtc::kAdmMaxGuidSize]; - int16_t deviceCount = audioModule->RecordingDevices(); + int16_t deviceCount = audioModule->RecordingDevices(); - jni::JavaArrayList deviceList(env, deviceCount); + jni::JavaArrayList deviceList(env, deviceCount); - for (int i = 0; i < deviceCount; ++i) { - if (audioModule->RecordingDeviceName(i, name, guid) == 0) { - auto device = std::make_shared(name, guid); - device -> directionType = jni::avdev::AudioDeviceDirectionType::adtCapture; + for (int i = 0; i < deviceCount; ++i) { + if (audioModule->RecordingDeviceName(i, name, guid) == 0) { + auto device = std::make_shared(name, guid); + device -> directionType = jni::avdev::AudioDeviceDirectionType::adtCapture; - deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); + deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); + } } - } - return deviceList.listObject().release(); + return deviceList.listObject().release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setPlayoutDevice (JNIEnv * env, jobject caller, jobject device) { - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); + try { + webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); + CHECK_HANDLE(audioModule); - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "AudioDevice is null")); - return; - } + if (!device) { + env->Throw(jni::JavaNullPointerException(env, "AudioDevice is null")); + return; + } - jni::JavaObject obj(env, jni::JavaLocalRef(env, device)); + jni::JavaObject obj(env, jni::JavaLocalRef(env, device)); - const auto javaClass = jni::JavaClasses::get(env); - const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor)); + const auto javaClass = jni::JavaClasses::get(env); + const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor)); - uint16_t index = 0; - int16_t deviceCount = audioModule->PlayoutDevices(); + uint16_t index = 0; + int16_t deviceCount = audioModule->PlayoutDevices(); - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; + char name[webrtc::kAdmMaxDeviceNameSize]; + char guid[webrtc::kAdmMaxGuidSize]; - for (int i = 0; i < deviceCount; ++i) { - if ((audioModule->PlayoutDeviceName(i, name, guid) == 0) && devGuid == std::string(guid)) { - index = i; - break; + for (int i = 0; i < deviceCount; ++i) { + if ((audioModule->PlayoutDeviceName(i, name, guid) == 0) && devGuid == std::string(guid)) { + index = i; + break; + } } - } - if (audioModule->SetPlayoutDevice(index) != 0) { - env->Throw(jni::JavaError(env, "Set playout device failed")); - return; + if (audioModule->SetPlayoutDevice(index) != 0) { + env->Throw(jni::JavaError(env, "Set playout device failed")); + return; + } + } + catch (...) { + ThrowCxxJavaException(env); } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setRecordingDevice (JNIEnv * env, jobject caller, jobject device) { - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); + try { + webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); + CHECK_HANDLE(audioModule); - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "AudioDevice is null")); - return; - } + if (!device) { + env->Throw(jni::JavaNullPointerException(env, "AudioDevice is null")); + return; + } - jni::JavaObject obj(env, jni::JavaLocalRef(env, device)); + jni::JavaObject obj(env, jni::JavaLocalRef(env, device)); - const auto javaClass = jni::JavaClasses::get(env); - const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor)); + const auto javaClass = jni::JavaClasses::get(env); + const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor)); - uint16_t index = 0; - int16_t deviceCount = audioModule->RecordingDevices(); + uint16_t index = 0; + int16_t deviceCount = audioModule->RecordingDevices(); - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; + char name[webrtc::kAdmMaxDeviceNameSize]; + char guid[webrtc::kAdmMaxGuidSize]; - for (int i = 0; i < deviceCount; ++i) { - if ((audioModule->RecordingDeviceName(i, name, guid) == 0) && devGuid == std::string(guid)) { - index = i; - break; + for (int i = 0; i < deviceCount; ++i) { + if ((audioModule->RecordingDeviceName(i, name, guid) == 0) && devGuid == std::string(guid)) { + index = i; + break; + } } - } - if (audioModule->SetRecordingDevice(index) != 0) { - env->Throw(jni::JavaError(env, "Set recording device failed")); - return; + if (audioModule->SetRecordingDevice(index) != 0) { + env->Throw(jni::JavaError(env, "Set recording device failed")); + return; + } + } + catch (...) { + ThrowCxxJavaException(env); } } @@ -388,19 +410,25 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_ JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_addSinkInternal (JNIEnv * env, jobject caller, jobject jSink) { - if (jSink == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioSink must not be null")); - return 0; - } + try { + if (jSink == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "AudioSink must not be null")); + return 0; + } - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); + webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); + CHECK_HANDLEV(audioModule, 0); - auto sink = new jni::AudioTransportSink(env, jni::JavaGlobalRef(env, jSink)); + auto sink = new jni::AudioTransportSink(env, jni::JavaGlobalRef(env, jSink)); - audioModule->RegisterAudioCallback(sink); + audioModule->RegisterAudioCallback(sink); - return reinterpret_cast(sink); + return reinterpret_cast(sink); + } + catch (...) { + ThrowCxxJavaException(env); + return 0; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSinkInternal @@ -421,19 +449,25 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_ JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_addSourceInternal (JNIEnv * env, jobject caller, jobject jSource) { - if (jSource == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioSource must not be null")); - return 0; - } + try { + if (jSource == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "AudioSource must not be null")); + return 0; + } - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); + webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); + CHECK_HANDLEV(audioModule, 0); - auto source = new jni::AudioTransportSource(env, jni::JavaGlobalRef(env, jSource)); + auto source = new jni::AudioTransportSource(env, jni::JavaGlobalRef(env, jSource)); - audioModule->RegisterAudioCallback(source); + audioModule->RegisterAudioCallback(source); - return reinterpret_cast(source); + return reinterpret_cast(source); + } + catch (...) { + ThrowCxxJavaException(env); + return 0; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSourceInternal diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp index eb341b3e5..b5f902537 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp @@ -38,10 +38,15 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_applyConfig (JNIEnv * env, jobject caller, jobject config) { - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLE(apm); + try { + webrtc::AudioProcessing * apm = GetHandle(env, caller); + CHECK_HANDLE(apm); - apm->ApplyConfig(jni::AudioProcessingConfig::toNative(env, jni::JavaLocalRef(env, config))); + apm->ApplyConfig(jni::AudioProcessingConfig::toNative(env, jni::JavaLocalRef(env, config))); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_setStreamDelayMs diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp index d85e8c0f5..6eece0e45 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp @@ -36,46 +36,62 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_dispose JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_initialize (JNIEnv * env, jobject caller) { - webrtc::PushResampler * resampler = new webrtc::PushResampler(); + try { + webrtc::PushResampler * resampler = new webrtc::PushResampler(); - SetHandle(env, caller, resampler); + SetHandle(env, caller, resampler); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_initialize (JNIEnv* env, jobject caller, jint srcSamplesPerChannel, jint dstSamplesPerChannel, jint channels) { - webrtc::PushResampler * resampler = new webrtc::PushResampler(srcSamplesPerChannel, dstSamplesPerChannel, channels); + try { + webrtc::PushResampler * resampler = new webrtc::PushResampler(srcSamplesPerChannel, dstSamplesPerChannel, channels); - SetHandle(env, caller, resampler); + SetHandle(env, caller, resampler); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_resampleInternal (JNIEnv * env, jobject caller, jbyteArray samplesIn, jint srcSamplesPerChannel, jbyteArray samplesOut, jint dstSamplesPerChannel, jint channels) { - webrtc::PushResampler * resampler = GetHandle>(env, caller); - CHECK_HANDLEV(resampler, -1); + try { + webrtc::PushResampler * resampler = GetHandle>(env, caller); + CHECK_HANDLEV(resampler, -1); - jboolean isDstCopy = JNI_FALSE; + jboolean isDstCopy = JNI_FALSE; - jbyte * srcPtr = env->GetByteArrayElements(samplesIn, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(samplesOut, &isDstCopy); + jbyte * srcPtr = env->GetByteArrayElements(samplesIn, nullptr); + jbyte * dstPtr = env->GetByteArrayElements(samplesOut, &isDstCopy); - int16_t * src16Ptr = reinterpret_cast(srcPtr); - int16_t * dst16Ptr = reinterpret_cast(dstPtr); + int16_t * src16Ptr = reinterpret_cast(srcPtr); + int16_t * dst16Ptr = reinterpret_cast(dstPtr); - webrtc::InterleavedView src(src16Ptr, srcSamplesPerChannel, channels); - webrtc::InterleavedView dst(dst16Ptr, dstSamplesPerChannel, channels); + webrtc::InterleavedView src(src16Ptr, srcSamplesPerChannel, channels); + webrtc::InterleavedView dst(dst16Ptr, dstSamplesPerChannel, channels); - resampler->Resample(src, dst); + resampler->Resample(src, dst); - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(samplesOut); + if (isDstCopy == JNI_TRUE) { + jsize dstLength = env->GetArrayLength(samplesOut); - env->SetByteArrayRegion(samplesOut, 0, dstLength, dstPtr); - } + env->SetByteArrayRegion(samplesOut, 0, dstLength, dstPtr); + } - env->ReleaseByteArrayElements(samplesIn, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(samplesOut, dstPtr, JNI_ABORT); + env->ReleaseByteArrayElements(samplesIn, srcPtr, JNI_ABORT); + env->ReleaseByteArrayElements(samplesOut, dstPtr, JNI_ABORT); - return static_cast(dstSamplesPerChannel); + return static_cast(dstSamplesPerChannel); + } + catch (...) { + ThrowCxxJavaException(env); + return 0; + } } diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp index 81c75c962..c6bb14406 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp @@ -24,19 +24,25 @@ JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_addSinkInternal (JNIEnv * env, jobject caller, jobject jsink, jboolean packetInfos) { - if (jsink == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioTrackSink must not be null")); - return 0; - } + try { + if (jsink == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "AudioTrackSink must not be null")); + return 0; + } - webrtc::AudioTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, 0); + webrtc::AudioTrackInterface * track = GetHandle(env, caller); + CHECK_HANDLEV(track, 0); - auto sink = new jni::AudioTrackSink(env, jni::JavaGlobalRef(env, jsink), packetInfos); + auto sink = new jni::AudioTrackSink(env, jni::JavaGlobalRef(env, jsink), packetInfos); - track->AddSink(sink); + track->AddSink(sink); - return reinterpret_cast(sink); + return reinterpret_cast(sink); + } + catch (...) { + ThrowCxxJavaException(env); + return 0; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_removeSinkInternal diff --git a/webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp index 99ce8e1fa..595a18e2b 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp @@ -24,10 +24,15 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_initialize (JNIEnv * env, jobject caller) { - std::shared_ptr sync_clock = std::make_shared(); - webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); + try { + std::shared_ptr sync_clock = std::make_shared(); + webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); - SetHandle(env, caller, source.release()); + SetHandle(env, caller, source.release()); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_initializeWithClock @@ -62,31 +67,41 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_disp JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_pushAudioInternal (JNIEnv * env, jobject caller, jbyteArray audioData, jint bits_per_sample, jint sampleRate, jint channels, jint frameCount) { - jni::CustomAudioSource * source = GetHandle(env, caller); - CHECK_HANDLE(source); + try { + jni::CustomAudioSource * source = GetHandle(env, caller); + CHECK_HANDLE(source); - // The caller validated the format, the frame count and the array length. - jbyte * data = env->GetByteArrayElements(audioData, nullptr); + // The caller validated the format, the frame count and the array length. + jbyte * data = env->GetByteArrayElements(audioData, nullptr); - if (data != nullptr) { - source->PushAudioData(data, bits_per_sample, sampleRate, channels, frameCount); + if (data != nullptr) { + source->PushAudioData(data, bits_per_sample, sampleRate, channels, frameCount); - env->ReleaseByteArrayElements(audioData, data, JNI_ABORT); - } + env->ReleaseByteArrayElements(audioData, data, JNI_ABORT); + } + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_pushAudioTimestamped (JNIEnv * env, jobject caller, jbyteArray audioData, jint bits_per_sample, jint sampleRate, jint channels, jint frameCount, jlong timestampUs) { - jni::CustomAudioSource * source = GetHandle(env, caller); - CHECK_HANDLE(source); + try { + jni::CustomAudioSource * source = GetHandle(env, caller); + CHECK_HANDLE(source); - // The caller validated the format, the frame count and the array length. - jbyte * data = env->GetByteArrayElements(audioData, nullptr); + // The caller validated the format, the frame count and the array length. + jbyte * data = env->GetByteArrayElements(audioData, nullptr); - if (data != nullptr) { - source->PushAudioData(data, bits_per_sample, sampleRate, channels, frameCount, timestampUs); + if (data != nullptr) { + source->PushAudioData(data, bits_per_sample, sampleRate, channels, frameCount, timestampUs); - env->ReleaseByteArrayElements(audioData, data, JNI_ABORT); - } + env->ReleaseByteArrayElements(audioData, data, JNI_ABORT); + } + } + catch (...) { + ThrowCxxJavaException(env); + } } diff --git a/webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp index b23d11137..a075fee29 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp @@ -25,10 +25,15 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_initialize (JNIEnv * env, jobject caller) { - std::shared_ptr sync_clock = std::make_shared(); - webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); - - SetHandle(env, caller, source.release()); + try { + std::shared_ptr sync_clock = std::make_shared(); + webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); + + SetHandle(env, caller, source.release()); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_initializeWithClock diff --git a/webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp b/webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp index e1df6ed9e..542bfb6ca 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp @@ -44,35 +44,46 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapture JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_getDesktopSources (JNIEnv * env, jobject caller) { - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLEV(capturer, nullptr); + try { + jni::DesktopCapturer * capturer = GetHandle(env, caller); + CHECK_HANDLEV(capturer, nullptr); - webrtc::DesktopCapturer::SourceList sources; + webrtc::DesktopCapturer::SourceList sources; - if (!capturer->GetSourceList(&sources)) { - env->Throw(jni::JavaError(env, "Get source list failed")); - return nullptr; - } + if (!capturer->GetSourceList(&sources)) { + env->Throw(jni::JavaError(env, "Get source list failed")); + return nullptr; + } - jni::JavaArrayList sourceList(env, sources.size()); + jni::JavaArrayList sourceList(env, sources.size()); - for (const auto & source : sources) { - sourceList.add(jni::DesktopSource::toJava(env, source)); - } + for (const auto & source : sources) { + sourceList.add(jni::DesktopSource::toJava(env, source)); + } - return sourceList.listObject().release(); + return sourceList.listObject().release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_selectSource (JNIEnv * env, jobject caller, jobject jsource) { - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLE(capturer); + try { + jni::DesktopCapturer * capturer = GetHandle(env, caller); + CHECK_HANDLE(capturer); - auto source = jni::DesktopSource::toNative(env, jni::JavaLocalRef(env, jsource)); + auto source = jni::DesktopSource::toNative(env, jni::JavaLocalRef(env, jsource)); - if (!capturer->SelectSource(source.id)) { - env->Throw(jni::JavaError(env, "Select source failed")); + if (!capturer->SelectSource(source.id)) { + env->Throw(jni::JavaError(env, "Select source failed")); + } + } + catch (...) { + ThrowCxxJavaException(env); } } diff --git a/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp b/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp index 3d44fad3d..a7951c847 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp @@ -72,34 +72,44 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_addLogSink JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_log (JNIEnv * env, jclass caller, jobject jseverity, jstring jmessage) { - std::string message = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jmessage)); + try { + std::string message = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jmessage)); - auto severity = jni::JavaEnums::toNative(env, jseverity); + auto severity = jni::JavaEnums::toNative(env, jseverity); - RTC_LOG_V(severity) << message; + RTC_LOG_V(severity) << message; + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logToDebug (JNIEnv * env, jclass caller, jobject jseverity) { - int rtcSeverity = jni::JavaEnums::toNative(env, jseverity); + try { + int rtcSeverity = jni::JavaEnums::toNative(env, jseverity); - if (rtcSeverity < webrtc::LS_VERBOSE || rtcSeverity > webrtc::LS_NONE) { - return; - } + if (rtcSeverity < webrtc::LS_VERBOSE || rtcSeverity > webrtc::LS_NONE) { + return; + } - auto severity = static_cast(rtcSeverity); + auto severity = static_cast(rtcSeverity); - std::lock_guard lock(debugLogSinkMutex); + std::lock_guard lock(debugLogSinkMutex); - if (debugLogSinkAttached) { - webrtc::LogMessage::RemoveLogToStream(&debugLogSink); - debugLogSinkAttached = false; - } + if (debugLogSinkAttached) { + webrtc::LogMessage::RemoveLogToStream(&debugLogSink); + debugLogSinkAttached = false; + } - if (severity != webrtc::LS_NONE) { - webrtc::LogMessage::AddLogToStream(&debugLogSink, severity); - debugLogSinkAttached = true; + if (severity != webrtc::LS_NONE) { + webrtc::LogMessage::AddLogToStream(&debugLogSink, severity); + debugLogSinkAttached = true; + } + } + catch (...) { + ThrowCxxJavaException(env); } } diff --git a/webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp index 4a5762985..72cc887a5 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp @@ -23,8 +23,14 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaSource_getState (JNIEnv * env, jobject caller) { - webrtc::MediaSourceInterface * source = GetHandle(env, caller); - CHECK_HANDLEV(source, nullptr); + try { + webrtc::MediaSourceInterface * source = GetHandle(env, caller); + CHECK_HANDLEV(source, nullptr); - return jni::JavaEnums::toJava(env, source->state()).release(); + return jni::JavaEnums::toJava(env, source->state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp b/webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp index dbdb78761..568230079 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp @@ -28,10 +28,16 @@ JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStream_id (JNIEnv * env, jobject caller) { - webrtc::MediaStreamInterface * stream = GetHandle(env, caller); - CHECK_HANDLEV(stream, nullptr); + try { + webrtc::MediaStreamInterface * stream = GetHandle(env, caller); + CHECK_HANDLEV(stream, nullptr); - return jni::JavaString::toJava(env, stream->id()).release(); + return jni::JavaString::toJava(env, stream->id()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_media_MediaStream_getAudioTracks diff --git a/webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp b/webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp index 517f32b37..25231030e 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp @@ -20,6 +20,7 @@ #include "JavaError.h" #include "JavaFactories.h" #include "JavaString.h" +#include "JavaUtils.h" #include "WebRTCContext.h" #include "media/MediaStreamTrackObserver.h" @@ -66,19 +67,31 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_dispose JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getKind (JNIEnv * env, jobject caller) { - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, nullptr); + try { + webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); + CHECK_HANDLEV(track, nullptr); - return jni::JavaString::toJava(env, track->kind()).release(); + return jni::JavaString::toJava(env, track->kind()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getId (JNIEnv * env, jobject caller) { - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, nullptr); + try { + webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); + CHECK_HANDLEV(track, nullptr); - return jni::JavaString::toJava(env, track->id()).release(); + return jni::JavaString::toJava(env, track->id()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_isEnabled @@ -102,10 +115,16 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_setEnabled JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getState (JNIEnv * env, jobject caller) { - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, nullptr); + try { + webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); + CHECK_HANDLEV(track, nullptr); - return jni::JavaEnums::toJava(env, track->state()).release(); + return jni::JavaEnums::toJava(env, track->state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_addEndedEventListener diff --git a/webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp b/webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp index 10fb32fc0..3bcacfc40 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp @@ -17,6 +17,7 @@ #include "JNI_NativeI420Buffer.h" #include "api/VideoFrame.h" #include "JavaRuntimeException.h" +#include "JavaUtils.h" #include "api/video/i420_buffer.h" #include "libyuv/scale.h" @@ -24,31 +25,43 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_allocate (JNIEnv * env, jclass caller, jint width, jint height) { - webrtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Create(width, height); + try { + webrtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Create(width, height); - jni::JavaLocalRef jBuffer = jni::I420Buffer::toJava(env, i420Buffer); + jni::JavaLocalRef jBuffer = jni::I420Buffer::toJava(env, i420Buffer); - i420Buffer->AddRef(); + i420Buffer->AddRef(); - return jBuffer.release(); + return jBuffer.release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_copy (JNIEnv* env, jclass caller, jint width, jint height, jobject jSrcY, jint srcStrideY, jobject jSrcU, jint srcStrideU, jobject jSrcV, jint srcStrideV) { - const uint8_t * src_y = static_cast(env->GetDirectBufferAddress(jSrcY)); - const uint8_t * src_u = static_cast(env->GetDirectBufferAddress(jSrcU)); - const uint8_t * src_v = static_cast(env->GetDirectBufferAddress(jSrcV)); + try { + const uint8_t * src_y = static_cast(env->GetDirectBufferAddress(jSrcY)); + const uint8_t * src_u = static_cast(env->GetDirectBufferAddress(jSrcU)); + const uint8_t * src_v = static_cast(env->GetDirectBufferAddress(jSrcV)); - webrtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Copy(width, height, - src_y, srcStrideY, src_u, srcStrideU, src_v, srcStrideV); + webrtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Copy(width, height, + src_y, srcStrideY, src_u, srcStrideU, src_v, srcStrideV); - jni::JavaLocalRef jBuffer = jni::I420Buffer::toJava(env, i420Buffer); + jni::JavaLocalRef jBuffer = jni::I420Buffer::toJava(env, i420Buffer); - i420Buffer->AddRef(); + i420Buffer->AddRef(); - return jBuffer.release(); + return jBuffer.release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_cropAndScale diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index 91056b20b..19c3c6fd1 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -245,49 +245,61 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_setDeviceCap JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createAudioSourceInternal (JNIEnv * env, jobject caller, jobject jAudioOptions) { - if (jAudioOptions == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioOptions is null")); - return nullptr; - } + try { + if (jAudioOptions == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "AudioOptions is null")); + return nullptr; + } - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); + webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); + CHECK_HANDLEV(factory, nullptr); + + auto audioOptions = jni::AudioOptions::toNative(env, jni::JavaLocalRef(env, jAudioOptions)); - auto audioOptions = jni::AudioOptions::toNative(env, jni::JavaLocalRef(env, jAudioOptions)); + webrtc::scoped_refptr audioSource = factory->CreateAudioSource(audioOptions); - webrtc::scoped_refptr audioSource = factory->CreateAudioSource(audioOptions); + if (audioSource == nullptr) { + env->Throw(jni::JavaError(env, "Create audio-track source failed")); + return nullptr; + } - if (audioSource == nullptr) { - env->Throw(jni::JavaError(env, "Create audio-track source failed")); + return jni::JavaFactories::create(env, audioSource.release()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::JavaFactories::create(env, audioSource.release()).release(); } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createAudioTrackInternal (JNIEnv * env, jobject caller, jstring jlabel, jobject jsource) { - if (jlabel == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "Audio track label is null")); - return nullptr; - } - if (jsource == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioTrackSource is null")); - return nullptr; - } + try { + if (jlabel == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "Audio track label is null")); + return nullptr; + } + if (jsource == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "AudioTrackSource is null")); + return nullptr; + } - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); + webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); + CHECK_HANDLEV(factory, nullptr); - webrtc::AudioSourceInterface * source = GetHandle(env, jsource); - CHECK_HANDLEV(source, nullptr); + webrtc::AudioSourceInterface * source = GetHandle(env, jsource); + CHECK_HANDLEV(source, nullptr); - std::string label = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jlabel)); + std::string label = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jlabel)); - webrtc::scoped_refptr audioTrack = factory->CreateAudioTrack(label, source); + webrtc::scoped_refptr audioTrack = factory->CreateAudioTrack(label, source); - return jni::JavaFactories::create(env, audioTrack.release()).release(); + return jni::JavaFactories::create(env, audioTrack.release()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_isSinkFedAudioTrack @@ -321,27 +333,33 @@ JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_isSinkFe JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createVideoTrack (JNIEnv * env, jobject caller, jstring jlabel, jobject jsource) { - if (jlabel == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "Video track label is null")); - return nullptr; - } - if (jsource == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "VideoTrackSource is null")); - return nullptr; - } + try { + if (jlabel == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "Video track label is null")); + return nullptr; + } + if (jsource == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "VideoTrackSource is null")); + return nullptr; + } - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); + webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); + CHECK_HANDLEV(factory, nullptr); - webrtc::VideoTrackSourceInterface * source = GetHandle(env, jsource); - CHECK_HANDLEV(source, nullptr); + webrtc::VideoTrackSourceInterface * source = GetHandle(env, jsource); + CHECK_HANDLEV(source, nullptr); - std::string label = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jlabel)); + std::string label = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jlabel)); - webrtc::scoped_refptr videoTrack = factory->CreateVideoTrack( - webrtc::scoped_refptr(source), label); + webrtc::scoped_refptr videoTrack = factory->CreateVideoTrack( + webrtc::scoped_refptr(source), label); - return jni::JavaFactories::create(env, videoTrack.release()).release(); + return jni::JavaFactories::create(env, videoTrack.release()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPeerConnectionInternal @@ -406,23 +424,35 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPee JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_getRtpReceiverCapabilities (JNIEnv * env, jobject caller, jobject mediaType) { - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); + try { + webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); + CHECK_HANDLEV(factory, nullptr); - auto type = jni::JavaEnums::toNative(env, mediaType); - auto capabilities = factory->GetRtpReceiverCapabilities(type); + auto type = jni::JavaEnums::toNative(env, mediaType); + auto capabilities = factory->GetRtpReceiverCapabilities(type); - return jni::RTCRtpCapabilities::toJava(env, capabilities).release(); + return jni::RTCRtpCapabilities::toJava(env, capabilities).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_getRtpSenderCapabilities (JNIEnv * env, jobject caller, jobject mediaType) { - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); + try { + webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); + CHECK_HANDLEV(factory, nullptr); - auto type = jni::JavaEnums::toNative(env, mediaType); - auto capabilities = factory->GetRtpSenderCapabilities(type); + auto type = jni::JavaEnums::toNative(env, mediaType); + auto capabilities = factory->GetRtpSenderCapabilities(type); - return jni::RTCRtpCapabilities::toJava(env, capabilities).release(); + return jni::RTCRtpCapabilities::toJava(env, capabilities).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp index 2cdcea0db..5b42f8654 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp @@ -33,17 +33,22 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_registerObserver (JNIEnv * env, jobject caller, jobject jObserver) { - webrtc::DataChannelInterface * channel = GetHandle(env, caller); - CHECK_HANDLE(channel); + try { + webrtc::DataChannelInterface * channel = GetHandle(env, caller); + CHECK_HANDLE(channel); - // Unregister and free a previously registered observer before replacing - // it, otherwise it would leak along with its JNI global reference. - channel->UnregisterObserver(); + // Unregister and free a previously registered observer before replacing + // it, otherwise it would leak along with its JNI global reference. + channel->UnregisterObserver(); - auto observer = new jni::RTCDataChannelObserver(env, jni::JavaGlobalRef(env, jObserver)); - ReplaceNativeObserver(env, caller, "observerHandle", observer); + auto observer = new jni::RTCDataChannelObserver(env, jni::JavaGlobalRef(env, jObserver)); + ReplaceNativeObserver(env, caller, "observerHandle", observer); - channel->RegisterObserver(observer); + channel->RegisterObserver(observer); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_unregisterObserver @@ -60,10 +65,16 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_unregisterObserver JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getLabel (JNIEnv * env, jobject caller) { - webrtc::DataChannelInterface * channel = GetHandle(env, caller); - CHECK_HANDLEV(channel, nullptr); + try { + webrtc::DataChannelInterface * channel = GetHandle(env, caller); + CHECK_HANDLEV(channel, nullptr); - return jni::JavaString::toJava(env, channel->label()).release(); + return jni::JavaString::toJava(env, channel->label()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isReliable @@ -105,10 +116,16 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getMaxRetransmits JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getProtocol (JNIEnv * env, jobject caller) { - webrtc::DataChannelInterface * channel = GetHandle(env, caller); - CHECK_HANDLEV(channel, nullptr); + try { + webrtc::DataChannelInterface * channel = GetHandle(env, caller); + CHECK_HANDLEV(channel, nullptr); - return jni::JavaString::toJava(env, channel->protocol()).release(); + return jni::JavaString::toJava(env, channel->protocol()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isNegotiated @@ -123,22 +140,28 @@ JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isNegotiated JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getPriority (JNIEnv * env, jobject caller) { - webrtc::DataChannelInterface * channel = GetHandle(env, caller); - CHECK_HANDLEV(channel, nullptr); + try { + webrtc::DataChannelInterface * channel = GetHandle(env, caller); + CHECK_HANDLEV(channel, nullptr); - // The priority is a number on the wire; a remote peer may announce one - // between the four levels, which is rounded up to the next level. - const uint16_t value = channel->priority().value(); - webrtc::Priority priority = webrtc::Priority::kHigh; + // The priority is a number on the wire; a remote peer may announce one + // between the four levels, which is rounded up to the next level. + const uint16_t value = channel->priority().value(); + webrtc::Priority priority = webrtc::Priority::kHigh; - for (auto level : { webrtc::Priority::kVeryLow, webrtc::Priority::kLow, webrtc::Priority::kMedium }) { - if (value <= webrtc::PriorityValue(level).value()) { - priority = level; - break; + for (auto level : { webrtc::Priority::kVeryLow, webrtc::Priority::kLow, webrtc::Priority::kMedium }) { + if (value <= webrtc::PriorityValue(level).value()) { + priority = level; + break; + } } - } - return jni::JavaEnums::toJava(env, priority).release(); + return jni::JavaEnums::toJava(env, priority).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getId @@ -153,10 +176,16 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getId JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getState (JNIEnv * env, jobject caller) { - webrtc::DataChannelInterface * channel = GetHandle(env, caller); - CHECK_HANDLEV(channel, nullptr); + try { + webrtc::DataChannelInterface * channel = GetHandle(env, caller); + CHECK_HANDLEV(channel, nullptr); - return jni::JavaEnums::toJava(env, channel->state()).release(); + return jni::JavaEnums::toJava(env, channel->state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getBufferedAmount diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp index 4d331dc94..24daf06cf 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp @@ -28,62 +28,85 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getIceTransport (JNIEnv * env, jobject caller) { - webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); - CHECK_HANDLEV(transport, nullptr); + try { + webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); + CHECK_HANDLEV(transport, nullptr); - auto iceTransport = transport->ice_transport(); + auto iceTransport = transport->ice_transport(); - return jni::JavaFactories::create(env, iceTransport.get()).release(); + return jni::JavaFactories::create(env, iceTransport.get()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getState (JNIEnv * env, jobject caller) { - webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); - CHECK_HANDLEV(transport, nullptr); + try { + webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); + CHECK_HANDLEV(transport, nullptr); - auto info = transport->Information(); + auto info = transport->Information(); - return jni::JavaEnums::toJava(env, info.state()).release(); + return jni::JavaEnums::toJava(env, info.state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getRemoteCertificates (JNIEnv * env, jobject caller) { - webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); - CHECK_HANDLEV(transport, nullptr); + try { + webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); + CHECK_HANDLEV(transport, nullptr); - auto info = transport->Information(); - auto certChain = info.remote_ssl_certificates(); + auto info = transport->Information(); + auto certChain = info.remote_ssl_certificates(); - size_t count = certChain->GetSize(); + size_t count = certChain->GetSize(); - jni::JavaArrayList certificates(env, count); + jni::JavaArrayList certificates(env, count); - for (size_t i = 0; i < count; i++) { - const webrtc::SSLCertificate & certificate = certChain->Get(i); - const webrtc::RTCCertificatePEM pem("", certificate.ToPEMString()); + for (size_t i = 0; i < count; i++) { + const webrtc::SSLCertificate & certificate = certChain->Get(i); + const webrtc::RTCCertificatePEM pem("", certificate.ToPEMString()); - certificates.add(jni::RTCCertificatePEM::toJava(env, pem)); - } + certificates.add(jni::RTCCertificatePEM::toJava(env, pem)); + } - return certificates.listObject().release(); + return certificates.listObject().release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_registerObserver (JNIEnv * env, jobject caller, jobject observer) { - webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); - CHECK_HANDLE(transport); + try { + webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); + CHECK_HANDLE(transport); - // Unregister and free a previously registered observer before replacing - // it, otherwise it would leak along with its JNI global reference. - transport->UnregisterObserver(); + // Unregister and free a previously registered observer before replacing + // it, otherwise it would leak along with its JNI global reference. + transport->UnregisterObserver(); - auto newObserver = new jni::RTCDtlsTransportObserver(env, jni::JavaGlobalRef(env, observer)); - ReplaceNativeObserver(env, caller, "observerHandle", newObserver); + auto newObserver = new jni::RTCDtlsTransportObserver(env, jni::JavaGlobalRef(env, observer)); + ReplaceNativeObserver(env, caller, "observerHandle", newObserver); - transport->RegisterObserver(newObserver); + transport->RegisterObserver(newObserver); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_unregisterObserver diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp index 8db7b672a..2a0a157f2 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp @@ -33,21 +33,33 @@ JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_canInsertDtmf JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_insertDtmf (JNIEnv * env, jobject caller, jstring jTones, jint duration, jint interToneGap) { - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, false); - - std::string tones = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jTones)); - - return static_cast(sender->InsertDtmf(tones, static_cast(duration), static_cast(interToneGap))); + try { + webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLEV(sender, false); + + std::string tones = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jTones)); + + return static_cast(sender->InsertDtmf(tones, static_cast(duration), static_cast(interToneGap))); + } + catch (...) { + ThrowCxxJavaException(env); + return JNI_FALSE; + } } JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_tones (JNIEnv * env, jobject caller) { - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); - - return jni::JavaString::toJava(env, sender->tones()).release(); + try { + webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLEV(sender, nullptr); + + return jni::JavaString::toJava(env, sender->tones()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_duration @@ -71,17 +83,22 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_interToneGap JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_registerObserver (JNIEnv * env, jobject caller, jobject jObserver) { - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); - - // Unregister and free a previously registered observer before replacing - // it, otherwise it would leak along with its JNI global reference. - sender->UnregisterObserver(); - - auto observer = new jni::RTCDtmfSenderObserver(env, jni::JavaGlobalRef(env, jObserver)); - ReplaceNativeObserver(env, caller, "observerHandle", observer); - - sender->RegisterObserver(observer); + try { + webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLE(sender); + + // Unregister and free a previously registered observer before replacing + // it, otherwise it would leak along with its JNI global reference. + sender->UnregisterObserver(); + + auto observer = new jni::RTCDtmfSenderObserver(env, jni::JavaGlobalRef(env, jObserver)); + ReplaceNativeObserver(env, caller, "observerHandle", observer); + + sender->RegisterObserver(observer); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_unregisterObserver diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp index 21550ef0d..9330cd2ea 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp @@ -107,34 +107,40 @@ JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getTrans JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addTrackInternal (JNIEnv * env, jobject caller, jobject jTrack, jobject jStreamIds) { - if (jTrack == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "MediaStreamTrack must not be null")); - return nullptr; - } - if (jStreamIds == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "Stream IDs must not be null")); - return nullptr; - } + try { + if (jTrack == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "MediaStreamTrack must not be null")); + return nullptr; + } + if (jStreamIds == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "Stream IDs must not be null")); + return nullptr; + } - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); - webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); - CHECK_HANDLEV(track, nullptr); + webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); + CHECK_HANDLEV(track, nullptr); - std::vector streamIDs = jni::JavaList::toStringVector(env, jni::JavaLocalRef(env, jStreamIds)); + std::vector streamIDs = jni::JavaList::toStringVector(env, jni::JavaLocalRef(env, jStreamIds)); - auto result = pc->AddTrack(webrtc::scoped_refptr(track), streamIDs); + auto result = pc->AddTrack(webrtc::scoped_refptr(track), streamIDs); - if (result.ok()) { - auto sender = result.MoveValue(); + if (result.ok()) { + auto sender = result.MoveValue(); - return jni::JavaFactories::create(env, sender.release()).release(); - } + return jni::JavaFactories::create(env, sender.release()).release(); + } - env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result.error()).c_str())); + env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result.error()).c_str())); - return nullptr; + return nullptr; + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_removeTrack @@ -162,37 +168,43 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_removeTrack JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addTransceiverInternal (JNIEnv * env, jobject caller, jobject jTrack, jobject jTransceiverInit) { - if (jTrack == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "MediaStreamTrack must not be null")); - return nullptr; - } + try { + if (jTrack == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "MediaStreamTrack must not be null")); + return nullptr; + } - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); - webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); - CHECK_HANDLEV(track, nullptr); + webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); + CHECK_HANDLEV(track, nullptr); - webrtc::RTCErrorOr> result; + webrtc::RTCErrorOr> result; - if (jTransceiverInit != nullptr) { - auto init = jni::RTCRtpTransceiverInit::toNative(env, jni::JavaLocalRef(env, jTransceiverInit)); + if (jTransceiverInit != nullptr) { + auto init = jni::RTCRtpTransceiverInit::toNative(env, jni::JavaLocalRef(env, jTransceiverInit)); - result = pc->AddTransceiver(webrtc::scoped_refptr(track), init); - } - else { - result = pc->AddTransceiver(webrtc::scoped_refptr(track)); - } + result = pc->AddTransceiver(webrtc::scoped_refptr(track), init); + } + else { + result = pc->AddTransceiver(webrtc::scoped_refptr(track)); + } - if (result.ok()) { - auto transceiver = result.MoveValue(); + if (result.ok()) { + auto transceiver = result.MoveValue(); - return jni::JavaFactories::create(env, transceiver.release()).release(); - } + return jni::JavaFactories::create(env, transceiver.release()).release(); + } - env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result.error()).c_str())); + env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result.error()).c_str())); - return nullptr; + return nullptr; + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addTransceiverOfType @@ -328,79 +340,115 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createAnswer JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentLocalDescription (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); + + if (!pc->current_local_description()) { + return nullptr; + } - if (!pc->current_local_description()) { + return jni::RTCSessionDescription::toJava(env, pc->current_local_description()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::RTCSessionDescription::toJava(env, pc->current_local_description()).release(); } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getLocalDescription (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); - if (!pc->local_description()) { + if (!pc->local_description()) { + return nullptr; + } + + return jni::RTCSessionDescription::toJava(env, pc->local_description()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::RTCSessionDescription::toJava(env, pc->local_description()).release(); } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingLocalDescription (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); + + if (!pc->pending_local_description()) { + return nullptr; + } - if (!pc->pending_local_description()) { + return jni::RTCSessionDescription::toJava(env, pc->pending_local_description()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::RTCSessionDescription::toJava(env, pc->pending_local_description()).release(); } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentRemoteDescription (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); + + if (!pc->current_remote_description()) { + return nullptr; + } - if (!pc->current_remote_description()) { + return jni::RTCSessionDescription::toJava(env, pc->current_remote_description()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::RTCSessionDescription::toJava(env, pc->current_remote_description()).release(); } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getRemoteDescription (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); + + if (!pc->remote_description()) { + return nullptr; + } - if (!pc->remote_description()) { + return jni::RTCSessionDescription::toJava(env, pc->remote_description()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::RTCSessionDescription::toJava(env, pc->remote_description()).release(); } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingRemoteDescription (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); - if (!pc->pending_remote_description()) { + if (!pc->pending_remote_description()) { + return nullptr; + } + + return jni::RTCSessionDescription::toJava(env, pc->pending_remote_description()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::RTCSessionDescription::toJava(env, pc->pending_remote_description()).release(); } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setLocalDescription @@ -600,46 +648,76 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setAudioRecordin JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getSignalingState (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::SignalingState::kClosed).release()); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::SignalingState::kClosed).release()); - return jni::JavaEnums::toJava(env, pc->signaling_state()).release(); + return jni::JavaEnums::toJava(env, pc->signaling_state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceGatheringState (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringNew).release()); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringNew).release()); - return jni::JavaEnums::toJava(env, pc->ice_gathering_state()).release(); + return jni::JavaEnums::toJava(env, pc->ice_gathering_state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceConnectionState (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::IceConnectionState::kIceConnectionClosed).release()); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::IceConnectionState::kIceConnectionClosed).release()); - return jni::JavaEnums::toJava(env, pc->ice_connection_state()).release(); + return jni::JavaEnums::toJava(env, pc->ice_connection_state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConnectionState (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::PeerConnectionState::kClosed).release()); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLE_DEFAULT(pc, jni::JavaEnums::toJava(env, webrtc::PeerConnectionInterface::PeerConnectionState::kClosed).release()); - return jni::JavaEnums::toJava(env, pc->peer_connection_state()).release(); + return jni::JavaEnums::toJava(env, pc->peer_connection_state()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConfiguration (JNIEnv * env, jobject caller) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLEV(pc, nullptr); - return jni::RTCConfiguration::toJava(env, pc->GetConfiguration()).release(); + return jni::RTCConfiguration::toJava(env, pc->GetConfiguration()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setConfiguration @@ -670,63 +748,78 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setConfiguration JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 (JNIEnv * env, jobject caller, jobject jcallback) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE(pc); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLE(pc); - if (jcallback == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); - return; - } + if (jcallback == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); + return; + } - auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); + auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); - pc->GetStats(callback); + pc->GetStats(callback); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCRtpReceiver_2Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 (JNIEnv * env, jobject caller, jobject jreceiver, jobject jcallback) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE(pc); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLE(pc); - if (jreceiver == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCRtpReceiver is null")); - return; - } - if (jcallback == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); - return; - } + if (jreceiver == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "RTCRtpReceiver is null")); + return; + } + if (jcallback == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); + return; + } - webrtc::RtpReceiverInterface * receiver = GetHandle(env, jreceiver); - CHECK_HANDLE(receiver); + webrtc::RtpReceiverInterface * receiver = GetHandle(env, jreceiver); + CHECK_HANDLE(receiver); - auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); + auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); - pc->GetStats(webrtc::scoped_refptr(receiver), webrtc::scoped_refptr(callback)); + pc->GetStats(webrtc::scoped_refptr(receiver), webrtc::scoped_refptr(callback)); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCRtpSender_2Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 (JNIEnv * env, jobject caller, jobject jsender, jobject jcallback) { - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE(pc); + try { + webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); + CHECK_HANDLE(pc); - if (jsender == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCRtpSender is null")); - return; - } - if (jcallback == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); - return; - } + if (jsender == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "RTCRtpSender is null")); + return; + } + if (jcallback == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); + return; + } - webrtc::RtpSenderInterface * sender = GetHandle(env, jsender); - CHECK_HANDLE(sender); + webrtc::RtpSenderInterface * sender = GetHandle(env, jsender); + CHECK_HANDLE(sender); - auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); + auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); - pc->GetStats(webrtc::scoped_refptr(sender), webrtc::scoped_refptr(callback)); + pc->GetStats(webrtc::scoped_refptr(sender), webrtc::scoped_refptr(callback)); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_restartIce diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp index 4a8291b0b..848cb4404 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp @@ -47,55 +47,79 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getTrack JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getTransport (JNIEnv * env, jobject caller) { - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); + try { + webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); + CHECK_HANDLEV(receiver, nullptr); - auto transport = receiver->dtls_transport(); + auto transport = receiver->dtls_transport(); - return jni::JavaFactories::create(env, transport.get()).release(); + return jni::JavaFactories::create(env, transport.get()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getParameters (JNIEnv * env, jobject caller) { - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); + try { + webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); + CHECK_HANDLEV(receiver, nullptr); - return jni::RTCRtpParameters::toJava(env, receiver->GetParameters()).release(); + return jni::RTCRtpParameters::toJava(env, receiver->GetParameters()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getContributingSources (JNIEnv * env, jobject caller) { - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); + try { + webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); + CHECK_HANDLEV(receiver, nullptr); - std::vector sources = receiver->GetSources(); - std::vector csrc; + std::vector sources = receiver->GetSources(); + std::vector csrc; - std::copy_if(sources.begin(), sources.end(), std::back_inserter(csrc), - [](webrtc::RtpSource s) { return s.source_type() == webrtc::RtpSourceType::CSRC; }); + std::copy_if(sources.begin(), sources.end(), std::back_inserter(csrc), + [](webrtc::RtpSource s) { return s.source_type() == webrtc::RtpSourceType::CSRC; }); - auto list = jni::JavaList::toArrayList(env, csrc, jni::RTCRtpContributingSource::toJava); + auto list = jni::JavaList::toArrayList(env, csrc, jni::RTCRtpContributingSource::toJava); - return list.release(); + return list.release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getSynchronizationSources (JNIEnv * env, jobject caller) { - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); + try { + webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); + CHECK_HANDLEV(receiver, nullptr); - std::vector sources = receiver->GetSources(); - std::vector ssrc; + std::vector sources = receiver->GetSources(); + std::vector ssrc; - std::copy_if(sources.begin(), sources.end(), std::back_inserter(ssrc), - [](webrtc::RtpSource s) { return s.source_type() == webrtc::RtpSourceType::SSRC; }); + std::copy_if(sources.begin(), sources.end(), std::back_inserter(ssrc), + [](webrtc::RtpSource s) { return s.source_type() == webrtc::RtpSourceType::SSRC; }); - auto list = jni::JavaList::toArrayList(env, ssrc, jni::RTCRtpSynchronizationSource::toJava); + auto list = jni::JavaList::toArrayList(env, ssrc, jni::RTCRtpSynchronizationSource::toJava); - return list.release(); + return list.release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_setTransform @@ -149,10 +173,16 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_requestKeyFrame JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getId (JNIEnv * env, jobject caller) { - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); + try { + webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); + CHECK_HANDLEV(receiver, nullptr); - return jni::JavaString::toJava(env, receiver->id()).release(); + return jni::JavaString::toJava(env, receiver->id()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_setObserver diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp index ff29148f7..03769f71b 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp @@ -47,12 +47,18 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getTrack JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getTransport (JNIEnv * env, jobject caller) { - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); + try { + webrtc::RtpSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLEV(sender, nullptr); - auto transport = sender->dtls_transport(); + auto transport = sender->dtls_transport(); - return jni::JavaFactories::create(env, transport.get()).release(); + return jni::JavaFactories::create(env, transport.get()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_replaceTrack @@ -73,53 +79,75 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_replaceTrack JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_setParameters (JNIEnv * env, jobject caller, jobject jParams) { - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); + try { + webrtc::RtpSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLE(sender); - webrtc::RtpParameters rtp_parameters = jni::RTCRtpSendParameters::toNative(env, jni::JavaLocalRef(env, jParams)); - webrtc::RTCError result = sender->SetParameters(rtp_parameters); + webrtc::RtpParameters rtp_parameters = jni::RTCRtpSendParameters::toNative(env, jni::JavaLocalRef(env, jParams)); + webrtc::RTCError result = sender->SetParameters(rtp_parameters); - if (!result.ok()) { - env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result).c_str())); + if (!result.ok()) { + env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result).c_str())); + } + } + catch (...) { + ThrowCxxJavaException(env); } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getParameters (JNIEnv * env, jobject caller) { - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); + try { + webrtc::RtpSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLEV(sender, nullptr); - return jni::RTCRtpSendParameters::toJava(env, sender->GetParameters()).release(); + return jni::RTCRtpSendParameters::toJava(env, sender->GetParameters()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_setStreams (JNIEnv * env, jobject caller, jobject streamIdList) { - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); + try { + webrtc::RtpSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLE(sender); - std::vector streamIDs = jni::JavaList::toStringVector(env, jni::JavaLocalRef(env, streamIdList)); + std::vector streamIDs = jni::JavaList::toStringVector(env, jni::JavaLocalRef(env, streamIdList)); - sender->SetStreams(streamIDs); + sender->SetStreams(streamIDs); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getDtmfSender (JNIEnv * env, jobject caller) { - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); + try { + webrtc::RtpSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLEV(sender, nullptr); - auto dtmfSender = sender->GetDtmfSender(); - if (!dtmfSender) { - return nullptr; - } + auto dtmfSender = sender->GetDtmfSender(); + if (!dtmfSender) { + return nullptr; + } - auto jDtmfSender = jni::RTCDtmfSender::toJava(env); + auto jDtmfSender = jni::RTCDtmfSender::toJava(env); - SetHandle(env, jDtmfSender, dtmfSender.get()); + SetHandle(env, jDtmfSender, dtmfSender.get()); - return jDtmfSender.release(); + return jDtmfSender.release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_setTransform @@ -238,10 +266,16 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_createAudioFrameIn JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getId (JNIEnv * env, jobject caller) { - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); + try { + webrtc::RtpSenderInterface * sender = GetHandle(env, caller); + CHECK_HANDLEV(sender, nullptr); - return jni::JavaString::toJava(env, sender->id()).release(); + return jni::JavaString::toJava(env, sender->id()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getStreams diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp index be116e249..19aa34803 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp @@ -31,76 +31,111 @@ JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getMid (JNIEnv * env, jobject caller) { - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); + try { + webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); + CHECK_HANDLEV(transceiver, nullptr); - return jni::JavaString::toJava(env, transceiver->mid().value_or("")).release(); + return jni::JavaString::toJava(env, transceiver->mid().value_or("")).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getSender (JNIEnv * env, jobject caller) { - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); + try { + webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); + CHECK_HANDLEV(transceiver, nullptr); - webrtc::scoped_refptr sender = transceiver->sender(); + webrtc::scoped_refptr sender = transceiver->sender(); - // Transfer the reference this local scoped_refptr holds into the Java - // wrapper, which owns and disposes it -- otherwise the wrapper would be - // left with a pointer nothing on the Java/JNI side keeps alive. - return jni::JavaFactories::create(env, sender.release()).release(); + // Transfer the reference this local scoped_refptr holds into the Java + // wrapper, which owns and disposes it -- otherwise the wrapper would be + // left with a pointer nothing on the Java/JNI side keeps alive. + return jni::JavaFactories::create(env, sender.release()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getReceiver (JNIEnv * env, jobject caller) { - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); + try { + webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); + CHECK_HANDLEV(transceiver, nullptr); - webrtc::scoped_refptr receiver = transceiver->receiver(); + webrtc::scoped_refptr receiver = transceiver->receiver(); - // Transfer the reference this local scoped_refptr holds into the Java - // wrapper, which owns and disposes it -- otherwise the wrapper would be - // left with a pointer nothing on the Java/JNI side keeps alive. - return jni::JavaFactories::create(env, receiver.release()).release(); + // Transfer the reference this local scoped_refptr holds into the Java + // wrapper, which owns and disposes it -- otherwise the wrapper would be + // left with a pointer nothing on the Java/JNI side keeps alive. + return jni::JavaFactories::create(env, receiver.release()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getDirection (JNIEnv * env, jobject caller) { - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); + try { + webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); + CHECK_HANDLEV(transceiver, nullptr); - return jni::JavaEnums::toJava(env, transceiver->direction()).release(); + return jni::JavaEnums::toJava(env, transceiver->direction()).release(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_setDirection (JNIEnv * env, jobject caller, jobject jDirection) { - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLE(transceiver); + try { + webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); + CHECK_HANDLE(transceiver); - webrtc::RTCError result = transceiver->SetDirectionWithError(jni::JavaEnums::toNative(env, jDirection)); + webrtc::RTCError result = transceiver->SetDirectionWithError(jni::JavaEnums::toNative(env, jDirection)); - if (!result.ok()) { - env->Throw(jni::JavaRuntimeException(env, "Set direction failed: %s %s", - ToString(result.type()), result.message())); + if (!result.ok()) { + env->Throw(jni::JavaRuntimeException(env, "Set direction failed: %s %s", + ToString(result.type()), result.message())); + } + } + catch (...) { + ThrowCxxJavaException(env); } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getCurrentDirection (JNIEnv * env, jobject caller) { - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); + try { + webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); + CHECK_HANDLEV(transceiver, nullptr); - auto directionOpt = transceiver->current_direction(); + auto directionOpt = transceiver->current_direction(); - if (!directionOpt.has_value()) { + if (!directionOpt.has_value()) { + return nullptr; + } + + return jni::JavaEnums::toJava(env, directionOpt.value()).release(); + } + catch (...) { + ThrowCxxJavaException(env); return nullptr; } - - return jni::JavaEnums::toJava(env, directionOpt.value()).release(); } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_stop @@ -129,12 +164,18 @@ JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_stopped JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getCodecPreferences (JNIEnv * env, jobject caller) { - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); + try { + webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); + CHECK_HANDLEV(transceiver, nullptr); - auto capabilities = jni::JavaList::toArrayList(env, transceiver->codec_preferences(), jni::RTCRtpCodecCapability::toJava); + auto capabilities = jni::JavaList::toArrayList(env, transceiver->codec_preferences(), jni::RTCRtpCodecCapability::toJava); - return capabilities.get(); + return capabilities.get(); + } + catch (...) { + ThrowCxxJavaException(env); + return nullptr; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_setCodecPreferences diff --git a/webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp b/webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp index faafdc51f..63ffcc021 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp @@ -23,9 +23,14 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_SyncClock_initialize (JNIEnv * env, jobject caller) { - jni::SyncClock * clock = new jni::SyncClock(); + try { + jni::SyncClock * clock = new jni::SyncClock(); - SetHandle(env, caller, clock); + SetHandle(env, caller, clock); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_SyncClock_getTimestampUs diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp index 11a684ed7..c7af93ead 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp @@ -16,6 +16,7 @@ #include "JNI_VideoBufferConverter.h" #include "JavaRuntimeException.h" +#include "JavaUtils.h" #include "api/video/i420_buffer.h" @@ -64,34 +65,39 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I (JNIEnv * env, jclass cls, jobject jSrcY, jint srcStrideY, jobject jSrcU, jint srcStrideU, jobject jSrcV, jint srcStrideV, jbyteArray dst, jint width, jint height, jint fourCC) { - jsize arrayLength = env->GetArrayLength(dst); - size_t requiredSize = CalcBufferSize(width, height, fourCC); + try { + jsize arrayLength = env->GetArrayLength(dst); + size_t requiredSize = CalcBufferSize(width, height, fourCC); - if (arrayLength < requiredSize) { - env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %d, need %zd]", - arrayLength, requiredSize)); - return; - } + if (arrayLength < requiredSize) { + env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %d, need %zd]", + arrayLength, requiredSize)); + return; + } - const uint8_t * srcY = static_cast(env->GetDirectBufferAddress(jSrcY)); - const uint8_t * srcU = static_cast(env->GetDirectBufferAddress(jSrcU)); - const uint8_t * srcV = static_cast(env->GetDirectBufferAddress(jSrcV)); + const uint8_t * srcY = static_cast(env->GetDirectBufferAddress(jSrcY)); + const uint8_t * srcU = static_cast(env->GetDirectBufferAddress(jSrcU)); + const uint8_t * srcV = static_cast(env->GetDirectBufferAddress(jSrcV)); - jbyte * arrayPtr = env->GetByteArrayElements(dst, nullptr); - uint8_t * dstPtr = reinterpret_cast(arrayPtr); + jbyte * arrayPtr = env->GetByteArrayElements(dst, nullptr); + uint8_t * dstPtr = reinterpret_cast(arrayPtr); + + const int conversionResult = libyuv::ConvertFromI420(srcY, srcStrideY, srcU, srcStrideU, + srcV, srcStrideV, dstPtr, 0, width, height, static_cast(fourCC)); - const int conversionResult = libyuv::ConvertFromI420(srcY, srcStrideY, srcU, srcStrideU, - srcV, srcStrideV, dstPtr, 0, width, height, static_cast(fourCC)); + if (conversionResult < 0) { + env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", + conversionResult)); + } + else { + env->SetByteArrayRegion(dst, 0, arrayLength, arrayPtr); + } - if (conversionResult < 0) { - env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", - conversionResult)); + env->ReleaseByteArrayElements(dst, arrayPtr, JNI_ABORT); } - else { - env->SetByteArrayRegion(dst, 0, arrayLength, arrayPtr); + catch (...) { + ThrowCxxJavaException(env); } - - env->ReleaseByteArrayElements(dst, arrayPtr, JNI_ABORT); } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I420toDirectBuffer @@ -131,36 +137,41 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_b (JNIEnv * env, jclass cls, jbyteArray src, jint width, jint height, jobject jDstY, jint dstStrideY, jobject jDstU, jint dstStrideU, jobject jDstV, jint dstStrideV, jint fourCC) { - jsize arrayLength = env->GetArrayLength(src); - size_t requiredSize = CalcBufferSize(width, height, fourCC); + try { + jsize arrayLength = env->GetArrayLength(src); + size_t requiredSize = CalcBufferSize(width, height, fourCC); - if (arrayLength < requiredSize) { - env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %d, need %zd]", - arrayLength, requiredSize)); - return; - } + if (arrayLength < requiredSize) { + env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %d, need %zd]", + arrayLength, requiredSize)); + return; + } - uint8_t * dstY = static_cast(env->GetDirectBufferAddress(jDstY)); - uint8_t * dstU = static_cast(env->GetDirectBufferAddress(jDstU)); - uint8_t * dstV = static_cast(env->GetDirectBufferAddress(jDstV)); + uint8_t * dstY = static_cast(env->GetDirectBufferAddress(jDstY)); + uint8_t * dstU = static_cast(env->GetDirectBufferAddress(jDstU)); + uint8_t * dstV = static_cast(env->GetDirectBufferAddress(jDstV)); - jbyte * arrayPtr = env->GetByteArrayElements(src, nullptr); - const uint8_t * srcPtr = reinterpret_cast(arrayPtr); + jbyte * arrayPtr = env->GetByteArrayElements(src, nullptr); + const uint8_t * srcPtr = reinterpret_cast(arrayPtr); + + const int conversionResult = libyuv::ConvertToI420( + srcPtr, arrayLength, + dstY, dstStrideY, + dstU, dstStrideU, + dstV, dstStrideV, + 0, 0, width, height, width, height, + libyuv::kRotate0, static_cast(fourCC)); - const int conversionResult = libyuv::ConvertToI420( - srcPtr, arrayLength, - dstY, dstStrideY, - dstU, dstStrideU, - dstV, dstStrideV, - 0, 0, width, height, width, height, - libyuv::kRotate0, static_cast(fourCC)); + if (conversionResult < 0) { + env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", + conversionResult)); + } - if (conversionResult < 0) { - env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", - conversionResult)); + env->ReleaseByteArrayElements(src, arrayPtr, JNI_ABORT); + } + catch (...) { + ThrowCxxJavaException(env); } - - env->ReleaseByteArrayElements(src, arrayPtr, JNI_ABORT); } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_directBufferToI420 diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp index 287c353ca..55c44f2db 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp @@ -30,17 +30,22 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureDevice (JNIEnv * env, jobject caller, jobject device) { - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null")); - return; - } + try { + if (!device) { + env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null")); + return; + } - jni::VideoCaptureBase * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); + jni::VideoCaptureBase * videoSource = GetHandle(env, caller); + CHECK_HANDLE(videoSource); - const auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef(env, device)); + const auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef(env, device)); - videoSource->setDevice(std::make_shared(dev.getName(), dev.getDescriptor())); + videoSource->setDevice(std::make_shared(dev.getName(), dev.getDescriptor())); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureCapability @@ -122,9 +127,14 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_dispose JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_initialize (JNIEnv * env, jobject caller) { -#ifdef __APPLE__ - SetHandle(env, caller, new jni::VideoCaptureMac()); -#else - SetHandle(env, caller, new jni::VideoCapture()); -#endif + try { + #ifdef __APPLE__ + SetHandle(env, caller, new jni::VideoCaptureMac()); + #else + SetHandle(env, caller, new jni::VideoCapture()); + #endif + } + catch (...) { + ThrowCxxJavaException(env); + } } \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp index 820328ba9..66160a5cd 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp @@ -32,22 +32,27 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_setVideoCaptureDevice (JNIEnv * env, jobject caller, jobject device) { - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null")); - return; - } + try { + if (!device) { + env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null")); + return; + } -#ifdef __APPLE__ - jni::VideoTrackDeviceSourceMac * videoSource = GetHandle(env, caller); -#else - jni::VideoTrackDeviceSource * videoSource = GetHandle(env, caller); -#endif + #ifdef __APPLE__ + jni::VideoTrackDeviceSourceMac * videoSource = GetHandle(env, caller); + #else + jni::VideoTrackDeviceSource * videoSource = GetHandle(env, caller); + #endif - CHECK_HANDLE(videoSource); + CHECK_HANDLE(videoSource); - const auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef(env, device)); + const auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef(env, device)); - videoSource->setVideoDevice(std::make_shared(dev.getName(), dev.getDescriptor())); + videoSource->setVideoDevice(std::make_shared(dev.getName(), dev.getDescriptor())); + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_setVideoCaptureCapability diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp index 95bc599f7..cfc2bf305 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp @@ -24,19 +24,25 @@ JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_video_VideoTrack_addSinkInternal (JNIEnv * env, jobject caller, jobject jsink) { - if (jsink == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "VideoTrackSink must not be null")); - return 0; - } + try { + if (jsink == nullptr) { + env->Throw(jni::JavaNullPointerException(env, "VideoTrackSink must not be null")); + return 0; + } - webrtc::VideoTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, 0); + webrtc::VideoTrackInterface * track = GetHandle(env, caller); + CHECK_HANDLEV(track, 0); - auto sink = new jni::VideoTrackSink(env, jni::JavaGlobalRef(env, jsink)); + auto sink = new jni::VideoTrackSink(env, jni::JavaGlobalRef(env, jsink)); - track->AddOrUpdateSink(sink, webrtc::VideoSinkWants()); + track->AddOrUpdateSink(sink, webrtc::VideoSinkWants()); - return reinterpret_cast(sink); + return reinterpret_cast(sink); + } + catch (...) { + ThrowCxxJavaException(env); + return 0; + } } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoTrack_removeSinkInternal From 3186e53cab9a3be9a762e98d26066bc044398652 Mon Sep 17 00:00:00 2001 From: Alex Andres Date: Thu, 22 Oct 2026 08:02:49 +0200 Subject: [PATCH 2/2] fix: check pinned arrays and frame lengths in the audio and video buffer natives Null results of GetByteArrayElements went unchecked, AudioProcessing leaked both arrays on its early return, and processStream read and wrote past arrays shorter than the configured frame; it now returns kBadDataLengthError for them. --- .../src/main/cpp/src/JNI_AudioConverter.cpp | 29 ++-- .../src/main/cpp/src/JNI_AudioProcessing.cpp | 156 +++++++----------- .../src/main/cpp/src/JNI_AudioResampler.cpp | 33 ++-- .../main/cpp/src/JNI_VideoBufferConverter.cpp | 30 ++-- .../media/audio/AudioProcessingTest.java | 14 ++ 5 files changed, 132 insertions(+), 130 deletions(-) diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp index 9ab11b28b..2db13ac3a 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp @@ -19,6 +19,8 @@ #include "media/audio/AudioConverter.h" #include "JavaUtils.h" +#include + JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_convertInternal (JNIEnv * env, jobject caller, jbyteArray src, jint nSrcSamples, jbyteArray dst, jint nDstSamples) { @@ -26,21 +28,24 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_convert jni::AudioConverter * converter = GetHandle(env, caller); CHECK_HANDLE(converter); - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(src, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(dst, &isDstCopy); - - converter->convert(reinterpret_cast(srcPtr), nSrcSamples, reinterpret_cast(dstPtr), nDstSamples); - - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dst); + auto releaseSrc = [env, src](jbyte * bytes) { + env->ReleaseByteArrayElements(src, bytes, JNI_ABORT); + }; + std::unique_ptr srcPtr(env->GetByteArrayElements(src, nullptr), releaseSrc); + if (!srcPtr) { + return; + } - env->SetByteArrayRegion(dst, 0, dstLength, dstPtr); + // Mode 0 writes the samples back when the VM handed out a copy. + auto releaseDst = [env, dst](jbyte * bytes) { + env->ReleaseByteArrayElements(dst, bytes, 0); + }; + std::unique_ptr dstPtr(env->GetByteArrayElements(dst, nullptr), releaseDst); + if (!dstPtr) { + return; } - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dst, dstPtr, JNI_ABORT); + converter->convert(reinterpret_cast(srcPtr.get()), nSrcSamples, reinterpret_cast(dstPtr.get()), nDstSamples); } catch (...) { ThrowCxxJavaException(env); diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp index b5f902537..3f7547b1c 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp @@ -35,6 +35,9 @@ #include "modules/audio_processing/include/audio_processing.h" #include "rtc_base/logging.h" +#include +#include + JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_applyConfig (JNIEnv * env, jobject caller, jobject config) { @@ -67,120 +70,87 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_getStr return apm->stream_delay_ms(); } -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processStream -(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest) +// Shared by processStream and processReverseStream, which differ only in the +// direction they feed the audio processing module. +static jint processFrame(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, + jobject outputConfig, jbyteArray dest, bool reverse) { - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLEV(apm, 0); - - webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, inputConfig)); - webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, outputConfig)); - - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(src, NULL); - jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy); - - const int16_t * srcFrame = reinterpret_cast(srcPtr); - int16_t * dstFrame = reinterpret_cast(dstPtr); + try { + webrtc::AudioProcessing * apm = GetHandle(env, caller); + CHECK_HANDLEV(apm, 0); - int result; + webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, inputConfig)); + webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, outputConfig)); - if (srcConfig.num_channels() == 1 && dstConfig.num_channels() == 2) { - // Up-mixing, only mono to stereo. + // Up-mixing, only mono to stereo, builds the stereo input in dest. // For complex channel layouts a channel mixer is required. - + const bool upMix = srcConfig.num_channels() == 1 && dstConfig.num_channels() == 2; const size_t srcNumSamples = srcConfig.num_samples(); const size_t dstNumChannels = dstConfig.num_channels(); - const size_t frameSize = srcNumSamples * dstNumChannels; + const size_t dstNumSamples = upMix + ? std::max(srcNumSamples * dstNumChannels, dstConfig.num_samples()) + : dstConfig.num_samples(); - if (frameSize > webrtc::AudioFrame::kMaxDataSizeSamples) { - return -9; + if (upMix && srcNumSamples * dstNumChannels > webrtc::AudioFrame::kMaxDataSizeSamples) { + return webrtc::AudioProcessing::kBadNumberChannelsError; } - - for (int i = static_cast(srcNumSamples) - 1; i >= 0; i--) { - for (size_t j = 0; j < dstNumChannels; ++j) { - dstFrame[dstNumChannels * i + j] = srcFrame[i]; - } + if (static_cast(env->GetArrayLength(src)) < srcNumSamples * sizeof(int16_t) || + static_cast(env->GetArrayLength(dest)) < dstNumSamples * sizeof(int16_t)) { + return webrtc::AudioProcessing::kBadDataLengthError; } - srcConfig.set_num_channels(dstNumChannels); - - result = apm->ProcessStream(dstFrame, srcConfig, dstConfig, dstFrame); - } - else { - // Will also down-mix if required, e.g. from stereo to mono. - result = apm->ProcessStream(srcFrame, srcConfig, dstConfig, dstFrame); - } - - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dest); - - env->SetByteArrayRegion(dest, 0, dstLength, dstPtr); - } - - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dest, dstPtr, JNI_ABORT); - - return result; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processReverseStream -(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLEV(apm, 0); - - webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, inputConfig)); - webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, outputConfig)); - - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(src, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy); - - const int16_t * srcFrame = reinterpret_cast(srcPtr); - int16_t * dstFrame = reinterpret_cast(dstPtr); - - int result; - - if (srcConfig.num_channels() == 1 && dstConfig.num_channels() == 2) { - // Up-mixing, only mono to stereo. - // For complex channel layouts a channel mixer is required. - - const size_t srcNumSamples = srcConfig.num_samples(); - const size_t dstNumChannels = dstConfig.num_channels(); - const size_t frameSize = srcNumSamples * dstNumChannels; + auto releaseSrc = [env, src](jbyte * bytes) { + env->ReleaseByteArrayElements(src, bytes, JNI_ABORT); + }; + std::unique_ptr srcPtr(env->GetByteArrayElements(src, nullptr), releaseSrc); + if (!srcPtr) { + return webrtc::AudioProcessing::kUnspecifiedError; + } - if (frameSize > webrtc::AudioFrame::kMaxDataSizeSamples) { - return -9; + // Mode 0 writes the samples back when the VM handed out a copy. + auto releaseDst = [env, dest](jbyte * bytes) { + env->ReleaseByteArrayElements(dest, bytes, 0); + }; + std::unique_ptr dstPtr(env->GetByteArrayElements(dest, nullptr), releaseDst); + if (!dstPtr) { + return webrtc::AudioProcessing::kUnspecifiedError; } - for (int i = static_cast(srcNumSamples) - 1; i >= 0; i--) { - for (size_t j = 0; j < dstNumChannels; ++j) { - dstFrame[dstNumChannels * i + j] = srcFrame[i]; + const int16_t * srcFrame = reinterpret_cast(srcPtr.get()); + int16_t * dstFrame = reinterpret_cast(dstPtr.get()); + + if (upMix) { + for (int i = static_cast(srcNumSamples) - 1; i >= 0; i--) { + for (size_t j = 0; j < dstNumChannels; ++j) { + dstFrame[dstNumChannels * i + j] = srcFrame[i]; + } } - } - srcConfig.set_num_channels(dstNumChannels); + srcConfig.set_num_channels(dstNumChannels); + srcFrame = dstFrame; + } - result = apm->ProcessReverseStream(dstFrame, srcConfig, dstConfig, dstFrame); - } - else { // Will also down-mix if required, e.g. from stereo to mono. - result = apm->ProcessReverseStream(srcFrame, srcConfig, dstConfig, dstFrame); + return reverse + ? apm->ProcessReverseStream(srcFrame, srcConfig, dstConfig, dstFrame) + : apm->ProcessStream(srcFrame, srcConfig, dstConfig, dstFrame); } - - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dest); - - env->SetByteArrayRegion(dest, 0, dstLength, dstPtr); + catch (...) { + ThrowCxxJavaException(env); + return webrtc::AudioProcessing::kUnspecifiedError; } +} - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dest, dstPtr, JNI_ABORT); +JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processStream +(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest) +{ + return processFrame(env, caller, src, inputConfig, outputConfig, dest, false); +} - return result; +JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processReverseStream +(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest) +{ + return processFrame(env, caller, src, inputConfig, outputConfig, dest, true); } JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_dispose diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp index 6eece0e45..8322a6345 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp @@ -22,6 +22,8 @@ #include "common_audio/resampler/include/push_resampler.h" +#include + JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_dispose (JNIEnv * env, jobject caller) { @@ -66,28 +68,31 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_resampl webrtc::PushResampler * resampler = GetHandle>(env, caller); CHECK_HANDLEV(resampler, -1); - jboolean isDstCopy = JNI_FALSE; + auto releaseSrc = [env, samplesIn](jbyte * bytes) { + env->ReleaseByteArrayElements(samplesIn, bytes, JNI_ABORT); + }; + std::unique_ptr srcPtr(env->GetByteArrayElements(samplesIn, nullptr), releaseSrc); + if (!srcPtr) { + return -1; + } - jbyte * srcPtr = env->GetByteArrayElements(samplesIn, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(samplesOut, &isDstCopy); + // Mode 0 writes the samples back when the VM handed out a copy. + auto releaseDst = [env, samplesOut](jbyte * bytes) { + env->ReleaseByteArrayElements(samplesOut, bytes, 0); + }; + std::unique_ptr dstPtr(env->GetByteArrayElements(samplesOut, nullptr), releaseDst); + if (!dstPtr) { + return -1; + } - int16_t * src16Ptr = reinterpret_cast(srcPtr); - int16_t * dst16Ptr = reinterpret_cast(dstPtr); + int16_t * src16Ptr = reinterpret_cast(srcPtr.get()); + int16_t * dst16Ptr = reinterpret_cast(dstPtr.get()); webrtc::InterleavedView src(src16Ptr, srcSamplesPerChannel, channels); webrtc::InterleavedView dst(dst16Ptr, dstSamplesPerChannel, channels); resampler->Resample(src, dst); - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(samplesOut); - - env->SetByteArrayRegion(samplesOut, 0, dstLength, dstPtr); - } - - env->ReleaseByteArrayElements(samplesIn, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(samplesOut, dstPtr, JNI_ABORT); - return static_cast(dstSamplesPerChannel); } catch (...) { diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp index c7af93ead..91af80794 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp @@ -23,6 +23,8 @@ #include "libyuv/convert.h" #include "libyuv/video_common.h" +#include + size_t CalcBufferSize(int width, int height, int fourCC) { size_t bufferSize = 0; @@ -79,8 +81,15 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I const uint8_t * srcU = static_cast(env->GetDirectBufferAddress(jSrcU)); const uint8_t * srcV = static_cast(env->GetDirectBufferAddress(jSrcV)); - jbyte * arrayPtr = env->GetByteArrayElements(dst, nullptr); - uint8_t * dstPtr = reinterpret_cast(arrayPtr); + // Mode 0 writes the picture back when the VM handed out a copy. + auto releaseArray = [env, dst](jbyte * bytes) { + env->ReleaseByteArrayElements(dst, bytes, 0); + }; + std::unique_ptr arrayPtr(env->GetByteArrayElements(dst, nullptr), releaseArray); + if (!arrayPtr) { + return; + } + uint8_t * dstPtr = reinterpret_cast(arrayPtr.get()); const int conversionResult = libyuv::ConvertFromI420(srcY, srcStrideY, srcU, srcStrideU, srcV, srcStrideV, dstPtr, 0, width, height, static_cast(fourCC)); @@ -89,11 +98,6 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", conversionResult)); } - else { - env->SetByteArrayRegion(dst, 0, arrayLength, arrayPtr); - } - - env->ReleaseByteArrayElements(dst, arrayPtr, JNI_ABORT); } catch (...) { ThrowCxxJavaException(env); @@ -151,8 +155,14 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_b uint8_t * dstU = static_cast(env->GetDirectBufferAddress(jDstU)); uint8_t * dstV = static_cast(env->GetDirectBufferAddress(jDstV)); - jbyte * arrayPtr = env->GetByteArrayElements(src, nullptr); - const uint8_t * srcPtr = reinterpret_cast(arrayPtr); + auto releaseArray = [env, src](jbyte * bytes) { + env->ReleaseByteArrayElements(src, bytes, JNI_ABORT); + }; + std::unique_ptr arrayPtr(env->GetByteArrayElements(src, nullptr), releaseArray); + if (!arrayPtr) { + return; + } + const uint8_t * srcPtr = reinterpret_cast(arrayPtr.get()); const int conversionResult = libyuv::ConvertToI420( srcPtr, arrayLength, @@ -166,8 +176,6 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_b env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", conversionResult)); } - - env->ReleaseByteArrayElements(src, arrayPtr, JNI_ABORT); } catch (...) { ThrowCxxJavaException(env); diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java index b5b19f016..46c5760ab 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java @@ -252,6 +252,20 @@ void processReverseStream() { assertEquals(0, processReverse(audioProcessing, buffer)); } + @Test + void processShortBuffersRejected() { + ProcessBuffer buffer = new ProcessBuffer(48000, 48000, 1, 2); + buffer.dst = new byte[buffer.dst.length - 2]; + + assertEquals(-8, process(audioProcessing, buffer)); + assertEquals(-8, processReverse(audioProcessing, buffer)); + + buffer = new ProcessBuffer(48000, 48000, 2, 2); + buffer.src = new byte[buffer.src.length - 2]; + + assertEquals(-8, process(audioProcessing, buffer)); + } + @Test void streamDelay() { int delay = 70;