Audio-hal: Variable bit rate mode support for aac.

Add bit rate mode support for aac codec.

Change-Id: I72a5bc3d4a88a02b5203198bcabf7f0ee9e1a59c
diff --git a/configs/lito/lito.mk b/configs/lito/lito.mk
index f0838f9..4de7076 100644
--- a/configs/lito/lito.mk
+++ b/configs/lito/lito.mk
@@ -407,6 +407,10 @@
 PRODUCT_PROPERTY_OVERRIDES += \
 persist.vendor.bt.aac_frm_ctl.enabled=true
 
+#enable VBR frame ctl
+PRODUCT_PROPERTY_OVERRIDES += \
+persist.vendor.bt.aac_vbr_frm_ctl.enabled=true
+
 #add dynamic feature flags here
 ifeq ($(GENERIC_ODM_IMAGE),true)
 # Generic ODM varient related
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index e0aebf0..00e581f 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -250,6 +250,7 @@
 typedef enum {
     MTU_SIZE,
     PEAK_BIT_RATE,
+    BIT_RATE_MODE,
 } frame_control_type_t;
 
 // --- external function dependency ---
@@ -390,6 +391,7 @@
     /* Control value
      * MTU_SIZE: MTU size in bytes
      * PEAK_BIT_RATE: Peak bitrate in bits per second.
+     * BIT_RATE_MODE: Variable bitrate
      */
     uint32_t ctl_value;
 };
@@ -451,6 +453,12 @@
     struct aac_frame_size_control_t frame_ctl;
 } __attribute__ ((packed));
 
+struct aac_enc_cfg_v3_t {
+    struct aac_enc_cfg_t aac_enc_cfg;
+    struct aac_frame_size_control_t frame_ctl;
+    struct aac_frame_size_control_t aac_key_value_ctl;
+} __attribute__ ((packed));
+
 typedef struct audio_aac_decoder_config_t audio_aac_decoder_config_t;
 struct audio_aac_decoder_config_t {
     uint16_t      aac_fmt_flag; /* LATM*/
@@ -710,6 +718,13 @@
     struct aac_frame_size_control_t frame_ctl;
 } audio_aac_encoder_config_v2;
 
+typedef struct {
+    audio_aac_encoder_config audio_aac_enc_cfg;
+    struct aac_frame_size_control_t frame_ctl;
+    uint8_t size_control_struct;
+    struct aac_frame_size_control_t* frame_ptr_ctl;
+} audio_aac_encoder_config_v3;
+
 /* Information about BT CELT encoder configuration
  * This data is used between audio HAL module and
  * BT IPC library to configure DSP encoder
@@ -2173,6 +2188,76 @@
     return is_configured;
 }
 
+bool configure_aac_enc_format_v3(audio_aac_encoder_config_v3 *aac_bt_cfg)
+{
+    struct mixer_ctl *ctl_enc_data = NULL;
+    struct aac_enc_cfg_v3_t aac_dsp_cfg;
+    struct aac_frame_size_control_t* frame_vbr_ctl = NULL;
+    bool is_configured = false;
+    int ret = 0;
+
+    if (aac_bt_cfg == NULL)
+        return false;
+
+    ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
+    if (!ctl_enc_data) {
+        ALOGE(" ERROR  a2dp encoder CONFIG data mixer control not identifed");
+        is_configured = false;
+        goto fail;
+    }
+    memset(&aac_dsp_cfg, 0x0, sizeof(struct aac_enc_cfg_v3_t));
+    aac_dsp_cfg.aac_enc_cfg.enc_format = MEDIA_FMT_AAC;
+    aac_dsp_cfg.aac_enc_cfg.bit_rate = aac_bt_cfg->audio_aac_enc_cfg.bitrate;
+    aac_dsp_cfg.aac_enc_cfg.sample_rate = aac_bt_cfg->audio_aac_enc_cfg.sampling_rate;
+    switch (aac_bt_cfg->audio_aac_enc_cfg.enc_mode) {
+        case 0:
+            aac_dsp_cfg.aac_enc_cfg.enc_mode = MEDIA_FMT_AAC_AOT_LC;
+            break;
+        case 2:
+            aac_dsp_cfg.aac_enc_cfg.enc_mode = MEDIA_FMT_AAC_AOT_PS;
+            break;
+        case 1:
+        default:
+            aac_dsp_cfg.aac_enc_cfg.enc_mode = MEDIA_FMT_AAC_AOT_SBR;
+            break;
+    }
+    aac_dsp_cfg.aac_enc_cfg.aac_fmt_flag = aac_bt_cfg->audio_aac_enc_cfg.format_flag;
+    aac_dsp_cfg.aac_enc_cfg.channel_cfg = aac_bt_cfg->audio_aac_enc_cfg.channels;
+    aac_dsp_cfg.frame_ctl.ctl_type = aac_bt_cfg->frame_ctl.ctl_type;
+    aac_dsp_cfg.frame_ctl.ctl_value = aac_bt_cfg->frame_ctl.ctl_value;
+    frame_vbr_ctl =  aac_bt_cfg->frame_ptr_ctl;
+
+    if (frame_vbr_ctl != NULL) {
+        aac_dsp_cfg.aac_key_value_ctl.ctl_type = frame_vbr_ctl->ctl_type;
+        aac_dsp_cfg.aac_key_value_ctl.ctl_value = frame_vbr_ctl->ctl_value;
+    } else {
+        ALOGE("%s: VBR cannot be enabled, fall back to default",__func__);
+        aac_dsp_cfg.aac_key_value_ctl.ctl_type = 0;
+        aac_dsp_cfg.aac_key_value_ctl.ctl_value = 0;
+    }
+
+    ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aac_dsp_cfg,
+                              sizeof(struct aac_enc_cfg_v3_t));
+    if (ret != 0) {
+        ALOGE("%s: Failed to set AAC encoder config", __func__);
+        is_configured = false;
+        goto fail;
+    }
+    ret = a2dp_set_bit_format(aac_bt_cfg->audio_aac_enc_cfg.bits_per_sample);
+    if (ret != 0) {
+        is_configured = false;
+        goto fail;
+    }
+    is_configured = true;
+    a2dp.bt_encoder_format = CODEC_TYPE_AAC;
+    a2dp.enc_sampling_rate = aac_bt_cfg->audio_aac_enc_cfg.sampling_rate;
+    a2dp.enc_channels = aac_bt_cfg->audio_aac_enc_cfg.channels;
+    ALOGV("%s: Successfully updated AAC enc format with sampling rate: %d channels:%d",
+           __func__, aac_dsp_cfg.aac_enc_cfg.sample_rate, aac_dsp_cfg.aac_enc_cfg.channel_cfg);
+fail:
+    return is_configured;
+}
+
 bool configure_celt_enc_format(audio_celt_encoder_config *celt_bt_cfg)
 {
     struct mixer_ctl *ctl_enc_data = NULL;
@@ -2361,11 +2446,16 @@
 #endif
         case CODEC_TYPE_AAC:
             ALOGD(" Received AAC encoder supported BT device");
+            bool is_aac_vbr_enabled =
+                    property_get_bool("persist.vendor.bt.aac_vbr_frm_ctl.enabled", false);
             bool is_aac_frame_ctl_enabled =
                     property_get_bool("persist.vendor.bt.aac_frm_ctl.enabled", false);
-            is_configured = is_aac_frame_ctl_enabled ?
-                  configure_aac_enc_format_v2((audio_aac_encoder_config_v2 *) codec_info) :
-                  configure_aac_enc_format((audio_aac_encoder_config *) codec_info);
+            if (is_aac_vbr_enabled)
+                is_configured = configure_aac_enc_format_v3((audio_aac_encoder_config_v3 *) codec_info);
+            else
+                is_configured = is_aac_frame_ctl_enabled ?
+                                configure_aac_enc_format_v2((audio_aac_encoder_config_v2 *) codec_info) :
+                                configure_aac_enc_format((audio_aac_encoder_config *) codec_info);
             break;
         case CODEC_TYPE_CELT:
             ALOGD(" Received CELT encoder supported BT device");