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