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