• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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