1 /*
2 * Copyright 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // #define LOG_NDEBUG 0
18 #define LOG_TAG "bt_btif_avrcp_audio_track"
19
20 #include "btif_avrcp_audio_track.h"
21
22 #ifndef __INTRODUCED_IN
23 #define __INTRODUCED_IN(x)
24 #endif
25
26 #include <aaudio/AAudio.h>
27 #include <bluetooth/log.h>
28
29 #include <algorithm>
30 #include <cstddef>
31 #include <cstdint>
32 #include <thread>
33
34 // TODO(b/369381361) Enfore -Wmissing-prototypes
35 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
36
37 using namespace bluetooth;
38
39 typedef struct {
40 AAudioStream* stream;
41 int bitsPerSample;
42 int channelCount;
43 float* buffer;
44 size_t bufferLength;
45 float gain;
46 } BtifAvrcpAudioTrack;
47
48 // Maximum track gain that can be set.
49 constexpr float kMaxTrackGain = 1.0f;
50 // Minimum track gain that can be set.
51 constexpr float kMinTrackGain = 0.0f;
52
53 struct AudioEngine {
54 int trackFreq = 0;
55 int channelCount = 0;
56 std::thread* thread = nullptr;
57 void* trackHandle = nullptr;
58 } s_AudioEngine;
59
60 void ErrorCallback(AAudioStream* stream, void* userdata, aaudio_result_t error);
61
BtifAvrcpAudioErrorHandle()62 void BtifAvrcpAudioErrorHandle() {
63 AAudioStreamBuilder* builder;
64 AAudioStream* stream;
65
66 aaudio_result_t result = AAudio_createStreamBuilder(&builder);
67 AAudioStreamBuilder_setSampleRate(builder, s_AudioEngine.trackFreq);
68 AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
69 AAudioStreamBuilder_setChannelCount(builder, s_AudioEngine.channelCount);
70 AAudioStreamBuilder_setSessionId(builder, AAUDIO_SESSION_ID_ALLOCATE);
71 AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
72 AAudioStreamBuilder_setErrorCallback(builder, ErrorCallback, nullptr);
73 result = AAudioStreamBuilder_openStream(builder, &stream);
74 log::assert_that(result == AAUDIO_OK, "assert failed: result == AAUDIO_OK");
75 AAudioStreamBuilder_delete(builder);
76
77 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(s_AudioEngine.trackHandle);
78
79 trackHolder->stream = stream;
80
81 if (trackHolder != nullptr && trackHolder->stream != NULL) {
82 log::debug("AAudio Error handle: restart A2dp Sink AudioTrack");
83 AAudioStream_requestStart(trackHolder->stream);
84 }
85 s_AudioEngine.thread = nullptr;
86 }
87
ErrorCallback(AAudioStream *,void *,aaudio_result_t error)88 void ErrorCallback(AAudioStream* /* stream */, void* /* userdata */, aaudio_result_t error) {
89 if (error == AAUDIO_ERROR_DISCONNECTED) {
90 if (s_AudioEngine.thread == nullptr) {
91 s_AudioEngine.thread = new std::thread(BtifAvrcpAudioErrorHandle);
92 }
93 }
94 }
95
BtifAvrcpAudioTrackCreate(int trackFreq,int bitsPerSample,int channelCount)96 void* BtifAvrcpAudioTrackCreate(int trackFreq, int bitsPerSample, int channelCount) {
97 log::info("Track.cpp: btCreateTrack freq {} bps {} channel {}", trackFreq, bitsPerSample,
98 channelCount);
99
100 AAudioStreamBuilder* builder;
101 AAudioStream* stream;
102 aaudio_result_t result = AAudio_createStreamBuilder(&builder);
103 AAudioStreamBuilder_setSampleRate(builder, trackFreq);
104 AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
105 AAudioStreamBuilder_setChannelCount(builder, channelCount);
106 AAudioStreamBuilder_setSessionId(builder, AAUDIO_SESSION_ID_ALLOCATE);
107 AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
108 AAudioStreamBuilder_setErrorCallback(builder, ErrorCallback, nullptr);
109 result = AAudioStreamBuilder_openStream(builder, &stream);
110 log::assert_that(result == AAUDIO_OK, "assert failed: result == AAUDIO_OK");
111 AAudioStreamBuilder_delete(builder);
112
113 BtifAvrcpAudioTrack* trackHolder = new BtifAvrcpAudioTrack;
114 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
115 trackHolder->stream = stream;
116 trackHolder->bitsPerSample = bitsPerSample;
117 trackHolder->channelCount = channelCount;
118 trackHolder->bufferLength =
119 trackHolder->channelCount * AAudioStream_getBufferSizeInFrames(stream);
120 trackHolder->gain = kMaxTrackGain;
121 trackHolder->buffer = new float[trackHolder->bufferLength]();
122
123 s_AudioEngine.trackFreq = trackFreq;
124 s_AudioEngine.channelCount = channelCount;
125 s_AudioEngine.trackHandle = (void*)trackHolder;
126
127 return (void*)trackHolder;
128 }
129
BtifAvrcpAudioTrackStart(void * handle)130 void BtifAvrcpAudioTrackStart(void* handle) {
131 if (handle == NULL) {
132 log::error("handle is null!");
133 return;
134 }
135 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
136 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
137 log::assert_that(trackHolder->stream != NULL, "assert failed: trackHolder->stream != NULL");
138 log::verbose("Track.cpp: btStartTrack");
139 AAudioStream_requestStart(trackHolder->stream);
140 }
141
BtifAvrcpAudioTrackStop(void * handle)142 void BtifAvrcpAudioTrackStop(void* handle) {
143 if (handle == NULL) {
144 log::info("handle is null.");
145 return;
146 }
147 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
148 if (trackHolder != NULL && trackHolder->stream != NULL) {
149 log::verbose("Track.cpp: btStopTrack");
150 AAudioStream_requestStop(trackHolder->stream);
151 }
152 }
153
BtifAvrcpAudioTrackDelete(void * handle)154 void BtifAvrcpAudioTrackDelete(void* handle) {
155 if (handle == NULL) {
156 log::info("handle is null.");
157 return;
158 }
159 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
160 if (trackHolder != NULL && trackHolder->stream != NULL) {
161 log::verbose("Track.cpp: btStartTrack");
162 AAudioStream_close(trackHolder->stream);
163 delete trackHolder->buffer;
164 delete trackHolder;
165 }
166 }
167
BtifAvrcpAudioTrackPause(void * handle)168 void BtifAvrcpAudioTrackPause(void* handle) {
169 if (handle == NULL) {
170 log::info("handle is null.");
171 return;
172 }
173 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
174 if (trackHolder != NULL && trackHolder->stream != NULL) {
175 log::verbose("Track.cpp: btPauseTrack");
176 AAudioStream_requestPause(trackHolder->stream);
177 AAudioStream_requestFlush(trackHolder->stream);
178 }
179 }
180
BtifAvrcpSetAudioTrackGain(void * handle,float gain)181 void BtifAvrcpSetAudioTrackGain(void* handle, float gain) {
182 if (handle == NULL) {
183 log::info("handle is null.");
184 return;
185 }
186 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
187 if (trackHolder != NULL) {
188 const float clampedGain = std::clamp(gain, kMinTrackGain, kMaxTrackGain);
189 if (clampedGain != gain) {
190 log::warn("Out of bounds gain set. Clamping the gain from :{:f} to {:f}", gain, clampedGain);
191 }
192 trackHolder->gain = clampedGain;
193 log::info("Avrcp audio track gain is set to {:f}", trackHolder->gain);
194 }
195 }
196
197 constexpr float kScaleQ15ToFloat = 1.0f / 32768.0f;
198 constexpr float kScaleQ23ToFloat = 1.0f / 8388608.0f;
199 constexpr float kScaleQ31ToFloat = 1.0f / 2147483648.0f;
200
sampleSizeFor(BtifAvrcpAudioTrack * trackHolder)201 static size_t sampleSizeFor(BtifAvrcpAudioTrack* trackHolder) {
202 return trackHolder->bitsPerSample / 8;
203 }
204
transcodeQ15ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)205 static size_t transcodeQ15ToFloat(uint8_t* buffer, size_t length,
206 BtifAvrcpAudioTrack* trackHolder) {
207 size_t sampleSize = sampleSizeFor(trackHolder);
208 size_t i = 0;
209 const float scaledGain = trackHolder->gain * kScaleQ15ToFloat;
210 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
211 trackHolder->buffer[i] = ((int16_t*)buffer)[i] * scaledGain;
212 }
213 return i * sampleSize;
214 }
215
transcodeQ23ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)216 static size_t transcodeQ23ToFloat(uint8_t* buffer, size_t length,
217 BtifAvrcpAudioTrack* trackHolder) {
218 size_t sampleSize = sampleSizeFor(trackHolder);
219 size_t i = 0;
220 const float scaledGain = trackHolder->gain * kScaleQ23ToFloat;
221 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
222 size_t offset = i * sampleSize;
223 int32_t sample = *((int32_t*)(buffer + offset - 1)) & 0x00FFFFFF;
224 trackHolder->buffer[i] = sample * scaledGain;
225 }
226 return i * sampleSize;
227 }
228
transcodeQ31ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)229 static size_t transcodeQ31ToFloat(uint8_t* buffer, size_t length,
230 BtifAvrcpAudioTrack* trackHolder) {
231 size_t sampleSize = sampleSizeFor(trackHolder);
232 size_t i = 0;
233 const float scaledGain = trackHolder->gain * kScaleQ31ToFloat;
234 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
235 trackHolder->buffer[i] = ((int32_t*)buffer)[i] * scaledGain;
236 }
237 return i * sampleSize;
238 }
239
transcodeToPcmFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)240 static size_t transcodeToPcmFloat(uint8_t* buffer, size_t length,
241 BtifAvrcpAudioTrack* trackHolder) {
242 switch (trackHolder->bitsPerSample) {
243 case 16:
244 return transcodeQ15ToFloat(buffer, length, trackHolder);
245 case 24:
246 return transcodeQ23ToFloat(buffer, length, trackHolder);
247 case 32:
248 return transcodeQ31ToFloat(buffer, length, trackHolder);
249 }
250 return -1;
251 }
252
253 constexpr int64_t kTimeoutNanos = 100 * 1000 * 1000; // 100 ms
254
BtifAvrcpAudioTrackWriteData(void * handle,void * audioBuffer,int bufferLength)255 int BtifAvrcpAudioTrackWriteData(void* handle, void* audioBuffer, int bufferLength) {
256 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
257 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
258 log::assert_that(trackHolder->stream != NULL, "assert failed: trackHolder->stream != NULL");
259 aaudio_result_t retval = -1;
260
261 size_t sampleSize = sampleSizeFor(trackHolder);
262 int transcodedCount = 0;
263 do {
264 transcodedCount += transcodeToPcmFloat(((uint8_t*)audioBuffer) + transcodedCount,
265 bufferLength - transcodedCount, trackHolder);
266
267 retval = AAudioStream_write(trackHolder->stream, trackHolder->buffer,
268 transcodedCount / (sampleSize * trackHolder->channelCount),
269 kTimeoutNanos);
270 log::verbose("Track.cpp: btWriteData len = {} ret = {}", bufferLength, retval);
271 } while (transcodedCount < bufferLength);
272
273 return transcodedCount;
274 }
275