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