/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2021. All rights reserved. * Description: video/audio interface. * Author: Hisilicon * Create: 2019-11-01 */ #include "adp_uapi_ext.h" #include #include #include #include #include #include "securec.h" #include "uapi_avplay.h" #include "uapi_sound.h" #include "uapi_ai.h" #include "uapi_acodec.h" #include "ha_codec.h" #include "ha_codec_g711.h" #include "ha_codec_mp3dec.h" #include "ha_codec_mp2dec.h" #include "ha_codec_aacdec.h" #include "ha_codec_pcmdec.h" #include "ha_codec_amrnb.h" #include "ha_codec_amrwb.h" #include "ha_codec_dolbytruehddec.h" #include "ha_codec_dtshddec.h" #if defined (DOLBYPLUS_HACODEC_SUPPORT) #include "ha_codec_dolbyplusdec.h" #endif #include "ha_codec_passthrough.h" #include "ha_codec_aacenc.h" #include "ha_codec_dolbyms12dec.h" #include "ha_codec_voice.h" #include "ha_codec_opus.h" #include "ha_codec_vorbis.h" #include "ha_codec_dtsm6dec.h" #include "ha_codec_dradec.h" #ifdef ANDROID #include #endif #include "adp_common_ext.h" #include "uapi_system.h" #define ADP_DEMUX_NUM 5 #define ADP_DEMUX_PLAY 0 #define ADP_DEMUX_REC_0 1 #define ADP_DEMUX_REC_1 2 #define ADP_DEMUX_TIMESHIFT 3 #define ADP_DEMUX_PLAYBACK 4 #define ADP_UHD_WIDTH 3840 #define ADP_UHD_HEIGHT 2160 #define ADP_FHD_WIDTH 1920 #define ADP_FHD_HEIGHT 1080 #define ADP_HD_WIDTH 1280 #define ADP_HD_HEIGHT 720 /* * big-endian pcm output format, if extword is 1, choose normal pcm decoder, * if extword is 2, choose wifidsp_lpcm decoder(Frame Header:0xA0,0x06) * if others, fail to decode. */ #define NORMAL_PCM_EXTWORD 1 #define WIFIDSP_LPCM_EXTWORD 2 #define DEC_OPEN_BUF_LEN 1024 #define MAX_ADEC_OPEN_CONFIG_LEN 1024 td_u8 g_dec_open_buf[DEC_OPEN_BUF_LEN]; static td_u8 g_adec_open_config[MAX_ADEC_OPEN_CONFIG_LEN] = {0}; #if defined (DOLBYPLUS_HACODEC_SUPPORT) static ha_codec_dolbyplus_stream_info g_ddp_stream_info = {0}; /* dolby Dual Mono type control */ #endif #ifdef ANDROID #define LOG_MAX_LEN 1024 void log_print(const char *format, ...) { char log_str[LOG_MAX_LEN]; va_list args; td_s32 ret; va_start(args, format); ret = vsnprintf_s(log_str, LOG_MAX_LEN, LOG_MAX_LEN - 1, format, args); va_end(args); if (ret < 0) { printf("call vsnprintf_s failed.\n"); return; } android_printLog(ANDROID_LOG_ERROR, "SAMPLE", "%s", log_str); } #endif __attribute__ ((constructor)) static void stdin_constructor(void) { td_s32 flags = fcntl(STDIN_FILENO, F_GETFL, 0); if (flags < 0) { printf("[%s:%d][ERROR] get flags failed.\n", __FUNCTION__, __LINE__); } else if (((td_u32)flags & O_NONBLOCK) != 0) { flags = (td_u32)flags & (~O_NONBLOCK); flags = fcntl(STDIN_FILENO, F_SETFL, flags); if (flags < 0) { printf("[%s:%d][ERROR] set flags failed.\n", __FUNCTION__, __LINE__); } } } typedef struct { uapi_acodec_channel uapi_channel; ha_codec_channel mpi_channel; } tran_channel; static tran_channel g_tran_channel[] = { {UAPI_ACODEC_CHANNEL_NONE, HA_CODEC_CHANNEL_NONE}, {UAPI_ACODEC_CHANNEL_LF, HA_CODEC_CHANNEL_LF}, {UAPI_ACODEC_CHANNEL_RF, HA_CODEC_CHANNEL_RF}, {UAPI_ACODEC_CHANNEL_CF, HA_CODEC_CHANNEL_CF}, {UAPI_ACODEC_CHANNEL_LS, HA_CODEC_CHANNEL_LS}, {UAPI_ACODEC_CHANNEL_RS, HA_CODEC_CHANNEL_RS}, {UAPI_ACODEC_CHANNEL_LFE, HA_CODEC_CHANNEL_LFE}, {UAPI_ACODEC_CHANNEL_CS, HA_CODEC_CHANNEL_CS}, {UAPI_ACODEC_CHANNEL_LR, HA_CODEC_CHANNEL_LR}, {UAPI_ACODEC_CHANNEL_RR, HA_CODEC_CHANNEL_RR}, {UAPI_ACODEC_CHANNEL_MAX, HA_CODEC_CHANNEL_MAX}, }; static ha_codec_channel track_channel_uapi_to_mpi(const uapi_acodec_channel uapi_in) { td_u32 i; for (i = 0; i < sizeof(g_tran_channel) / sizeof(g_tran_channel[0]); i++) { if (uapi_in == g_tran_channel[i].uapi_channel) { return g_tran_channel[i].mpi_channel; } } return HA_CODEC_CHANNEL_MAX; } static uapi_acodec_channel track_channel_mpi_to_uapi(const ha_codec_channel mpi_in) { td_u32 i; for (i = 0; i < sizeof(g_tran_channel) / sizeof(g_tran_channel[0]); i++) { if (mpi_in == g_tran_channel[i].mpi_channel) { return g_tran_channel[i].uapi_channel; } } return UAPI_ACODEC_CHANNEL_MAX; } td_s32 trans_dec_param_mpi_to_uapi(uapi_acodec_dec_param *uapi_param, const ha_codec_dec_param *param) { td_u32 i; if (uapi_param == TD_NULL || param == TD_NULL) { return TD_FAILURE; } uapi_param->private_data = param->private_data; uapi_param->private_data_size = param->private_data_size; uapi_param->pcm_attr.desired_out_channels = param->pcm_attr.desired_out_channels; uapi_param->pcm_attr.interleaved = param->pcm_attr.interleaved; uapi_param->pcm_attr.bit_per_sample = param->pcm_attr.bit_per_sample; uapi_param->pcm_attr.desired_sample_rate = param->pcm_attr.desired_sample_rate; for (i = 0; i < HA_CODEC_MAX_CHANNEL; i++) { uapi_param->pcm_attr.channel_map[i] = track_channel_mpi_to_uapi(param->pcm_attr.channel_map[i]); } switch (param->dec_mode) { case HA_CODEC_DEC_MODE_RAWPCM: uapi_param->dec_mode = UAPI_ACODEC_DEC_MODE_RAWPCM; break; case HA_CODEC_DEC_MODE_THRU: uapi_param->dec_mode = UAPI_ACODEC_DEC_MODE_THRU; break; case HA_CODEC_DEC_MODE_SIMUL: uapi_param->dec_mode = UAPI_ACODEC_DEC_MODE_SIMUL; break; default: uapi_param->dec_mode = UAPI_ACODEC_DEC_MODE_MAX; break; } return TD_SUCCESS; } td_s32 trans_dec_param_uapi_to_mpi(const uapi_acodec_dec_param *uapi_param, ha_codec_dec_param *param) { td_u32 i; if (uapi_param == TD_NULL || param == TD_NULL) { return TD_FAILURE; } param->private_data = uapi_param->private_data; param->private_data_size = uapi_param->private_data_size; param->pcm_attr.desired_out_channels = uapi_param->pcm_attr.desired_out_channels; param->pcm_attr.interleaved = uapi_param->pcm_attr.interleaved; param->pcm_attr.bit_per_sample = uapi_param->pcm_attr.bit_per_sample; param->pcm_attr.desired_sample_rate = uapi_param->pcm_attr.desired_sample_rate; for (i = 0; i < HA_CODEC_MAX_CHANNEL; i++) { param->pcm_attr.channel_map[i] = track_channel_uapi_to_mpi(uapi_param->pcm_attr.channel_map[i]); } switch (uapi_param->dec_mode) { case UAPI_ACODEC_DEC_MODE_RAWPCM: param->dec_mode = HA_CODEC_DEC_MODE_RAWPCM; break; case UAPI_ACODEC_DEC_MODE_THRU: param->dec_mode = HA_CODEC_DEC_MODE_THRU; break; case UAPI_ACODEC_DEC_MODE_SIMUL: param->dec_mode = HA_CODEC_DEC_MODE_SIMUL; break; default: param->dec_mode = HA_CODEC_DEC_MODE_MAX; break; } return TD_SUCCESS; } td_s32 trans_enc_param_mpi_to_uapi(uapi_acodec_enc_param *uapi_param, const ha_codec_enc_param *param) { if (uapi_param == TD_NULL || param == TD_NULL) { return TD_FAILURE; } uapi_param->desired_out_channels = param->desired_out_channels; uapi_param->interleaved = param->interleaved; uapi_param->bit_per_sample = param->bit_per_sample; uapi_param->desired_sample_rate = param->desired_sample_rate; uapi_param->sample_per_frame = param->sample_per_frame; uapi_param->private_data = param->private_data; uapi_param->private_data_size = param->private_data_size; return TD_SUCCESS; } td_s32 trans_enc_param_uapi_to_mpi(const uapi_acodec_enc_param *uapi_param, ha_codec_enc_param *param) { if (uapi_param == TD_NULL || param == TD_NULL) { return TD_FAILURE; } param->desired_out_channels = uapi_param->desired_out_channels; param->interleaved = uapi_param->interleaved; param->bit_per_sample = uapi_param->bit_per_sample; param->desired_sample_rate = uapi_param->desired_sample_rate; param->sample_per_frame = uapi_param->sample_per_frame; param->private_data = uapi_param->private_data; param->private_data_size = uapi_param->private_data_size; return TD_SUCCESS; } td_s32 adp_uapi_snd_init(td_void) { td_s32 ret; uapi_snd_attr attr; ret = uapi_snd_init(); if (ret != TD_SUCCESS) { SAMPLE_COMMON_PRINTF("call uapi_snd_init failed.\n"); return ret; } ret = uapi_snd_get_default_open_attr(UAPI_SND_0, &attr); if (ret != TD_SUCCESS) { SAMPLE_COMMON_PRINTF("call uapi_snd_get_default_open_attr failed.\n"); return ret; } ret = uapi_snd_open(UAPI_SND_0, &attr); if (ret != TD_SUCCESS) { SAMPLE_COMMON_PRINTF("call uapi_snd_open failed.\n"); return ret; } return TD_SUCCESS; } td_s32 adp_uapi_snd_deinit(td_void) { td_s32 ret; ret = uapi_snd_close(UAPI_SND_0); if (ret != TD_SUCCESS) { SAMPLE_COMMON_PRINTF("call uapi_snd_close failed.\n"); return ret; } ret = uapi_snd_deinit(); if (ret != TD_SUCCESS) { SAMPLE_COMMON_PRINTF("call uapi_snd_deinit failed.\n"); return ret; } return TD_SUCCESS; } #define sample_common_dofunc_no_return(func) do { \ td_s32 ret_val_; \ ret_val_ = (func); \ if (ret_val_ != TD_SUCCESS) { \ SAMPLE_COMMON_PRINTF("\n\n!!! some audio codec NOT found. you may NOT able to decode some audio type.\n\n");; \ } \ } while (0) static td_s32 adp_avplay_reg_adec_lib(td_void) { sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.AMRWB.codec.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.MP3.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.MP2.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.AAC.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.DOLBYTRUEHD.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.AMRNB.codec.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.COOK.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.VOICE.codec.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.G711.codec.so")); #ifdef DOLBYPLUS_HACODEC_SUPPORT sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.DOLBYPLUS.decode.so")); #endif sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.DTSHD.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.DTSM6.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.PASSTHROUGH.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.PCM.decode.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.OPUS.codec.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.VORBIS.codec.so")); sample_common_dofunc_no_return(uapi_avplay_register_acodec_lib("libHA.AUDIO.AVS3.decode.so")); return TD_SUCCESS; } td_s32 adp_uapi_avplay_init(td_void) { (td_void)adp_avplay_reg_adec_lib(); return uapi_avplay_init(); } #if defined (DOLBYPLUS_HACODEC_SUPPORT) static td_void dd_plus_call_back(ha_codec_dolbyplus_event event, td_void *app_data) { ha_codec_dolbyplus_stream_info *info = (ha_codec_dolbyplus_stream_info *)app_data; td_u32 dolby_acmod = 0; td_bool draw_chn_bar = TD_TRUE; dolby_acmod = (td_u32)(info->acmod); if (event == EXT_DOLBYPLUS_EVENT_SOURCE_CHANGE) { draw_chn_bar = TD_TRUE; } printf("dolby_acmod(%u) draw_chn_bar(%d)\n", dolby_acmod, draw_chn_bar); return; } #endif static td_s32 set_pcm_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is PCM\n"); td_bool is_big_endian = TD_FALSE; ha_codec_wav_format wav_format = {0}; ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); if (is_big_endian == TD_TRUE) { wav_format.cb_size = 4; /* 4: Size of the extension */ wav_format.cb_ext_word[0] = NORMAL_PCM_EXTWORD; } if (wav_format.cb_ext_word[0] == NORMAL_PCM_EXTWORD || is_big_endian == TD_FALSE) { wav_format.channels = 1; wav_format.samples_per_sec = 48000; /* 48000: Sampling rate */ wav_format.bits_per_sample = 16; /* 16: Bits per sample */ } ha_codec_pcm_dec_get_default_open_param(¶m, &wav_format); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_mp2_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is MP2\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_mp2_dec_get_default_open_param(¶m); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_aac_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is AAC\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_aac_dec_get_default_open_param(¶m); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_mp3_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is MP3\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_mp3_dec_get_default_open_param(¶m); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_amrnb_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is AMRNB\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_amrnb_decode_open_config *config = (ha_codec_amrnb_decode_open_config*)g_adec_open_config; ha_amrnb_get_dec_default_open_param(¶m, config); config->format = HA_CODEC_AMRNB_MIME; trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_amrwb_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is AMRWB\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_amrwb_decode_open_config *config = (ha_codec_amrwb_decode_open_config*)g_adec_open_config; ha_codec_amrwb_get_dec_default_open_param(¶m, config); config->format = HA_CODEC_AMRWB_FORMAT_MIME; trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_g711_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is G711\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); adec_attr->id = UAPI_ACODEC_ID_VOICE; ha_codec_voice_open_config *config = (ha_codec_voice_open_config*)g_adec_open_config; config->voice_format = HA_CODEC_VOICE_G711_A; config->sample_per_frame = 320; /* 320: Bytes per frame */ ha_codec_voice_get_dec_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_g726_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is G726\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); adec_attr->id = UAPI_ACODEC_ID_VOICE; ha_codec_voice_open_config *config = (ha_codec_voice_open_config*)g_adec_open_config; config->voice_format = HA_CODEC_VOICE_G726_40KBPS; config->sample_per_frame = 320; /* 320: Bytes per frame */ ha_codec_voice_get_dec_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_adpcm_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is ADPCM\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); adec_attr->id = UAPI_ACODEC_ID_VOICE; ha_codec_voice_open_config *config = (ha_codec_voice_open_config*)g_adec_open_config; config->voice_format = HA_CODEC_VOICE_ADPCM_DVI4; config->sample_per_frame = 320; /* 320: Bytes per frame */ ha_codec_voice_get_dec_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_ac3passthrough_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is AC3_PASSTHROUGH\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); adec_attr->id = UAPI_ACODEC_ID_PASSTHROUGH; ha_codec_passthrough_decode_open_config *config = (ha_codec_passthrough_decode_open_config *)g_adec_open_config; config->codec_id = HA_CODEC_ID_AC3PASSTHROUGH; ha_codec_passthrough_dec_get_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adec_attr->param.dec_mode = UAPI_ACODEC_DEC_MODE_THRU; adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_dtspassthrough_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is DTSPASSTHROUGH\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); adec_attr->id = UAPI_ACODEC_ID_PASSTHROUGH; ha_codec_passthrough_decode_open_config *config = (ha_codec_passthrough_decode_open_config *)g_adec_open_config; config->codec_id = HA_CODEC_ID_DTSPASSTHROUGH; ha_codec_passthrough_dec_get_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adec_attr->param.dec_mode = UAPI_ACODEC_DEC_MODE_THRU; adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_truehd_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is TRUEHD\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); adec_attr->id = UAPI_ACODEC_ID_PASSTHROUGH; ha_codec_passthrough_decode_open_config *config = (ha_codec_passthrough_decode_open_config *)g_adec_open_config; config->codec_id = HA_CODEC_ID_TRUEHD; ha_codec_passthrough_dec_get_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adec_attr->param.dec_mode = UAPI_ACODEC_DEC_MODE_THRU; adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_dolby_truehd_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is DOLBY_TRUEHD\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_truehd_decode_open_config *config = (ha_codec_truehd_decode_open_config*)g_adec_open_config; ha_codec_dolby_truehd_dec_get_default_open_config(config); ha_codec_dolby_truehd_dec_get_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_dtshd_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is DTSHD\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_dtshd_decode_open_config *config = (ha_codec_dtshd_decode_open_config*)g_adec_open_config; ha_codec_dtshd_dec_get_default_open_config(config); ha_codec_dtshd_dec_get_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adec_attr->param.dec_mode = UAPI_ACODEC_DEC_MODE_SIMUL; adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_dtsm6_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is DTSM6\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_dtsm6_decode_open_config *config = (ha_codec_dtsm6_decode_open_config*)g_adec_open_config; ha_codec_dtsm6_dec_get_default_open_config(config); ha_codec_dtsm6_dec_get_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } #if defined (DOLBYPLUS_HACODEC_SUPPORT) static td_s32 set_dolby_plus_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is DOLBY_PLUS\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_dolbyplus_decode_openconfig *config = (ha_codec_dolbyplus_decode_openconfig*)g_adec_open_config; ha_codec_dolbyplus_dec_get_default_open_config(config); config->pfn_evt_cb_func[EXT_DOLBYPLUS_EVENT_SOURCE_CHANGE] = dd_plus_call_back; config->app_data[EXT_DOLBYPLUS_EVENT_SOURCE_CHANGE] = &g_ddp_stream_info; config->drc_mode = DOLBYPLUS_DRC_RF; /* Dolby DVB Broadcast default settings */ config->dmx_mode = DOLBYPLUS_DMX_SRND; /* Dolby DVB Broadcast default settings */ ha_codec_dolbyplus_dec_get_default_open_param(¶m, config); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adec_attr->param.dec_mode = UAPI_ACODEC_DEC_MODE_SIMUL; adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } #endif static td_s32 set_ms12_ddp_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is MS12_DDP\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_dolbyms12_open_config ms12_cfg = {0}; ha_codec_dolbyms12_get_default_open_config(&ms12_cfg); ha_codec_dolbyms12_get_default_open_param(¶m, &ms12_cfg); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_ms12_aac_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is MS12_AAC\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_dolbyms12_open_config ms12_cfg = {0}; ha_codec_dolbyms12_get_default_open_config(&ms12_cfg); ms12_cfg.input_type = MS12_HEAAC; ha_codec_dolbyms12_get_default_open_param(¶m, &ms12_cfg); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_vorbis_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is VORBIS\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_vorbis_dec_get_defalut_open_param(¶m); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_opus_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is OPUS\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_opus_head_config opus_head_cfg = {0}; ha_codec_opus_dec_get_default_head_config(&opus_head_cfg); opus_head_cfg.version = 1; opus_head_cfg.chan = 6; /* 6: Number of channels */ opus_head_cfg.preskip = 312; /* 312: preskip value. */ opus_head_cfg.gain = 0; opus_head_cfg.sample_rate = 48000; /* 48000: Sampling rate */ opus_head_cfg.nb_streams = 4; /* 4: number of streams */ opus_head_cfg.nb_coupled = 2; /* 2: number of coupled */ opus_head_cfg.channel_map = 1; opus_head_cfg.stream_map[0] = 0; /* 0: stream map index. 0: stream map data. */ opus_head_cfg.stream_map[1] = 4; /* 1: stream map index. 4: stream map data. */ opus_head_cfg.stream_map[2] = 1; /* 2: stream map index. 1: stream map data. */ opus_head_cfg.stream_map[3] = 2; /* 3: stream map index. 2: stream map data. */ opus_head_cfg.stream_map[4] = 3; /* 4: stream map index. 3: stream map data. */ opus_head_cfg.stream_map[5] = 5; /* 5: stream map index. 5: stream map data. */ ha_codec_opus_dec_get_default_open_param(¶m, &opus_head_cfg); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_dra_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { SAMPLE_COMMON_PRINTF("acodec id is MULTICH PCM\n"); ha_codec_dec_param param; trans_dec_param_uapi_to_mpi(&(adec_attr->param), ¶m); ha_codec_dra_dec_get_open_param_multich_pcm(¶m); trans_dec_param_mpi_to_uapi(&(adec_attr->param), ¶m); adp_api_run_return(uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr)); return TD_SUCCESS; } static td_s32 set_avs3_attr(td_handle avplay, uapi_audio_decode_attr *adec_attr) { td_s32 ret; SAMPLE_COMMON_PRINTF("acodec id is AVS3\n"); if (adec_attr == TD_NULL) { SAMPLE_COMMON_PRINTF("avplay == 0x%x\n", avplay); return TD_FAILURE; } SAMPLE_COMMON_PRINTF("acodec id is 0x%x\n", adec_attr->id); ret = uapi_avplay_set_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, adec_attr); if (ret != TD_SUCCESS) { printf("set_attr failed, ret:0x%x\n", ret); } return TD_SUCCESS; } typedef td_s32 (*set_adec_attr_fn) (td_handle avplay, uapi_audio_decode_attr *adec_attr); typedef struct { uapi_acodec_id acodec_id; set_adec_attr_fn set_adec_attr; } acodec_attr_map; static acodec_attr_map g_acodec_attr_map[] = { {UAPI_ACODEC_ID_PCM, set_pcm_attr}, {UAPI_ACODEC_ID_MP2, set_mp2_attr}, {UAPI_ACODEC_ID_AAC, set_aac_attr}, {UAPI_ACODEC_ID_MP3, set_mp3_attr}, {UAPI_ACODEC_ID_AMRNB, set_amrnb_attr}, {UAPI_ACODEC_ID_AMRWB, set_amrwb_attr}, {UAPI_ACODEC_ID_G711, set_g711_attr}, {UAPI_ACODEC_ID_G726, set_g726_attr}, {UAPI_ACODEC_ID_ADPCM, set_adpcm_attr}, {UAPI_ACODEC_ID_AC3PASSTHROUGH, set_ac3passthrough_attr}, {UAPI_ACODEC_ID_DTSPASSTHROUGH, set_dtspassthrough_attr}, {UAPI_ACODEC_ID_TRUEHD, set_truehd_attr}, {UAPI_ACODEC_ID_DOLBY_TRUEHD, set_dolby_truehd_attr}, {UAPI_ACODEC_ID_DTSHD, set_dtshd_attr}, {UAPI_ACODEC_ID_DTSM6, set_dtsm6_attr}, #if defined (DOLBYPLUS_HACODEC_SUPPORT) {UAPI_ACODEC_ID_DOLBY_PLUS, set_dolby_plus_attr}, #endif {UAPI_ACODEC_ID_MS12_DDP, set_ms12_ddp_attr}, {UAPI_ACODEC_ID_MS12_AAC, set_ms12_aac_attr}, {UAPI_ACODEC_ID_VORBIS, set_vorbis_attr}, {UAPI_ACODEC_ID_OPUS, set_opus_attr}, {UAPI_ACODEC_ID_AVS3, set_avs3_attr}, {UAPI_ACODEC_ID_DRA, set_dra_attr}, }; td_s32 adp_uapi_avplay_set_adec_attr(td_handle avplay, td_u32 acodec_id) { uapi_audio_decode_attr adec_attr = {0}; td_s32 map_size = (td_s32)(sizeof(g_acodec_attr_map) / sizeof(g_acodec_attr_map[0])); adp_api_run_return(uapi_avplay_get_attr(avplay, UAPI_AVPLAY_ATTR_ID_ADEC, &adec_attr)); adec_attr.id = acodec_id; for (int i = 0; i < map_size; i++) { if (g_acodec_attr_map[i].acodec_id == acodec_id) { return g_acodec_attr_map[i].set_adec_attr(avplay, &adec_attr); } } return set_dra_attr(avplay, &adec_attr); }