1 /*
2 * Copyright (C) 2014 - 2017 Sony Corporation
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 #include "ldacBT_abr.h"
18
19 #include <stdlib.h>
20 #include <string.h>
21
22 #define LDAC_ABR_OBSERVING_TIME_MS 500 /* [ms] the time length for storing Tx Queue Depth */
23 #define LDAC_ABR_PENALTY_MAX 4
24
25 /* Number of observing count to judge whether EQMID may be increase.
26 * Those count can convert in time by following formula:
27 * Time [ms] = (Count - abrQualityModeID) * LDAC_ABR_OBSERVING_TIME_MS
28 * where abrQualityModeID is the value which converted EQMID by aEqmidToAbrQualityModeID[].
29 * Therefore, using the default value of 12, the observation time in each abrQualityModeID is
30 * as follows:
31 * ----------------------------------------------------
32 * | abrQualityModeID | 0 | 1 | 2 | 3 | 4 |
33 * | observation time [s] | 6 | 5 | 4 | 3 | 2 |
34 * ----------------------------------------------------
35 */
36 #define LDAC_ABR_OBSERVING_COUNT_TO_JUDGE_INC_QUALITY 12
37 #define LDAC_ABR_OBSERVING_COUNT_FOR_INIT 6 /* = 3sec. keep same EQMID in first 3sec */
38 /* Default value for thresholds */
39 #define LDAC_ABR_THRESHOLD_CRITICAL_DEFAULT 6
40 #define LDAC_ABR_THRESHOLD_DANGEROUSTREND_DEFAULT 4
41 #define LDAC_ABR_THRESHOLD_SAFETY_FOR_HQSQ_DEFAULT 2
42 /* Number of steady state count to judge */
43 #define LDAC_ABR_NUM_STEADY_STATE_TO_JUDGE_STEADY 3
44 /* Number of steady state count to reset for LDACBT_EQMID_HQ */
45 #define LDAC_ABR_NUM_STEADY_STATE_TO_RESET_PENALTY_FOR_HQ 60
46
47
48 typedef struct _tx_queue_param
49 {
50 unsigned char *pHist;
51 unsigned int szHist;
52 int sum;
53 unsigned int cnt;
54 unsigned int idx;
55 } TxQ_INFO;
56
57 typedef struct _ldacbt_abr_param
58 {
59 TxQ_INFO TxQD_Info;
60 int cntToIncQuality;
61 int nSteadyState;
62 int nPenalty;
63 int abrQualityModeIdSteady;
64 unsigned int numToEvaluate;
65 /* thresholds */
66 unsigned int thCritical;
67 unsigned int thDangerousTrend;
68 unsigned int thSafety4HQSQ;
69 } LDAC_ABR_PARAMS;
70
71 #define clear_data(ptr, n) memset(ptr, 0, n)
72
73 #ifdef LOCAL_DEBUG
74 #include <android/log.h>
75 #define ABRDBG(fmt, ... ) \
76 __android_log_print( ANDROID_LOG_INFO, "******** LDAC ABR ********",\
77 "%s@%s:%d::"fmt, __func__, __FILE__, __LINE__, ## __VA_ARGS__ )
78 #else
79 #define ABRDBG(fmt, ...)
80 #endif /* LOCAL_DEBUG */
81
82 /* A table for converting EQMID to abrQualityModeID which is sorted in descending order by bit rate.
83 * The relationship between EQMID, bit rate and abrQualityModeID when the sampling frequency is
84 * 96 kHz is as follows:
85 * ----------------------------------------------------
86 * | EQMID | 0 | 1 | 2 | 3 | 4 |
87 * | bit rate [kbps] | 990 | 660 | 330 | 492 | 396 |
88 * | abrQualityModeID | 0 | 1 | 4 | 2 | 3 |
89 * ----------------------------------------------------
90 */
91 static const int aEqmidToAbrQualityModeID[]={ 0, 1, 4, 2, 3};
92 static const int sizeOfEqmidToBitrateSortedIdTable = (int)(sizeof(aEqmidToAbrQualityModeID)
93 / sizeof(aEqmidToAbrQualityModeID[0]));
94
95 /* Get LDAC ABR handle */
ldac_ABR_get_handle(void)96 HANDLE_LDAC_ABR ldac_ABR_get_handle(void)
97 {
98 HANDLE_LDAC_ABR hLdacAbr;
99 ABRDBG( "" );
100 if ((hLdacAbr = (HANDLE_LDAC_ABR)malloc(sizeof(LDAC_ABR_PARAMS))) == NULL) {
101 ABRDBG( "[ERR] Failed to allocate memory for handle." );
102 return NULL;
103 }
104 hLdacAbr->TxQD_Info.pHist = NULL;
105 return hLdacAbr;
106 }
107
108 /* Free LDAC ABR handle */
ldac_ABR_free_handle(HANDLE_LDAC_ABR hLdacAbr)109 void ldac_ABR_free_handle(HANDLE_LDAC_ABR hLdacAbr)
110 {
111 ABRDBG( "" );
112 if (hLdacAbr != NULL) {
113 if (hLdacAbr->TxQD_Info.pHist) {
114 free(hLdacAbr->TxQD_Info.pHist);
115 }
116 free(hLdacAbr);
117 }
118 }
119
120 /* Initialize LDAC ABR */
ldac_ABR_Init(HANDLE_LDAC_ABR hLdacAbr,unsigned int interval_ms)121 int ldac_ABR_Init( HANDLE_LDAC_ABR hLdacAbr, unsigned int interval_ms )
122 {
123 ABRDBG( "hLdacAbr:0x%x, interval_ms:%u", (unsigned int)hLdacAbr, interval_ms );
124 if (hLdacAbr == NULL) return -1;
125 if (interval_ms == 0) return -1;
126 if (interval_ms > LDAC_ABR_OBSERVING_TIME_MS) return -1;
127
128 hLdacAbr->numToEvaluate = LDAC_ABR_OBSERVING_TIME_MS / interval_ms;
129 hLdacAbr->TxQD_Info.sum = 0;
130 hLdacAbr->TxQD_Info.cnt = 0;
131 hLdacAbr->TxQD_Info.idx = 0;
132 hLdacAbr->TxQD_Info.szHist = hLdacAbr->numToEvaluate + 1;
133 if (hLdacAbr->TxQD_Info.pHist) free(hLdacAbr->TxQD_Info.pHist);
134 if ((hLdacAbr->TxQD_Info.pHist =
135 (unsigned char*)malloc(hLdacAbr->TxQD_Info.szHist * sizeof(unsigned char))) == NULL){
136 return -1;
137 }
138 clear_data(hLdacAbr->TxQD_Info.pHist, hLdacAbr->TxQD_Info.szHist * sizeof(unsigned char));
139
140 hLdacAbr->nSteadyState = 0;
141 hLdacAbr->nPenalty = 1;
142 hLdacAbr->abrQualityModeIdSteady = aEqmidToAbrQualityModeID[LDACBT_EQMID_HQ];
143 hLdacAbr->cntToIncQuality = LDAC_ABR_OBSERVING_COUNT_FOR_INIT;
144 /* thresholds */
145 hLdacAbr->thCritical = LDAC_ABR_THRESHOLD_CRITICAL_DEFAULT;
146 hLdacAbr->thDangerousTrend = LDAC_ABR_THRESHOLD_DANGEROUSTREND_DEFAULT;
147 hLdacAbr->thSafety4HQSQ = LDAC_ABR_THRESHOLD_SAFETY_FOR_HQSQ_DEFAULT;
148
149 return 0;
150 }
151
152 /* Setup thresholds for LDAC ABR */
ldac_ABR_set_thresholds(HANDLE_LDAC_ABR hLdacAbr,unsigned int thCritical,unsigned int thDangerousTrend,unsigned int thSafety4HQSQ)153 int ldac_ABR_set_thresholds( HANDLE_LDAC_ABR hLdacAbr, unsigned int thCritical,
154 unsigned int thDangerousTrend, unsigned int thSafety4HQSQ )
155 {
156 ABRDBG( "thCritical=%u, thDangerousTrend=%u, thSafety4HQSQ=%u",
157 thCritical, thDangerousTrend, thSafety4HQSQ);
158 if (hLdacAbr == NULL) return -1;
159 if (thCritical < thDangerousTrend) return -1;
160 if (thDangerousTrend < thSafety4HQSQ) return -1;
161 hLdacAbr->thCritical = thCritical;
162 hLdacAbr->thDangerousTrend = thDangerousTrend;
163 hLdacAbr->thSafety4HQSQ = thSafety4HQSQ;
164 return 0;
165 }
166
167 /* LDAC ABR main process */
ldac_ABR_Proc(HANDLE_LDAC_BT hLDAC,HANDLE_LDAC_ABR hLdacAbr,unsigned int TxQueueDepth,unsigned int flagEnable)168 int ldac_ABR_Proc( HANDLE_LDAC_BT hLDAC, HANDLE_LDAC_ABR hLdacAbr,
169 unsigned int TxQueueDepth, unsigned int flagEnable)
170 {
171 int nStepsToChangeEQMID, abrQualityModeID, eqmid, i;
172 unsigned int TxQD_curr, TxQD_prev;
173 #ifdef LOCAL_DEBUG
174 int qd, TxQ; // for debug
175 #endif
176
177 if (hLDAC == NULL) return -1;
178 if (hLdacAbr == NULL) return -1;
179
180 eqmid = ldacBT_get_eqmid(hLDAC);
181 abrQualityModeID = -1;
182 if ((LDACBT_EQMID_HQ <= eqmid) && (eqmid < sizeOfEqmidToBitrateSortedIdTable)) {
183 abrQualityModeID = aEqmidToAbrQualityModeID[eqmid];
184 }
185 #ifdef LOCAL_DEBUG
186 ABRDBG( "[LDAC ABR] - abrQualityModeID : %d -- eqmid : %d -- TxQue : %d --------------",
187 abrQualityModeID, eqmid, TxQueueDepth);
188 #endif
189 /* check for the situation when unsupported eqmid was return from ldacBT_get_eqmid(). */
190 if (abrQualityModeID < 0) return eqmid; /* return current eqmid. */
191
192 /* update */
193 TxQD_curr = TxQueueDepth;
194 if ((i = hLdacAbr->TxQD_Info.idx - 1) < 0 ) i = hLdacAbr->TxQD_Info.szHist - 1;
195 TxQD_prev = hLdacAbr->TxQD_Info.pHist[i];
196
197 hLdacAbr->TxQD_Info.sum -= hLdacAbr->TxQD_Info.pHist[hLdacAbr->TxQD_Info.idx];
198 hLdacAbr->TxQD_Info.pHist[hLdacAbr->TxQD_Info.idx] = (unsigned char)TxQD_curr;
199 if (++hLdacAbr->TxQD_Info.idx >= hLdacAbr->TxQD_Info.szHist) hLdacAbr->TxQD_Info.idx = 0;
200
201 hLdacAbr->TxQD_Info.sum += TxQD_curr;
202 ++hLdacAbr->TxQD_Info.cnt;
203
204 #ifdef LOCAL_DEBUG
205 qd = (abrQualityModeID * 100000000);
206 qd += (hLdacAbr->nPenalty * 1000000);
207 qd += (hLdacAbr->cntToIncQuality *1000);
208 qd += (hLdacAbr->nSteadyState);
209 TxQ = TxQD_prev * 100 + TxQD_curr;
210 #endif
211
212 /* judge */
213 nStepsToChangeEQMID = 0;
214 if (TxQD_curr >= hLdacAbr->thCritical) {
215 /* for Critical situation */
216 ABRDBG("Critical: %d, %d", TxQ, qd);
217 nStepsToChangeEQMID = -1;
218 if ((eqmid == LDACBT_EQMID_HQ) || (eqmid == LDACBT_EQMID_SQ)) {
219 nStepsToChangeEQMID = -2;
220 }
221 }
222 else if ((TxQD_curr > hLdacAbr->thDangerousTrend) && (TxQD_curr > TxQD_prev)) {
223 ABRDBG("Dangerous: %d, %d", TxQ, qd);
224 nStepsToChangeEQMID = -1;
225 }
226 else if ((TxQD_curr > hLdacAbr->thSafety4HQSQ) &&
227 ((eqmid == LDACBT_EQMID_HQ) || (eqmid == LDACBT_EQMID_SQ))) {
228 ABRDBG("Safety4HQSQ: %d, %d", TxQ, qd);
229 nStepsToChangeEQMID = -1;
230 }
231 else if (hLdacAbr->TxQD_Info.cnt >= hLdacAbr->numToEvaluate) {
232 int ave10;
233 hLdacAbr->TxQD_Info.cnt = hLdacAbr->numToEvaluate;
234 /* eanble average process */
235 ave10 = (hLdacAbr->TxQD_Info.sum * 10) / hLdacAbr->TxQD_Info.cnt;
236
237 if (ave10 > 15) { /* if average of TxQue_Count in 0.5[s] was larger than 1.5 */
238 ABRDBG("ave: %d, %d, %d", TxQ, qd, ave10);
239 nStepsToChangeEQMID = -1;
240 }
241 else {
242 ++hLdacAbr->nSteadyState;
243 #ifdef LOCAL_DEBUG
244 qd = (abrQualityModeID * 100000000);
245 qd += (hLdacAbr->nPenalty * 1000000);
246 qd += (hLdacAbr->cntToIncQuality *1000);
247 qd += (hLdacAbr->nSteadyState);
248 #endif
249
250 if (hLdacAbr->TxQD_Info.sum == 0) {
251 if (--hLdacAbr->cntToIncQuality <= 0) {
252 ABRDBG("inc1: %d, %d, %d", TxQ, qd, ave10);
253 nStepsToChangeEQMID = 1;
254 }
255 else {
256 ABRDBG("reset: %d, %d, %d", TxQ, qd, ave10);
257 hLdacAbr->TxQD_Info.cnt = 0; // reset the number of sample for average proc.
258 }
259 }
260 else {
261 ABRDBG( "reset cntToIncQuality, %d,%d, %d", TxQ,qd, ave10);
262 hLdacAbr->cntToIncQuality = LDAC_ABR_OBSERVING_COUNT_TO_JUDGE_INC_QUALITY
263 - 2 * abrQualityModeID;
264 if (abrQualityModeID >= hLdacAbr->abrQualityModeIdSteady) {
265 hLdacAbr->cntToIncQuality *= hLdacAbr->nPenalty;
266 }
267 }
268 }
269 }
270 #ifdef LOCAL_DEBUG
271 else {
272 ABRDBG("Nothing %d, hLdacAbr->TxQD_Info.cnt %u", TxQ, hLdacAbr->TxQD_Info.cnt);
273 }
274 #endif
275 if (flagEnable) {
276 if (nStepsToChangeEQMID) {
277 int abrQualityModeIDNew;
278 if (nStepsToChangeEQMID < 0) {
279 for (i = 0; i > nStepsToChangeEQMID; --i) {
280 if (ldacBT_alter_eqmid_priority(hLDAC, LDACBT_EQMID_INC_CONNECTION)) {
281 #ifdef LOCAL_DEBUG
282 int err;
283 err = ldacBT_get_error_code(hLDAC);
284 ABRDBG("Info@%d : %d ,%d, %d", __LINE__,
285 LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err), LDACBT_BLOCK_ERR(err));
286 #endif
287 break;// EQMID was already the ID of the highest connectivity.
288 }
289 }
290
291 eqmid = ldacBT_get_eqmid(hLDAC);
292 abrQualityModeIDNew = abrQualityModeID;
293 if (eqmid >= 0) {
294 if (eqmid < sizeOfEqmidToBitrateSortedIdTable) {
295 abrQualityModeIDNew = aEqmidToAbrQualityModeID[eqmid];
296 }
297 }
298
299 if (hLdacAbr->nSteadyState < LDAC_ABR_NUM_STEADY_STATE_TO_JUDGE_STEADY) {
300 hLdacAbr->abrQualityModeIdSteady = abrQualityModeIDNew - 1;
301 if (hLdacAbr->abrQualityModeIdSteady < 0) hLdacAbr->abrQualityModeIdSteady = 0;
302 hLdacAbr->nPenalty *= 2;
303 if(hLdacAbr->nPenalty > LDAC_ABR_PENALTY_MAX) {
304 hLdacAbr->nPenalty = LDAC_ABR_PENALTY_MAX; // MAX PENALTY
305 }
306 }
307 }
308 else {
309 if (ldacBT_alter_eqmid_priority( hLDAC, LDACBT_EQMID_INC_QUALITY )) {
310 #ifdef LOCAL_DEBUG
311 int err;
312 err = ldacBT_get_error_code(hLDAC);
313 ABRDBG("Info@%d : %d ,%d, %d", __LINE__,
314 LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err), LDACBT_BLOCK_ERR(err));
315 #endif
316 ;// EQMID was already the ID of the highest sound quality.
317 }
318 eqmid = ldacBT_get_eqmid(hLDAC);
319 abrQualityModeIDNew = abrQualityModeID;
320 if (eqmid >= 0) {
321 if (eqmid < sizeOfEqmidToBitrateSortedIdTable) {
322 abrQualityModeIDNew = aEqmidToAbrQualityModeID[eqmid];
323 }
324 }
325 if (abrQualityModeIDNew < hLdacAbr->abrQualityModeIdSteady) {
326 hLdacAbr->nPenalty = 1;
327 }
328 if (abrQualityModeIDNew == aEqmidToAbrQualityModeID[0]) { /* for HQ */
329 if (hLdacAbr->nSteadyState > LDAC_ABR_NUM_STEADY_STATE_TO_RESET_PENALTY_FOR_HQ) {
330 hLdacAbr->nPenalty = 1;
331 }
332 }
333 }
334
335 hLdacAbr->nSteadyState = 0;
336 // reset the number of sample for average proc.
337 hLdacAbr->TxQD_Info.cnt = 0;
338 hLdacAbr->cntToIncQuality = LDAC_ABR_OBSERVING_COUNT_TO_JUDGE_INC_QUALITY
339 - 2 * abrQualityModeIDNew;
340 if (hLdacAbr->cntToIncQuality <= 0) {
341 // set minimum value. e1 f == 0.5[s]
342 hLdacAbr->cntToIncQuality = 1;
343 }
344 hLdacAbr->cntToIncQuality *= hLdacAbr->nPenalty;
345 ABRDBG("EQMID NOW %d", eqmid);
346 }
347 }
348 #ifdef LOCAL_DEBUG
349 else if (TxQueueDepth) {
350 ABRDBG("flagEnable false: %d ,%d", TxQ, qd);
351 }
352 #endif
353
354 return eqmid;
355 }
356