Home | History | Annotate | Download | only in jni
      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
     23 static JavaVM* g_vm = NULL;
     24 static jclass g_osr = NULL;
     25 
     26 namespace webrtc {
     27 
     28 template <class InputType, class OutputType>
     29 class 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 
     72 class 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 
    101 OpenSlRunner* OpenSlRunner::g_runner = NULL;
    102 
    103 }  // namespace webrtc
    104 
    105 jint 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