Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,37 @@
#include "media/audio/AudioConverter.h"
#include "JavaUtils.h"

#include <memory>

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<jni::AudioConverter>(env, caller);
CHECK_HANDLE(converter);

jboolean isDstCopy = JNI_FALSE;
try {
jni::AudioConverter * converter = GetHandle<jni::AudioConverter>(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<jbyte, decltype(releaseSrc)> srcPtr(env->GetByteArrayElements(src, nullptr), releaseSrc);
if (!srcPtr) {
return;
}

converter->convert(reinterpret_cast<const int16_t *>(srcPtr), nSrcSamples, reinterpret_cast<int16_t *>(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<jbyte, decltype(releaseDst)> 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<const int16_t *>(srcPtr.get()), nSrcSamples, reinterpret_cast<int16_t *>(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
Expand Down
29 changes: 17 additions & 12 deletions webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<jni::WebRTCContext*>(javaContext);
auto audioLayer = jni::JavaEnums::toNative<webrtc::AudioDeviceModule::AudioLayer>(env, jAudioLayer);
try {
jni::WebRTCContext * context = static_cast<jni::WebRTCContext*>(javaContext);
auto audioLayer = jni::JavaEnums::toNative<webrtc::AudioDeviceModule::AudioLayer>(env, jAudioLayer);

webrtc::scoped_refptr<webrtc::AudioDeviceModule> audioModule = webrtc::CreateAudioDeviceModule(context->webrtcEnv, audioLayer);
webrtc::scoped_refptr<webrtc::AudioDeviceModule> 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);
}
}
206 changes: 120 additions & 86 deletions webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLEV(audioModule, nullptr);
try {
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(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<jni::avdev::AudioDevice>(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<jni::avdev::AudioDevice>(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<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLEV(audioModule, nullptr);
try {
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(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<jni::avdev::AudioDevice>(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<jni::avdev::AudioDevice>(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<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLE(audioModule);
try {
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(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<jobject>(env, device));
jni::JavaObject obj(env, jni::JavaLocalRef<jobject>(env, device));

const auto javaClass = jni::JavaClasses::get<jni::AudioDevice::JavaAudioDeviceClass>(env);
const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor));
const auto javaClass = jni::JavaClasses::get<jni::AudioDevice::JavaAudioDeviceClass>(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<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLE(audioModule);
try {
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(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<jobject>(env, device));
jni::JavaObject obj(env, jni::JavaLocalRef<jobject>(env, device));

const auto javaClass = jni::JavaClasses::get<jni::AudioDevice::JavaAudioDeviceClass>(env);
const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor));
const auto javaClass = jni::JavaClasses::get<jni::AudioDevice::JavaAudioDeviceClass>(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);
}
}

Expand Down Expand Up @@ -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<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLEV(audioModule, 0);
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLEV(audioModule, 0);

auto sink = new jni::AudioTransportSink(env, jni::JavaGlobalRef<jobject>(env, jSink));
auto sink = new jni::AudioTransportSink(env, jni::JavaGlobalRef<jobject>(env, jSink));

audioModule->RegisterAudioCallback(sink);
audioModule->RegisterAudioCallback(sink);

return reinterpret_cast<jlong>(sink);
return reinterpret_cast<jlong>(sink);
}
catch (...) {
ThrowCxxJavaException(env);
return 0;
}
}

JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSinkInternal
Expand All @@ -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<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLEV(audioModule, 0);
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);
CHECK_HANDLEV(audioModule, 0);

auto source = new jni::AudioTransportSource(env, jni::JavaGlobalRef<jobject>(env, jSource));
auto source = new jni::AudioTransportSource(env, jni::JavaGlobalRef<jobject>(env, jSource));

audioModule->RegisterAudioCallback(source);
audioModule->RegisterAudioCallback(source);

return reinterpret_cast<jlong>(source);
return reinterpret_cast<jlong>(source);
}
catch (...) {
ThrowCxxJavaException(env);
return 0;
}
}

JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSourceInternal
Expand Down
Loading
Loading