1 /* 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_OPENSLES_RECORDER_H_ 12 #define SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_OPENSLES_RECORDER_H_ 13 14 #include <SLES/OpenSLES.h> 15 #include <SLES/OpenSLES_Android.h> 16 #include <SLES/OpenSLES_AndroidConfiguration.h> 17 18 #include <memory> 19 20 #include "api/scoped_refptr.h" 21 #include "modules/audio_device/audio_device_buffer.h" 22 #include "modules/audio_device/fine_audio_buffer.h" 23 #include "modules/audio_device/include/audio_device_defines.h" 24 #include "rtc_base/thread_checker.h" 25 #include "sdk/android/src/jni/audio_device/audio_common.h" 26 #include "sdk/android/src/jni/audio_device/audio_device_module.h" 27 #include "sdk/android/src/jni/audio_device/opensles_common.h" 28 29 namespace webrtc { 30 31 class FineAudioBuffer; 32 33 namespace jni { 34 35 // Implements 16-bit mono PCM audio input support for Android using the 36 // C based OpenSL ES API. No calls from C/C++ to Java using JNI is done. 37 // 38 // An instance can be created on any thread, but must then be used on one and 39 // the same thread. All public methods must also be called on the same thread. A 40 // thread checker will RTC_DCHECK if any method is called on an invalid thread. 41 // Recorded audio buffers are provided on a dedicated internal thread managed by 42 // the OpenSL ES layer. 43 // 44 // The existing design forces the user to call InitRecording() after 45 // StopRecording() to be able to call StartRecording() again. This is inline 46 // with how the Java-based implementation works. 47 // 48 // As of API level 21, lower latency audio input is supported on select devices. 49 // To take advantage of this feature, first confirm that lower latency output is 50 // available. The capability for lower latency output is a prerequisite for the 51 // lower latency input feature. Then, create an AudioRecorder with the same 52 // sample rate and buffer size as would be used for output. OpenSL ES interfaces 53 // for input effects preclude the lower latency path. 54 // See https://developer.android.com/ndk/guides/audio/opensl-prog-notes.html 55 // for more details. 56 class OpenSLESRecorder : public AudioInput { 57 public: 58 // Beginning with API level 17 (Android 4.2), a buffer count of 2 or more is 59 // required for lower latency. Beginning with API level 18 (Android 4.3), a 60 // buffer count of 1 is sufficient for lower latency. In addition, the buffer 61 // size and sample rate must be compatible with the device's native input 62 // configuration provided via the audio manager at construction. 63 // TODO(henrika): perhaps set this value dynamically based on OS version. 64 static const int kNumOfOpenSLESBuffers = 2; 65 66 OpenSLESRecorder(const AudioParameters& audio_parameters, 67 rtc::scoped_refptr<OpenSLEngineManager> engine_manager); 68 ~OpenSLESRecorder() override; 69 70 int Init() override; 71 int Terminate() override; 72 73 int InitRecording() override; 74 bool RecordingIsInitialized() const override; 75 76 int StartRecording() override; 77 int StopRecording() override; 78 bool Recording() const override; 79 80 void AttachAudioBuffer(AudioDeviceBuffer* audio_buffer) override; 81 82 // TODO(henrika): add support using OpenSL ES APIs when available. 83 bool IsAcousticEchoCancelerSupported() const override; 84 bool IsNoiseSuppressorSupported() const override; 85 int EnableBuiltInAEC(bool enable) override; 86 int EnableBuiltInNS(bool enable) override; 87 88 private: 89 // Obtaines the SL Engine Interface from the existing global Engine object. 90 // The interface exposes creation methods of all the OpenSL ES object types. 91 // This method defines the |engine_| member variable. 92 bool ObtainEngineInterface(); 93 94 // Creates/destroys the audio recorder and the simple-buffer queue object. 95 bool CreateAudioRecorder(); 96 void DestroyAudioRecorder(); 97 98 // Allocate memory for audio buffers which will be used to capture audio 99 // via the SLAndroidSimpleBufferQueueItf interface. 100 void AllocateDataBuffers(); 101 102 // These callback methods are called when data has been written to the input 103 // buffer queue. They are both called from an internal "OpenSL ES thread" 104 // which is not attached to the Dalvik VM. 105 static void SimpleBufferQueueCallback(SLAndroidSimpleBufferQueueItf caller, 106 void* context); 107 void ReadBufferQueue(); 108 109 // Wraps calls to SLAndroidSimpleBufferQueueState::Enqueue() and it can be 110 // called both on the main thread (but before recording has started) and from 111 // the internal audio thread while input streaming is active. It uses 112 // |simple_buffer_queue_| but no lock is needed since the initial calls from 113 // the main thread and the native callback thread are mutually exclusive. 114 bool EnqueueAudioBuffer(); 115 116 // Returns the current recorder state. 117 SLuint32 GetRecordState() const; 118 119 // Returns the current buffer queue state. 120 SLAndroidSimpleBufferQueueState GetBufferQueueState() const; 121 122 // Number of buffers currently in the queue. 123 SLuint32 GetBufferCount(); 124 125 // Prints a log message of the current queue state. Can be used for debugging 126 // purposes. 127 void LogBufferState() const; 128 129 // Ensures that methods are called from the same thread as this object is 130 // created on. 131 rtc::ThreadChecker thread_checker_; 132 133 // Stores thread ID in first call to SimpleBufferQueueCallback() from internal 134 // non-application thread which is not attached to the Dalvik JVM. 135 // Detached during construction of this object. 136 rtc::ThreadChecker thread_checker_opensles_; 137 138 const AudioParameters audio_parameters_; 139 140 // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the 141 // AudioDeviceModuleImpl class and called by AudioDeviceModule::Create(). 142 AudioDeviceBuffer* audio_device_buffer_; 143 144 // PCM-type format definition. 145 // TODO(henrika): add support for SLAndroidDataFormat_PCM_EX (android-21) if 146 // 32-bit float representation is needed. 147 SLDataFormat_PCM pcm_format_; 148 149 bool initialized_; 150 bool recording_; 151 152 const rtc::scoped_refptr<OpenSLEngineManager> engine_manager_; 153 // This interface exposes creation methods for all the OpenSL ES object types. 154 // It is the OpenSL ES API entry point. 155 SLEngineItf engine_; 156 157 // The audio recorder media object records audio to the destination specified 158 // by the data sink capturing it from the input specified by the data source. 159 ScopedSLObjectItf recorder_object_; 160 161 // This interface is supported on the audio recorder object and it controls 162 // the state of the audio recorder. 163 SLRecordItf recorder_; 164 165 // The Android Simple Buffer Queue interface is supported on the audio 166 // recorder. For recording, an app should enqueue empty buffers. When a 167 // registered callback sends notification that the system has finished writing 168 // data to the buffer, the app can read the buffer. 169 SLAndroidSimpleBufferQueueItf simple_buffer_queue_; 170 171 // Consumes audio of native buffer size and feeds the WebRTC layer with 10ms 172 // chunks of audio. 173 std::unique_ptr<FineAudioBuffer> fine_audio_buffer_; 174 175 // Queue of audio buffers to be used by the recorder object for capturing 176 // audio. They will be used in a Round-robin way and the size of each buffer 177 // is given by AudioParameters::frames_per_buffer(), i.e., it corresponds to 178 // the native OpenSL ES buffer size. 179 std::unique_ptr<std::unique_ptr<SLint16[]>[]> audio_buffers_; 180 181 // Keeps track of active audio buffer 'n' in the audio_buffers_[n] queue. 182 // Example (kNumOfOpenSLESBuffers = 2): counts 0, 1, 0, 1, ... 183 int buffer_index_; 184 185 // Last time the OpenSL ES layer delivered recorded audio data. 186 uint32_t last_rec_time_; 187 }; 188 189 } // namespace jni 190 191 } // namespace webrtc 192 193 #endif // SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_OPENSLES_RECORDER_H_ 194