1/* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include <assert.h> 12#include <jni.h> 13 14#include "webrtc/examples/android/opensl_loopback/fake_audio_device_buffer.h" 15#include "webrtc/modules/audio_device/android/audio_device_template.h" 16#include "webrtc/modules/audio_device/android/audio_record_jni.h" 17#include "webrtc/modules/audio_device/android/audio_track_jni.h" 18#include "webrtc/modules/audio_device/android/opensles_input.h" 19#include "webrtc/modules/audio_device/android/opensles_output.h" 20#include "webrtc/system_wrappers/interface/scoped_ptr.h" 21 22// Java globals 23static JavaVM* g_vm = NULL; 24static jclass g_osr = NULL; 25 26namespace webrtc { 27 28template <class InputType, class OutputType> 29class OpenSlRunnerTemplate { 30 public: 31 OpenSlRunnerTemplate() 32 : output_(0), 33 input_(0, &output_) { 34 output_.AttachAudioBuffer(&audio_buffer_); 35 if (output_.Init() != 0) { 36 assert(false); 37 } 38 if (output_.InitPlayout() != 0) { 39 assert(false); 40 } 41 input_.AttachAudioBuffer(&audio_buffer_); 42 if (input_.Init() != 0) { 43 assert(false); 44 } 45 if (input_.InitRecording() != 0) { 46 assert(false); 47 } 48 } 49 50 ~OpenSlRunnerTemplate() {} 51 52 void StartPlayRecord() { 53 output_.StartPlayout(); 54 input_.StartRecording(); 55 } 56 57 void StopPlayRecord() { 58 // There are large enough buffers to compensate for recording and playing 59 // jitter such that the timing of stopping playing or recording should not 60 // result in over or underrun. 61 input_.StopRecording(); 62 output_.StopPlayout(); 63 audio_buffer_.ClearBuffer(); 64 } 65 66 private: 67 OutputType output_; 68 InputType input_; 69 FakeAudioDeviceBuffer audio_buffer_; 70}; 71 72class OpenSlRunner 73 : public OpenSlRunnerTemplate<OpenSlesInput, OpenSlesOutput> { 74 public: 75 // Global class implementing native code. 76 static OpenSlRunner* g_runner; 77 78 79 OpenSlRunner() {} 80 virtual ~OpenSlRunner() {} 81 82 static JNIEXPORT void JNICALL RegisterApplicationContext( 83 JNIEnv* env, 84 jobject obj, 85 jobject context) { 86 assert(!g_runner); // Should only be called once. 87 OpenSlesInput::SetAndroidAudioDeviceObjects(g_vm, env, context); 88 OpenSlesOutput::SetAndroidAudioDeviceObjects(g_vm, env, context); 89 g_runner = new OpenSlRunner(); 90 } 91 92 static JNIEXPORT void JNICALL Start(JNIEnv * env, jobject) { 93 g_runner->StartPlayRecord(); 94 } 95 96 static JNIEXPORT void JNICALL Stop(JNIEnv * env, jobject) { 97 g_runner->StopPlayRecord(); 98 } 99}; 100 101OpenSlRunner* OpenSlRunner::g_runner = NULL; 102 103} // namespace webrtc 104 105jint JNI_OnLoad(JavaVM* vm, void* reserved) { 106 // Only called once. 107 assert(!g_vm); 108 JNIEnv* env; 109 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 110 return -1; 111 } 112 113 jclass local_osr = env->FindClass("org/webrtc/app/OpenSlRunner"); 114 assert(local_osr != NULL); 115 g_osr = static_cast<jclass>(env->NewGlobalRef(local_osr)); 116 JNINativeMethod nativeFunctions[] = { 117 {"RegisterApplicationContext", "(Landroid/content/Context;)V", 118 reinterpret_cast<void*>( 119 &webrtc::OpenSlRunner::RegisterApplicationContext)}, 120 {"Start", "()V", reinterpret_cast<void*>(&webrtc::OpenSlRunner::Start)}, 121 {"Stop", "()V", reinterpret_cast<void*>(&webrtc::OpenSlRunner::Stop)} 122 }; 123 int ret_val = env->RegisterNatives(g_osr, nativeFunctions, 3); 124 if (ret_val != 0) { 125 assert(false); 126 } 127 g_vm = vm; 128 return JNI_VERSION_1_6; 129} 130