127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org/*
227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *
427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org */
1027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
1127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org/*
1227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org *  Android audio device implementation (JNI/AudioRecord usage)
1327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org */
1427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
1527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org// TODO(xians): Break out attach and detach current thread to JVM to
1627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org// separate functions.
1727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
1827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include "webrtc/modules/audio_device/android/audio_record_jni.h"
1927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
2027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include <android/log.h>
2127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include <stdlib.h>
2227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
2327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include "webrtc/modules/audio_device/android/audio_common.h"
2427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include "webrtc/modules/audio_device/audio_device_config.h"
2527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include "webrtc/modules/audio_device/audio_device_utility.h"
2627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
2727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h"
2827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include "webrtc/system_wrappers/interface/thread_wrapper.h"
2927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
3027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
3127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgnamespace webrtc {
3227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
3327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgJavaVM* AudioRecordJni::globalJvm = NULL;
3427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgJNIEnv* AudioRecordJni::globalJNIEnv = NULL;
3527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgjobject AudioRecordJni::globalContext = NULL;
3627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgjclass AudioRecordJni::globalScClass = NULL;
3727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
3827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetAndroidAudioDeviceObjects(void* javaVM, void* env,
3927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                                     void* context) {
40f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  assert(env);
4127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  globalJvm = reinterpret_cast<JavaVM*>(javaVM);
42f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalJNIEnv = reinterpret_cast<JNIEnv*>(env);
43f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  // Get java class type (note path to class packet).
44f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  jclass javaScClassLocal = globalJNIEnv->FindClass(
45f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org      "org/webrtc/voiceengine/WebRtcAudioRecord");
46f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  if (!javaScClassLocal) {
47f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
48f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org                 "%s: could not find java class", __FUNCTION__);
49f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    return -1; // exception thrown
50f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  }
51f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org
52f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  // Create a global reference to the class (to tell JNI that we are
53f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  // referencing it after this function has returned).
54f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalScClass = reinterpret_cast<jclass> (
55f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org      globalJNIEnv->NewGlobalRef(javaScClassLocal));
56f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  if (!globalScClass) {
57f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
58f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org                 "%s: could not create reference", __FUNCTION__);
59f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    return -1;
60f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  }
6127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
62f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalContext = globalJNIEnv->NewGlobalRef(
63f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org      reinterpret_cast<jobject>(context));
64f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  if (!globalContext) {
65f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
66f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org                 "%s: could not create context reference", __FUNCTION__);
67f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    return -1;
6827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
6927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
70f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  // Delete local class ref, we only use the global ref
71f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalJNIEnv->DeleteLocalRef(javaScClassLocal);
7227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
73f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  return 0;
74f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org}
7527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
76f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.orgvoid AudioRecordJni::ClearAndroidAudioDeviceObjects() {
77f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, -1,
78f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org               "%s: env is NULL, assuming deinit", __FUNCTION__);
7927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
80f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalJvm = NULL;;
81f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  if (!globalJNIEnv) {
82f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, -1,
83f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org                 "%s: saved env already NULL", __FUNCTION__);
84f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org    return;
8527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
8627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
87f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalJNIEnv->DeleteGlobalRef(globalContext);
88f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalContext = reinterpret_cast<jobject>(NULL);
89f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org
90f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalJNIEnv->DeleteGlobalRef(globalScClass);
91f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalScClass = reinterpret_cast<jclass>(NULL);
92f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org
93f3a2ef39a9ba3d382916bcfb67c952781ab91df3henrike@webrtc.org  globalJNIEnv = reinterpret_cast<JNIEnv*>(NULL);
9427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
9527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
9627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgAudioRecordJni::AudioRecordJni(
9727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    const int32_t id, PlayoutDelayProvider* delay_provider)
9827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    : _javaVM(NULL),
9927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _jniEnvRec(NULL),
10027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _javaScClass(0),
10127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _javaScObj(0),
10227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _javaRecBuffer(0),
10327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _javaDirectRecBuffer(NULL),
10427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _javaMidRecAudio(0),
10527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _ptrAudioBuffer(NULL),
10627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
10727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _id(id),
10827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _delay_provider(delay_provider),
10927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _initialized(false),
11027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _timeEventRec(*EventWrapper::Create()),
11127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recStartStopEvent(*EventWrapper::Create()),
11227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _ptrThreadRec(NULL),
11327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recThreadID(0),
11427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recThreadIsInitialized(false),
11527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _shutdownRecThread(false),
11627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recordingDeviceIsSpecified(false),
11727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recording(false),
11827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recIsInitialized(false),
11927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _micIsInitialized(false),
12027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _startRec(false),
12127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recWarning(0),
12227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recError(0),
12327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _delayRecording(0),
12427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _AGC(false),
12527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _samplingFreqIn((N_REC_SAMPLES_PER_SEC/1000)),
12627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recAudioSource(1) { // 1 is AudioSource.MIC which is our default
12727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  memset(_recBuffer, 0, sizeof(_recBuffer));
12827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
12927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
13027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgAudioRecordJni::~AudioRecordJni() {
13127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id,
13227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "%s destroyed", __FUNCTION__);
13327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
13427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  Terminate();
13527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
13627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  delete &_recStartStopEvent;
13727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  delete &_timeEventRec;
13827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  delete &_critSect;
13927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
14027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
14127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::Init() {
14227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  CriticalSectionScoped lock(&_critSect);
14327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
14427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_initialized)
14527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
14627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return 0;
14727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
14827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
14927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recWarning = 0;
15027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recError = 0;
15127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
15227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Init Java member variables
15327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // and set up JNI interface to
15427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // AudioDeviceAndroid java class
15527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (InitJavaResources() != 0)
15627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
15727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
15827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: Failed to init Java resources", __FUNCTION__);
15927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
16027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
16127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
16227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Check the sample rate to be used for playback and recording
16327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // and the max playout volume
16427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (InitSampleRate() != 0)
16527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
16627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
16727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: Failed to init samplerate", __FUNCTION__);
16827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
16927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
17027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
17127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  const char* threadName = "jni_audio_capture_thread";
17227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _ptrThreadRec = ThreadWrapper::CreateThread(RecThreadFunc, this,
17327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                              kRealtimePriority, threadName);
17427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_ptrThreadRec == NULL)
17527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
17627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
17727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  failed to create the rec audio thread");
17827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
17927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
18027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
18127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  unsigned int threadID(0);
18227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_ptrThreadRec->Start(threadID))
18327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
18427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
18527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  failed to start the rec audio thread");
18627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    delete _ptrThreadRec;
18727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _ptrThreadRec = NULL;
18827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
18927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
19027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recThreadID = threadID;
19127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _initialized = true;
19227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
19327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
19427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
19527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
19627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::Terminate() {
19727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  CriticalSectionScoped lock(&_critSect);
19827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
19927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_initialized)
20027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
20127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return 0;
20227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
20327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
20427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  StopRecording();
20527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _shutdownRecThread = true;
20627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _timeEventRec.Set(); // Release rec thread from waiting state
20727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_ptrThreadRec)
20827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
20927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // First, the thread must detach itself from Java VM
21027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _critSect.Leave();
21127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (kEventSignaled != _recStartStopEvent.Wait(5000))
21227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
21327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(
21427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          kTraceError,
21527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          kTraceAudioDevice,
21627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          _id,
21727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          "%s: Recording thread shutdown timed out, cannot "
21827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          "terminate thread",
21927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          __FUNCTION__);
22027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // If we close thread anyway, the app will crash
22127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
22227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
22327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recStartStopEvent.Reset();
22427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _critSect.Enter();
22527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
22627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Close down rec thread
22727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    ThreadWrapper* tmpThread = _ptrThreadRec;
22827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _ptrThreadRec = NULL;
22927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _critSect.Leave();
23027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    tmpThread->SetNotAlive();
23127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Release again, we might have returned to waiting state
23227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _timeEventRec.Set();
23327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (tmpThread->Stop())
23427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
23527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      delete tmpThread;
23627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _jniEnvRec = NULL;
23727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
23827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    else
23927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
24027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
24127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "  failed to close down the rec audio thread");
24227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
24327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _critSect.Enter();
24427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
24527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recThreadIsInitialized = false;
24627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
24727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _micIsInitialized = false;
24827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recordingDeviceIsSpecified = false;
24927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
25027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
25127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  JNIEnv *env;
25227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  bool isAttached = false;
25327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
25427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
25527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_javaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
25627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
25727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // try to attach the thread and get the env
25827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Attach this thread to JVM
25927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint res = _javaVM->AttachCurrentThread(&env, NULL);
26027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if ((res < 0) || !env)
26127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
26227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
26327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: Could not attach thread to JVM (%d, %p)",
26427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   __FUNCTION__, res, env);
26527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
26627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
26727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    isAttached = true;
26827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
26927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
27027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Make method IDs and buffer pointers unusable
27127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaMidRecAudio = 0;
27227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaDirectRecBuffer = NULL;
27327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
27427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Delete the references to the java buffers, this allows the
27527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // garbage collector to delete them
27627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  env->DeleteGlobalRef(_javaRecBuffer);
27727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaRecBuffer = 0;
27827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
27927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Delete the references to the java object and class, this allows the
28027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // garbage collector to delete them
28127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  env->DeleteGlobalRef(_javaScObj);
28227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaScObj = 0;
28327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaScClass = 0;
28427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
28527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Detach this thread if it was attached
28627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (isAttached)
28727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
28827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_javaVM->DetachCurrentThread() < 0)
28927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
29027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
29127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: Could not detach thread from JVM", __FUNCTION__);
29227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
29327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
29427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
29527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _initialized = false;
29627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
29727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
29827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
29927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
30027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::RecordingDeviceName(uint16_t index,
30127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                            char name[kAdmMaxDeviceNameSize],
30227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                            char guid[kAdmMaxGuidSize]) {
30327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (0 != index)
30427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
30527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
30627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Device index is out of range [0,0]");
30727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
30827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
30927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
31027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Return empty string
31127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  memset(name, 0, kAdmMaxDeviceNameSize);
31227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
31327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (guid)
31427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
31527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    memset(guid, 0, kAdmMaxGuidSize);
31627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
31727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
31827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
31927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
32027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
32127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetRecordingDevice(uint16_t index) {
32227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_recIsInitialized)
32327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
32427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
32527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording already initialized");
32627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
32727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
32827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
32927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Recording device index will be used for specifying recording
33027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // audio source, allow any value
33127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recAudioSource = index;
33227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recordingDeviceIsSpecified = true;
33327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
33427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
33527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
33627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
33727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetRecordingDevice(
33827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    AudioDeviceModule::WindowsDeviceType device) {
33927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
34027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
34127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
34227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
34327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
34427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::RecordingIsAvailable(bool& available) {  // NOLINT
34527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  available = false;
34627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
34727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Try to initialize the playout side
34827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  int32_t res = InitRecording();
34927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
35027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Cancel effect of initialization
35127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  StopRecording();
35227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
35327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (res != -1)
35427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
35527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    available = true;
35627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
35727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
35827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return res;
35927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
36027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
36127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::InitRecording() {
36227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  CriticalSectionScoped lock(&_critSect);
36327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
36427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_initialized)
36527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
36627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
36727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Not initialized");
36827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
36927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
37027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
37127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_recording)
37227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
37327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
37427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording already started");
37527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
37627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
37727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
37827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_recordingDeviceIsSpecified)
37927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
38027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
38127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording device is not specified");
38227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
38327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
38427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
38527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_recIsInitialized)
38627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
38727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
38827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording already initialized");
38927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return 0;
39027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
39127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
39227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Initialize the microphone
39327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (InitMicrophone() == -1)
39427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
39527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
39627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  InitMicrophone() failed");
39727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
39827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
39927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
40027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  JNIEnv *env;
40127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  bool isAttached = false;
40227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
40327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
40427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_javaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
40527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
40627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // try to attach the thread and get the env
40727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Attach this thread to JVM
40827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint res = _javaVM->AttachCurrentThread(&env, NULL);
40927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if ((res < 0) || !env)
41027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
41127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
41227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "  Could not attach thread to JVM (%d, %p)", res, env);
41327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
41427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
41527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    isAttached = true;
41627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
41727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
41827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the method ID
41927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jmethodID initRecordingID = env->GetMethodID(_javaScClass, "InitRecording",
42027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                               "(II)I");
42127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
42227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  int samplingFreq = 44100;
42327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_samplingFreqIn != 44)
42427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
42527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    samplingFreq = _samplingFreqIn * 1000;
42627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
42727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
42827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  int retVal = -1;
42927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
43027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // call java sc object method
43127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jint res = env->CallIntMethod(_javaScObj, initRecordingID, _recAudioSource,
43227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                samplingFreq);
43327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (res < 0)
43427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
43527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
43627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "InitRecording failed (%d)", res);
43727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
43827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  else
43927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
44027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Set the audio device buffer sampling rate
44127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _ptrAudioBuffer->SetRecordingSampleRate(_samplingFreqIn * 1000);
44227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
44327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // the init rec function returns a fixed delay
44427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _delayRecording = res / _samplingFreqIn;
44527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
44627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recIsInitialized = true;
44727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    retVal = 0;
44827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
44927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
45027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Detach this thread if it was attached
45127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (isAttached)
45227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
45327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_javaVM->DetachCurrentThread() < 0)
45427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
45527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
45627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "  Could not detach thread from JVM");
45727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
45827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
45927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
46027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return retVal;
46127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
46227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
46327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::StartRecording() {
46427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  CriticalSectionScoped lock(&_critSect);
46527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
46627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_recIsInitialized)
46727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
46827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
46927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording not initialized");
47027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
47127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
47227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
47327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_recording)
47427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
47527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
47627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording already started");
47727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return 0;
47827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
47927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
48027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
48127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  JNIEnv *env;
48227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  bool isAttached = false;
48327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
48427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
48527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_javaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
48627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
48727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // try to attach the thread and get the env
48827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Attach this thread to JVM
48927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint res = _javaVM->AttachCurrentThread(&env, NULL);
49027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if ((res < 0) || !env)
49127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
49227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
49327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "  Could not attach thread to JVM (%d, %p)", res, env);
49427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
49527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
49627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    isAttached = true;
49727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
49827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
49927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the method ID
50027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jmethodID startRecordingID = env->GetMethodID(_javaScClass,
50127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                                "StartRecording", "()I");
50227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
50327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Call java sc object method
50427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jint res = env->CallIntMethod(_javaScObj, startRecordingID);
50527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (res < 0)
50627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
50727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
50827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "StartRecording failed (%d)", res);
50927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
51027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
51127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
51227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recWarning = 0;
51327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recError = 0;
51427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
51527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Signal to recording thread that we want to start
51627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _startRec = true;
51727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _timeEventRec.Set(); // Release thread from waiting state
51827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _critSect.Leave();
51927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Wait for thread to init
52027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (kEventSignaled != _recStartStopEvent.Wait(5000))
52127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
52227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
52327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Timeout or error starting");
52427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
52527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recStartStopEvent.Reset();
52627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _critSect.Enter();
52727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
52827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Detach this thread if it was attached
52927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (isAttached)
53027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
53127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_javaVM->DetachCurrentThread() < 0)
53227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
53327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
53427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "  Could not detach thread from JVM");
53527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
53627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
53727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
53827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
53927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
54027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
54127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
54227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::StopRecording() {
54327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  CriticalSectionScoped lock(&_critSect);
54427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
54527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_recIsInitialized)
54627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
54727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
54827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording is not initialized");
54927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return 0;
55027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
55127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
55227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // make sure we don't start recording (it's asynchronous),
55327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // assuming that we are under lock
55427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _startRec = false;
55527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
55627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
55727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  JNIEnv *env;
55827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  bool isAttached = false;
55927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
56027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
56127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_javaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
56227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
56327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // try to attach the thread and get the env
56427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Attach this thread to JVM
56527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint res = _javaVM->AttachCurrentThread(&env, NULL);
56627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if ((res < 0) || !env)
56727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
56827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
56927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "  Could not attach thread to JVM (%d, %p)", res, env);
57027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
57127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
57227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    isAttached = true;
57327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
57427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
57527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the method ID
57627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jmethodID stopRecordingID = env->GetMethodID(_javaScClass, "StopRecording",
57727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                               "()I");
57827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
57927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Call java sc object method
58027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jint res = env->CallIntMethod(_javaScObj, stopRecordingID);
58127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (res < 0)
58227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
58327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
58427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "StopRecording failed (%d)", res);
58527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
58627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
58727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recIsInitialized = false;
58827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recording = false;
58927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recWarning = 0;
59027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recError = 0;
59127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
59227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Detach this thread if it was attached
59327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (isAttached)
59427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
59527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_javaVM->DetachCurrentThread() < 0)
59627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
59727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
59827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "  Could not detach thread from JVM");
59927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
60027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
60127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
60227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
60327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
60427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
60527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
60627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetAGC(bool enable) {
60727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _AGC = enable;
60827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
60927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
61027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
61127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::InitMicrophone() {
61227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  CriticalSectionScoped lock(&_critSect);
61327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
61427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_recording)
61527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
61627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
61727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording already started");
61827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
61927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
62027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
62127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_recordingDeviceIsSpecified)
62227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
62327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
62427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Recording device is not specified");
62527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
62627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
62727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
62827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Nothing needs to be done here, we use a flag to have consistent
62927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // behavior with other platforms
63027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _micIsInitialized = true;
63127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
63227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
63327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
63427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
63527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MicrophoneVolumeIsAvailable(
63627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    bool& available) {  // NOLINT
63727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  available = false;  // Mic volume not supported on Android
63827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
63927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
64027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
64127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetMicrophoneVolume( uint32_t /*volume*/) {
64227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
64327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
64427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
64527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
64627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
64727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
64827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MicrophoneVolume(uint32_t& volume) const {  // NOLINT
64927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
65027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
65127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
65227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
65327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
65427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MaxMicrophoneVolume(
65527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    uint32_t& maxVolume) const {  // NOLINT
65627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
65727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
65827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
65927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
66027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
66127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MinMicrophoneVolume(
66227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    uint32_t& minVolume) const {  // NOLINT
66327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
66427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
66527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
66627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
66727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
66827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MicrophoneVolumeStepSize(
66927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    uint16_t& stepSize) const {
67027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
67127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
67227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
67327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
67427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
67527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MicrophoneMuteIsAvailable(bool& available) {  // NOLINT
67627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  available = false; // Mic mute not supported on Android
67727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
67827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
67927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
68027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetMicrophoneMute(bool enable) {
68127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
68227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
68327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
68427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
68527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
68627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MicrophoneMute(bool& enabled) const {  // NOLINT
68727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
68827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "  API call not supported on this platform");
68927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return -1;
69027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
69127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
69227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MicrophoneBoostIsAvailable(bool& available) {  // NOLINT
69327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  available = false; // Mic boost not supported on Android
69427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
69527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
69627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
69727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetMicrophoneBoost(bool enable) {
69827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_micIsInitialized)
69927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
70027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
70127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Microphone not initialized");
70227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
70327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
70427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
70527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (enable)
70627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
70727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
70827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Enabling not available");
70927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
71027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
71127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
71227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
71327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
71427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
71527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::MicrophoneBoost(bool& enabled) const {  // NOLINT
71627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_micIsInitialized)
71727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
71827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
71927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Microphone not initialized");
72027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
72127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
72227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
72327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  enabled = false;
72427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
72527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
72627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
72727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
72827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::StereoRecordingIsAvailable(bool& available) {  // NOLINT
72927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  available = false; // Stereo recording not supported on Android
73027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
73127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
73227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
73327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetStereoRecording(bool enable) {
73427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (enable)
73527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
73627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
73727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Enabling not available");
73827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
73927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
74027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
74127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
74227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
74327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
74427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::StereoRecording(bool& enabled) const {  // NOLINT
74527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  enabled = false;
74627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
74727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
74827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
74927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::RecordingDelay(uint16_t& delayMS) const {  // NOLINT
75027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  delayMS = _delayRecording;
75127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
75227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
75327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
75427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgbool AudioRecordJni::RecordingWarning() const {
75527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return (_recWarning > 0);
75627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
75727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
75827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgbool AudioRecordJni::RecordingError() const {
75927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return (_recError > 0);
76027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
76127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
76227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgvoid AudioRecordJni::ClearRecordingWarning() {
76327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recWarning = 0;
76427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
76527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
76627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgvoid AudioRecordJni::ClearRecordingError() {
76727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _recError = 0;
76827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
76927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
77027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgvoid AudioRecordJni::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {
77127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  CriticalSectionScoped lock(&_critSect);
77227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _ptrAudioBuffer = audioBuffer;
77327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // inform the AudioBuffer about default settings for this implementation
77427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _ptrAudioBuffer->SetRecordingSampleRate(N_REC_SAMPLES_PER_SEC);
77527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _ptrAudioBuffer->SetRecordingChannels(N_REC_CHANNELS);
77627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
77727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
77827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::SetRecordingSampleRate(const uint32_t samplesPerSec) {
77927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (samplesPerSec > 48000 || samplesPerSec < 8000)
78027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
78127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
78227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Invalid sample rate");
78327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
78427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
78527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
78627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // set the recording sample rate to use
78727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (samplesPerSec == 44100)
78827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
78927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _samplingFreqIn = 44;
79027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
79127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  else
79227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
79327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _samplingFreqIn = samplesPerSec / 1000;
79427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
79527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
79627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Update the AudioDeviceBuffer
79727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _ptrAudioBuffer->SetRecordingSampleRate(samplesPerSec);
79827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
79927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
80027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
80127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
80227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::InitJavaResources() {
80327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // todo: Check if we already have created the java object
80427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaVM = globalJvm;
80527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaScClass = globalScClass;
80627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
80727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // use the jvm that has been set
80827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_javaVM)
80927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
81027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
81127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: Not a valid Java VM pointer", __FUNCTION__);
81227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
81327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
81427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
81527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
81627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  JNIEnv *env;
81727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  bool isAttached = false;
81827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
81927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
82027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_javaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
82127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
82227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // try to attach the thread and get the env
82327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Attach this thread to JVM
82427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint res = _javaVM->AttachCurrentThread(&env, NULL);
82527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if ((res < 0) || !env)
82627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
82727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
82827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: Could not attach thread to JVM (%d, %p)",
82927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   __FUNCTION__, res, env);
83027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
83127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
83227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    isAttached = true;
83327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
83427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
83527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice, _id,
83627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "get method id");
83727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
83827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the method ID for the void(void) constructor
83927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jmethodID cid = env->GetMethodID(_javaScClass, "<init>", "()V");
84027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (cid == NULL)
84127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
84227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
84327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not get constructor ID", __FUNCTION__);
84427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1; /* exception thrown */
84527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
84627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
84727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice, _id,
84827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "construct object", __FUNCTION__);
84927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
85027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // construct the object
85127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jobject javaScObjLocal = env->NewObject(_javaScClass, cid);
85227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!javaScObjLocal)
85327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
85427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
85527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not create Java sc object", __FUNCTION__);
85627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
85727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
85827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
85927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Create a reference to the object (to tell JNI that we are referencing it
86027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // after this function has returned).
86127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaScObj = env->NewGlobalRef(javaScObjLocal);
86227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_javaScObj)
86327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
86427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
86527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not create Java sc object reference",
86627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 __FUNCTION__);
86727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
86827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
86927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
87027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Delete local object ref, we only use the global ref.
87127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  env->DeleteLocalRef(javaScObjLocal);
87227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
87327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  //////////////////////
87427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // AUDIO MANAGEMENT
87527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
87627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // This is not mandatory functionality
87727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (globalContext) {
87827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jfieldID context_id = env->GetFieldID(globalScClass,
87927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                          "_context",
88027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                          "Landroid/content/Context;");
88127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (!context_id) {
88227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
88327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: could not get _context id", __FUNCTION__);
88427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
88527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
88627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
88727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    env->SetObjectField(_javaScObj, context_id, globalContext);
88827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jobject javaContext = env->GetObjectField(_javaScObj, context_id);
88927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (!javaContext) {
89027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
89127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: could not set or get _context", __FUNCTION__);
89227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
89327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
89427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
89527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  else {
89627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
89727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: did not set Context - some functionality is not "
89827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "supported",
89927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 __FUNCTION__);
90027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
90127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
90227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Get rec buffer field ID.
90327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jfieldID fidRecBuffer = env->GetFieldID(_javaScClass, "_recBuffer",
90427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                          "Ljava/nio/ByteBuffer;");
90527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!fidRecBuffer)
90627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
90727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
90827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not get rec buffer fid", __FUNCTION__);
90927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
91027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
91127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
91227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Get rec buffer object.
91327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jobject javaRecBufferLocal = env->GetObjectField(_javaScObj, fidRecBuffer);
91427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!javaRecBufferLocal)
91527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
91627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
91727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not get rec buffer", __FUNCTION__);
91827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
91927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
92027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
92127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Create a global reference to the object (to tell JNI that we are
92227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // referencing it after this function has returned)
92327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // NOTE: we are referencing it only through the direct buffer (see below).
92427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaRecBuffer = env->NewGlobalRef(javaRecBufferLocal);
92527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_javaRecBuffer)
92627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
92727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
92827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not get rec buffer reference", __FUNCTION__);
92927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
93027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
93127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
93227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Delete local object ref, we only use the global ref.
93327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  env->DeleteLocalRef(javaRecBufferLocal);
93427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
93527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Get direct buffer.
93627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaDirectRecBuffer = env->GetDirectBufferAddress(_javaRecBuffer);
93727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_javaDirectRecBuffer)
93827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
93927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
94027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not get direct rec buffer", __FUNCTION__);
94127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
94227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
94327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
94427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Get the rec audio method ID.
94527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  _javaMidRecAudio = env->GetMethodID(_javaScClass, "RecordAudio", "(I)I");
94627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_javaMidRecAudio)
94727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
94827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
94927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "%s: could not get rec audio mid", __FUNCTION__);
95027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    return -1;
95127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
95227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
95327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Detach this thread if it was attached.
95427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (isAttached)
95527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
95627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_javaVM->DetachCurrentThread() < 0)
95727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
95827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
95927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: Could not detach thread from JVM", __FUNCTION__);
96027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
96127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
96227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
96327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
96427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
96527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
96627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
96727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgint32_t AudioRecordJni::InitSampleRate() {
96827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  int samplingFreq = 44100;
96927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jint res = 0;
97027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
97127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
97227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  JNIEnv *env;
97327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  bool isAttached = false;
97427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
97527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the JNI env for this thread
97627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_javaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
97727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
97827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // try to attach the thread and get the env
97927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Attach this thread to JVM
98027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint res = _javaVM->AttachCurrentThread(&env, NULL);
98127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if ((res < 0) || !env)
98227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
98327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
98427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: Could not attach thread to JVM (%d, %p)",
98527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   __FUNCTION__, res, env);
98627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return -1;
98727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
98827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    isAttached = true;
98927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
99027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
99127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_samplingFreqIn > 0)
99227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
99327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // read the configured sampling rate
99427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    samplingFreq = 44100;
99527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_samplingFreqIn != 44)
99627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
99727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      samplingFreq = _samplingFreqIn * 1000;
99827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
99927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
100027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "  Trying configured recording sampling rate %d",
100127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 samplingFreq);
100227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
100327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
100427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the method ID
100527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jmethodID initRecordingID = env->GetMethodID(_javaScClass, "InitRecording",
100627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                               "(II)I");
100727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
100827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  bool keepTrying = true;
100927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  while (keepTrying)
101027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
101127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // call java sc object method
101227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    res = env->CallIntMethod(_javaScObj, initRecordingID, _recAudioSource,
101327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                             samplingFreq);
101427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (res < 0)
101527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
101627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      switch (samplingFreq)
101727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      {
101827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        case 44100:
101927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          samplingFreq = 16000;
102027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          break;
102127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        case 16000:
102227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          samplingFreq = 8000;
102327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          break;
102427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        default: // error
102527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          WEBRTC_TRACE(kTraceError,
102627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                       kTraceAudioDevice, _id,
102727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                       "%s: InitRecording failed (%d)", __FUNCTION__,
102827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                       res);
102927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org          return -1;
103027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      }
103127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
103227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    else
103327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
103427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      keepTrying = false;
103527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
103627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
103727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
103827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // set the recording sample rate to use
103927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (samplingFreq == 44100)
104027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
104127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _samplingFreqIn = 44;
104227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
104327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  else
104427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
104527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _samplingFreqIn = samplingFreq / 1000;
104627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
104727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
104827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
104927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org               "Recording sample rate set to (%d)", _samplingFreqIn);
105027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
105127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // get the method ID
105227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  jmethodID stopRecordingID = env->GetMethodID(_javaScClass, "StopRecording",
105327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                               "()I");
105427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
105527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Call java sc object method
105627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  res = env->CallIntMethod(_javaScObj, stopRecordingID);
105727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (res < 0)
105827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
105927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
106027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "StopRecording failed (%d)", res);
106127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
106227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
106327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // Detach this thread if it was attached
106427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (isAttached)
106527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
106627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_javaVM->DetachCurrentThread() < 0)
106727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
106827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
106927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "%s: Could not detach thread from JVM", __FUNCTION__);
107027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
107127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
107227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
107327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return 0;
107427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
107527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
107627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgbool AudioRecordJni::RecThreadFunc(void* pThis)
107727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org{
107827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return (static_cast<AudioRecordJni*> (pThis)->RecThreadProcess());
107927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
108027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
108127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.orgbool AudioRecordJni::RecThreadProcess()
108227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org{
108327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_recThreadIsInitialized)
108427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
108527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Do once when thread is started
108627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
108727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Attach this thread to JVM
108827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint res = _javaVM->AttachCurrentThread(&_jniEnvRec, NULL);
108927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
109027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Get the JNI env for this thread
109127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if ((res < 0) || !_jniEnvRec)
109227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
109327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice,
109427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   _id, "Could not attach rec thread to JVM (%d, %p)",
109527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   res, _jniEnvRec);
109627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      return false; // Close down thread
109727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
109827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
109927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recThreadIsInitialized = true;
110027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
110127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
110227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  // just sleep if rec has not started
110327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (!_recording)
110427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
110527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    switch (_timeEventRec.Wait(1000))
110627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
110727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      case kEventSignaled:
110827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice,
110927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                     _id, "Recording thread event signal");
111027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        _timeEventRec.Reset();
111127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        break;
111227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      case kEventError:
111327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice,
111427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                     _id, "Recording thread event error");
111527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        return true;
111627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      case kEventTimeout:
111727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice,
111827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                     _id, "Recording thread event timeout");
111927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org        return true;
112027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
112127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
112227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
112327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  Lock();
112427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
112527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_startRec)
112627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
112727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
112827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "_startRec true, performing initial actions");
112927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _startRec = false;
113027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recording = true;
113127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recWarning = 0;
113227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recError = 0;
113327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    _recStartStopEvent.Set();
113427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
113527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
113627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_recording)
113727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
113827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    uint32_t samplesToRec = _samplingFreqIn * 10;
113927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
114027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Call java sc object method to record data to direct buffer
114127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Will block until data has been recorded (see java sc class),
114227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // therefore we must release the lock
114327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    UnLock();
114427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    jint recDelayInSamples = _jniEnvRec->CallIntMethod(_javaScObj,
114527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                                        _javaMidRecAudio,
114627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                                        2 * samplesToRec);
114727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (recDelayInSamples < 0)
114827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
114927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
115027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "RecordAudio failed");
115127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recWarning = 1;
115227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
115327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    else
115427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
115527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _delayRecording = recDelayInSamples / _samplingFreqIn;
115627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
115727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    Lock();
115827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
115927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Check again since recording may have stopped during Java call
116027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_recording)
116127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
116227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      //            WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice, _id,
116327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      //                         "total delay is %d", msPlayDelay + _delayRecording);
116427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
116527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // Copy data to our direct buffer (held by java sc object)
116627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // todo: Give _javaDirectRecBuffer directly to VoE?
116727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // todo: Check count <= 480 ?
116827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      memcpy(_recBuffer, _javaDirectRecBuffer, 2 * samplesToRec);
116927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
117027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // store the recorded buffer (no action will be taken if the
117127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // #recorded samples is not a full buffer)
117227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _ptrAudioBuffer->SetRecordedBuffer(_recBuffer, samplesToRec);
117327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
117427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // store vqe delay values
117527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _ptrAudioBuffer->SetVQEData(_delay_provider->PlayoutDelayMs(),
117627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                                  _delayRecording, 0);
117727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
117827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // deliver recorded samples at specified sample rate, mic level
117927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // etc. to the observer using callback
118027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      UnLock();
118127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _ptrAudioBuffer->DeliverRecordedData();
118227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      Lock();
118327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
118427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
118527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }  // _recording
118627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
118727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  if (_shutdownRecThread)
118827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  {
118927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice, _id,
119027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                 "Detaching rec thread from Java VM");
119127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
119227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    // Detach thread from Java VM
119327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    if (_javaVM->DetachCurrentThread() < 0)
119427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
119527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice,
119627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   _id, "Could not detach recording thread from JVM");
119727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _shutdownRecThread = false;
119827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // If we say OK (i.e. set event) and close thread anyway,
119927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      // app will crash
120027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
120127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    else
120227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    {
120327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _jniEnvRec = NULL;
120427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _shutdownRecThread = false;
120527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      _recStartStopEvent.Set(); // Signal to Terminate() that we are done
120627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
120727f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org      WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice, _id,
120827f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org                   "Sent signal rec");
120927f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org    }
121027f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  }
121127f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
121227f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  UnLock();
121327f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org  return true;
121427f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}
121527f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org
121627f08414780932bbd4bd0fa2bbf759787b9c2e03henrike@webrtc.org}  // namespace webrtc
1217