1 /* 2 * Copyright (c) 2015 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_PLAYER_H_ 12 #define SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_OPENSLES_PLAYER_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 "absl/types/optional.h" 21 #include "api/scoped_refptr.h" 22 #include "api/sequence_checker.h" 23 #include "modules/audio_device/audio_device_buffer.h" 24 #include "modules/audio_device/fine_audio_buffer.h" 25 #include "modules/audio_device/include/audio_device_defines.h" 26 #include "sdk/android/src/jni/audio_device/audio_common.h" 27 #include "sdk/android/src/jni/audio_device/audio_device_module.h" 28 #include "sdk/android/src/jni/audio_device/opensles_common.h" 29 30 namespace webrtc { 31 32 class FineAudioBuffer; 33 34 namespace jni { 35 36 // Implements 16-bit mono PCM audio output support for Android using the 37 // C based OpenSL ES API. No calls from C/C++ to Java using JNI is done. 38 // 39 // An instance can be created on any thread, but must then be used on one and 40 // the same thread. All public methods must also be called on the same thread. A 41 // thread checker will RTC_DCHECK if any method is called on an invalid thread. 42 // Decoded audio buffers are requested on a dedicated internal thread managed by 43 // the OpenSL ES layer. 44 // 45 // The existing design forces the user to call InitPlayout() after Stoplayout() 46 // to be able to call StartPlayout() again. This is inline with how the Java- 47 // based implementation works. 48 // 49 // OpenSL ES is a native C API which have no Dalvik-related overhead such as 50 // garbage collection pauses and it supports reduced audio output latency. 51 // If the device doesn't claim this feature but supports API level 9 (Android 52 // platform version 2.3) or later, then we can still use the OpenSL ES APIs but 53 // the output latency may be higher. 54 class OpenSLESPlayer : public AudioOutput { 55 public: 56 // Beginning with API level 17 (Android 4.2), a buffer count of 2 or more is 57 // required for lower latency. Beginning with API level 18 (Android 4.3), a 58 // buffer count of 1 is sufficient for lower latency. In addition, the buffer 59 // size and sample rate must be compatible with the device's native output 60 // configuration provided via the audio manager at construction. 61 // TODO(henrika): perhaps set this value dynamically based on OS version. 62 static const int kNumOfOpenSLESBuffers = 2; 63 64 OpenSLESPlayer(const AudioParameters& audio_parameters, 65 rtc::scoped_refptr<OpenSLEngineManager> engine_manager); 66 ~OpenSLESPlayer() override; 67 68 int Init() override; 69 int Terminate() override; 70 71 int InitPlayout() override; 72 bool PlayoutIsInitialized() const override; 73 74 int StartPlayout() override; 75 int StopPlayout() override; 76 bool Playing() const override; 77 78 bool SpeakerVolumeIsAvailable() override; 79 int SetSpeakerVolume(uint32_t volume) override; 80 absl::optional<uint32_t> SpeakerVolume() const override; 81 absl::optional<uint32_t> MaxSpeakerVolume() const override; 82 absl::optional<uint32_t> MinSpeakerVolume() const override; 83 84 void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override; 85 GetPlayoutUnderrunCount()86 int GetPlayoutUnderrunCount() override { return -1; } 87 88 private: 89 // These callback methods are called when data is required for playout. 90 // They are both called from an internal "OpenSL ES thread" which is not 91 // attached to the Dalvik VM. 92 static void SimpleBufferQueueCallback(SLAndroidSimpleBufferQueueItf caller, 93 void* context); 94 void FillBufferQueue(); 95 // Reads audio data in PCM format using the AudioDeviceBuffer. 96 // Can be called both on the main thread (during Start()) and from the 97 // internal audio thread while output streaming is active. 98 // If the `silence` flag is set, the audio is filled with zeros instead of 99 // asking the WebRTC layer for real audio data. This procedure is also known 100 // as audio priming. 101 void EnqueuePlayoutData(bool silence); 102 103 // Allocate memory for audio buffers which will be used to render audio 104 // via the SLAndroidSimpleBufferQueueItf interface. 105 void AllocateDataBuffers(); 106 107 // Obtaines the SL Engine Interface from the existing global Engine object. 108 // The interface exposes creation methods of all the OpenSL ES object types. 109 // This method defines the `engine_` member variable. 110 bool ObtainEngineInterface(); 111 112 // Creates/destroys the output mix object. 113 bool CreateMix(); 114 void DestroyMix(); 115 116 // Creates/destroys the audio player and the simple-buffer object. 117 // Also creates the volume object. 118 bool CreateAudioPlayer(); 119 void DestroyAudioPlayer(); 120 121 SLuint32 GetPlayState() const; 122 123 // Ensures that methods are called from the same thread as this object is 124 // created on. 125 SequenceChecker thread_checker_; 126 127 // Stores thread ID in first call to SimpleBufferQueueCallback() from internal 128 // non-application thread which is not attached to the Dalvik JVM. 129 // Detached during construction of this object. 130 SequenceChecker thread_checker_opensles_; 131 132 const AudioParameters audio_parameters_; 133 134 // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the 135 // AudioDeviceModuleImpl class and called by AudioDeviceModule::Create(). 136 AudioDeviceBuffer* audio_device_buffer_; 137 138 bool initialized_; 139 bool playing_; 140 141 // PCM-type format definition. 142 // TODO(henrika): add support for SLAndroidDataFormat_PCM_EX (android-21) if 143 // 32-bit float representation is needed. 144 SLDataFormat_PCM pcm_format_; 145 146 // Queue of audio buffers to be used by the player object for rendering 147 // audio. 148 std::unique_ptr<SLint16[]> audio_buffers_[kNumOfOpenSLESBuffers]; 149 150 // FineAudioBuffer takes an AudioDeviceBuffer which delivers audio data 151 // in chunks of 10ms. It then allows for this data to be pulled in 152 // a finer or coarser granularity. I.e. interacting with this class instead 153 // of directly with the AudioDeviceBuffer one can ask for any number of 154 // audio data samples. 155 // Example: native buffer size can be 192 audio frames at 48kHz sample rate. 156 // WebRTC will provide 480 audio frames per 10ms but OpenSL ES asks for 192 157 // in each callback (one every 4th ms). This class can then ask for 192 and 158 // the FineAudioBuffer will ask WebRTC for new data approximately only every 159 // second callback and also cache non-utilized audio. 160 std::unique_ptr<FineAudioBuffer> fine_audio_buffer_; 161 162 // Keeps track of active audio buffer 'n' in the audio_buffers_[n] queue. 163 // Example (kNumOfOpenSLESBuffers = 2): counts 0, 1, 0, 1, ... 164 int buffer_index_; 165 166 const rtc::scoped_refptr<OpenSLEngineManager> engine_manager_; 167 // This interface exposes creation methods for all the OpenSL ES object types. 168 // It is the OpenSL ES API entry point. 169 SLEngineItf engine_; 170 171 // Output mix object to be used by the player object. 172 ScopedSLObjectItf output_mix_; 173 174 // The audio player media object plays out audio to the speakers. It also 175 // supports volume control. 176 ScopedSLObjectItf player_object_; 177 178 // This interface is supported on the audio player and it controls the state 179 // of the audio player. 180 SLPlayItf player_; 181 182 // The Android Simple Buffer Queue interface is supported on the audio player 183 // and it provides methods to send audio data from the source to the audio 184 // player for rendering. 185 SLAndroidSimpleBufferQueueItf simple_buffer_queue_; 186 187 // This interface exposes controls for manipulating the object’s audio volume 188 // properties. This interface is supported on the Audio Player object. 189 SLVolumeItf volume_; 190 191 // Last time the OpenSL ES layer asked for audio data to play out. 192 uint32_t last_play_time_; 193 }; 194 195 } // namespace jni 196 197 } // namespace webrtc 198 199 #endif // SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_OPENSLES_PLAYER_H_ 200