• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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