You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

637 lines
14 KiB

/*
* 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 */