Skip to content

Commit 8b33c7c

Browse files
committed
Introduced AudioSink and AudioSource interfaces which can be passed to the AudioDeviceModule
1 parent 68a61b9 commit 8b33c7c

File tree

13 files changed

+589
-71
lines changed

13 files changed

+589
-71
lines changed

webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModule.h

Lines changed: 34 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2021 Alex Andres
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef JNI_WEBRTC_API_AUDIO_TRANSPORT_SINK_H_
18+
#define JNI_WEBRTC_API_AUDIO_TRANSPORT_SINK_H_
19+
20+
#include "JavaClass.h"
21+
#include "JavaRef.h"
22+
23+
#include "AudioSink.h"
24+
25+
#include <jni.h>
26+
27+
namespace jni
28+
{
29+
class AudioTransportSink : public AudioSink
30+
{
31+
public:
32+
AudioTransportSink(JNIEnv * env, const JavaGlobalRef<jobject> & sink);
33+
~AudioTransportSink() = default;
34+
35+
// AudioTransport implementation.
36+
int32_t RecordedDataIsAvailable(
37+
const void * audioSamples,
38+
const size_t nSamples,
39+
const size_t nBytesPerSample,
40+
const size_t nChannels,
41+
const uint32_t samplesPerSec,
42+
const uint32_t totalDelayMS,
43+
const int32_t clockDrift,
44+
const uint32_t currentMicLevel,
45+
const bool keyPressed,
46+
uint32_t & newMicLevel) override;
47+
48+
private:
49+
class JavaAudioSinkClass : public JavaClass
50+
{
51+
public:
52+
explicit JavaAudioSinkClass(JNIEnv * env);
53+
54+
jmethodID onRecordedData;
55+
};
56+
57+
private:
58+
JavaGlobalRef<jobject> sink;
59+
60+
const std::shared_ptr<JavaAudioSinkClass> javaClass;
61+
};
62+
}
63+
64+
#endif
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2021 Alex Andres
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef JNI_WEBRTC_API_AUDIO_TRANSPORT_SOURCE_H_
18+
#define JNI_WEBRTC_API_AUDIO_TRANSPORT_SOURCE_H_
19+
20+
#include "JavaClass.h"
21+
#include "JavaRef.h"
22+
23+
#include "AudioSource.h"
24+
25+
#include <jni.h>
26+
27+
namespace jni
28+
{
29+
class AudioTransportSource : public AudioSource
30+
{
31+
public:
32+
AudioTransportSource(JNIEnv * env, const JavaGlobalRef<jobject> & sink);
33+
~AudioTransportSource() = default;
34+
35+
// AudioTransport implementation.
36+
int32_t NeedMorePlayData(
37+
const size_t nSamples,
38+
const size_t nBytesPerSample,
39+
const size_t nChannels,
40+
const uint32_t samplesPerSec,
41+
void * audioSamples,
42+
size_t & nSamplesOut,
43+
int64_t * elapsed_time_ms,
44+
int64_t * ntp_time_ms) override;
45+
46+
private:
47+
class JavaAudioSourceClass : public JavaClass
48+
{
49+
public:
50+
explicit JavaAudioSourceClass(JNIEnv * env);
51+
52+
jmethodID onPlaybackData;
53+
};
54+
55+
private:
56+
JavaGlobalRef<jobject> source;
57+
58+
const std::shared_ptr<JavaAudioSourceClass> javaClass;
59+
};
60+
}
61+
62+
#endif

webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "JavaString.h"
2525
#include "JavaUtils.h"
2626
#include "media/audio/AudioDevice.h"
27+
#include "media/audio/AudioTransportSink.h"
28+
#include "media/audio/AudioTransportSource.h"
2729

2830
#include "api/scoped_refptr.h"
2931
#include "api/task_queue/default_task_queue_factory.h"
@@ -127,7 +129,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_g
127129
}
128130

129131
JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_getRecordingDevices
130-
(JNIEnv* env, jobject caller)
132+
(JNIEnv * env, jobject caller)
131133
{
132134
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);
133135
CHECK_HANDLEV(audioModule, nullptr);
@@ -380,7 +382,73 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_setM
380382
}
381383
}
382384

383-
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_dispose
385+
JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_addSinkInternal
386+
(JNIEnv * env, jobject caller, jobject jSink)
387+
{
388+
if (jSink == nullptr) {
389+
env->Throw(jni::JavaNullPointerException(env, "AudioSink must not be null"));
390+
return 0;
391+
}
392+
393+
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);
394+
CHECK_HANDLEV(audioModule, 0);
395+
396+
auto sink = new jni::AudioTransportSink(env, jni::JavaGlobalRef<jobject>(env, jSink));
397+
398+
audioModule->RegisterAudioCallback(sink);
399+
400+
return reinterpret_cast<jlong>(sink);
401+
}
402+
403+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_removeSinkInternal
404+
(JNIEnv * env, jobject caller, jlong sinkHandle)
405+
{
406+
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);
407+
CHECK_HANDLE(audioModule);
408+
409+
auto sink = reinterpret_cast<jni::AudioTransportSink *>(sinkHandle);
410+
411+
if (sink != nullptr) {
412+
audioModule->RegisterAudioCallback(nullptr);
413+
414+
delete sink;
415+
}
416+
}
417+
418+
JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_addSourceInternal
419+
(JNIEnv * env, jobject caller, jobject jSource)
420+
{
421+
if (jSource == nullptr) {
422+
env->Throw(jni::JavaNullPointerException(env, "AudioSource must not be null"));
423+
return 0;
424+
}
425+
426+
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);
427+
CHECK_HANDLEV(audioModule, 0);
428+
429+
auto source = new jni::AudioTransportSource(env, jni::JavaGlobalRef<jobject>(env, jSource));
430+
431+
audioModule->RegisterAudioCallback(source);
432+
433+
return reinterpret_cast<jlong>(source);
434+
}
435+
436+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_removeSourceInternal
437+
(JNIEnv * env, jobject caller, jlong sourceHandle)
438+
{
439+
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);
440+
CHECK_HANDLE(audioModule);
441+
442+
auto source = reinterpret_cast<jni::AudioTransportSource *>(sourceHandle);
443+
444+
if (source != nullptr) {
445+
audioModule->RegisterAudioCallback(nullptr);
446+
447+
delete source;
448+
}
449+
}
450+
451+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_disposeInternal
384452
(JNIEnv * env, jobject caller)
385453
{
386454
webrtc::AudioDeviceModule * audioModule = GetHandle<webrtc::AudioDeviceModule>(env, caller);

webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp

Lines changed: 24 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,82 +40,58 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_applyC
4040
apm->ApplyConfig(jni::AudioProcessingConfig::toNative(env, jni::JavaLocalRef<jobject>(env, config)));
4141
}
4242

43-
JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_ProcessStream___3SLdev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2Ldev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2_3S
44-
(JNIEnv * env, jobject caller, jshortArray src, jobject inputConfig, jobject outputConfig, jshortArray dest)
43+
JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processStream___3BLdev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2Ldev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2_3B
44+
(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest)
4545
{
4646
webrtc::AudioProcessing * apm = GetHandle<webrtc::AudioProcessing>(env, caller);
4747
CHECK_HANDLEV(apm, 0);
4848

4949
webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, inputConfig));
5050
webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, outputConfig));
5151

52-
jshort * srcPtr = env->GetShortArrayElements(src, nullptr);
53-
jshort * dstPtr = env->GetShortArrayElements(dest, nullptr);
52+
jboolean isDstCopy = JNI_FALSE;
5453

55-
int result = apm->ProcessStream(srcPtr, srcConfig, dstConfig, dstPtr);
54+
jbyte * srcPtr = env->GetByteArrayElements(src, nullptr);
55+
jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy);
5656

57-
env->ReleaseShortArrayElements(src, srcPtr, JNI_ABORT);
58-
env->ReleaseShortArrayElements(dest, dstPtr, JNI_ABORT);
57+
int result = apm->ProcessStream(reinterpret_cast<int16_t *>(srcPtr), srcConfig, dstConfig, reinterpret_cast<int16_t *>(dstPtr));
5958

60-
return result;
61-
}
62-
63-
JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_ProcessStream___3FLdev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2Ldev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2_3F
64-
(JNIEnv * env, jobject caller, jfloatArray src, jobject inputConfig, jobject outputConfig, jfloatArray dest)
65-
{
66-
webrtc::AudioProcessing* apm = GetHandle<webrtc::AudioProcessing>(env, caller);
67-
CHECK_HANDLEV(apm, 0);
59+
if (isDstCopy == JNI_TRUE) {
60+
jsize dstLength = env->GetArrayLength(dest);
6861

69-
webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, inputConfig));
70-
webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, outputConfig));
71-
72-
jfloat * srcPtr = env->GetFloatArrayElements(src, nullptr);
73-
jfloat * dstPtr = env->GetFloatArrayElements(dest, nullptr);
74-
75-
int result = apm->ProcessStream(reinterpret_cast<float**>(srcPtr), srcConfig, dstConfig, reinterpret_cast<float**>(dstPtr));
62+
env->SetByteArrayRegion(dest, 0, dstLength, dstPtr);
63+
}
7664

77-
env->ReleaseFloatArrayElements(src, srcPtr, JNI_ABORT);
78-
env->ReleaseFloatArrayElements(dest, dstPtr, JNI_ABORT);
65+
env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT);
66+
env->ReleaseByteArrayElements(dest, dstPtr, JNI_ABORT);
7967

8068
return result;
8169
}
8270

83-
JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_ProcessReverseStream___3SLdev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2Ldev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2_3S
84-
(JNIEnv * env, jobject caller, jshortArray src, jobject inputConfig, jobject outputConfig, jshortArray dest)
71+
JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processReverseStream___3BLdev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2Ldev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2_3B
72+
(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest)
8573
{
8674
webrtc::AudioProcessing * apm = GetHandle<webrtc::AudioProcessing>(env, caller);
8775
CHECK_HANDLEV(apm, 0);
8876

8977
webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, inputConfig));
9078
webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, outputConfig));
9179

92-
jshort * srcPtr = env->GetShortArrayElements(src, nullptr);
93-
jshort * dstPtr = env->GetShortArrayElements(dest, nullptr);
80+
jboolean isDstCopy = JNI_FALSE;
9481

95-
int result = apm->ProcessReverseStream(srcPtr, srcConfig, dstConfig, dstPtr);
82+
jbyte * srcPtr = env->GetByteArrayElements(src, nullptr);
83+
jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy);
9684

97-
env->ReleaseShortArrayElements(src, srcPtr, JNI_ABORT);
98-
env->ReleaseShortArrayElements(dest, dstPtr, JNI_ABORT);
85+
int result = apm->ProcessReverseStream(reinterpret_cast<int16_t *>(srcPtr), srcConfig, dstConfig, reinterpret_cast<int16_t *>(dstPtr));
9986

100-
return result;
101-
}
102-
103-
JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_ProcessReverseStream___3FLdev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2Ldev_onvoid_webrtc_media_audio_AudioProcessingStreamConfig_2_3F
104-
(JNIEnv * env, jobject caller, jfloatArray src, jobject inputConfig, jobject outputConfig, jfloatArray dest)
105-
{
106-
webrtc::AudioProcessing* apm = GetHandle<webrtc::AudioProcessing>(env, caller);
107-
CHECK_HANDLEV(apm, 0);
87+
if (isDstCopy == JNI_TRUE) {
88+
jsize dstLength = env->GetArrayLength(dest);
10889

109-
webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, inputConfig));
110-
webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef<jobject>(env, outputConfig));
111-
112-
jfloat * srcPtr = env->GetFloatArrayElements(src, nullptr);
113-
jfloat * dstPtr = env->GetFloatArrayElements(dest, nullptr);
114-
115-
int result = apm->ProcessStream(reinterpret_cast<float**>(srcPtr), srcConfig, dstConfig, reinterpret_cast<float**>(dstPtr));
90+
env->SetByteArrayRegion(dest, 0, dstLength, dstPtr);
91+
}
11692

117-
env->ReleaseFloatArrayElements(src, srcPtr, JNI_ABORT);
118-
env->ReleaseFloatArrayElements(dest, dstPtr, JNI_ABORT);
93+
env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT);
94+
env->ReleaseByteArrayElements(dest, dstPtr, JNI_ABORT);
11995

12096
return result;
12197
}

0 commit comments

Comments
 (0)