Home | History | Annotate | Download | only in src
      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