/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved. * Description: API of adec * Author: audio * Create: 2019-05-30 */ #include "mpi_adec_debug.h" #include "mpi_memory_ext.h" #include "mpi_adec_ext.h" #include "adec_core.h" #include "adec_lock.h" #include "adec_common.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define adec_get_real_chn(adec) \ do { \ (adec) = TD_HANDLE_GET_CHAN_ID((adec)); \ check_adec_handle((adec)); \ } while (0) static td_u32 g_adec_init_cnt = 0; static td_u32 g_stream_cnt[ADEC_INSTANCE_MAXNUM]; static td_void *g_adec_arry[ADEC_INSTANCE_MAXNUM]; typedef enum { MPI_ADEC_PTS_ESIN = 0, MPI_ADEC_PTS_PCMOUT } mpi_adec_pts_type; #ifdef AUDIO_SAVE_ADECDATA static FILE *g_f_stream = TD_NULL; static FILE *g_f_pcm = TD_NULL; static FILE *g_f_lbr = TD_NULL; static FILE *g_f_hbr = TD_NULL; static FILE *g_pts = TD_NULL; static td_void adec_open_save_file(td_void) { if (g_f_stream == TD_NULL) { g_f_stream = fopen("/mnt/adec_dump.es", "wb"); if (g_f_stream == TD_NULL) { soc_log_err("open /mnt/adec_dump.es fail\n"); } } if (g_f_pcm == TD_NULL) { g_f_pcm = fopen("/mnt/adec_dump.pcm", "wb"); if (g_f_pcm == TD_NULL) { soc_log_err("open adec_dump.pcm fail\n"); } } if (g_f_lbr == TD_NULL) { g_f_lbr = fopen("/mnt/adec_dump.lbr", "wb"); if (g_f_lbr == TD_NULL) { soc_log_err("open adec_dump.lbr fail\n"); } } if (g_f_hbr == TD_NULL) { g_f_hbr = fopen("/mnt/adec_dump.hbr", "wb"); if (g_f_hbr == TD_NULL) { soc_log_err("open adec_dump.hbr fail\n"); } } if (g_pts == TD_NULL) { g_pts = fopen("/mnt/adec_dump.pts", "wb"); if (g_pts == TD_NULL) { soc_log_err("open adec_dump.pts fail\n"); } } } static td_void adec_close_save_file(td_void) { if (g_f_stream != TD_NULL) { fclose(g_f_stream); g_f_stream = TD_NULL; } if (g_f_pcm != TD_NULL) { fclose(g_f_pcm); g_f_pcm = TD_NULL; } if (g_f_lbr != TD_NULL) { fclose(g_f_lbr); g_f_lbr = TD_NULL; } if (g_f_hbr != TD_NULL) { fclose(g_f_hbr); g_f_hbr = TD_NULL; } if (g_pts != TD_NULL) { fclose(g_pts); g_pts = TD_NULL; } } static td_void adec_save_es_in_stream(const ext_stream_buf *stream) { if (g_f_stream != TD_NULL) { fwrite(stream->data, 1, stream->size, g_f_stream); fflush(g_f_stream); } } static td_void adec_save_output_data(ext_ao_frame *ao_frame) { if (g_f_pcm != TD_NULL) { if (ao_frame->bit_depth == EXT_BIT_DEPTH_16) { fwrite(ao_frame->pcm_buffer, sizeof(td_u16), ao_frame->pcm_samples * ao_frame->channels, g_f_pcm); } else { fwrite(ao_frame->pcm_buffer, sizeof(td_u32), ao_frame->pcm_samples * ao_frame->channels, g_f_pcm); } fflush(g_f_pcm); } if (g_f_lbr != TD_NULL) { fwrite(ao_frame->bits_buffer, 1, adec_lbr_size(ao_frame->bits_bytes), g_f_lbr); fflush(g_f_lbr); } if (g_f_hbr != TD_NULL) { fwrite((td_u8 *)ao_frame->bits_buffer + adec_lbr_size(ao_frame->bits_bytes), 1, adec_hbr_size(ao_frame->bits_bytes), g_f_hbr); fflush(g_f_hbr); } } #endif td_s32 ext_mpi_adec_register_codec(const td_char *codec_name, td_u32 length) { TD_UNUSED(length); return adec_register_decoder(codec_name); } td_s32 ext_mpi_adec_get_codec_id(const uapi_acodec_format format, td_u32 *codec_id) { return adec_get_codec_id(format, codec_id); } uapi_acodec_decode *ext_mpi_adec_get_codec_list(td_void) { return adec_get_decoder_list(); } td_s32 ext_mpi_adec_init(td_void) { adec_mpi_lock(); if (g_adec_init_cnt == 0) { adec_init(); } g_adec_init_cnt++; adec_mpi_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_adec_deinit(td_void) { adec_mpi_lock(); if (g_adec_init_cnt == 0) { adec_mpi_unlock(); return TD_SUCCESS; } g_adec_init_cnt--; if (g_adec_init_cnt == 0) { adec_deinit(); } adec_mpi_unlock(); return TD_SUCCESS; } static td_s32 mpi_adec_open(td_handle *adec) { td_s32 ret; td_u32 adec_id = ADEC_INSTANCE_MAXNUM; td_void *buf = TD_NULL; *adec = TD_INVALID_HANDLE; ret = adec_open(&adec_id); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(adec_open, ret); return ret; } if (adec_id >= ADEC_INSTANCE_MAXNUM) { soc_err_print_u32(adec_id); goto out; } buf = malloc(ADEC_MAX_INPUT_BLOCK_SIZE); if (buf == TD_NULL) { soc_log_err("Call malloc( failed\n"); goto out; } adec_api_lock(adec_id); g_adec_arry[adec_id] = buf; g_stream_cnt[adec_id] = 0; adec_api_unlock(adec_id); *adec = TD_HANDLE_INIT(SOC_ID_ADEC, 0, adec_id); return TD_SUCCESS; out: ret = adec_close(adec_id); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(adec_close, ret); return ret; } return TD_FAILURE; } static td_s32 mpi_adec_close(td_u32 adec_id) { td_s32 ret; adec_api_lock(adec_id); if (g_adec_arry[adec_id] != TD_NULL) { free(g_adec_arry[adec_id]); g_adec_arry[adec_id] = TD_NULL; g_stream_cnt[adec_id] = 0; } ret = adec_close(adec_id); adec_api_unlock(adec_id); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(adec_close, ret); return ret; } return TD_SUCCESS; } td_s32 ext_mpi_adec_open(td_handle *adec) { td_s32 ret; check_adec_null_ptr(adec); adec_mpi_lock(); if (g_adec_init_cnt == 0) { soc_log_err("adec not inited\n"); adec_mpi_unlock(); return TD_FAILURE; } ret = mpi_adec_open(adec); adec_mpi_unlock(); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(mpi_adec_open, ret); return ret; } #ifdef AUDIO_SAVE_ADECDATA adec_open_save_file(); #endif return TD_SUCCESS; } td_s32 ext_mpi_adec_close(td_handle adec) { adec_get_real_chn(adec); #ifdef AUDIO_SAVE_ADECDATA adec_close_save_file(); #endif return mpi_adec_close(adec); } td_s32 ext_mpi_adec_start(td_handle adec) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_start(adec); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_stop(td_handle adec) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_stop(adec); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_set_speed(td_handle adec, const ext_adec_speed *speed) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_set_speed(adec, speed); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_get_speed(td_handle adec, ext_adec_speed *speed) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_get_speed(adec, speed); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_pause(td_handle adec) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_pause(adec); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_resume(td_handle adec) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_resume(adec); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_set_attr(td_handle adec, const ext_adec_attr *attr) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_set_attr(adec, attr); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_get_attr(td_handle adec, ext_adec_attr *attr) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_get_attr(adec, attr); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_get_delay(td_handle adec, td_u32 *delay) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_get_delay_ms(adec, delay); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_send_stream(td_handle adec, const ext_stream_buf *stream, td_s64 pts) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); adec_dbg_count_try_send_stream(adec); ret = adec_send_stream(adec, stream, pts); if (ret != TD_SUCCESS) { adec_api_unlock(adec); return ret; } adec_dbg_count_send_stream(adec); adec_api_unlock(adec); #ifdef AUDIO_SAVE_ADECDATA adec_save_es_in_stream(stream); adec_proc_save_pts(MPI_ADEC_PTS_ESIN, adec_input_pts(pts), g_pts); #endif return TD_SUCCESS; } td_s32 ext_mpi_adec_get_buffer(td_handle adec, td_u32 size, ext_stream_buf *stream) { td_s32 ret; ext_stream_buf stream1 = {0}; ext_stream_buf stream2 = {0}; check_adec_null_ptr(stream); adec_get_real_chn(adec); adec_api_lock(adec); if (g_adec_arry[adec] == TD_NULL) { adec_api_unlock(adec); return SOC_ERR_ADEC_NULL_PTR; } adec_dbg_count_try_get_buffer(adec); ret = adec_get_buffer(adec, size, &stream1, &stream2); if (ret != TD_SUCCESS) { adec_api_unlock(adec); return ret; } if (stream2.size > 0) { stream->data = (td_u8 *)(g_adec_arry[adec]); stream->size = size; g_stream_cnt[adec] = ADEC_SEND_STREAM; } else { stream->data = stream1.data; stream->size = size; g_stream_cnt[adec] = ADEC_PUT_BUFFER; } adec_dbg_count_get_buffer(adec); adec_api_unlock(adec); return TD_SUCCESS; } td_s32 ext_mpi_adec_put_buffer(td_handle adec, const ext_stream_buf *stream, td_s64 pts) { td_s32 ret; check_adec_null_ptr(stream); adec_get_real_chn(adec); if (stream->size == 0) { soc_err_print_h32(stream->size); return TD_SUCCESS; } adec_api_lock(adec); if (g_adec_arry[adec] == TD_NULL) { adec_api_unlock(adec); return TD_FAILURE; } adec_dbg_count_try_put_buffer(adec); if (g_stream_cnt[adec] == ADEC_PUT_BUFFER) { ret = adec_put_buffer(adec, stream, pts); } else if (g_stream_cnt[adec] == ADEC_SEND_STREAM) { ret = adec_send_stream(adec, stream, pts); } else { soc_err_print_u32(adec); soc_err_print_u32(g_stream_cnt[adec]); adec_api_unlock(adec); return SOC_ERR_ADEC_INVALID_PARA; } g_stream_cnt[adec] = 0; if (ret == TD_SUCCESS) { adec_dbg_count_put_buffer(adec); #ifdef AUDIO_SAVE_ADECDATA adec_save_es_in_stream(stream); adec_proc_save_pts(MPI_ADEC_PTS_ESIN, adec_input_pts(pts), g_pts); #endif } adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_acquire_frame(td_handle adec, ext_ao_frame *frame, ext_adec_ext_frame_info *ext_info) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); adec_dbg_count_try_receive_frame(adec); ret = adec_acquire_frame(adec, frame, ext_info); if (ret != TD_SUCCESS) { adec_api_unlock(adec); return ret; } adec_dbg_count_receive_frame(adec); adec_api_unlock(adec); #ifdef AUDIO_SAVE_ADECDATA adec_save_output_data(frame); adec_proc_save_pts(MPI_ADEC_PTS_PCMOUT, adec_input_pts(frame->pts), g_pts); #endif return TD_SUCCESS; } td_s32 ext_mpi_adec_release_frame(td_handle adec, const ext_ao_frame *frame) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_release_frame(adec, frame); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_get_info(td_handle adec, ext_adec_info_type info_type, td_void *arg) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); switch (info_type) { case EXT_ADEC_STATUS_INFO: ret = adec_get_status_info(adec, (ext_adec_status *)arg); break; case EXT_ADEC_STREAM_INFO: ret = adec_get_stream_info(adec, (ext_adec_stream_info *)arg); break; case EXT_ADEC_BUFFER_STATUS: ret = adec_get_buffer_status(adec, (ext_adec_buf_status *)arg); break; case EXT_ADEC_DEBUG_INFO: ret = adec_get_debug_info(adec, (ext_adec_debug_info *)arg); break; case EXT_ADEC_CODEC_NAME: ret = adec_get_codec_name(adec, (ha_codec_name *)arg); break; default: soc_err_print_u32(info_type); ret = SOC_ERR_ADEC_INVALID_PARA; break; } adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_config_codec(const td_u32 codec_id, td_void *config) { return adec_set_config_decoder(codec_id, config); } td_s32 ext_mpi_adec_set_eos(td_handle adec) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_set_eos_flag(adec); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_drop_stream(td_handle adec, td_u32 seek_pts) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_drop_stream(adec, seek_pts); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_set_codec_cmd(td_handle adec, td_void *cmd) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_set_codec_cmd(adec, cmd); adec_api_unlock(adec); return ret; } td_s32 ext_mpi_adec_register_event(td_handle adec, td_handle user_handle, ext_mpi_adec_event_fn fun) { td_s32 ret; adec_get_real_chn(adec); adec_api_lock(adec); ret = adec_register_event(adec, user_handle, fun); adec_api_unlock(adec); return ret; } #ifdef __cplusplus } #endif /* __cplusplus */