xref: /aosp_15_r20/external/webrtc/sdk/android/src/jni/audio_device/opensles_player.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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