/* Copyright Statement: * * * * This software/firmware and related documentation ("MediaTek Software") are * * protected under relevant copyright laws. The information contained herein * * is confidential and proprietary to MediaTek Inc. and/or its licensors. * * Without the prior written permission of MediaTek inc. and/or its licensors, * * any reproduction, modification, use or disclosure of MediaTek Software, * * and information contained herein, in whole or in part, shall be strictly * * prohibited. * * * * MediaTek Inc. (C) 2016. All rights reserved. * * * * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES * * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") * * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER * * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL * * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * * NONINFRINGEMENT. * * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE * * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR * * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO * * SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER * * EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN * * FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK SOFTWARE. * * MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES * * MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR * * OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND * * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED * * HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK * * SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE * * PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. * * * * The following software/firmware and/or related documentation ("MediaTek Software") * * have been modified by MediaTek Inc. All revisions are subject to any receiver's * * applicable license agreements with MediaTek Inc. * */ #define LOG_TAG "a2dp_aac_vbr" #define ATRACE_TAG ATRACE_TAG_AUDIO #include #ifndef OS_GENERIC #include #endif #include #include #include #include #include "common/time_util.h" #include "osi/include/log.h" #include "osi/include/osi.h" #include "mtk_btif_av.h" #include "a2dp_aac_encoder.h" #include "a2dp_aac_constants.h" #include "osi/include/properties.h" #include "mediatek/stack/include/a2dp_aac_vbr.h" #if defined(MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) #include "interop_mtk.h" #include "btif_av.h" #endif static bool bPropSupportVbr; static int iPeerSupportVbrVal; static bool bPropUpdate = false; static int iMaxVbrMode; // Here, Set VBR params: #define DOWN_QUEUE_LENGTH (2) /*!< If >= DOWN_QUEUE_LENGTH, It's mean link bad state */ #define UP_QUEUE_LENGTH (0) /*!< If = UP_QUEUE_LENGTH, It's mean link good state */ #define DOWN_SAMPLE_COUNT (10) /*!< Down: Sample 10*20ms=200ms. */ #define UP_SAMPLE_COUNT (50) /*!< Up: Sample 50*20ms=1s. */ #define DOWN_ADJ_VBR_LEVEL (2) /*!< If the current mode >= mode3, adjust to reduce two level */ #define MIN_A2DP_VBR_MODE (AACENC_BR_MODE_VBR_1) #define MAX_A2DP_VBR_MODE (AACENC_BR_MODE_VBR_5) #define AAC_VBR_DEFAULT_MODE (AACENC_BR_MODE_VBR_4) struct vbr_helper_st { unsigned int dnBitrateCnt; unsigned int dnBitrateSum; unsigned int dnthreshold; unsigned int upBitrateCnt; unsigned int upBitrateSum; unsigned int upthreshold; int last_mode; int cur_mode; }; static struct vbr_helper_st stVbrHelper = { 0, 0, DOWN_SAMPLE_COUNT, 0, 0, UP_SAMPLE_COUNT, AACENC_BR_MODE_INVALID, AAC_VBR_DEFAULT_MODE}; static void resetDnBitRateParam() { stVbrHelper.dnBitrateCnt = 0; stVbrHelper.dnBitrateSum = 0; } static void resetUpBitRateParam() { stVbrHelper.upBitrateCnt = 0; stVbrHelper.upBitrateSum = 0; } void mtk_aac_vbr_prop_updated() { bPropUpdate = false; } void mtk_aac_vbr_set_support(int bitrate_support_val) { iPeerSupportVbrVal = bitrate_support_val; } void mtk_aac_vbr_set_max_mode(int max_vbr_mode) { iMaxVbrMode = max_vbr_mode; } int mtk_aac_vbr_get_max_mode() { return (int)iMaxVbrMode > MAX_A2DP_VBR_MODE ? AAC_VBR_DEFAULT_MODE : iMaxVbrMode; } /******************************************************************************* ** ** Function mtk_aac_vbr_enabled ** ** Description Check AAC VBR for enable, Input three Vaule: ** 1). persist.bluetooth.a2dp_aac_vbr.enable. ** 2). iPeerSupportVbrVal. ** 3). bPropUpdate. ** ** Returns bool ** *******************************************************************************/ bool mtk_aac_vbr_enabled() { if (!bPropUpdate) { char value_aacvbr[PROPERTY_VALUE_MAX] = {'\0'}; osi_property_get("vendor.bluetooth.a2dp_aac_vbr.enable", value_aacvbr, "true"); bPropSupportVbr = (strcmp(value_aacvbr, "true") == 0); bPropUpdate = true; } return (iPeerSupportVbrVal == A2DP_AAC_VARIABLE_BIT_RATE_ENABLED) && bPropUpdate && bPropSupportVbr; } /******************************************************************************* ** ** Function mtk_aac_vbr_get_mode ** ** Description Input queueLen to gets the current VBR mode. ** ** Returns int vbr_mode ** *******************************************************************************/ int mtk_aac_vbr_get_mode(size_t queueLen) { int vbr_mode = AACENC_BR_MODE_INVALID; stVbrHelper.upBitrateSum += queueLen; stVbrHelper.dnBitrateSum += queueLen; stVbrHelper.upBitrateCnt++; stVbrHelper.dnBitrateCnt++; if (stVbrHelper.dnBitrateCnt >= stVbrHelper.dnthreshold) { size_t queueLength = stVbrHelper.dnBitrateSum / stVbrHelper.dnBitrateCnt; resetDnBitRateParam(); if (queueLength >= DOWN_QUEUE_LENGTH && stVbrHelper.cur_mode > MIN_A2DP_VBR_MODE) { if (stVbrHelper.cur_mode >= AACENC_BR_MODE_VBR_3) stVbrHelper.cur_mode -= DOWN_ADJ_VBR_LEVEL; else stVbrHelper.cur_mode = MIN_A2DP_VBR_MODE; LOG_INFO("%s: [Down Bitrate] Adjust to low VBR mode(%d), queue length(%zu)", __func__, stVbrHelper.cur_mode, queueLength); resetUpBitRateParam(); } } if (stVbrHelper.upBitrateCnt >= stVbrHelper.upthreshold) { size_t queueLength = stVbrHelper.upBitrateSum / stVbrHelper.upBitrateCnt; resetUpBitRateParam(); int support_max_vbr_mode = mtk_aac_vbr_get_max_mode(); if (queueLength == UP_QUEUE_LENGTH && stVbrHelper.cur_mode < support_max_vbr_mode) { stVbrHelper.cur_mode++; if (stVbrHelper.cur_mode > support_max_vbr_mode) stVbrHelper.cur_mode = support_max_vbr_mode; LOG_INFO("%s: [Up Bitrate] Adjust to high VBR mode(%d)", __func__, stVbrHelper.cur_mode); resetDnBitRateParam(); } } if (stVbrHelper.last_mode != stVbrHelper.cur_mode) { vbr_mode = stVbrHelper.cur_mode; stVbrHelper.last_mode = vbr_mode; } return vbr_mode; } #undef ATRACE_TAG