diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp index 47e1a336..2db13ac3 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp @@ -19,27 +19,37 @@ #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) { - jni::AudioConverter * converter = GetHandle(env, caller); - CHECK_HANDLE(converter); - - jboolean isDstCopy = JNI_FALSE; + try { + jni::AudioConverter * converter = GetHandle(env, caller); + CHECK_HANDLE(converter); - jbyte * srcPtr = env->GetByteArrayElements(src, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(dst, &isDstCopy); + auto releaseSrc = [env, src](jbyte * bytes) { + env->ReleaseByteArrayElements(src, bytes, JNI_ABORT); + }; + std::unique_ptr srcPtr(env->GetByteArrayElements(src, nullptr), releaseSrc); + if (!srcPtr) { + return; + } - converter->convert(reinterpret_cast(srcPtr), nSrcSamples, reinterpret_cast(dstPtr), nDstSamples); + // 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; + } - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dst); - - env->SetByteArrayRegion(dst, 0, dstLength, dstPtr); + converter->convert(reinterpret_cast(srcPtr.get()), nSrcSamples, reinterpret_cast(dstPtr.get()), nDstSamples); + } + catch (...) { + ThrowCxxJavaException(env); } - - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dst, dstPtr, JNI_ABORT); } 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 2528d252..5373f131 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 38b82567..a2aedc57 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 eb341b3e..3f7547b1 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp @@ -35,13 +35,21 @@ #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) { - 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 @@ -62,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); + try { + webrtc::AudioProcessing * apm = GetHandle(env, caller); + CHECK_HANDLEV(apm, 0); - const int16_t * srcFrame = reinterpret_cast(srcPtr); - int16_t * dstFrame = reinterpret_cast(dstPtr); + webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, inputConfig)); + webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, outputConfig)); - int result; - - 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 d85e8c0f..8322a634 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) { @@ -36,46 +38,65 @@ 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); - - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(samplesIn, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(samplesOut, &isDstCopy); - - int16_t * src16Ptr = reinterpret_cast(srcPtr); - int16_t * dst16Ptr = reinterpret_cast(dstPtr); - - 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); + try { + webrtc::PushResampler * resampler = GetHandle>(env, caller); + CHECK_HANDLEV(resampler, -1); + + 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; + } + + // 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.get()); + int16_t * dst16Ptr = reinterpret_cast(dstPtr.get()); + + webrtc::InterleavedView src(src16Ptr, srcSamplesPerChannel, channels); + webrtc::InterleavedView dst(dst16Ptr, dstSamplesPerChannel, channels); + + resampler->Resample(src, dst); + + return static_cast(dstSamplesPerChannel); + } + catch (...) { + ThrowCxxJavaException(env); + return 0; } - - env->ReleaseByteArrayElements(samplesIn, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(samplesOut, dstPtr, JNI_ABORT); - - return static_cast(dstSamplesPerChannel); } diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp index 81c75c96..c6bb1440 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 99ce8e1f..595a18e2 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 b23d1113..a075fee2 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 e1df6ed9..542bfb6c 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 3d44fad3..a7951c84 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 4a576298..72cc887a 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 dbdb7876..56823007 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 517f32b3..25231030 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 10fb32fc..3bcacfc4 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 91056b20..19c3c6fd 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 2cdcea0d..5b42f865 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 4d331dc9..24daf06c 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 8db7b672..2a0a157f 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 21550ef0..9330cd2e 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 4a8291b0..848cb440 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 ff29148f..03769f71 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 be116e24..19aa3480 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 faafdc51..63ffcc02 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 11a684ed..91af8079 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp @@ -16,12 +16,15 @@ #include "JNI_VideoBufferConverter.h" #include "JavaRuntimeException.h" +#include "JavaUtils.h" #include "api/video/i420_buffer.h" #include "libyuv/convert.h" #include "libyuv/video_common.h" +#include + size_t CalcBufferSize(int width, int height, int fourCC) { size_t bufferSize = 0; @@ -64,34 +67,41 @@ 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); + // 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)); + 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)); + if (conversionResult < 0) { + env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", + conversionResult)); + } } - 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 +141,45 @@ 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); + 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, - 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)); + } + } + 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 287c353c..55c44f2d 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 820328ba..66160a5c 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 95bc599f..cfc2bf30 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 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 b5b19f01..46c5760a 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;