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