Audio: mp3 ad mix level not work [1/1]

PD#SWPL-188029

Problem:
1)there's no process about mp3 ad mix level
and ad vol when nonms12;
2)and no process about mp3 pan/fade.

Solution:
1) in ms12 case, ms12 process mp3 ad mix level
and ad vol;
in nonms12, add decoder gain for mp3 and aac,
and then decoders only need care and apply the
decoder gain, and not need care about
pan/fade/ad vol/mix level.

2) ad vol, mix level and pan are convert to
ad's mp3 decoder gain,
mix level and fade are also convert to
main's mp3 decoder gain.

Verify:
yocto.

Change-Id: I92d6a251f4049ac3dea35bbddb337baefee9d82d
Signed-off-by: wei.wang1 <wei.wang1@amlogic.com>
diff --git a/audio_hal/aml_audio_ms12_render.c b/audio_hal/aml_audio_ms12_render.c
index 089cd68..caefe00 100644
--- a/audio_hal/aml_audio_ms12_render.c
+++ b/audio_hal/aml_audio_ms12_render.c
@@ -186,7 +186,7 @@
     int left_bytes    = ainput.size;
     struct audio_buffer out_abuffer = {0};
 
-    AM_LOGI_IF(debug_enable, "new_in_pts:0x%"PRIx64" (%"PRId64" ms) size: %"PRId32"", ainput.pts, ainput.pts/90, ainput.size);
+    AM_LOGI_IF(debug_enable, "dec: %p, new_in_pts:0x%"PRIx64" (%"PRId64" ms) size: %"PRId32"", aml_dec, ainput.pts, ainput.pts/90, ainput.size);
     do {
         ainput.buffer += used_size;
         ainput.size   = left_bytes;
@@ -328,7 +328,7 @@
         ainput.buffer += used_size;
         ainput.size   = left_bytes;
 
-        AM_LOGI_IF(adev->debug_flag, "out %p,in pts:0x%"PRIx64" (%"PRId64" ms) size: %"PRId32", used %d, total used %d", aml_out,
+        AM_LOGI_IF(adev->debug_flag, "out %p, dec: %p, in pts:0x%"PRIx64" (%"PRId64" ms) size: %"PRId32", used %d, total used %d", aml_out, aml_dec,
             ainput.pts, ainput.pts/90, ainput.size, used_size, dec_used_size);
         ret = aml_decoder_process(aml_dec, &ainput, &used_size);
         if (0 > ret) {
diff --git a/audio_hal/aml_audio_nonms12_render.c b/audio_hal/aml_audio_nonms12_render.c
index 783c808..72882ba 100644
--- a/audio_hal/aml_audio_nonms12_render.c
+++ b/audio_hal/aml_audio_nonms12_render.c
@@ -236,7 +236,7 @@
             ainput.buffer += used_size;
             ainput.size = left_bytes;
 
-            AM_LOGI_IF(adev->debug_flag, "in pts:0x%"PRIx64" (%"PRIu64" ms) size: %"PRId32"", ainput.pts, ainput.pts/90, ainput.size);
+            AM_LOGI_IF(adev->debug_flag, "dec: %p, in pts:0x%"PRIx64" (%"PRIu64" ms) size: %"PRId32"", aml_dec, ainput.pts, ainput.pts/90, ainput.size);
             int decoder_ret = -1;
             decoder_ret = aml_decoder_process(aml_dec, &ainput, &used_size);
             if (decoder_ret == AML_DEC_RETURN_TYPE_CACHE_DATA) {
@@ -945,13 +945,10 @@
 
     if (aml_out->ad_substream_supported) {
         ddp_config->decoding_mode = DDP_DECODE_MODE_AD_SUBSTREAM;
-    } else {
+    } else if (aml_out->dec_param.ad_mix_enable) {
         ddp_config->decoding_mode = DDP_DECODE_MODE_AD_INDEPENDENT;
-    }
-
-    audio_format_t output_format = get_dcvlib_output_format(aml_out->hal_internal_format, adev);
-    if (output_format != AUDIO_FORMAT_PCM_16_BIT && output_format != AUDIO_FORMAT_PCM_32_BIT) {
-            ddp_config->decoding_mode = DDP_DECODE_MODE_SINGLE;
+    } else {
+        ddp_config->decoding_mode = DDP_DECODE_MODE_SINGLE;
     }
 
     if (aml_out->hal_internal_format == AUDIO_FORMAT_E_AC3) {
@@ -1114,10 +1111,15 @@
     struct aml_stream_out *aml_out = (struct aml_stream_out *)stream;
     struct aml_audio_device *adev = aml_out->dev;
 
-    dec_config->ad_mixing_enable = aml_out->dec_param.ad_mix_enable;
-    dec_config->mixer_level = aml_out->dec_param.mixing_level;
-    dec_config->advol_level = aml_out->dec_param.advol_level;
-    AM_LOGI("mixer_level %d ad_mixing_enable %d advol %d", dec_config->mixer_level, dec_config->ad_mixing_enable, dec_config->advol_level);
+    if (eDolbyMS12Lib != adev->dolby_lib_type && aml_out->source_type == DTV_SRC) {
+        dec_config->dec_left_gain = dec_config->dec_right_gain = aml_out->dec_param.dec_gain;
+        dec_config->ad_mixing_enable = aml_out->dec_param.ad_mix_enable;
+        dec_config->mixer_level = aml_out->dec_param.mixing_level;
+        dec_config->advol_level = aml_out->dec_param.advol_level;
+        AM_LOGI("out %p, mixer_level %d ad_mixing_enable %d advol %d. dec gain %f", aml_out, dec_config->mixer_level, dec_config->ad_mixing_enable, dec_config->advol_level, dec_config->dec_left_gain);
+    } else {
+        dec_config->dec_left_gain = dec_config->dec_right_gain = 1.0;
+    }
 
 #ifdef NO_SERVER
     adev->decoder_drc_control = aml_audio_get_drc_control(&adev->alsa_mixer);
diff --git a/audio_hal/audio_hw.c b/audio_hal/audio_hw.c
index 34eee65..c62fc65 100644
--- a/audio_hal/audio_hw.c
+++ b/audio_hal/audio_hw.c
@@ -7754,6 +7754,7 @@
     dprintf(fd, "[AML_HAL]dap_out_drc_target_volume   : %10f\n", aml_dev->ms12.dap_out_drc_target_volume);
 
     dprintf(fd, "[AML_HAL]      master volume: %10f, mute: %d\n", aml_dev->master_volume, aml_dev->master_mute);
+    dprintf(fd, "[AML_HAL]      ad vol: %10d, mix level: %10d\n", aml_dev->advol_level, aml_dev->mixing_level);
     aml_decoder_info_dump(aml_dev, fd);
     aml_adev_stream_out_dump(aml_dev, fd);
     dprintf(fd, "\nAML stream outs:\n");
diff --git a/audio_hal/audio_hw.h b/audio_hal/audio_hw.h
index 09689e0..68eda67 100644
--- a/audio_hal/audio_hw.h
+++ b/audio_hal/audio_hw.h
@@ -655,7 +655,7 @@
     int ac4_prefer_presentation_selection;
     int ac4_presentation_id;
     unsigned int hal_decode_block_size;
-
+    float dec_gain;
     char ac4_1st_lang[4];
     char ac4_2nd_lang[4];
 } aml_dec_param_t;
diff --git a/audio_hal/audio_hw_ms12_v2.c b/audio_hal/audio_hw_ms12_v2.c
index 878cf79..2b57f11 100644
--- a/audio_hal/audio_hw_ms12_v2.c
+++ b/audio_hal/audio_hw_ms12_v2.c
@@ -1687,7 +1687,7 @@
     } while ((0 < associate_size) && !aml_out->fast_quit);
 
     if (get_ms12_dump_enable(DUMP_MS12_INPUT_ASSOCIATE)) {
-        dump_ms12_output_data((void*)associate_frame_buffer, dolby_ms12_input_bytes, MS12_INPUT_SYS_ASSOCIATE_FILE);
+        dump_ms12_output_data((void*)abuffer->buffer, abuffer->size, MS12_INPUT_SYS_ASSOCIATE_FILE);
     }
     return 0;
 }
diff --git a/decoder/aml_aac_dec_api.c b/decoder/aml_aac_dec_api.c
index 3766973..38e0d7a 100644
--- a/decoder/aml_aac_dec_api.c
+++ b/decoder/aml_aac_dec_api.c
@@ -59,7 +59,6 @@
     aml_dec_t  aml_dec;
     aml_faad_config_t aac_config;
     faad_decoder_operations_t faad_op;
-    faad_decoder_operations_t ad_faad_op;
     aml_dec_stream_info_t stream_info;
     unsigned long total_raw_size;
     unsigned long total_pcm_size;
@@ -69,20 +68,13 @@
     char remain_data[AAC_REMAIN_BUFFER_SIZE];
     int remain_size;
     uint64_t remain_data_pts; //unit 90k;
-    bool ad_mixing_enable;
-    int advol_level;
-    int  mixer_level;
-    char ad_remain_data[AAC_REMAIN_BUFFER_SIZE];
-    int ad_need_cache_frames;
-    int ad_remain_size;
-    unsigned char ad_fade;
-    unsigned char ad_pan;
+    float left_gain;
+    float right_gain;
 };
 
 static  int unload_faad_decoder_lib(struct aac_dec_t *aac_dec)
 {
     faad_decoder_operations_t *faad_op = &aac_dec->faad_op;
-    faad_decoder_operations_t *ad_faad_op = &aac_dec->ad_faad_op;
     if (faad_op != NULL ) {
         faad_op->init = NULL;
         faad_op->decode = NULL;
@@ -91,12 +83,6 @@
 
     }
 
-    if (ad_faad_op != NULL ) {
-        ad_faad_op->init = NULL;
-        ad_faad_op->decode = NULL;
-        ad_faad_op->release = NULL;
-        ad_faad_op->getinfo = NULL;
-    }
     if (aac_dec->pdecoder!= NULL) {
         dlclose(aac_dec->pdecoder);
         aac_dec->pdecoder = NULL;
@@ -108,7 +94,6 @@
 static  int load_faad_decoder_lib(struct aac_dec_t *aac_dec)
 {
     faad_decoder_operations_t *faad_op = &aac_dec->faad_op;
-    faad_decoder_operations_t *ad_faad_op = &aac_dec->ad_faad_op;
     aac_dec->pdecoder = dlopen(FAAD_LIB_PATH, RTLD_NOW);
     if (!aac_dec->pdecoder) {
         aac_dec->pdecoder = dlopen(FAAD_LIB_PATH1, RTLD_NOW);
@@ -119,7 +104,7 @@
     }
     ALOGV("<%s::%d>--[faad_op->pdecoder]", __FUNCTION__, __LINE__);
 
-    faad_op->init = ad_faad_op->init = (int (*) (void *)) dlsym(aac_dec->pdecoder, "audio_dec_init");
+    faad_op->init = (int (*) (void *)) dlsym(aac_dec->pdecoder, "audio_dec_init");
     if (faad_op->init == NULL) {
         ALOGE("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
         return -1;
@@ -127,7 +112,7 @@
         ALOGV("<%s::%d> audio_dec_init", __FUNCTION__, __LINE__);
     }
 
-    faad_op->decode = ad_faad_op->decode = (int (*)(void *, char *outbuf, int *outlen, char *inbuf, int inlen))
+    faad_op->decode = (int (*)(void *, char *outbuf, int *outlen, char *inbuf, int inlen))
                           dlsym(aac_dec->pdecoder, "audio_dec_decode");
     if (faad_op->decode  == NULL) {
         ALOGE("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
@@ -136,7 +121,7 @@
         ALOGV("<%s::%d>--[audio_dec_decode:]", __FUNCTION__, __LINE__);
     }
 
-    faad_op->release = ad_faad_op->release =(int (*)(void *)) dlsym(aac_dec->pdecoder, "audio_dec_release");
+    faad_op->release = (int (*)(void *)) dlsym(aac_dec->pdecoder, "audio_dec_release");
     if ( faad_op->release== NULL) {
         ALOGE("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
         return -1;
@@ -144,7 +129,7 @@
         ALOGV("<%s::%d>--[audio_dec_release:]", __FUNCTION__, __LINE__);
     }
 
-    faad_op->getinfo = ad_faad_op->getinfo = (int (*)(void *, AudioInfo *pAudioInfo)) dlsym(aac_dec->pdecoder, "audio_dec_getinfo");
+    faad_op->getinfo = (int (*)(void *, AudioInfo *pAudioInfo)) dlsym(aac_dec->pdecoder, "audio_dec_getinfo");
     if (faad_op->getinfo == NULL) {
         ALOGI("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
         return -1;
@@ -161,7 +146,6 @@
     aml_dec_t  *aml_dec = NULL;
     aml_faad_config_t *aac_config = NULL;
     dec_data_info_t *dec_aac_data = NULL;
-    dec_data_info_t *ad_dec_pcm_data = NULL;
 
     if (dec_config == NULL) {
         ALOGE("AAC config is NULL\n");
@@ -204,51 +188,27 @@
         goto exit;
     }
 
-    ad_dec_pcm_data = &aml_dec->ad_dec_pcm_data;
-
-    ad_dec_pcm_data->buf_size = AAC_MAX_LENGTH;
-    ad_dec_pcm_data->buf = (unsigned char*) aml_audio_calloc(1, ad_dec_pcm_data->buf_size);
-    if (!ad_dec_pcm_data->buf) {
-        ALOGE("malloc ad buffer failed\n");
-        goto exit;
-    }
-
-    ALOGI("ad_dec_pcm_data->buf %p", ad_dec_pcm_data->buf);
     if (load_faad_decoder_lib(aac_dec) == 0) {
        if (aac_config->aac_format == AUDIO_FORMAT_AAC_LATM) {
            aac_dec->faad_op.nAudioDecoderType = ACODEC_FMT_AAC_LATM;
-           aac_dec->ad_faad_op.nAudioDecoderType = ACODEC_FMT_AAC_LATM;
        } else if (aac_config->aac_format == AUDIO_FORMAT_AAC) {
            aac_dec->faad_op.nAudioDecoderType = ACODEC_FMT_AAC;
-           aac_dec->ad_faad_op.nAudioDecoderType = ACODEC_FMT_AAC;
        }
        int ret = aac_dec->faad_op.init((void *)&aac_dec->faad_op);
        if (ret != 0) {
            ALOGI("faad decoder init failed !");
            goto exit;
        }
-
-       ret = aac_dec->ad_faad_op.init((void *)&aac_dec->ad_faad_op);
-       if (ret != 0) {
-           ALOGI("faad decoder init failed !");
-           goto exit;
-       }
     } else {
          goto exit;
     }
     aml_dec->status = 1;
-    aac_dec->ad_need_cache_frames = AAC_AD_NEED_CACHE_FRAME_COUNT;
     *ppaml_dec = (aml_dec_t *)aac_dec;
-    aac_dec->ad_mixing_enable = dec_config->ad_mixing_enable;
-    aac_dec->mixer_level = dec_config->mixer_level;
-    aac_dec->advol_level = dec_config->advol_level;
-    aac_dec->ad_fade = dec_config->ad_fade;
-    aac_dec->ad_pan = dec_config->ad_pan;
+    aac_dec->left_gain = dec_config->dec_left_gain;
+    aac_dec->right_gain = dec_config->dec_right_gain;
     aac_dec->remain_size = 0;
     memset(aac_dec->remain_data , 0 , AAC_REMAIN_BUFFER_SIZE * sizeof(char ));
-    aac_dec->ad_remain_size = 0;
-    memset(aac_dec->ad_remain_data , 0 , AAC_REMAIN_BUFFER_SIZE * sizeof(char ));
-    ALOGE("%s success", __func__);
+    ALOGE("%s success, aac_dec: %p. gain(%f, %f)", __func__, aac_dec, aac_dec->left_gain, aac_dec->right_gain);
     return 0;
 
 exit:
@@ -256,9 +216,6 @@
         if (dec_aac_data->buf) {
             aml_audio_free(dec_aac_data->buf);
         }
-        if (ad_dec_pcm_data) {
-            aml_audio_free(ad_dec_pcm_data->buf);
-        }
         aml_audio_free(aac_dec);
     }
     *ppaml_dec = NULL;
@@ -272,7 +229,6 @@
     dec_data_info_t *ad_dec_pcm_data = NULL;
     struct aac_dec_t *aac_dec = (struct aac_dec_t *)aml_dec;
     faad_decoder_operations_t *faad_op = &aac_dec->faad_op;
-    faad_decoder_operations_t *ad_faad_op = &aac_dec->ad_faad_op;
     if (aml_dec != NULL) {
         dec_pcm_data = &aml_dec->dec_pcm_data;
         if (dec_pcm_data->buf) {
@@ -285,7 +241,6 @@
         if (ad_dec_pcm_data->buf) {
             aml_audio_free(ad_dec_pcm_data->buf);
         }
-        ad_faad_op->release((void *)ad_faad_op);
 
         unload_faad_decoder_lib(aac_dec);
         aml_audio_free(aml_dec);
@@ -295,7 +250,7 @@
 }
 static void dump_faad_data(void *buffer, int size, char *file_name)
 {
-   if (property_get_bool("vendor.audio.faad.outdump",false)) {
+   if (get_debug_value(AML_DUMP_AUDIOHAL_DECODER)) {
         FILE *fp1 = fopen(file_name, "a+");
         if (fp1) {
             int flen = fwrite((char *)buffer, 1, size, fp1);
@@ -319,17 +274,14 @@
     aac_dec = (struct aac_dec_t *)aml_dec;
     aac_config = &aac_dec->aac_config;
     faad_decoder_operations_t *faad_op = &aac_dec->faad_op;
-    faad_decoder_operations_t *ad_faad_op = &aac_dec->ad_faad_op;
     dec_data_info_t * dec_pcm_data = &aml_dec->dec_pcm_data;
-    dec_data_info_t * ad_dec_pcm_data = &aml_dec->ad_dec_pcm_data;
     memset(&pAudioInfo, 0, sizeof(pAudioInfo));
     memset(&pADAudioInfo, 0, sizeof(pADAudioInfo));
 
     int used_size = 0;
     int used_size_return = 0;
     int mark_remain_size = aac_dec->remain_size;
-    AM_LOGI_IF(aml_dec->debug_level, "remain_size %d bytes %d ad_mixing_enable %d advol_level %d mixer_level %d",
-        aac_dec->remain_size ,bytes, aac_dec->ad_mixing_enable, aac_dec->advol_level,aac_dec->mixer_level );
+    AM_LOGI_IF(aml_dec->debug_level, "remain_size %d bytes %d", aac_dec->remain_size ,bytes);
     if (bytes > 0) {
         if (true == abuffer->b_pts_valid)
         {
@@ -418,13 +370,15 @@
     dec_pcm_data->data_sr  = pAudioInfo.samplerate;
     dec_pcm_data->data_ch  = pAudioInfo.channels;
     dec_pcm_data->data_format  = aac_config->aac_format;
-    if (dec_pcm_data->data_len != ad_dec_pcm_data->data_len ) {
-        ALOGV("dec_pcm_data->data_len %d ad_dec_pcm_data->data_len %d",dec_pcm_data->data_len ,ad_dec_pcm_data->data_len);
+    if (aac_dec->left_gain < 1.0 || aac_dec->right_gain < 1.0) {
+        apply_left_right_volume(dec_pcm_data->buf, aac_dec->left_gain, aac_dec->right_gain, sizeof(uint16_t), dec_pcm_data->data_len);
     }
-    ad_dec_pcm_data->data_len  = 0;
-    dump_faad_data(dec_pcm_data->buf, dec_pcm_data->data_len, "/data/vendor/audiohal/faad_output.pcm");
-    AM_LOGI_IF(aml_dec->debug_level, "pts: 0x%"PRIx64" (%"PRId64" ms) pcm len %d, buffer len %d, used_size_return %d",
-        dec_pcm_data->pts, dec_pcm_data->pts/90, dec_pcm_data->data_len, dec_pcm_data->buf_size, used_size_return);
+    char file_name[128] = { 0 };
+    snprintf(file_name, 128, "/data/vendor/audiohal/%p.faad_output.pcm", aac_dec);
+
+    dump_faad_data(dec_pcm_data->buf, dec_pcm_data->data_len, file_name);
+    AM_LOGI_IF(aml_dec->debug_level, "dec %p, pts: 0x%"PRIx64" (%"PRId64" ms) pcm len %d, buffer len %d, used_size_return %d. gain(%f, %f)", aac_dec,
+        dec_pcm_data->pts, dec_pcm_data->pts/90, dec_pcm_data->data_len, dec_pcm_data->buf_size, used_size_return, aac_dec->left_gain, aac_dec->right_gain);
     return used_size_return;
 }
 
@@ -463,29 +417,14 @@
         return ret;
     }
     switch (config_type) {
-    case AML_DEC_CONFIG_MIXER_LEVEL: {
-        aac_dec->mixer_level = dec_config->mixer_level;
-        ALOGI("dec_config->mixer_level %d",dec_config->mixer_level);
+    case AML_DEC_CONFIG_LEFT_GAIN: {
+        aac_dec->left_gain = dec_config->dec_left_gain;
+        ALOGI("aac_dec(%p) left_gain %f", aac_dec, aac_dec->left_gain);
         break;
     }
-    case AML_DEC_CONFIG_MIXING_ENABLE: {
-        aac_dec->ad_mixing_enable = dec_config->ad_mixing_enable;
-        ALOGI("dec_config->ad_mixing_enable %d",dec_config->ad_mixing_enable);
-        break;
-    }
-    case AML_DEC_CONFIG_AD_VOL: {
-        aac_dec->advol_level = dec_config->advol_level;
-        ALOGI("dec_config->advol_level %d",dec_config->advol_level);
-        break;
-    }
-    case AML_DEC_CONFIG_FADE: {
-        aac_dec->ad_fade = dec_config->ad_fade;
-        ALOGI("dec_config->ad_fade %d",dec_config->ad_fade);
-        break;
-    }
-    case AML_DEC_CONFIG_PAN: {
-        aac_dec->ad_pan = dec_config->ad_pan;
-        ALOGI("dec_config->ad_pan %d",dec_config->ad_pan);
+    case AML_DEC_CONFIG_RIGHT_GAIN: {
+        aac_dec->right_gain = dec_config->dec_right_gain;
+        ALOGI("aac_dec(%p) right_gain %f", aac_dec, aac_dec->right_gain);
         break;
     }
     default:
diff --git a/decoder/aml_ddp_dec_api.c b/decoder/aml_ddp_dec_api.c
index d7fd12a..03fc122 100644
--- a/decoder/aml_ddp_dec_api.c
+++ b/decoder/aml_ddp_dec_api.c
@@ -707,7 +707,7 @@
     int ad_substream_supported = 0;
     AM_LOGV("%x %x", read_pointer[0], read_pointer[1]);
 
-    while (offset <  write_len -1) {
+    while (offset < write_len -1) {
         if ((read_pointer[0] == 0x0b && read_pointer[1] == 0x77) || \
                     (read_pointer[0] == 0x77 && read_pointer[1] == 0x0b)) {
             Get_Parameters(read_pointer, &mSample_rate, &mFrame_size, &mChNum,&is_eac3, &ad_substream_supported);
@@ -719,7 +719,6 @@
         read_pointer++;
     }
     return 0;
-
 }
 int dcv_decoder_process_patch(aml_dec_t * aml_dec, struct audio_buffer *abuffer)
 {
@@ -758,46 +757,7 @@
     dec_raw_data->data_len = 0;
     raw_in_data->data_len  = 0;
 
-    /* dual input is from dtv, and it is similar with MS12,
-     * main and associate is packaged with IEC61937
-     */
-    if (ddp_dec->decoding_mode == DDP_DECODE_MODE_AD_DUAL) {
-        int dual_decoder_used_bytes = 0;
-        int dual_input_ret = 0;
-        void *main_frame_buffer = NULL;
-        int main_frame_size = 0;
-        void *associate_frame_buffer = NULL;
-        int associate_frame_size = 0;
-        /*dual_input_ret = scan_dolby_main_associate_frame(buffer
-                 , bytes
-                 , &dual_decoder_used_bytes
-                 , &main_frame_buffer
-                 , &main_frame_size
-                 , &associate_frame_buffer
-                 , &associate_frame_size);
-        if (dual_input_ret) {
-            ALOGE("%s used size %d dont find the iec61937 format header, rescan next time!\n", __FUNCTION__, dual_decoder_used_bytes);
-            goto EXIT;
-        }*/
-        associate_frame_size = aml_dec->ad_size;
-        main_frame_size = abuffer->size;
-        ALOGV("main frame size =%d ad frame size =%d", main_frame_size, associate_frame_size);
-        if ((main_frame_size + associate_frame_size) > ddp_dec->inbuf_size) {
-            ALOGE("too big frame size =%d %d", main_frame_size, associate_frame_size);
-            goto EXIT;
-        }
-        /* copy main data */
-        memcpy((char *)ddp_dec->inbuf, abuffer->buffer, main_frame_size);
-        /* copy ad data */
-        memcpy((char *)ddp_dec->inbuf + main_frame_size, aml_dec->ad_data, associate_frame_size);
-        ddp_dec->remain_size = main_frame_size + associate_frame_size;
-        mFrame_size = main_frame_size + associate_frame_size;
-        n_bytes_frame = mFrame_size; // not used currently
-        read_pointer = ddp_dec->inbuf;
-        read_offset = 0;
-        in_sync = 1;
-        total_used_size = bytes;
-    } else {
+    {
         //check if the buffer overflow
         if ((ddp_dec->remain_size + bytes) > ddp_dec->inbuf_size) {
             ALOGE("too big input size =%d %d", ddp_dec->remain_size, bytes);
diff --git a/decoder/aml_dec_api.c b/decoder/aml_dec_api.c
index bf5cbb0..25ba127 100644
--- a/decoder/aml_dec_api.c
+++ b/decoder/aml_dec_api.c
@@ -140,12 +140,6 @@
     aml_dec_handel->frame_cnt = 0;
     aml_dec_handel->format = format;
     aml_dec_handel->fragment_left_size = 0;
-    dec_config->advol_level = 100;
-    dec_config->mixer_level = 0;
-    dec_config->ad_fade = 0;
-    dec_config->ad_pan = 0;
-    aml_dec_handel->ad_data = NULL;
-    aml_dec_handel->ad_size = 0;
     aml_dec_handel->out_frame_pts = -1;
     aml_dec_handel->last_in_frame_pts = -1;
     aml_dec_handel->debug_level = get_debug_value(AML_DEBUG_AUDIOHAL_DECODED_INFO);
@@ -198,8 +192,6 @@
     }
 
     return ret;
-
-
 }
 int aml_decoder_set_config(aml_dec_t *aml_dec, aml_dec_config_type_t config_type, aml_dec_config_t * dec_config)
 {
@@ -409,30 +401,6 @@
 
 }
 
-void aml_decoder_calc_coefficient(unsigned char ad_fade,float * mix_coefficient,float * ad_coefficient)
-{
-            #define MAIN_MIXER_VAL (0.8709635900f)
-            #define AD_MIXER_VAL (0.4897788194f)
-            float mixing_coefficient = MAIN_MIXER_VAL;
-            float ad_mixing_coefficient = AD_MIXER_VAL;
-            if (ad_fade == 0)
-            {
-                //mixing_coefficient = 1.0f;
-                //ad_mixing_coefficient = 1.0f;
-            }
-            else if (ad_fade == 0xFF)
-            {
-                mixing_coefficient = 0.0f;
-                ad_mixing_coefficient = 0.0f;
-            }
-            else if ((ad_fade > 0) && (ad_fade < 0xff))
-            {
-                mixing_coefficient = (1.0f-(float)(ad_fade)/256)*MAIN_MIXER_VAL;
-                ad_mixing_coefficient = (1.0f-(float)(ad_fade)/256)*AD_MIXER_VAL;
-            }
-            *mix_coefficient = mixing_coefficient;
-            *ad_coefficient = ad_mixing_coefficient;
-}
 eDTSLibType_t detect_dts_lib_type(void)
 {
     void *hDTSLibHanle = NULL;
diff --git a/decoder/aml_dec_api.h b/decoder/aml_dec_api.h
index 0cdcb78..d2f2947 100644
--- a/decoder/aml_dec_api.h
+++ b/decoder/aml_dec_api.h
@@ -22,6 +22,7 @@
 #include "aml_ringbuffer.h"
 #include "aml_volume_utils.h"
 #include "aml_malloc_debug.h"
+#include "aml_dump_debug.h"
 #include "adec-armdec-mgt.h"
 #include "audio_buffer.h"
 #include "audio_hw_resource_mgr.h"
@@ -67,7 +68,9 @@
     AML_DEC_CONFIG_FADE,
     AML_DEC_CONFIG_PAN,
     AML_DEC_CONFIG_DRC_CONTROL,
-    AML_DEC_CONFIG_DOWNMIX_TYPE
+    AML_DEC_CONFIG_DOWNMIX_TYPE,
+    AML_DEC_CONFIG_LEFT_GAIN,
+    AML_DEC_CONFIG_RIGHT_GAIN,
 } aml_dec_config_type_t;
 
 typedef enum {
@@ -133,8 +136,6 @@
     dec_data_info_t dec_raw_data;
     dec_data_info_t raw_in_data;
     dec_data_info_t multi_channel_data;
-    char *ad_data;
-    int ad_size;
     int64_t last_in_frame_pts;
     int64_t out_frame_pts;
     int status;
@@ -239,10 +240,10 @@
     bool ad_mixing_enable;
     int advol_level;
     int  mixer_level;   /* AML_DEC_CONFIG_MIXER_LEVEL */
-    unsigned char ad_fade;
-    unsigned char ad_pan;
     int drc_control; /*config the drc control*/
     int downmix_type; /*config the dowmmix cfg*/
+    float dec_left_gain;
+    float dec_right_gain;
 } aml_dec_config_t;
 
 
@@ -275,7 +276,6 @@
 int aml_decoder_process(aml_dec_t *aml_dec, struct audio_buffer *abuffer, int * used_bytes);
 int aml_decoder_ad_process(struct audio_stream_out *stream, struct audio_buffer *abuffer, int *used_bytes);
 int aml_decoder_set_config(aml_dec_t *aml_dec, aml_dec_config_type_t config_type, aml_dec_config_t * dec_config);
-void aml_decoder_calc_coefficient(unsigned char ad_fade,float * mix_coefficient,float * ad_coefficient);
 int aml_decoder_get_info(aml_dec_t *aml_dec, aml_dec_info_type_t info_type, aml_dec_info_t * dec_info);
 eDTSLibType_t detect_dts_lib_type(void);
 eDTSLibType_t get_dts_lib_type(void);
diff --git a/decoder/aml_mpeg_dec_api.c b/decoder/aml_mpeg_dec_api.c
index f687961..713de2f 100644
--- a/decoder/aml_mpeg_dec_api.c
+++ b/decoder/aml_mpeg_dec_api.c
@@ -58,26 +58,18 @@
     aml_dec_t  aml_dec;
     aml_mad_config_t mad_config;
     mad_decoder_operations_t mad_op;
-    mad_decoder_operations_t ad_mad_op;
     aml_dec_stream_info_t stream_info;
     void *pdecoder;
     char remain_data[MAD_REMAIN_BUFFER_SIZE];
     int remain_size;
     uint64_t remain_data_pts; //unit 90k;
-    bool ad_mixing_enable;
-    int advol_level;
-    int  mixer_level;
-    char ad_remain_data[MAD_REMAIN_BUFFER_SIZE];
-    int ad_remain_size;
-    int ad_need_cache_frames;
-    unsigned char ad_fade;
-    unsigned char ad_pan;
+    float left_gain;
+    float right_gain;
 };
 
 static  int unload_mad_decoder_lib(struct mad_dec_t *mad_dec)
 {
     mad_decoder_operations_t *mad_op = &mad_dec->mad_op;
-    mad_decoder_operations_t *ad_mad_op = &mad_dec->ad_mad_op;
     if (mad_op != NULL ) {
         mad_op->init = NULL;
         mad_op->decode = NULL;
@@ -86,12 +78,6 @@
 
     }
 
-    if (ad_mad_op != NULL ) {
-        ad_mad_op->init = NULL;
-        ad_mad_op->decode = NULL;
-        ad_mad_op->release = NULL;
-        ad_mad_op->getinfo = NULL;
-    }
     if (mad_dec->pdecoder) {
         dlclose(mad_dec->pdecoder);
         mad_dec->pdecoder = NULL;
@@ -102,7 +88,6 @@
 static  int load_mad_decoder_lib(struct mad_dec_t *mad_dec)
 {
     mad_decoder_operations_t *mad_op = &mad_dec->mad_op;
-    mad_decoder_operations_t *ad_mad_op = &mad_dec->ad_mad_op;
     mad_dec->pdecoder = dlopen(MAD_LIB_PATH, RTLD_NOW);
     if (!mad_dec->pdecoder) {
         mad_dec->pdecoder = dlopen(MAD_LIB_PATH1, RTLD_NOW);
@@ -113,7 +98,7 @@
     }
     ALOGV("<%s::%d>--[faad_op->pdecoder]", __FUNCTION__, __LINE__);
 
-    mad_op->init = ad_mad_op->init = (int (*) (void *)) dlsym(mad_dec->pdecoder, "audio_dec_init");
+    mad_op->init = (int (*) (void *)) dlsym(mad_dec->pdecoder, "audio_dec_init");
     if (mad_op->init == NULL) {
         ALOGE("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
         return -1;
@@ -121,7 +106,7 @@
         ALOGV("<%s::%d> audio_dec_init", __FUNCTION__, __LINE__);
     }
 
-    mad_op->decode = ad_mad_op->decode = (int (*)(void *, char *outbuf, int *outlen, char *inbuf, int inlen))
+    mad_op->decode = (int (*)(void *, char *outbuf, int *outlen, char *inbuf, int inlen))
                           dlsym(mad_dec->pdecoder, "audio_dec_decode");
     if (mad_op->decode  == NULL) {
         ALOGE("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
@@ -130,7 +115,7 @@
         ALOGV("<%s::%d>--[audio_dec_decode:]", __FUNCTION__, __LINE__);
     }
 
-    mad_op->release = ad_mad_op->release = (int (*)(void *)) dlsym(mad_dec->pdecoder, "audio_dec_release");
+    mad_op->release = (int (*)(void *)) dlsym(mad_dec->pdecoder, "audio_dec_release");
     if ( mad_op->release== NULL) {
         ALOGE("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
         return -1;
@@ -138,7 +123,7 @@
         ALOGV("<%s::%d>--[audio_dec_release:]", __FUNCTION__, __LINE__);
     }
 
-    mad_op->getinfo = ad_mad_op->getinfo = (int (*)(void *, AudioInfo *pAudioInfo)) dlsym(mad_dec->pdecoder, "audio_dec_getinfo");
+    mad_op->getinfo = (int (*)(void *, AudioInfo *pAudioInfo)) dlsym(mad_dec->pdecoder, "audio_dec_getinfo");
     if (mad_op->getinfo == NULL) {
         ALOGI("%s,cant find decoder lib,%s\n", __FUNCTION__, dlerror());
         return -1;
@@ -155,7 +140,6 @@
     aml_dec_t  *aml_dec = NULL;
     aml_mad_config_t *mad_config = NULL;
     dec_data_info_t * dec_pcm_data = NULL;
-    dec_data_info_t * ad_dec_pcm_data = NULL;
 
     if (dec_config == NULL) {
         ALOGE("mad config is NULL\n");
@@ -192,42 +176,22 @@
         ALOGE("malloc buffer failed\n");
         goto exit;
     }
-    ad_dec_pcm_data = &aml_dec->ad_dec_pcm_data;
-
-    ad_dec_pcm_data->buf_size = MAD_MAX_LENGTH;
-    ad_dec_pcm_data->buf = (unsigned char*) aml_audio_calloc(1, ad_dec_pcm_data->buf_size);
-    if (!ad_dec_pcm_data->buf) {
-        ALOGE("malloc ad buffer failed\n");
-        goto exit;
-    }
     if (load_mad_decoder_lib(mad_dec) == 0) {
-
        int ret = mad_dec->mad_op.init((void *)&mad_dec->mad_op);
        if (ret != 0) {
            ALOGI("faad decoder init failed !");
            goto exit;
        }
-       ret = mad_dec->ad_mad_op.init((void *)&mad_dec->ad_mad_op);
-       if (ret != 0) {
-           ALOGI("mad ad decoder init failed !");
-           goto exit;
-       }
     } else {
          goto exit;
     }
     aml_dec->status = 1;
     *ppaml_dec = (aml_dec_t *)mad_dec;
-    mad_dec->ad_mixing_enable = dec_config->ad_mixing_enable;
-    mad_dec->mixer_level = dec_config->mixer_level;
-    mad_dec->advol_level = dec_config->advol_level;
-    mad_dec->ad_fade = dec_config->ad_fade;
-    mad_dec->ad_pan = dec_config->ad_pan;
-    mad_dec->ad_need_cache_frames = MAD_AD_NEED_CACHE_FRAME_COUNT;
     mad_dec->remain_size = 0;
+    mad_dec->left_gain = dec_config->dec_left_gain;
+    mad_dec->right_gain = dec_config->dec_left_gain;
     memset(mad_dec->remain_data , 0 , MAD_REMAIN_BUFFER_SIZE * sizeof(char ));
-    mad_dec->ad_remain_size = 0;
-    memset(mad_dec->ad_remain_data , 0 ,MAD_REMAIN_BUFFER_SIZE * sizeof(char ));
-    ALOGE("%s success", __func__);
+    ALOGE("%s success, mad_dec: %p. gain(%f, %f)", __func__, mad_dec, mad_dec->left_gain, mad_dec->right_gain);
     return 0;
 
 exit:
@@ -235,9 +199,6 @@
         if (dec_pcm_data->buf) {
             aml_audio_free(dec_pcm_data->buf);
         }
-        if (ad_dec_pcm_data) {
-            aml_audio_free(ad_dec_pcm_data->buf);
-        }
         aml_audio_free(mad_dec);
     }
     *ppaml_dec = NULL;
@@ -251,18 +212,12 @@
     dec_data_info_t *ad_dec_pcm_data = NULL;
     struct mad_dec_t *mad_dec = (struct mad_dec_t *)aml_dec;
     mad_decoder_operations_t *mad_op = &mad_dec->mad_op;
-    mad_decoder_operations_t *ad_mad_op = &mad_dec->ad_mad_op;
     if (aml_dec != NULL) {
         dec_pcm_data = &aml_dec->dec_pcm_data;
         if (dec_pcm_data->buf) {
             aml_audio_free(dec_pcm_data->buf);
         }
         mad_op->release((void *)mad_op);
-        ad_dec_pcm_data = &aml_dec->ad_dec_pcm_data;
-        if (ad_dec_pcm_data->buf) {
-            aml_audio_free(ad_dec_pcm_data->buf);
-        }
-        ad_mad_op->release((void *)ad_mad_op);
         unload_mad_decoder_lib(mad_dec);
         aml_audio_free(aml_dec);
     }
@@ -271,7 +226,7 @@
 }
 static void dump_mad_data(void *buffer, int size, char *file_name)
 {
-   if (property_get_bool("vendor.media.mad.dump",false)) {
+   if (get_debug_value(AML_DUMP_AUDIOHAL_DECODER)) {
         FILE *fp1 = fopen(file_name, "a+");
         if (fp1) {
             int flen = fwrite((char *)buffer, 1, size, fp1);
@@ -297,17 +252,14 @@
     mad_dec = (struct mad_dec_t *)aml_dec;
     mad_config = &mad_dec->mad_config;
     mad_decoder_operations_t *mad_op = &mad_dec->mad_op;
-    mad_decoder_operations_t *ad_mad_op = &mad_dec->ad_mad_op;
     dec_data_info_t * dec_pcm_data = &aml_dec->dec_pcm_data;
-    dec_data_info_t * ad_dec_pcm_data = &aml_dec->ad_dec_pcm_data;
     memset(&pAudioInfo, 0, sizeof(pAudioInfo));
     memset(&pADAudioInfo, 0, sizeof(pADAudioInfo));
 
     int used_size = 0;
     int used_size_return = 0;
     int mark_remain_size = mad_dec->remain_size;
-    AM_LOGI_IF(aml_dec->debug_level, "remain_size %d bytes %d ad_mixing_enable %d advol_level %d mixer_level %d",
-        mad_dec->remain_size, bytes, mad_dec->ad_mixing_enable, mad_dec->advol_level, mad_dec->mixer_level);
+    AM_LOGI_IF(aml_dec->debug_level, "remain_size %d bytes %d", mad_dec->remain_size, bytes);
     if (bytes > 0) {
         if ((mad_dec->remain_size  + bytes >=  MAD_REMAIN_BUFFER_SIZE) || (mad_dec->remain_size < 0)) {
            ALOGE("mad_dec->remain_size + bytes  %d > %d  ,overflow", mad_dec->remain_size + bytes, MAD_REMAIN_BUFFER_SIZE );
@@ -387,14 +339,15 @@
     dec_pcm_data->data_sr  = pAudioInfo.samplerate;
     dec_pcm_data->data_ch  = pAudioInfo.channels;
     dec_pcm_data->data_format  = mad_config->mpeg_format;
-    if (dec_pcm_data->data_len != ad_dec_pcm_data->data_len ) {
-        ALOGV("dec_pcm_data->data_len %d ad_dec_pcm_data->data_len %d",dec_pcm_data->data_len ,ad_dec_pcm_data->data_len);
+    if (mad_dec->left_gain < 1.0 || mad_dec->right_gain < 1.0) {
+        apply_left_right_volume(dec_pcm_data->buf, mad_dec->left_gain, mad_dec->right_gain, sizeof(uint16_t), dec_pcm_data->data_len);
     }
-    ad_dec_pcm_data->data_len  = 0;
-    dump_mad_data(dec_pcm_data->buf, dec_pcm_data->data_len, "/data/mad_output.pcm");
+    char file_name[128] = { 0 };
+    snprintf(file_name, 128, "/data/vendor/audiohal/%p.mad_output.pcm", mad_dec);
+    dump_mad_data(dec_pcm_data->buf, dec_pcm_data->data_len, file_name);
 
-    AM_LOGI_IF(aml_dec->debug_level, "pts: 0x%"PRIx64" (%"PRIu64" ms) pcm len %d, buffer len %d, used_size_return %d",
-        dec_pcm_data->pts, dec_pcm_data->pts/90, dec_pcm_data->data_len, dec_pcm_data->buf_size, used_size_return);
+    AM_LOGI_IF(aml_dec->debug_level, "dec %p, pts: 0x%"PRIx64" (%"PRIu64" ms) pcm len %d, buffer len %d, used_size_return %d. gain(%f, %f)", mad_dec,
+        dec_pcm_data->pts, dec_pcm_data->pts/90, dec_pcm_data->data_len, dec_pcm_data->buf_size, used_size_return, mad_dec->left_gain, mad_dec->right_gain);
     return used_size_return;
 }
 
@@ -427,29 +380,14 @@
         return ret;
     }
     switch (config_type) {
-    case AML_DEC_CONFIG_MIXER_LEVEL: {
-        mad_dec->mixer_level = dec_config->mixer_level;
-        ALOGI("dec_config->mixer_level %d",dec_config->mixer_level);
+    case AML_DEC_CONFIG_LEFT_GAIN: {
+        mad_dec->left_gain = dec_config->dec_left_gain;
+        ALOGI("mad_dec(%p) left_gain %f", mad_dec, mad_dec->left_gain);
         break;
     }
-    case AML_DEC_CONFIG_MIXING_ENABLE: {
-        mad_dec->ad_mixing_enable = dec_config->ad_mixing_enable;
-        ALOGI("dec_config->ad_mixing_enable %d",dec_config->ad_mixing_enable);
-        break;
-    }
-    case AML_DEC_CONFIG_AD_VOL: {
-        mad_dec->advol_level = dec_config->advol_level;
-        ALOGI("dec_config->advol_level %d",dec_config->advol_level);
-        break;
-    }
-    case AML_DEC_CONFIG_FADE: {
-        mad_dec->ad_fade = dec_config->ad_fade;
-        ALOGI("dec_config->ad_fade %d",dec_config->ad_fade);
-        break;
-    }
-    case AML_DEC_CONFIG_PAN: {
-        mad_dec->ad_pan = dec_config->ad_pan;
-        ALOGI("dec_config->ad_pan %d",dec_config->ad_pan);
+    case AML_DEC_CONFIG_RIGHT_GAIN: {
+        mad_dec->right_gain = dec_config->dec_right_gain;
+        ALOGI("mad_dec(%p) right_gain %f", mad_dec, mad_dec->right_gain);
         break;
     }
     default:
diff --git a/input/dtv_patch.c b/input/dtv_patch.c
index ec265a1..84e4f55 100644
--- a/input/dtv_patch.c
+++ b/input/dtv_patch.c
@@ -86,6 +86,8 @@
 static int create_dtv_ad_output_stream_thread(dtv_path_t *path);
 static int release_dtv_output_stream_thread(dtv_path_t *path);
 static int dtv_path_cmd_process_thread(void *data);
+static void dtv_update_ad_vol_parameter(dtv_path_t *path);
+static void dtv_update_pan_fade_parameter(dtv_path_t *path);
 
 static void dmx_enable_main(aml_demux_audiopara_t *demux_info, bool enable)
 {
@@ -325,14 +327,14 @@
             }
             adev->mixing_level = (val * 64 - 32 * 100) / 100; //[0,100] mapping to [-32,32]
             AM_LOGI("mixing_level set to %d", adev->mixing_level);
-            if (path->dtv_aml_out) {
+            if (path->dtv_aml_out && eDolbyMS12Lib == adev->dolby_lib_type) {
                 set_ms12_ad_mixing_level((struct audio_stream_out *)path->dtv_aml_out, adev->mixing_level);
             }
             break;
         case AUDIO_DTV_PATCH_CMD_SET_MEDIA_PRESENTATION_ID:
             demux_info->media_presentation_id = val;
             AM_LOGI("media_presentation_id %d", demux_info->media_presentation_id);
-            if (path->dtv_aml_out) {
+            if (path->dtv_aml_out && eDolbyMS12Lib == adev->dolby_lib_type) {
                 set_ms12_ac4_presentation_group_index((struct audio_stream_out *)path->dtv_aml_out, demux_info->media_presentation_id);
             }
             break;
@@ -341,7 +343,7 @@
             char first_lang[4] = {0};
             language_code_convert_to_string(demux_info->media_first_lang, first_lang);
             AM_LOGI("media_first_lang %s,%x,%d",first_lang,val,val);
-            if (path->dtv_aml_out) {
+            if (path->dtv_aml_out && eDolbyMS12Lib == adev->dolby_lib_type) {
                 set_ms12_ac4_1st_preferred_language_code((struct audio_stream_out *)path->dtv_aml_out, first_lang);
             }
             break;
@@ -351,7 +353,7 @@
             char second_lang[4] = {0};
             language_code_convert_to_string(demux_info->media_second_lang, second_lang);
             AM_LOGI("media_second_lang %s,%x,%d",second_lang, val, val);
-            if (path->dtv_aml_out) {
+            if (path->dtv_aml_out && eDolbyMS12Lib == adev->dolby_lib_type) {
                 set_ms12_ac4_2nd_preferred_language_code((struct audio_stream_out *)path->dtv_aml_out, second_lang);
             }
             break;
@@ -444,8 +446,11 @@
 
     //init decoder-related param, they would be used when config dec later
     aml_out->dec_param.ad_mix_enable = demux_info->associate_audio_mixing_enable;
-    aml_out->dec_param.advol_level = aml_dev->advol_level;
+    aml_out->dec_param.advol_level = aml_dev->advol_level;//to init ms12 and dcv decoder
     aml_out->dec_param.mixing_level = aml_dev->mixing_level;
+    if (eDolbyMS12Lib != aml_dev->dolby_lib_type && aml_out->hal_format != AUDIO_FORMAT_AC3 && aml_out->hal_format != AUDIO_FORMAT_E_AC3) {
+        aml_out->dec_param.dec_gain = demux_info->associate_audio_mixing_enable ? dtv_ad_mixlevel_vol_convert_to_gain(aml_out) : 1.0;//to init mp3/aac decoder gain
+    }
     if (aml_out->hal_format == AUDIO_FORMAT_AC4) {
         aml_out->dec_param.ac4_presentation_id = demux_info->media_presentation_id;
         language_code_convert_to_string(demux_info->media_first_lang, aml_out->dec_param.ac4_1st_lang);
@@ -559,7 +564,6 @@
     struct mAudioEsDataInfo *mAdEsData = NULL;
     struct audio_config stream_config;
     int ret = -1, ret_ad = 0, main_size_in_queue = 0, ad_size_in_queue = 0;
-    int associate_audio_mixing_enable = -1, mixing_level = 0, advol_level = 100;
     struct timespec ts, watch_start_ts;
     bool watch_flag = false, need_hold_data = false;
     aml_demux_audiopara_t *demux_info = (aml_demux_audiopara_t *)(&path->demux_info);
@@ -578,7 +582,7 @@
 
     if (aml_dev->hw_device.open_output_stream) {
         ret = aml_dev->hw_device.open_output_stream((struct audio_hw_device *)aml_dev, 0,
-                                        AUDIO_DEVICE_OUT_SPEAKER,        // devices_t
+                                        AUDIO_DEVICE_OUT_SPEAKER,
                                         AUDIO_OUTPUT_FLAG_DIRECT + AUDIO_OUTPUT_FLAG_AD_STREAM, // flags
                                         &stream_config, &ad_stream_out, "AML_DTV_SOURCE");
     }
@@ -588,6 +592,9 @@
     }
     ad_aml_out = (struct aml_stream_out *)ad_stream_out;
     path->dtv_ad_aml_out = ad_aml_out;
+    if (eDolbyMS12Lib != aml_dev->dolby_lib_type && ad_aml_out->hal_format != AUDIO_FORMAT_AC3 && ad_aml_out->hal_format != AUDIO_FORMAT_E_AC3) {
+        ad_aml_out->dec_param.dec_gain = dtv_ad_mixlevel_vol_convert_to_gain(ad_aml_out);//to init mp3/aac decoder gain
+    }
     AM_LOGI("create a AD output stream(%p) success now, ad_output_thread_exit %d. main stream %p", ad_aml_out, path->ad_output_thread_exit, main_aml_out);
 
     while (!path->ad_output_thread_exit) {
@@ -633,25 +640,12 @@
             continue;
         }
 #endif
-
-        if (associate_audio_mixing_enable != demux_info->associate_audio_mixing_enable
-            || advol_level != aml_dev->advol_level
-            || mixing_level != aml_dev->mixing_level) {
-            associate_audio_mixing_enable = demux_info->associate_audio_mixing_enable;
-            advol_level = aml_dev->advol_level;
-            mixing_level = aml_dev->mixing_level;
-            if (eDolbyMS12Lib == aml_dev->dolby_lib_type) {
-                set_ms12_ad_mixing_enable(ad_stream_out, associate_audio_mixing_enable);
-                set_ms12_ad_mixing_level(ad_stream_out, mixing_level);
-                set_ms12_ad_vol(ad_stream_out, advol_level);
-                AM_LOGI("associate_audio_mixing_enable:%d, advol_level:%d, mixing_level:%d",
-                        associate_audio_mixing_enable, advol_level, mixing_level);
-            }
-            if (false == associate_audio_mixing_enable) {
-                usleep(20000);
-                continue;
-            }
+        dtv_update_ad_vol_parameter(path);
+        if (0 == demux_info->associate_audio_mixing_enable) {
+            usleep(20000);
+            continue;
         }
+
         if (mAdEsData == NULL) {
             ret_ad = Get_ADAudio_Es(demux_handle, &mAdEsData);
             if (ret_ad != AM_AUDIO_Dmx_SUCCESS || !mAdEsData) {
@@ -696,19 +690,16 @@
         abuffer_out.buffer = mAdEsData->data;
         abuffer_out.size = mAdEsData->size;
         abuffer_out.pts = mAdEsData->pts;
+        demux_info->ad_fade = mAdEsData->adfade;
+        demux_info->ad_pan = mAdEsData->adpan;
 
         ret_ad = ad_aml_out->write(ad_stream_out, &abuffer_out);
 
         AM_LOGI_IF((aml_dev->debug_flag > 1), "fade %d, pan %d, mixing_level %d, advol %d, ret_ad %d",
                 mAdEsData->adfade, mAdEsData->adpan, aml_dev->mixing_level, aml_dev->advol_level, ret_ad);
 
-        if (eDolbyMS12Lib == aml_dev->dolby_lib_type &&
-            (ad_aml_out->hal_internal_format == AUDIO_FORMAT_HE_AAC_V1 || ad_aml_out->hal_internal_format == AUDIO_FORMAT_HE_AAC_V2)) {
-            struct dolby_ms12_desc *ms12 = &(aml_dev->ms12);
-            set_ms12_fade_pan(ad_stream_out, mAdEsData->adfade /* fade byte*/
-                , 0 /*gain_byte_center*/, 0 /*gain_byte_front */
-                , 0 /*gain_byte_surround*/, mAdEsData->adpan /*pan byte*/);
-        }
+        dtv_update_pan_fade_parameter(path);
+
 free_data:
         dtv_es_data_free(mAdEsData);
         mAdEsData = NULL;
@@ -719,6 +710,7 @@
     if (ad_aml_out && aml_dev->hw_device.close_output_stream) {
         aml_dev->hw_device.close_output_stream((struct audio_hw_device *)aml_dev, ad_stream_out);
         path->dtv_ad_aml_out = NULL;
+        path->ad_fade = path->ad_pan = 0;
     }
     dtv_es_data_free(mAdEsData);
 exit_open:
@@ -1079,3 +1071,92 @@
     pthread_mutex_unlock(&dtv_path->dtv_path_lock);
     return ret;
 }
+
+static void dtv_set_decoder_gain(dtv_path_t *path, struct audio_stream_out *stream) {
+    struct aml_stream_out *aml_out = (struct aml_stream_out *) stream;
+    struct aml_audio_device *adev = (struct aml_audio_device *)adev_get_handle();
+    float gain = 1.0;
+    if (eDolbyMS12Lib != adev->dolby_lib_type) {//when ms12, ad vol & mix level would be set to ms12
+        if ((aml_out->stream_type == STREAM_MAIN_INPUT && aml_out->dec_param.ad_mix_enable) || aml_out->stream_type == STREAM_AD_INPUT)
+            gain = dtv_ad_mixlevel_vol_convert_to_gain(aml_out);
+    }
+    if (aml_out->stream_type == STREAM_MAIN_INPUT) {
+        float fade_coef = 1.0;
+        if (path->ad_fade && aml_out->dec_param.ad_mix_enable)
+            fade_coef = DbToAmpl(path->ad_fade * (-0.3f));
+        AM_LOGI("[main]fade %d fade_coef %f; mix level: %d, gain: %f", path->ad_fade, fade_coef, adev->mixing_level, gain);
+        aml_out->dec_config.dec_left_gain = gain * fade_coef;
+        aml_out->dec_config.dec_right_gain = aml_out->dec_config.dec_left_gain;
+    } else if (aml_out->stream_type == STREAM_AD_INPUT) {
+        float left_vol = 1.0, right_vol = 1.0;
+        if (path->ad_pan > 0 && path->ad_pan < 0xFF) {
+            get_left_right_volume(path->ad_pan, &left_vol, &right_vol);
+        }
+        AM_LOGI("[ad]pan %d(L %f, R %f); ad vol %d, mix level: %d, gain: %f", path->ad_pan, left_vol, right_vol, adev->advol_level, adev->mixing_level, gain);
+        aml_out->dec_config.dec_left_gain = left_vol * gain;
+        aml_out->dec_config.dec_right_gain = right_vol * gain;
+    }
+    aml_decoder_set_config(aml_out->aml_dec, AML_DEC_CONFIG_LEFT_GAIN, &aml_out->dec_config);
+    aml_decoder_set_config(aml_out->aml_dec, AML_DEC_CONFIG_RIGHT_GAIN, &aml_out->dec_config);
+    return;
+}
+
+static void dtv_update_ad_vol_parameter(dtv_path_t *path) {
+    struct aml_stream_out *main_aml_out = path->dtv_aml_out;
+    struct aml_stream_out *ad_aml_out = path->dtv_ad_aml_out;
+    struct aml_audio_device *aml_dev = (struct aml_audio_device *)adev_get_handle();
+    aml_demux_audiopara_t *demux_info = (aml_demux_audiopara_t *)(&path->demux_info);
+
+    if (main_aml_out->dec_param.ad_mix_enable != demux_info->associate_audio_mixing_enable) {
+        main_aml_out->dec_param.ad_mix_enable = demux_info->associate_audio_mixing_enable;
+        if (eDolbyMS12Lib == aml_dev->dolby_lib_type) {
+            set_ms12_ad_mixing_enable((struct audio_stream_out *)main_aml_out, demux_info->associate_audio_mixing_enable);//set to ms12
+        } else if (main_aml_out->hal_format == AUDIO_FORMAT_AC3 || main_aml_out->hal_format == AUDIO_FORMAT_E_AC3) {
+            main_aml_out->dec_config.ad_mixing_enable = demux_info->associate_audio_mixing_enable;
+            aml_decoder_set_config(main_aml_out->aml_dec, AML_DEC_CONFIG_MIXING_ENABLE, &main_aml_out->dec_config);//set to dcv
+        } else {
+            dtv_set_decoder_gain(path, (struct audio_stream_out *)main_aml_out);//mp3/aac use decoder gain
+        }
+    }
+    if (main_aml_out->dec_param.advol_level != aml_dev->advol_level) {
+        main_aml_out->dec_param.advol_level = aml_dev->advol_level;
+        if (eDolbyMS12Lib == aml_dev->dolby_lib_type) {
+            set_ms12_ad_vol((struct audio_stream_out *)main_aml_out, aml_dev->advol_level);//set to ms12
+        } else if (main_aml_out->hal_format == AUDIO_FORMAT_AC3 || main_aml_out->hal_format == AUDIO_FORMAT_E_AC3) {
+            main_aml_out->dec_config.advol_level = aml_dev->advol_level;
+            aml_decoder_set_config(main_aml_out->aml_dec, AML_DEC_CONFIG_AD_VOL, &main_aml_out->dec_config);//set to dcv
+        } else {
+            dtv_set_decoder_gain(path, (struct audio_stream_out *)ad_aml_out);//mp3/aac use decoder gain
+        }
+    }
+    if (main_aml_out->dec_param.mixing_level != aml_dev->mixing_level) {
+        main_aml_out->dec_param.mixing_level = aml_dev->mixing_level;
+        if (eDolbyMS12Lib == aml_dev->dolby_lib_type) {////set to ms12
+            set_ms12_ad_mixing_level((struct audio_stream_out *)main_aml_out, aml_dev->mixing_level);
+        } else if (ad_aml_out->hal_format == AUDIO_FORMAT_AC3 || ad_aml_out->hal_format == AUDIO_FORMAT_E_AC3) {
+            main_aml_out->dec_config.mixer_level = aml_dev->mixing_level;
+            aml_decoder_set_config(main_aml_out->aml_dec, AML_DEC_CONFIG_MIXER_LEVEL, &main_aml_out->dec_config);//set to dcv
+        } else {
+            dtv_set_decoder_gain(path, (struct audio_stream_out *)ad_aml_out);//mp3/aac use decoder gain
+            dtv_set_decoder_gain(path, (struct audio_stream_out *)main_aml_out);
+        }
+    }
+}
+
+static void dtv_update_pan_fade_parameter(dtv_path_t *path) {
+    struct aml_stream_out *main_aml_out = path->dtv_aml_out;
+    struct aml_stream_out *ad_aml_out = path->dtv_ad_aml_out;
+    struct aml_audio_device *aml_dev = (struct aml_audio_device *)adev_get_handle();
+    aml_demux_audiopara_t *demux_info = (aml_demux_audiopara_t *)(&path->demux_info);
+
+    if (eDolbyMS12Lib == aml_dev->dolby_lib_type &&
+        (ad_aml_out->hal_internal_format == AUDIO_FORMAT_HE_AAC_V1 || ad_aml_out->hal_internal_format == AUDIO_FORMAT_HE_AAC_V2)) {
+        set_ms12_fade_pan((struct audio_stream_out *)main_aml_out, demux_info->ad_fade, 0, 0, 0, demux_info->ad_pan);//set to ms12
+    } else if (demux_info->ad_fade != path->ad_fade) {
+        path->ad_fade = demux_info->ad_fade;
+        dtv_set_decoder_gain(path, (struct audio_stream_out *)main_aml_out);//mp3/aac use decoder gain
+    } else if (demux_info->ad_pan != path->ad_pan) {
+        path->ad_pan = demux_info->ad_pan;
+        dtv_set_decoder_gain(path, (struct audio_stream_out *)ad_aml_out);//mp3/aac use decoder gain
+    }
+}
diff --git a/input/dtv_patch_utils.c b/input/dtv_patch_utils.c
index 1e50188..3e3546b 100644
--- a/input/dtv_patch_utils.c
+++ b/input/dtv_patch_utils.c
@@ -263,6 +263,26 @@
     }
 }
 
+float dtv_ad_mixlevel_vol_convert_to_gain(struct aml_stream_out *aml_out) {
+    struct aml_audio_device *adev = (struct aml_audio_device *)adev_get_handle();
+    float gain = 1.0;
+    if (aml_out->stream_type == STREAM_MAIN_INPUT) {
+        if (adev->mixing_level == 32) {
+            gain = 0.0;
+        } else if (adev->mixing_level > 0) {
+            gain = DbToAmpl((-1.0) * adev->mixing_level);
+        }
+    } else if (aml_out->stream_type == STREAM_AD_INPUT) {
+        if (adev->mixing_level == -32) {
+            gain = 0.0;
+        } else if (adev->mixing_level < 0) {
+            gain = DbToAmpl(adev->mixing_level);
+        }
+        gain *= (adev->advol_level / 100.0f);
+    }
+    AM_LOGI("aout %p, mix level:%d, vol %d, gain %f", aml_out, adev->mixing_level, adev->advol_level, gain);
+    return gain;
+}
 void dtv_check_audio_reset()
 {
     AM_LOGI("reset dtv audio port");
diff --git a/input/include/dtv_patch.h b/input/include/dtv_patch.h
index b1aff99..c50b7ba 100644
--- a/input/include/dtv_patch.h
+++ b/input/include/dtv_patch.h
@@ -114,7 +114,9 @@
     int64_t last_valid_main_pts;
     int64_t last_valid_ad_pts;
     uint8_t pts_dts_flag;
-    int32_t PServerDev;
+
+    uint8_t ad_fade;
+    uint8_t ad_pan;
 } dtv_path_t;
 
 #ifdef BUILD_LINUX
diff --git a/input/include/dtv_patch_utils.h b/input/include/dtv_patch_utils.h
index 2f9da7a..7a6cebf 100644
--- a/input/include/dtv_patch_utils.h
+++ b/input/include/dtv_patch_utils.h
@@ -135,6 +135,7 @@
 void dtv_do_ease_out(struct aml_audio_device *aml_dev);
 void dtv_check_audio_reset();
 void dmx_info_clean(aml_demux_audiopara_t *demux_info);
+float dtv_ad_mixlevel_vol_convert_to_gain(struct aml_stream_out *aml_out);
 
 AD_PACK_STATUS_T check_ad_package_status(int64_t main_pts, int64_t ad_pts,  aml_demux_audiopara_t *demux_info);
 
diff --git a/utils/aml_volume_utils.c b/utils/aml_volume_utils.c
index b3d3bd6..234aedb 100644
--- a/utils/aml_volume_utils.c
+++ b/utils/aml_volume_utils.c
@@ -75,73 +75,33 @@
     return;
 }
 
-const float msmix_pes_pan_LEFT_RGHT[43] = {
-  (0.5000000000f),
-  (0.4996503524f),
-  (0.4986018986f),
-  (0.4968561049f),
-  (0.4944154131f),
-  (0.4912832366f),
-  (0.4874639561f),
-  (0.4829629131f),
-  (0.4777864029f),
-  (0.4719416652f),
-  (0.4654368743f),
-  (0.4582811279f),
-  (0.4504844340f),
-  (0.4420576968f),
-  (0.4330127019f),
-  (0.4233620996f),
-  (0.4131193872f),
-  (0.4022988899f),
-  (0.3909157412f),
-  (0.3789858616f),
-  (0.3665259359f),
-  (0.3535533906f),
-  (0.3400863689f),
-  (0.3261437056f),
-  (0.3117449009f),
-  (0.2969100928f),
-  (0.2816600290f),
-  (0.2660160383f),
-  (0.2500000000f),
-  (0.2336343141f),
-  (0.2169418696f),
-  (0.1999460122f),
-  (0.1826705122f),
-  (0.1651395310f),
-  (0.1473775872f),
-  (0.1294095226f),
-  (0.1112604670f),
-  (0.0929558036f),
-  (0.0745211331f),
-  (0.0559822381f),
-  (0.0373650468f),
-  (0.0186955971f),
-  (0.0000000000f)
-};
+static const unsigned int s_ulADPanTbl[22] = {
+    0x7fffffff, 0x73d72312, 0x68c9a15a, 0x5eb68c8c, 0x557d2ba6, 0x4d0324a4, 0x45377009, 0x3e027edf, 0x3757b810, 0x3128e7a0, 0x2b683272,
+    0x260ceb46, 0x210e863f, 0x1c62e99d, 0x18043a41, 0x13eb2cd9, 0x1012cfb7, 0x0c761164, 0x090fcbf6, 0x05dc8c52, 0x02d87346, 0x00000000};
 
-
-void get_left_right_volume(unsigned char panByte,float* leftvolume,float* rightvolume)
+void get_left_right_volume(unsigned char panByte,float* left_volume,float* right_volume)
 {
-    #define PAN_ONE    1.0f
-    #define PAN_ZERO   (0)     /**< Factor when no panning is applied. */
-    #define PAN_M3DB   0.707106769f /**< 3dB <=> 1/sqrt(2) */
-    *leftvolume  = PAN_M3DB;
-    *rightvolume = PAN_M3DB;
-    if ((panByte>0) && (panByte <= 0xff))
-    {
-     if ((panByte < 21)) {
-         * leftvolume = (msmix_pes_pan_LEFT_RGHT[42-(21-panByte)]);
-         * rightvolume = (msmix_pes_pan_LEFT_RGHT[21-panByte]);
-     } else if ((panByte >= 21) && (panByte <= 127)) {
-         * rightvolume = PAN_ONE;
-     } else if ((panByte >= 128) && (panByte <= 234)) {
-         * leftvolume = PAN_ONE;
-     } else if ((panByte >= 235) && (panByte <= 255)) {
-         * leftvolume = (msmix_pes_pan_LEFT_RGHT[panByte-235]);
-         * rightvolume = (msmix_pes_pan_LEFT_RGHT[42-(panByte-235)]);
-     }
+    int pan_index = panByte;
+    if (pan_index > 127) {
+           pan_index = pan_index - 256;
+    }
+    float base = 0x7fffffff;
+    if (pan_index > 0) {
+       if (pan_index > 21) {
+           *left_volume = s_ulADPanTbl[21] / base;
+           *right_volume = s_ulADPanTbl[0] / base;
+       } else {
+           *left_volume = s_ulADPanTbl[pan_index] / base;
+           *right_volume = s_ulADPanTbl[0] / base;
+       }
+    } else {
+       if (pan_index < -21) {
+           *left_volume = s_ulADPanTbl[0] / base;
+           *right_volume = s_ulADPanTbl[21] / base;
+       } else {
+           *left_volume = s_ulADPanTbl[0] / base;
+           *right_volume = s_ulADPanTbl[-pan_index] / base;
+       }
     }
 }
 
@@ -187,6 +147,40 @@
     return;
 }
 
+void apply_left_right_volume(void *buf, float leftvolume, float rightvolume, int sample_size, int bytes)
+{
+    int16_t *input16 = (int16_t *)buf;
+    int32_t *input32 = (int32_t *)buf;
+    unsigned int i = 0;
+    if (sample_size == 2) {
+        for (i = 0; i < bytes / sizeof(int16_t); i++) {
+            int32_t samp = (int32_t)(input16[i]);
+            if (0 == i%2)
+            {
+                input16[i] = clamp16((int32_t)(leftvolume * samp));
+            }
+            else
+            {
+                input16[i] = clamp16((int32_t)(rightvolume * samp));
+            }
+        }
+    } else if (sample_size == 4) {
+        for (i = 0; i < bytes / sizeof(int32_t); i++) {
+            int64_t samp = (int64_t)(input32[i]);
+            if (0 == i%2)
+            {
+                input32[i] = clamp32((int64_t)(leftvolume * samp));
+            }
+            else
+            {
+                input32[i] = clamp32((int64_t)(rightvolume * samp));
+            }
+        }
+    } else {
+        ALOGE("%s, unsupported audio format: %d!\n", __FUNCTION__, sample_size);
+    }
+    return;
+}
 
 void apply_volume_16to32(float volume, int16_t *in_buf, int32_t *out_buf, int bytes)
 {
diff --git a/utils/include/aml_volume_utils.h b/utils/include/aml_volume_utils.h
index dc717ed..e7b0e14 100644
--- a/utils/include/aml_volume_utils.h
+++ b/utils/include/aml_volume_utils.h
@@ -43,6 +43,8 @@
 int volume2Ms12DBGain(float inVol);
 void apply_volume(float volume, void *buf, int sample_size, int bytes);
 void apply_volume_pan(unsigned char panByte, void *buf, int sample_size, int bytes);
+void get_left_right_volume(unsigned char panByte,float* left_volume,float* right_volume);
+void apply_left_right_volume(void *buf, float leftvolume, float rightvolume, int sample_size, int bytes);
 
 void apply_volume_16to32(float volume, int16_t *in_buf, int32_t *out_buf, int bytes);
 void apply_volume_fade(float last_volume, float volume, void *buf, int sample_size, int channels, int bytes);