blob: 5b7c092343bcb798de1a2a52766ef48e25a677ed [file] [log] [blame]
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include <jni.h>
#include "webrtc/examples/android/opensl_loopback/fake_audio_device_buffer.h"
#include "webrtc/modules/audio_device/android/audio_device_template.h"
#include "webrtc/modules/audio_device/android/audio_record_jni.h"
#include "webrtc/modules/audio_device/android/audio_track_jni.h"
#include "webrtc/modules/audio_device/android/opensles_input.h"
#include "webrtc/modules/audio_device/android/opensles_output.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
// Java globals
static JavaVM* g_vm = NULL;
static jclass g_osr = NULL;
namespace webrtc {
template <class InputType, class OutputType>
class OpenSlRunnerTemplate {
public:
OpenSlRunnerTemplate()
: output_(0),
input_(0, &output_) {
output_.AttachAudioBuffer(&audio_buffer_);
if (output_.Init() != 0) {
assert(false);
}
if (output_.InitPlayout() != 0) {
assert(false);
}
input_.AttachAudioBuffer(&audio_buffer_);
if (input_.Init() != 0) {
assert(false);
}
if (input_.InitRecording() != 0) {
assert(false);
}
}
~OpenSlRunnerTemplate() {}
void StartPlayRecord() {
output_.StartPlayout();
input_.StartRecording();
}
void StopPlayRecord() {
// There are large enough buffers to compensate for recording and playing
// jitter such that the timing of stopping playing or recording should not
// result in over or underrun.
input_.StopRecording();
output_.StopPlayout();
audio_buffer_.ClearBuffer();
}
private:
OutputType output_;
InputType input_;
FakeAudioDeviceBuffer audio_buffer_;
};
class OpenSlRunner
: public OpenSlRunnerTemplate<OpenSlesInput, OpenSlesOutput> {
public:
// Global class implementing native code.
static OpenSlRunner* g_runner;
OpenSlRunner() {}
virtual ~OpenSlRunner() {}
static JNIEXPORT void JNICALL RegisterApplicationContext(
JNIEnv* env,
jobject obj,
jobject context) {
assert(!g_runner); // Should only be called once.
OpenSlesInput::SetAndroidAudioDeviceObjects(g_vm, env, context);
OpenSlesOutput::SetAndroidAudioDeviceObjects(g_vm, env, context);
g_runner = new OpenSlRunner();
}
static JNIEXPORT void JNICALL Start(JNIEnv * env, jobject) {
g_runner->StartPlayRecord();
}
static JNIEXPORT void JNICALL Stop(JNIEnv * env, jobject) {
g_runner->StopPlayRecord();
}
};
OpenSlRunner* OpenSlRunner::g_runner = NULL;
} // namespace webrtc
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// Only called once.
assert(!g_vm);
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
jclass local_osr = env->FindClass("org/webrtc/app/OpenSlRunner");
assert(local_osr != NULL);
g_osr = static_cast<jclass>(env->NewGlobalRef(local_osr));
JNINativeMethod nativeFunctions[] = {
{"RegisterApplicationContext", "(Landroid/content/Context;)V",
reinterpret_cast<void*>(
&webrtc::OpenSlRunner::RegisterApplicationContext)},
{"Start", "()V", reinterpret_cast<void*>(&webrtc::OpenSlRunner::Start)},
{"Stop", "()V", reinterpret_cast<void*>(&webrtc::OpenSlRunner::Stop)}
};
int ret_val = env->RegisterNatives(g_osr, nativeFunctions, 3);
if (ret_val != 0) {
assert(false);
}
g_vm = vm;
return JNI_VERSION_1_6;
}