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");