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 */ 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 */ 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 */ 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 */ 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 */ 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