Index: webrtc/modules/audio_device/android/opensles_recorder.h |
diff --git a/webrtc/modules/audio_device/android/opensles_recorder.h b/webrtc/modules/audio_device/android/opensles_recorder.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..dfb2cf1c2dc097e1624a6ce3a24a33007815ac5e |
--- /dev/null |
+++ b/webrtc/modules/audio_device/android/opensles_recorder.h |
@@ -0,0 +1,191 @@ |
+/* |
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#ifndef WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_RECORDER_H_ |
+#define WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_RECORDER_H_ |
+ |
+#include <SLES/OpenSLES.h> |
+#include <SLES/OpenSLES_Android.h> |
+#include <SLES/OpenSLES_AndroidConfiguration.h> |
+ |
+#include "webrtc/base/thread_checker.h" |
+#include "webrtc/modules/audio_device/android/audio_common.h" |
+#include "webrtc/modules/audio_device/android/audio_manager.h" |
+#include "webrtc/modules/audio_device/android/opensles_common.h" |
+#include "webrtc/modules/audio_device/include/audio_device_defines.h" |
+#include "webrtc/modules/audio_device/audio_device_generic.h" |
+#include "webrtc/modules/utility/include/helpers_android.h" |
+ |
+namespace webrtc { |
+ |
+class FineAudioBuffer; |
+ |
+// Implements 16-bit mono PCM audio input support for Android using the |
+// C based OpenSL ES API. No calls from C/C++ to Java using JNI is done. |
+// |
+// An instance must be created and destroyed on one and the same thread. |
+// All public methods must also be called on the same thread. A thread checker |
+// will RTC_DCHECK if any method is called on an invalid thread. Recorded audio |
+// buffers are provided on a dedicated internal thread managed by the OpenSL |
+// ES layer. |
+// |
+// The existing design forces the user to call InitRecording() after |
+// StopRecording() to be able to call StartRecording() again. This is inline |
+// with how the Java-based implementation works. |
+// |
+// As of API level 21, lower latency audio input is supported on select devices. |
+// To take advantage of this feature, first confirm that lower latency output is |
+// available. The capability for lower latency output is a prerequisite for the |
+// lower latency input feature. Then, create an AudioRecorder with the same |
+// sample rate and buffer size as would be used for output. OpenSL ES interfaces |
+// for input effects preclude the lower latency path. |
+// See https://developer.android.com/ndk/guides/audio/opensl-prog-notes.html |
+// for more details. |
+class OpenSLESRecorder { |
+ public: |
+ // Beginning with API level 17 (Android 4.2), a buffer count of 2 or more is |
+ // required for lower latency. Beginning with API level 18 (Android 4.3), a |
+ // buffer count of 1 is sufficient for lower latency. In addition, the buffer |
+ // size and sample rate must be compatible with the device's native input |
+ // configuration provided via the audio manager at construction. |
+ // TODO(henrika): perhaps set this value dynamically based on OS version. |
+ static const int kNumOfOpenSLESBuffers = 2; |
+ |
+ explicit OpenSLESRecorder(AudioManager* audio_manager); |
+ ~OpenSLESRecorder(); |
+ |
+ int Init(); |
+ int Terminate(); |
+ |
+ int InitRecording(); |
+ bool RecordingIsInitialized() const { return initialized_; } |
+ |
+ int StartRecording(); |
+ int StopRecording(); |
+ bool Recording() const { return recording_; } |
+ |
+ void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer); |
+ |
+ // TODO(henrika): add support using OpenSL ES APIs when available. |
+ int EnableBuiltInAEC(bool enable); |
+ int EnableBuiltInAGC(bool enable); |
+ int EnableBuiltInNS(bool enable); |
+ |
+ private: |
+ // Obtaines the SL Engine Interface from the existing global Engine object. |
+ // The interface exposes creation methods of all the OpenSL ES object types. |
+ // This method defines the |engine_| member variable. |
+ bool ObtainEngineInterface(); |
+ |
+ // Creates/destroys the audio recorder and the simple-buffer queue object. |
+ bool CreateAudioRecorder(); |
+ void DestroyAudioRecorder(); |
+ |
+ // Allocate memory for audio buffers which will be used to capture audio |
+ // via the SLAndroidSimpleBufferQueueItf interface. |
+ void AllocateDataBuffers(); |
+ |
+ // These callback methods are called when data has been written to the input |
+ // buffer queue. They are both called from an internal "OpenSL ES thread" |
+ // which is not attached to the Dalvik VM. |
+ static void SimpleBufferQueueCallback(SLAndroidSimpleBufferQueueItf caller, |
+ void* context); |
+ void ReadBufferQueue(); |
+ |
+ // Wraps calls to SLAndroidSimpleBufferQueueState::Enqueue() and it can be |
+ // called both on the main thread (but before recording has started) and from |
+ // the internal audio thread while input streaming is active. It uses |
+ // |simple_buffer_queue_| but no lock is needed since the initial calls from |
+ // the main thread and the native callback thread are mutually exclusive. |
+ bool EnqueueAudioBuffer(); |
+ |
+ // Returns the current recorder state. |
+ SLuint32 GetRecordState() const; |
+ |
+ // Returns the current buffer queue state. |
+ SLAndroidSimpleBufferQueueState GetBufferQueueState() const; |
+ |
+ // Number of buffers currently in the queue. |
+ SLuint32 GetBufferCount(); |
+ |
+ // Prints a log message of the current queue state. Can be used for debugging |
+ // purposes. |
+ void LogBufferState() const; |
+ |
+ // Ensures that methods are called from the same thread as this object is |
+ // created on. |
+ rtc::ThreadChecker thread_checker_; |
+ |
+ // Stores thread ID in first call to SimpleBufferQueueCallback() from internal |
+ // non-application thread which is not attached to the Dalvik JVM. |
+ // Detached during construction of this object. |
+ rtc::ThreadChecker thread_checker_opensles_; |
+ |
+ // Raw pointer to the audio manager injected at construction. Used to cache |
+ // audio parameters and to access the global SL engine object needed by the |
+ // ObtainEngineInterface() method. The audio manager outlives any instance of |
+ // this class. |
+ AudioManager* audio_manager_; |
tommi
2016/09/15 09:34:13
AudioManager* const audio_manager_;
henrika_webrtc
2016/09/16 13:30:48
But of course.
|
+ |
+ // Contains audio parameters provided to this class at construction by the |
+ // AudioManager. |
+ const AudioParameters audio_parameters_; |
+ |
+ // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the |
+ // AudioDeviceModuleImpl class and called by AudioDeviceModule::Create(). |
+ AudioDeviceBuffer* audio_device_buffer_; |
+ |
+ // PCM-type format definition. |
+ // TODO(henrika): add support for SLAndroidDataFormat_PCM_EX (android-21) if |
+ // 32-bit float representation is needed. |
+ SLDataFormat_PCM pcm_format_; |
+ |
+ bool initialized_; |
+ bool recording_; |
+ |
+ // This interface exposes creation methods for all the OpenSL ES object types. |
+ // It is the OpenSL ES API entry point. |
+ SLEngineItf engine_; |
+ |
+ // The audio recorder media object records audio to the destination specified |
+ // by the data sink capturing it from the input specified by the data source. |
+ webrtc::ScopedSLObjectItf recorder_object_; |
+ |
+ // This interface is supported on the audio recorder object and it controls |
+ // the state of the audio recorder. |
+ SLRecordItf recorder_; |
+ |
+ // The Android Simple Buffer Queue interface is supported on the audio |
+ // recorder. For recording, an app should enqueue empty buffers. When a |
+ // registered callback sends notification that the system has finished writing |
+ // data to the buffer, the app can read the buffer. |
+ SLAndroidSimpleBufferQueueItf simple_buffer_queue_; |
+ |
+ // Consumes audio of native buffer size and feeds the WebRTC layer with 10ms |
+ // chunks of audio. |
+ std::unique_ptr<FineAudioBuffer> fine_audio_buffer_; |
+ |
+ // Queue of audio buffers to be used by the recorder object for capturing |
+ // audio. They will be used in a Round-robin way and the size of each buffer |
+ // is given by AudioParameters::GetBytesPerBuffer(), i.e., it corresponds to |
+ // the native OpenSL ES buffer size. |
+ std::unique_ptr<std::unique_ptr<SLint8[]>[]> audio_buffers_; |
+ |
+ // Keeps track of active audio buffer 'n' in the audio_buffers_[n] queue. |
+ // Example (kNumOfOpenSLESBuffers = 2): counts 0, 1, 0, 1, ... |
+ int buffer_index_; |
+ |
+ // Last time the OpenSL ES layer delivered recorded audio data. |
+ uint32_t last_rec_time_; |
+}; |
+ |
+} // namespace webrtc |
+ |
+#endif // WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_RECORDER_H_ |