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 #include <utils/StrongPointer.h>
29
30 #include <algorithm>
31 #include <thread>
32
33 #include "internal_include/bt_target.h"
34 #include "os/log.h"
35
36 using namespace android;
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,
72 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
73 AAudioStreamBuilder_setErrorCallback(builder, ErrorCallback, nullptr);
74 result = AAudioStreamBuilder_openStream(builder, &stream);
75 log::assert_that(result == AAUDIO_OK, "assert failed: result == AAUDIO_OK");
76 AAudioStreamBuilder_delete(builder);
77
78 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(s_AudioEngine.trackHandle);
79
80 trackHolder->stream = stream;
81
82 if (trackHolder != NULL && trackHolder->stream != NULL) {
83 log::debug("AAudio Error handle: restart A2dp Sink AudioTrack");
84 AAudioStream_requestStart(trackHolder->stream);
85 }
86 s_AudioEngine.thread = nullptr;
87 }
88
ErrorCallback(AAudioStream * stream,void * userdata,aaudio_result_t error)89 void ErrorCallback(AAudioStream* stream,
90 void* userdata,
91 aaudio_result_t error) {
92 if (error == AAUDIO_ERROR_DISCONNECTED)
93 if (s_AudioEngine.thread == nullptr)
94 s_AudioEngine.thread = new std::thread(BtifAvrcpAudioErrorHandle);
95 }
96
BtifAvrcpAudioTrackCreate(int trackFreq,int bitsPerSample,int channelCount)97 void* BtifAvrcpAudioTrackCreate(int trackFreq, int bitsPerSample,
98 int channelCount) {
99 log::info("Track.cpp: btCreateTrack freq {} bps {} channel {}", trackFreq,
100 bitsPerSample, channelCount);
101
102 AAudioStreamBuilder* builder;
103 AAudioStream* stream;
104 aaudio_result_t result = AAudio_createStreamBuilder(&builder);
105 AAudioStreamBuilder_setSampleRate(builder, trackFreq);
106 AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
107 AAudioStreamBuilder_setChannelCount(builder, channelCount);
108 AAudioStreamBuilder_setSessionId(builder, AAUDIO_SESSION_ID_ALLOCATE);
109 AAudioStreamBuilder_setPerformanceMode(builder,
110 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
111 AAudioStreamBuilder_setErrorCallback(builder, ErrorCallback, nullptr);
112 result = AAudioStreamBuilder_openStream(builder, &stream);
113 log::assert_that(result == AAUDIO_OK, "assert failed: result == AAUDIO_OK");
114 AAudioStreamBuilder_delete(builder);
115
116 BtifAvrcpAudioTrack* trackHolder = new BtifAvrcpAudioTrack;
117 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
118 trackHolder->stream = stream;
119 trackHolder->bitsPerSample = bitsPerSample;
120 trackHolder->channelCount = channelCount;
121 trackHolder->bufferLength =
122 trackHolder->channelCount * AAudioStream_getBufferSizeInFrames(stream);
123 trackHolder->gain = kMaxTrackGain;
124 trackHolder->buffer = new float[trackHolder->bufferLength]();
125
126 s_AudioEngine.trackFreq = trackFreq;
127 s_AudioEngine.channelCount = channelCount;
128 s_AudioEngine.trackHandle = (void*)trackHolder;
129
130 return (void*)trackHolder;
131 }
132
BtifAvrcpAudioTrackStart(void * handle)133 void BtifAvrcpAudioTrackStart(void* handle) {
134 if (handle == NULL) {
135 log::error("handle is null!");
136 return;
137 }
138 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
139 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
140 log::assert_that(trackHolder->stream != NULL,
141 "assert failed: trackHolder->stream != NULL");
142 log::verbose("Track.cpp: btStartTrack");
143 AAudioStream_requestStart(trackHolder->stream);
144 }
145
BtifAvrcpAudioTrackStop(void * handle)146 void BtifAvrcpAudioTrackStop(void* handle) {
147 if (handle == NULL) {
148 log::info("handle is null.");
149 return;
150 }
151 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
152 if (trackHolder != NULL && trackHolder->stream != NULL) {
153 log::verbose("Track.cpp: btStopTrack");
154 AAudioStream_requestStop(trackHolder->stream);
155 }
156 }
157
BtifAvrcpAudioTrackDelete(void * handle)158 void BtifAvrcpAudioTrackDelete(void* handle) {
159 if (handle == NULL) {
160 log::info("handle is null.");
161 return;
162 }
163 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
164 if (trackHolder != NULL && trackHolder->stream != NULL) {
165 log::verbose("Track.cpp: btStartTrack");
166 AAudioStream_close(trackHolder->stream);
167 delete trackHolder->buffer;
168 delete trackHolder;
169 }
170 }
171
BtifAvrcpAudioTrackPause(void * handle)172 void BtifAvrcpAudioTrackPause(void* handle) {
173 if (handle == NULL) {
174 log::info("handle is null.");
175 return;
176 }
177 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
178 if (trackHolder != NULL && trackHolder->stream != NULL) {
179 log::verbose("Track.cpp: btPauseTrack");
180 AAudioStream_requestPause(trackHolder->stream);
181 AAudioStream_requestFlush(trackHolder->stream);
182 }
183 }
184
BtifAvrcpSetAudioTrackGain(void * handle,float gain)185 void BtifAvrcpSetAudioTrackGain(void* handle, float gain) {
186 if (handle == NULL) {
187 log::info("handle is null.");
188 return;
189 }
190 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
191 if (trackHolder != NULL) {
192 const float clampedGain = std::clamp(gain, kMinTrackGain, kMaxTrackGain);
193 if (clampedGain != gain) {
194 log::warn("Out of bounds gain set. Clamping the gain from :{:f} to {:f}",
195 gain, clampedGain);
196 }
197 trackHolder->gain = clampedGain;
198 log::info("Avrcp audio track gain is set to {:f}", trackHolder->gain);
199 }
200 }
201
202 constexpr float kScaleQ15ToFloat = 1.0f / 32768.0f;
203 constexpr float kScaleQ23ToFloat = 1.0f / 8388608.0f;
204 constexpr float kScaleQ31ToFloat = 1.0f / 2147483648.0f;
205
sampleSizeFor(BtifAvrcpAudioTrack * trackHolder)206 static size_t sampleSizeFor(BtifAvrcpAudioTrack* trackHolder) {
207 return trackHolder->bitsPerSample / 8;
208 }
209
transcodeQ15ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)210 static size_t transcodeQ15ToFloat(uint8_t* buffer, size_t length,
211 BtifAvrcpAudioTrack* trackHolder) {
212 size_t sampleSize = sampleSizeFor(trackHolder);
213 size_t i = 0;
214 const float scaledGain = trackHolder->gain * kScaleQ15ToFloat;
215 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
216 trackHolder->buffer[i] = ((int16_t*)buffer)[i] * scaledGain;
217 }
218 return i * sampleSize;
219 }
220
transcodeQ23ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)221 static size_t transcodeQ23ToFloat(uint8_t* buffer, size_t length,
222 BtifAvrcpAudioTrack* trackHolder) {
223 size_t sampleSize = sampleSizeFor(trackHolder);
224 size_t i = 0;
225 const float scaledGain = trackHolder->gain * kScaleQ23ToFloat;
226 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
227 size_t offset = i * sampleSize;
228 int32_t sample = *((int32_t*)(buffer + offset - 1)) & 0x00FFFFFF;
229 trackHolder->buffer[i] = sample * scaledGain;
230 }
231 return i * sampleSize;
232 }
233
transcodeQ31ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)234 static size_t transcodeQ31ToFloat(uint8_t* buffer, size_t length,
235 BtifAvrcpAudioTrack* trackHolder) {
236 size_t sampleSize = sampleSizeFor(trackHolder);
237 size_t i = 0;
238 const float scaledGain = trackHolder->gain * kScaleQ31ToFloat;
239 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
240 trackHolder->buffer[i] = ((int32_t*)buffer)[i] * scaledGain;
241 }
242 return i * sampleSize;
243 }
244
transcodeToPcmFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)245 static size_t transcodeToPcmFloat(uint8_t* buffer, size_t length,
246 BtifAvrcpAudioTrack* trackHolder) {
247 switch (trackHolder->bitsPerSample) {
248 case 16:
249 return transcodeQ15ToFloat(buffer, length, trackHolder);
250 case 24:
251 return transcodeQ23ToFloat(buffer, length, trackHolder);
252 case 32:
253 return transcodeQ31ToFloat(buffer, length, trackHolder);
254 }
255 return -1;
256 }
257
258 constexpr int64_t kTimeoutNanos = 100 * 1000 * 1000; // 100 ms
259
BtifAvrcpAudioTrackWriteData(void * handle,void * audioBuffer,int bufferLength)260 int BtifAvrcpAudioTrackWriteData(void* handle, void* audioBuffer,
261 int bufferLength) {
262 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
263 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
264 log::assert_that(trackHolder->stream != NULL,
265 "assert failed: trackHolder->stream != NULL");
266 aaudio_result_t retval = -1;
267
268 size_t sampleSize = sampleSizeFor(trackHolder);
269 int transcodedCount = 0;
270 do {
271 transcodedCount +=
272 transcodeToPcmFloat(((uint8_t*)audioBuffer) + transcodedCount,
273 bufferLength - transcodedCount, trackHolder);
274
275 retval = AAudioStream_write(
276 trackHolder->stream, trackHolder->buffer,
277 transcodedCount / (sampleSize * trackHolder->channelCount),
278 kTimeoutNanos);
279 log::verbose("Track.cpp: btWriteData len = {} ret = {}", bufferLength,
280 retval);
281 } while (transcodedCount < bufferLength);
282
283 return transcodedCount;
284 }
285