1587 lines
57 KiB
C
1587 lines
57 KiB
C
![]() |
/*
|
||
|
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
|
||
|
*/
|
||
|
|
||
|
#include "audio_aac_adp.h"
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include "audio_dl_adp.h"
|
||
|
#include "securec.h"
|
||
|
|
||
|
#define aac_check_false_return(x) \
|
||
|
do { \
|
||
|
if ((x) != TD_TRUE) { \
|
||
|
return (-1); \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
#define aac_bitrate_sel(is_mono, mono_bitrate, stereo_bitrate) ((is_mono) ? (mono_bitrate) : (stereo_bitrate))
|
||
|
|
||
|
#define AAC_ENC_LIB_NAME "libaac_enc.so"
|
||
|
#define AAC_DEC_LIB_NAME "libaac_dec.so"
|
||
|
|
||
|
#define AACENC_BITRATE_16K 16000
|
||
|
#define AACENC_BITRATE_24K 24000
|
||
|
#define AACENC_BITRATE_32K 32000
|
||
|
#define AACENC_BITRATE_44K 44000
|
||
|
#define AACENC_BITRATE_48K 48000
|
||
|
#define AACENC_BITRATE_64K 64000
|
||
|
#define AACENC_BITRATE_96K 96000
|
||
|
#define AACENC_BITRATE_128K 128000
|
||
|
#define AACENC_BITRATE_132K 132000
|
||
|
#define AACENC_BITRATE_144K 144000
|
||
|
#define AACENC_BITRATE_192K 192000
|
||
|
#define AACENC_BITRATE_256K 256000
|
||
|
#define AACENC_BITRATE_265K 265000
|
||
|
#define AACENC_BITRATE_288K 288000
|
||
|
#define AACENC_BITRATE_320K 320000
|
||
|
|
||
|
#define AACENC_CHANNEL_SINGLE 1
|
||
|
#define AACENC_CHANNEL_STEREO 2
|
||
|
|
||
|
#define DUMP_PATH_NAME_MAX_BYTES 256
|
||
|
#define DUMP_MAX_TIMES 10000
|
||
|
|
||
|
/* aac enc lib */
|
||
|
typedef td_s32 (*aacenc_get_version_callback)(ot_aacenc_version *version);
|
||
|
typedef td_s32 (*aacenc_init_default_config_callback)(ot_aacenc_config *config);
|
||
|
typedef td_s32 (*aac_encoder_open_callback)(ot_aac_encoder **ph_aac_plus_enc, const ot_aacenc_config *config);
|
||
|
typedef td_s32 (*aac_encoder_frame_callback)(ot_aac_encoder *aac_plus_enc, td_s16 *pcm_buf,
|
||
|
td_u8 *outbuf, td_s32 *num_out_bytes);
|
||
|
typedef td_void (*aac_encoder_close_callback)(ot_aac_encoder *aac_plus_enc);
|
||
|
|
||
|
/* aac dec lib */
|
||
|
typedef td_s32 (*aacdec_get_version_callback)(ot_aacdec_version *version);
|
||
|
typedef ot_aac_decoder (*aac_init_decoder_callback)(ot_aacdec_transport_type tran_type);
|
||
|
typedef td_void (*aac_free_decoder_callback)(ot_aac_decoder aac_decoder);
|
||
|
typedef td_s32 (*aac_set_raw_mode_callback)(ot_aac_decoder aac_decoder, td_s32 chans, td_s32 samp_rate);
|
||
|
typedef td_s32 (*aac_decode_find_sync_header_callback)(
|
||
|
ot_aac_decoder aac_decoder, td_u8 **pp_inbuf_ptr, td_s32 *bytes_left);
|
||
|
typedef td_s32 (*aac_decode_frame_callback)(ot_aac_decoder aac_decoder,
|
||
|
td_u8 **pp_inbuf_ptr, td_s32 *bytes_left, td_s16 *out_pcm);
|
||
|
typedef td_s32 (*aac_get_last_frame_info_callback)(ot_aac_decoder aac_decoder, ot_aacdec_frame_info *aac_frame_info);
|
||
|
typedef td_s32 (*aac_decoder_set_eos_flag_callback)(ot_aac_decoder aac_decoder, td_s32 eosflag);
|
||
|
typedef td_s32 (*aac_flush_codec_callback)(ot_aac_decoder aac_decoder);
|
||
|
|
||
|
typedef struct {
|
||
|
td_s32 open_cnt;
|
||
|
td_void *lib_handle;
|
||
|
|
||
|
aacenc_get_version_callback ot_aacenc_get_version;
|
||
|
aacenc_init_default_config_callback ot_aacenc_init_default_config;
|
||
|
aac_encoder_open_callback ot_aacenc_open;
|
||
|
aac_encoder_frame_callback ot_aacenc_frame;
|
||
|
aac_encoder_close_callback ot_aacenc_close;
|
||
|
} aacenc_fun;
|
||
|
|
||
|
typedef struct {
|
||
|
td_s32 open_cnt;
|
||
|
td_void *lib_handle;
|
||
|
|
||
|
aacdec_get_version_callback ot_aacdec_get_version;
|
||
|
aac_init_decoder_callback ot_aacdec_init_decoder;
|
||
|
aac_free_decoder_callback ot_aacdec_free_decoder;
|
||
|
aac_set_raw_mode_callback ot_aacdec_set_raw_mode;
|
||
|
aac_decode_find_sync_header_callback ot_aacdec_find_sync_header;
|
||
|
aac_decode_frame_callback ot_aacdec_frame;
|
||
|
aac_get_last_frame_info_callback ot_aacdec_get_last_frame_info;
|
||
|
aac_decoder_set_eos_flag_callback ot_aacdec_set_eos_flag;
|
||
|
aac_flush_codec_callback ot_aacdec_flush_codec;
|
||
|
} aacdec_fun;
|
||
|
|
||
|
/* if need, define DUMP_AACENC */
|
||
|
#ifdef DUMP_AACENC
|
||
|
FILE *g_in_enc_fd = NULL;
|
||
|
FILE *g_out_enc_fd = NULL;
|
||
|
#endif
|
||
|
|
||
|
/* if need, define DUMP_AACDEC */
|
||
|
#ifdef DUMP_AACDEC
|
||
|
FILE *g_in_dec_fd = NULL;
|
||
|
FILE *g_out_dec_fd = NULL;
|
||
|
FILE *g_out_dec_left_fd = NULL;
|
||
|
#endif
|
||
|
|
||
|
int g_cnt_aenc = 100000;
|
||
|
int g_cnt_adec = 100000;
|
||
|
|
||
|
static td_s32 g_aac_enc_handle = 0;
|
||
|
static td_s32 g_aac_dec_handle = 0;
|
||
|
|
||
|
#if defined(OT_AAC_USE_STATIC_MODULE_REGISTER) && defined(OT_AAC_HAVE_SBR_LIB)
|
||
|
static td_bool g_aac_enc_static_reg = TD_FALSE;
|
||
|
static td_bool g_aac_dec_static_reg = TD_FALSE;
|
||
|
#endif
|
||
|
|
||
|
static aacenc_fun g_aac_enc_func = {0};
|
||
|
static aacdec_fun g_aac_dec_func = {0};
|
||
|
|
||
|
#if defined(OT_AAC_USE_STATIC_MODULE_REGISTER) && defined(OT_AAC_HAVE_SBR_LIB)
|
||
|
static td_s32 aac_init_sbr_enc_lib(void)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
td_void *sbr_enc_handle = ot_aac_sbrenc_get_handle();
|
||
|
|
||
|
if (g_aac_enc_static_reg == TD_TRUE) {
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
ret = ot_aacenc_register_mod(sbr_enc_handle);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "init sbr_enc lib fail!\n");
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
g_aac_enc_static_reg = TD_TRUE;
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aac_init_sbr_dec_lib(void)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
td_void *sbr_dec_handle = ot_aac_sbrdec_get_handle();
|
||
|
|
||
|
if (g_aac_dec_static_reg == TD_TRUE) {
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
ret = ot_aacdec_register_mod(sbr_dec_handle);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "init sbr_dec lib fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
g_aac_dec_static_reg = TD_TRUE;
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef OT_AAC_USE_STATIC_MODULE_REGISTER
|
||
|
static td_s32 aac_init_enc_lib(void)
|
||
|
{
|
||
|
g_aac_enc_func.ot_aacenc_get_version = ot_aacenc_get_version;
|
||
|
g_aac_enc_func.ot_aacenc_init_default_config = ot_aacenc_init_default_config;
|
||
|
g_aac_enc_func.ot_aacenc_open = ot_aacenc_open;
|
||
|
g_aac_enc_func.ot_aacenc_frame = ot_aacenc_frame;
|
||
|
g_aac_enc_func.ot_aacenc_close = ot_aacenc_close;
|
||
|
#ifdef OT_AAC_HAVE_SBR_LIB
|
||
|
return aac_init_sbr_enc_lib();
|
||
|
#endif
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
#else
|
||
|
static td_s32 aac_enc_lib_dlsym(aacenc_fun *aac_enc_func)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_enc_func->ot_aacenc_get_version),
|
||
|
aac_enc_func->lib_handle, "ot_aacenc_get_version");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_enc_func->ot_aacenc_init_default_config),
|
||
|
aac_enc_func->lib_handle, "ot_aacenc_init_default_config");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_enc_func->ot_aacenc_open),
|
||
|
aac_enc_func->lib_handle, "ot_aacenc_open");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_enc_func->ot_aacenc_frame),
|
||
|
aac_enc_func->lib_handle, "ot_aacenc_frame");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_enc_func->ot_aacenc_close),
|
||
|
aac_enc_func->lib_handle, "ot_aacenc_close");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aac_init_enc_lib(void)
|
||
|
{
|
||
|
if (g_aac_enc_func.open_cnt == 0) {
|
||
|
td_s32 ret;
|
||
|
aacenc_fun aac_enc_func = {0};
|
||
|
|
||
|
ret = audio_dlopen(&(aac_enc_func.lib_handle), AAC_ENC_LIB_NAME);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "load aenc lib fail!\n");
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = aac_enc_lib_dlsym(&aac_enc_func);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "find symbol error!\n");
|
||
|
audio_dlclose(aac_enc_func.lib_handle);
|
||
|
aac_enc_func.lib_handle = TD_NULL;
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
(td_void)memcpy_s(&g_aac_enc_func, sizeof(g_aac_enc_func), &aac_enc_func, sizeof(aac_enc_func));
|
||
|
}
|
||
|
g_aac_enc_func.open_cnt++;
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
td_void aac_deinit_enc_lib(td_void)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
if (g_aac_enc_func.open_cnt != 0) {
|
||
|
g_aac_enc_func.open_cnt--;
|
||
|
}
|
||
|
|
||
|
if (g_aac_enc_func.open_cnt == 0) {
|
||
|
#ifndef OT_AAC_USE_STATIC_MODULE_REGISTER
|
||
|
if (g_aac_enc_func.lib_handle != TD_NULL) {
|
||
|
audio_dlclose(g_aac_enc_func.lib_handle);
|
||
|
}
|
||
|
#endif
|
||
|
ret = memset_s(&g_aac_enc_func, sizeof(aacenc_fun), 0, sizeof(aacenc_fun));
|
||
|
if (ret != EOK) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "memset_s aenc fun fail!\n");
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
td_s32 aacenc_get_version_adp(ot_aacenc_version *version)
|
||
|
{
|
||
|
if (g_aac_enc_func.ot_aacenc_get_version == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_enc_func.ot_aacenc_get_version(version);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_init_default_config_adp(ot_aacenc_config *config)
|
||
|
{
|
||
|
if (g_aac_enc_func.ot_aacenc_init_default_config == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_enc_func.ot_aacenc_init_default_config(config);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_encoder_open_adp(ot_aac_encoder **ph_aac_plus_enc, const ot_aacenc_config *config)
|
||
|
{
|
||
|
if (g_aac_enc_func.ot_aacenc_open == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_enc_func.ot_aacenc_open(ph_aac_plus_enc, config);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_encoder_frame_adp(ot_aac_encoder *aac_plus_enc, td_s16 *pcm_buf, td_u8 *outbuf, td_s32 *num_out_bytes)
|
||
|
{
|
||
|
if (g_aac_enc_func.ot_aacenc_frame == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_AENC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_enc_func.ot_aacenc_frame(aac_plus_enc, pcm_buf, outbuf, num_out_bytes);
|
||
|
}
|
||
|
|
||
|
td_void aac_encoder_close_adp(ot_aac_encoder *aac_plus_enc)
|
||
|
{
|
||
|
if (g_aac_enc_func.ot_aacenc_close == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return;
|
||
|
}
|
||
|
return g_aac_enc_func.ot_aacenc_close(aac_plus_enc);
|
||
|
}
|
||
|
|
||
|
#ifdef OT_AAC_USE_STATIC_MODULE_REGISTER
|
||
|
static td_s32 aac_init_dec_lib(void)
|
||
|
{
|
||
|
g_aac_dec_func.ot_aacdec_get_version = ot_aacdec_get_version;
|
||
|
g_aac_dec_func.ot_aacdec_init_decoder = ot_aacdec_init_decoder;
|
||
|
g_aac_dec_func.ot_aacdec_free_decoder = ot_aacdec_free_decoder;
|
||
|
g_aac_dec_func.ot_aacdec_set_raw_mode = ot_aacdec_set_raw_mode;
|
||
|
g_aac_dec_func.ot_aacdec_find_sync_header = ot_aacdec_find_sync_header;
|
||
|
g_aac_dec_func.ot_aacdec_frame = ot_aacdec_frame;
|
||
|
g_aac_dec_func.ot_aacdec_get_last_frame_info = ot_aacdec_get_last_frame_info;
|
||
|
g_aac_dec_func.ot_aacdec_set_eos_flag = ot_aacdec_set_eos_flag;
|
||
|
g_aac_dec_func.ot_aacdec_flush_codec = ot_aacdec_flush_codec;
|
||
|
#ifdef OT_AAC_HAVE_SBR_LIB
|
||
|
return aac_init_sbr_dec_lib();
|
||
|
#endif
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
#else
|
||
|
static td_s32 aac_dec_lib_dlsym(aacdec_fun *aac_dec_func)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_get_version),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_get_version");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_init_decoder),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_init_decoder");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_free_decoder),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_free_decoder");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_set_raw_mode),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_set_raw_mode");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_find_sync_header),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_find_sync_header");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_frame), aac_dec_func->lib_handle, "ot_aacdec_frame");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_get_last_frame_info),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_get_last_frame_info");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_set_eos_flag),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_set_eos_flag");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = audio_dlsym((td_void **)&(aac_dec_func->ot_aacdec_flush_codec),
|
||
|
aac_dec_func->lib_handle, "ot_aacdec_flush_codec");
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aac_init_dec_lib(void)
|
||
|
{
|
||
|
if (g_aac_dec_func.open_cnt == 0) {
|
||
|
td_s32 ret;
|
||
|
aacdec_fun aac_dec_func = {0};
|
||
|
|
||
|
ret = audio_dlopen(&(aac_dec_func.lib_handle), AAC_DEC_LIB_NAME);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "load aenc lib fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
ret = aac_dec_lib_dlsym(&aac_dec_func);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "find symbol error!\n");
|
||
|
audio_dlclose(aac_dec_func.lib_handle);
|
||
|
aac_dec_func.lib_handle = TD_NULL;
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
|
||
|
(td_void)memcpy_s(&g_aac_dec_func, sizeof(g_aac_dec_func), &aac_dec_func, sizeof(aac_dec_func));
|
||
|
}
|
||
|
g_aac_dec_func.open_cnt++;
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
td_void aac_deinit_dec_lib(td_void)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
if (g_aac_dec_func.open_cnt != 0) {
|
||
|
g_aac_dec_func.open_cnt--;
|
||
|
}
|
||
|
|
||
|
if (g_aac_dec_func.open_cnt == 0) {
|
||
|
#ifndef OT_AAC_USE_STATIC_MODULE_REGISTER
|
||
|
if (g_aac_dec_func.lib_handle != TD_NULL) {
|
||
|
audio_dlclose(g_aac_dec_func.lib_handle);
|
||
|
}
|
||
|
#endif
|
||
|
ret = memset_s(&g_aac_dec_func, sizeof(aacdec_fun), 0, sizeof(aacdec_fun));
|
||
|
if (ret != EOK) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "memset_s adec lib fail!\n");
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
td_s32 aacdec_get_version_adp(ot_aacdec_version *version)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_get_version == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_get_version(version);
|
||
|
}
|
||
|
|
||
|
ot_aac_decoder aac_init_decoder_adp(ot_aacdec_transport_type tran_type)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_init_decoder == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return TD_NULL;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_init_decoder(tran_type);
|
||
|
}
|
||
|
|
||
|
td_void aac_free_decoder_adp(ot_aac_decoder aac_decoder)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_free_decoder == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_free_decoder(aac_decoder);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_set_raw_mode_adp(ot_aac_decoder aac_decoder, td_s32 chans, td_s32 samp_rate)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_set_raw_mode == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_set_raw_mode(aac_decoder, chans, samp_rate);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_decode_find_sync_header_adp(ot_aac_decoder aac_decoder, td_u8 **pp_inbuf_ptr, td_s32 *bytes_left)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_find_sync_header == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_find_sync_header(aac_decoder, pp_inbuf_ptr, bytes_left);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_decode_frame_adp(ot_aac_decoder aac_decoder, td_u8 **pp_inbuf_ptr, td_s32 *bytes_left, td_s16 *out_pcm)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_frame == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_frame(aac_decoder, pp_inbuf_ptr, bytes_left, out_pcm);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_get_last_frame_info_adp(ot_aac_decoder aac_decoder, ot_aacdec_frame_info *aac_frame_info)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_get_last_frame_info == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_get_last_frame_info(aac_decoder, aac_frame_info);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_decoder_set_eos_flag_adp(ot_aac_decoder aac_decoder, td_s32 eosflag)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_set_eos_flag == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_set_eos_flag(aac_decoder, eosflag);
|
||
|
}
|
||
|
|
||
|
td_s32 aac_flush_codec_adp(ot_aac_decoder aac_decoder)
|
||
|
{
|
||
|
if (g_aac_dec_func.ot_aacdec_flush_codec == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "call aac function fail!\n");
|
||
|
return OT_ERR_ADEC_NOT_SUPPORT;
|
||
|
}
|
||
|
return g_aac_dec_func.ot_aacdec_flush_codec(aac_decoder);
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_check_aac_attr(const ot_aenc_attr_aac *aac_attr)
|
||
|
{
|
||
|
if (aac_attr->bit_width != OT_AUDIO_BIT_WIDTH_16) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "invalid bitwidth for AAC encoder");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if (aac_attr->snd_mode >= OT_AUDIO_SOUND_MODE_BUTT) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "invalid sound mode for AAC encoder");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if ((aac_attr->aac_type == OT_AAC_TYPE_EAACPLUS) && (aac_attr->snd_mode != OT_AUDIO_SOUND_MODE_STEREO)) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "invalid sound mode for AAC encoder");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if (aac_attr->transport_type == OT_AAC_TRANSPORT_TYPE_ADTS) {
|
||
|
if ((aac_attr->aac_type == OT_AAC_TYPE_AACLD) ||
|
||
|
(aac_attr->aac_type == OT_AAC_TYPE_AACELD)) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "OT_AACLD or OT_AACELD not support OT_AAC_TRANSPORT_TYPE_ADTS");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_get_aaclc_bitrate(const ot_aacenc_config *config, td_s32 *min_rate,
|
||
|
td_s32 *max_rate, td_s32 *recommemd_rate)
|
||
|
{
|
||
|
td_bool chn_single = (config->num_channels_in == AACENC_CHANNEL_SINGLE) ? TD_TRUE : TD_FALSE;
|
||
|
|
||
|
if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_32000) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_192K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_128K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_44100) {
|
||
|
*min_rate = AACENC_BITRATE_48K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_265K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_48000) {
|
||
|
*min_rate = AACENC_BITRATE_48K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_288K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_16000) {
|
||
|
*min_rate = AACENC_BITRATE_24K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_96K, AACENC_BITRATE_192K);
|
||
|
*recommemd_rate = AACENC_BITRATE_48K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_8000) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_96K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_24K, AACENC_BITRATE_32K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_24000) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_144K, AACENC_BITRATE_288K);
|
||
|
*recommemd_rate = AACENC_BITRATE_48K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_22050) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_132K, AACENC_BITRATE_265K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_48K);
|
||
|
} else {
|
||
|
printf("OT_AACLC invalid samplerate(%d)\n", config->sample_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_check_aaclc_config(const ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 min_bit_rate = 0;
|
||
|
td_s32 max_bit_rate = 0;
|
||
|
td_s32 recommemd_rate = 0;
|
||
|
td_s32 ret;
|
||
|
|
||
|
if (config->coder_format == OT_AACLC) {
|
||
|
if (config->num_channels_out != config->num_channels_in) {
|
||
|
printf("OT_AACLC num_channels_out(%d) in not equal to num_channels_in(%d)\n",
|
||
|
config->num_channels_out, config->num_channels_in);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
ret = aenc_get_aaclc_bitrate(config, &min_bit_rate, &max_bit_rate, &recommemd_rate);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if ((config->bit_rate < min_bit_rate) || (config->bit_rate > max_bit_rate)) {
|
||
|
printf("OT_AACLC %d Hz bit_rate(%d) should be %d ~ %d, recommed %d\n",
|
||
|
config->sample_rate, config->bit_rate, min_bit_rate, max_bit_rate, recommemd_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
} else {
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_get_eaac_bitrate(const ot_aacenc_config *config, td_s32 *min_rate,
|
||
|
td_s32 *max_rate, td_s32 *recommemd_rate)
|
||
|
{
|
||
|
td_bool chn_single = (config->num_channels_in == AACENC_CHANNEL_SINGLE) ? TD_TRUE : TD_FALSE;
|
||
|
|
||
|
if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_32000) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_64K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_44100) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_64K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_48000) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_64K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_16000) {
|
||
|
*min_rate = AACENC_BITRATE_24K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_96K);
|
||
|
*recommemd_rate = AACENC_BITRATE_32K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_22050) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_64K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_24000) {
|
||
|
*min_rate = AACENC_BITRATE_32K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_64K);
|
||
|
} else {
|
||
|
printf("OT_EAAC invalid samplerate(%d)\n", config->sample_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_check_eaac_config(const ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 min_bit_rate = 0;
|
||
|
td_s32 max_bit_rate = 0;
|
||
|
td_s32 recommemd_rate = 0;
|
||
|
td_s32 ret;
|
||
|
|
||
|
if (config->coder_format == OT_EAAC) {
|
||
|
if (config->num_channels_out != config->num_channels_in) {
|
||
|
printf("OT_EAAC num_channels_out(%d) is not equal to num_channels_in(%d)\n",
|
||
|
config->num_channels_out, config->num_channels_in);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
ret = aenc_get_eaac_bitrate(config, &min_bit_rate, &max_bit_rate, &recommemd_rate);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if ((config->bit_rate < min_bit_rate) || (config->bit_rate > max_bit_rate)) {
|
||
|
printf("OT_EAAC %d Hz bit_rate(%d) should be %d ~ %d, recommed %d\n",
|
||
|
config->sample_rate, config->bit_rate, min_bit_rate, max_bit_rate, recommemd_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
} else {
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_get_eaacplus_bitrate(const ot_aacenc_config *config, td_s32 *min_rate,
|
||
|
td_s32 *max_rate, td_s32 *recommemd_rate)
|
||
|
{
|
||
|
if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_32000) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = AACENC_BITRATE_64K;
|
||
|
*recommemd_rate = AACENC_BITRATE_32K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_44100) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = AACENC_BITRATE_64K;
|
||
|
*recommemd_rate = AACENC_BITRATE_48K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_48000) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = AACENC_BITRATE_64K;
|
||
|
*recommemd_rate = AACENC_BITRATE_48K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_16000) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = AACENC_BITRATE_48K;
|
||
|
*recommemd_rate = AACENC_BITRATE_32K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_22050) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = AACENC_BITRATE_64K;
|
||
|
*recommemd_rate = AACENC_BITRATE_32K;
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_24000) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = AACENC_BITRATE_64K;
|
||
|
*recommemd_rate = AACENC_BITRATE_32K;
|
||
|
} else {
|
||
|
printf("OT_EAACPLUS invalid samplerate(%d)\n", config->sample_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_check_eaacplus_config(const ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 min_bit_rate = 0;
|
||
|
td_s32 max_bit_rate = 0;
|
||
|
td_s32 recommemd_rate = 0;
|
||
|
td_s32 ret;
|
||
|
|
||
|
if (config->coder_format == OT_EAACPLUS) {
|
||
|
if ((config->num_channels_out != AACENC_CHANNEL_STEREO) ||
|
||
|
(config->num_channels_in != AACENC_CHANNEL_STEREO)) {
|
||
|
printf("OT_EAACPLUS num_channels_out(%d) and num_channels_in(%d) should be 2\n",
|
||
|
config->num_channels_out, config->num_channels_in);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
ret = aenc_get_eaacplus_bitrate(config, &min_bit_rate, &max_bit_rate, &recommemd_rate);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if ((config->bit_rate < min_bit_rate) || (config->bit_rate > max_bit_rate)) {
|
||
|
printf("OT_EAACPLUS %d Hz bit_rate(%d) should be %d ~ %d, recommed %d\n",
|
||
|
config->sample_rate, config->bit_rate, min_bit_rate, max_bit_rate, recommemd_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
} else {
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_get_aacld_bitrate(const ot_aacenc_config *config, td_s32 *min_rate,
|
||
|
td_s32 *max_rate, td_s32 *recommemd_rate)
|
||
|
{
|
||
|
td_bool chn_single = (config->num_channels_in == AACENC_CHANNEL_SINGLE) ? TD_TRUE : TD_FALSE;
|
||
|
|
||
|
if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_32000) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_64K);
|
||
|
*max_rate = AACENC_BITRATE_320K;
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_44100) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_44K);
|
||
|
*max_rate = AACENC_BITRATE_320K;
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_128K, AACENC_BITRATE_256K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_48000) {
|
||
|
*min_rate = AACENC_BITRATE_64K;
|
||
|
*max_rate = AACENC_BITRATE_320K;
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_128K, AACENC_BITRATE_256K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_16000) {
|
||
|
*min_rate = (chn_single) ? AACENC_BITRATE_24K : AACENC_BITRATE_32K;
|
||
|
*max_rate = (chn_single) ? AACENC_BITRATE_192K : AACENC_BITRATE_320K;
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_96K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_8000) {
|
||
|
*min_rate = AACENC_BITRATE_16K;
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_96K, AACENC_BITRATE_192K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_24K, AACENC_BITRATE_48K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_24000) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_32K, AACENC_BITRATE_48K);
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_256K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_22050) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_32K, AACENC_BITRATE_48K);
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_256K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_96K);
|
||
|
} else {
|
||
|
printf("OT_AACLD invalid samplerate(%d)\n", config->sample_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_check_aacld_config(const ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 min_bit_rate = 0;
|
||
|
td_s32 max_bit_rate = 0;
|
||
|
td_s32 recommemd_rate = 0;
|
||
|
td_s32 ret;
|
||
|
|
||
|
if (config->coder_format == OT_AACLD) {
|
||
|
if (config->num_channels_out != config->num_channels_in) {
|
||
|
printf("OT_AACLD num_channels_out(%d) in not equal to num_channels_in(%d)\n",
|
||
|
config->num_channels_out, config->num_channels_in);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
ret = aenc_get_aacld_bitrate(config, &min_bit_rate, &max_bit_rate, &recommemd_rate);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if ((config->bit_rate < min_bit_rate) || (config->bit_rate > max_bit_rate)) {
|
||
|
printf("OT_AACLD %d Hz bit_rate(%d) should be %d ~ %d, recommed %d\n",
|
||
|
config->sample_rate, config->bit_rate, min_bit_rate, max_bit_rate, recommemd_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
} else {
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_get_aaceld_bitrate(const ot_aacenc_config *config, td_s32 *min_rate,
|
||
|
td_s32 *max_rate, td_s32 *recommemd_rate)
|
||
|
{
|
||
|
td_bool chn_single = (config->num_channels_in == AACENC_CHANNEL_SINGLE) ? TD_TRUE : TD_FALSE;
|
||
|
|
||
|
if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_32000) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_32K, AACENC_BITRATE_64K);
|
||
|
*max_rate = AACENC_BITRATE_320K;
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_44100) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_96K, AACENC_BITRATE_192K);
|
||
|
*max_rate = AACENC_BITRATE_320K;
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_128K, AACENC_BITRATE_256K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_48000) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_96K, AACENC_BITRATE_192K);
|
||
|
*max_rate = AACENC_BITRATE_320K;
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_128K, AACENC_BITRATE_256K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_16000) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_16K, AACENC_BITRATE_32K);
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_256K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_96K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_8000) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_32K, AACENC_BITRATE_64K);
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_96K, AACENC_BITRATE_192K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_32K, AACENC_BITRATE_64K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_24000) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_24K, AACENC_BITRATE_32K);
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_256K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_64K, AACENC_BITRATE_128K);
|
||
|
} else if (config->sample_rate == OT_AUDIO_SAMPLE_RATE_22050) {
|
||
|
*min_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_24K, AACENC_BITRATE_32K);
|
||
|
*max_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_256K, AACENC_BITRATE_320K);
|
||
|
*recommemd_rate = aac_bitrate_sel(chn_single, AACENC_BITRATE_48K, AACENC_BITRATE_96K);
|
||
|
} else {
|
||
|
printf("OT_AACELD invalid samplerate(%d)\n", config->sample_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_check_aaceld_config(const ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 min_bit_rate = 0;
|
||
|
td_s32 max_bit_rate = 0;
|
||
|
td_s32 recommemd_rate = 0;
|
||
|
td_s32 ret;
|
||
|
|
||
|
if (config->coder_format == OT_AACELD) {
|
||
|
if (config->num_channels_out != config->num_channels_in) {
|
||
|
printf("OT_AACELD num_channels_out(%d) in not equal to num_channels_in(%d)\n",
|
||
|
config->num_channels_out, config->num_channels_in);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
ret = aenc_get_aaceld_bitrate(config, &min_bit_rate, &max_bit_rate, &recommemd_rate);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if ((config->bit_rate < min_bit_rate) || (config->bit_rate > max_bit_rate)) {
|
||
|
printf("AACELD %d Hz bit_rate(%d) should be %d ~ %d, recommed %d\n",
|
||
|
config->sample_rate, config->bit_rate, min_bit_rate, max_bit_rate, recommemd_rate);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
} else {
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 aenc_aac_check_coder_format(ot_aacenc_format coder_format)
|
||
|
{
|
||
|
if (coder_format != OT_AACLC && coder_format != OT_EAAC &&
|
||
|
coder_format != OT_EAACPLUS && coder_format != OT_AACLD &&
|
||
|
coder_format != OT_AACELD) {
|
||
|
printf("aacenc coder_format(%d) invalid\n", coder_format);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 aenc_aac_check_config(const ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 ret = 0;
|
||
|
|
||
|
if (config == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "config is null");
|
||
|
return OT_ERR_AENC_NULL_PTR;
|
||
|
}
|
||
|
|
||
|
if (aenc_aac_check_coder_format(config->coder_format) != TD_SUCCESS) {
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if (config->quality != OT_AACENC_QUALITY_EXCELLENT && config->quality != OT_AACENC_QUALITY_HIGH &&
|
||
|
config->quality != OT_AACENC_QUALITY_MEDIUM && config->quality != OT_AACENC_QUALITY_LOW) {
|
||
|
printf("aacenc quality(%d) invalid\n", config->quality);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if (config->bits_per_sample != 16) { /* 16: 16bit */
|
||
|
printf("aacenc bits_per_sample(%d) should be 16\n", config->bits_per_sample);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if ((config->trans_type < 0) || (config->trans_type > OT_AACENC_LATM_MCP1)) {
|
||
|
printf("invalid trans_type(%d), not in [0, 2]\n", config->trans_type);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if ((config->band_width != 0) && ((config->band_width < 1000) || /* 1000: band width */
|
||
|
(config->band_width > config->sample_rate / 2))) { /* 2: half */
|
||
|
printf("AAC band_width(%d) should be 0, or 1000 ~ %d\n",
|
||
|
config->band_width, config->sample_rate / 2); /* 2: half */
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
if (config->coder_format == OT_AACLC) {
|
||
|
ret = aenc_check_aaclc_config(config);
|
||
|
} else if (config->coder_format == OT_EAAC) {
|
||
|
ret = aenc_check_eaac_config(config);
|
||
|
} else if (config->coder_format == OT_EAACPLUS) {
|
||
|
ret = aenc_check_eaacplus_config(config);
|
||
|
} else if (config->coder_format == OT_AACLD) {
|
||
|
ret = aenc_check_aacld_config(config);
|
||
|
} else if (config->coder_format == OT_AACELD) {
|
||
|
ret = aenc_check_aaceld_config(config);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static td_void aenc_aac_init_config(const ot_aenc_attr_aac *attr, ot_aacenc_config *config)
|
||
|
{
|
||
|
config->coder_format = (ot_aacenc_format)attr->aac_type;
|
||
|
config->bit_rate = attr->bit_rate;
|
||
|
config->bits_per_sample = 8 * (1 << ((td_u32)attr->bit_width)); /* 8: 8bit */
|
||
|
config->sample_rate = attr->sample_rate;
|
||
|
config->band_width = attr->band_width;
|
||
|
config->trans_type = (ot_aacenc_transport_type)attr->transport_type;
|
||
|
|
||
|
if ((attr->snd_mode == OT_AUDIO_SOUND_MODE_MONO) && (attr->aac_type != OT_AAC_TYPE_EAACPLUS)) {
|
||
|
config->num_channels_in = AACENC_CHANNEL_SINGLE;
|
||
|
config->num_channels_out = AACENC_CHANNEL_SINGLE;
|
||
|
} else {
|
||
|
config->num_channels_in = AACENC_CHANNEL_STEREO;
|
||
|
config->num_channels_out = AACENC_CHANNEL_STEREO;
|
||
|
}
|
||
|
|
||
|
config->quality = OT_AACENC_QUALITY_HIGH;
|
||
|
}
|
||
|
|
||
|
#ifdef DUMP_AACENC
|
||
|
static td_void init_encoder_dump_file(const ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
td_char name_in[DUMP_PATH_NAME_MAX_BYTES] = {'\0'};
|
||
|
td_char name_out[DUMP_PATH_NAME_MAX_BYTES] = {'\0'};
|
||
|
|
||
|
ret = snprintf_s(name_in, DUMP_PATH_NAME_MAX_BYTES, DUMP_PATH_NAME_MAX_BYTES - 1,
|
||
|
"aacenc_sin_t%d_t%d.raw", config->coder_format, config->trans_type);
|
||
|
if (ret < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get encoder in dump name failed");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = snprintf_s(name_out, DUMP_PATH_NAME_MAX_BYTES, DUMP_PATH_NAME_MAX_BYTES - 1,
|
||
|
"aacenc_sout_t%d_t%d.aac", config->coder_format, config->trans_type);
|
||
|
if (ret < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get encoder in dump name failed");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
g_in_enc_fd = fopen(name_in, "w+");
|
||
|
if (g_in_enc_fd == TD_NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "open encoder in dump name failed");
|
||
|
}
|
||
|
|
||
|
g_out_enc_fd = fopen(name_out, "w+");
|
||
|
if (g_out_enc_fd == TD_NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "open encoder out dump name failed");
|
||
|
}
|
||
|
|
||
|
g_cnt_aenc = DUMP_MAX_TIMES;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static td_s32 open_aac_encoder_check_and_init(ot_aenc_attr_aac *attr, ot_aacenc_config *config)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
|
||
|
/* check attribute of encoder */
|
||
|
ret = aenc_check_aac_attr(attr);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* set default config to encoder */
|
||
|
ret = aac_init_default_config_adp(config);
|
||
|
if (ret) {
|
||
|
printf("[func]:%s [line]:%d ret:0x%x.#########\n", __FUNCTION__, __LINE__, ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
aenc_aac_init_config(attr, config);
|
||
|
|
||
|
ret = aenc_aac_check_config(config);
|
||
|
if (ret) {
|
||
|
printf("[func]:%s [line]:%d ret:0x%x.#########\n", __FUNCTION__, __LINE__, ret);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 open_aac_encoder(td_void *encoder_attr, td_void **pp_encoder)
|
||
|
{
|
||
|
aenc_aac_encoder *encoder = NULL;
|
||
|
ot_aenc_attr_aac *attr = (ot_aenc_attr_aac *)encoder_attr;
|
||
|
td_s32 ret;
|
||
|
ot_aacenc_config config = {0};
|
||
|
|
||
|
aac_check_false_return(encoder_attr != NULL);
|
||
|
aac_check_false_return(pp_encoder != NULL);
|
||
|
|
||
|
ret = open_aac_encoder_check_and_init(attr, &config);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* allocate memory for encoder */
|
||
|
encoder = (aenc_aac_encoder *)malloc(sizeof(aenc_aac_encoder));
|
||
|
if (encoder == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "no memory");
|
||
|
return OT_ERR_AENC_NO_MEM;
|
||
|
}
|
||
|
ret = memset_s(encoder, sizeof(aenc_aac_encoder), 0, sizeof(aenc_aac_encoder));
|
||
|
if (ret != EOK) {
|
||
|
free(encoder);
|
||
|
printf("[func]:%s [line]:%d memset_s fail, ret:0x%x.#########\n", __FUNCTION__, __LINE__, ret);
|
||
|
return OT_ERR_AENC_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
*pp_encoder = (td_void *)encoder;
|
||
|
|
||
|
/* create encoder */
|
||
|
ret = aac_encoder_open_adp(&encoder->aac_state, &config);
|
||
|
if (ret) {
|
||
|
free(encoder);
|
||
|
printf("[func]:%s [line]:%d ret:0x%x.#########\n", __FUNCTION__, __LINE__, ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
ret = memcpy_s(&encoder->aac_attr, sizeof(encoder->aac_attr), attr, sizeof(*attr));
|
||
|
if (ret != EOK) {
|
||
|
aac_encoder_close_adp(encoder->aac_state);
|
||
|
free(encoder);
|
||
|
printf("[func]:%s [line]:%d memcpy_s ret:0x%x.#########\n", __FUNCTION__, __LINE__, ret);
|
||
|
return OT_ERR_AENC_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
#ifdef DUMP_AACENC
|
||
|
init_encoder_dump_file(&config);
|
||
|
#endif
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static td_s32 encode_frm_check_and_init(aenc_aac_encoder *aac_encoder, const ot_audio_frame *frame,
|
||
|
td_s16 *in_data, td_s16 in_len)
|
||
|
{
|
||
|
td_s32 i;
|
||
|
td_u32 pt_nums, water_line;
|
||
|
|
||
|
if (aac_encoder->aac_attr.snd_mode == OT_AUDIO_SOUND_MODE_STEREO) {
|
||
|
/* whether the sound mode of frame and channel is match */
|
||
|
if (frame->snd_mode != OT_AUDIO_SOUND_MODE_STEREO) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n",
|
||
|
__FUNCTION__, __LINE__, "AAC encode receive a frame which not match its soundmode");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* water_line, equals to the frame sample frame of protocol */
|
||
|
if (aac_encoder->aac_attr.aac_type == OT_AAC_TYPE_AACLC) {
|
||
|
water_line = AACLC_SAMPLES_PER_FRAME;
|
||
|
} else if ((aac_encoder->aac_attr.aac_type == OT_AAC_TYPE_EAAC) ||
|
||
|
(aac_encoder->aac_attr.aac_type == OT_AAC_TYPE_EAACPLUS)) {
|
||
|
water_line = AACPLUS_SAMPLES_PER_FRAME;
|
||
|
} else if ((aac_encoder->aac_attr.aac_type == OT_AAC_TYPE_AACLD) ||
|
||
|
(aac_encoder->aac_attr.aac_type == OT_AAC_TYPE_AACELD)) {
|
||
|
water_line = AACLD_SAMPLES_PER_FRAME;
|
||
|
} else {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "invalid AAC coder type");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
/* calculate point number */
|
||
|
pt_nums = frame->len / (frame->bit_width + 1);
|
||
|
|
||
|
/* if frame sample larger than protocol sample, reject to receive, or buffer will be overflow */
|
||
|
if (pt_nums != water_line) {
|
||
|
printf("[func]:%s [line]:%d [info]:invalid pt_nums%d for aac_type:%d\n",
|
||
|
__FUNCTION__, __LINE__, pt_nums, aac_encoder->aac_attr.aac_type);
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* AAC encoder need interleaved data,here change LLLRRR to LRLRLR.
|
||
|
* OT_AACLC will encode 1024*2 point, and aa_cplus encode 2048*2 point
|
||
|
*/
|
||
|
if (aac_encoder->aac_attr.snd_mode == OT_AUDIO_SOUND_MODE_STEREO) {
|
||
|
if ((td_u32)(in_len / 2) < (water_line * 2)) { /* 2: 16bit */
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "invalid in_len");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
for (i = water_line - 1; i >= 0; i--) {
|
||
|
in_data[2 * i] = *((td_s16 *)frame->virt_addr[0] + i); /* 2: stereo */
|
||
|
in_data[2 * i + 1] = *((td_s16 *)frame->virt_addr[1] + i); /* 2: stereo */
|
||
|
}
|
||
|
} else {
|
||
|
/* if inbuf is momo, copy left to right */
|
||
|
if ((td_u32)(in_len / 2) < water_line) { /* 2: 16bit */
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "invalid in_len");
|
||
|
return OT_ERR_AENC_ILLEGAL_PARAM;
|
||
|
}
|
||
|
for (i = water_line - 1; i >= 0; i--) {
|
||
|
in_data[i] = *((td_s16 *)frame->virt_addr[0] + i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 encode_aac_frm(td_void *encoder, const ot_audio_frame *data,
|
||
|
td_u8 *outbuf, td_u32 *out_len)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
aenc_aac_encoder *encoder_tmp = NULL;
|
||
|
td_s16 data_tmp[OT_AACENC_BLOCK_SIZE * 2 * OT_AACENC_MAX_CHANNELS]; /* 2: 16bit = 2byte */
|
||
|
|
||
|
aac_check_false_return(encoder != NULL);
|
||
|
aac_check_false_return(data != NULL);
|
||
|
aac_check_false_return(outbuf != NULL);
|
||
|
aac_check_false_return(out_len != NULL);
|
||
|
|
||
|
encoder_tmp = (aenc_aac_encoder *)encoder;
|
||
|
|
||
|
ret = encode_frm_check_and_init(encoder_tmp, data, data_tmp, sizeof(data_tmp));
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#ifdef DUMP_AACENC
|
||
|
if ((g_cnt_aenc > 0) && (g_in_enc_fd != TD_NULL)) {
|
||
|
fwrite((td_u8 *)data_tmp, 1, (encoder_tmp->aac_attr.snd_mode == OT_AUDIO_SOUND_MODE_STEREO) ?
|
||
|
(data->len * 2) : data->len, g_in_enc_fd); /* 2:stereo */
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
ret = aac_encoder_frame_adp(encoder_tmp->aac_state, data_tmp, outbuf, (td_s32*)out_len);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "AAC encode failed");
|
||
|
}
|
||
|
|
||
|
#ifdef DUMP_AACENC
|
||
|
if (g_cnt_aenc > 0) {
|
||
|
if (g_out_enc_fd != TD_NULL) {
|
||
|
fwrite((td_u8 *)outbuf, 1, *((td_s32*)out_len), g_out_enc_fd);
|
||
|
}
|
||
|
g_cnt_aenc--;
|
||
|
}
|
||
|
#endif
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
td_s32 close_aac_encoder(td_void *encoder)
|
||
|
{
|
||
|
aenc_aac_encoder *encoder_tmp = NULL;
|
||
|
|
||
|
aac_check_false_return(encoder != NULL);
|
||
|
encoder_tmp = (aenc_aac_encoder *)encoder;
|
||
|
|
||
|
aac_encoder_close_adp(encoder_tmp->aac_state);
|
||
|
|
||
|
free(encoder_tmp);
|
||
|
|
||
|
#ifdef DUMP_AACENC
|
||
|
if (g_in_enc_fd != TD_NULL) {
|
||
|
fclose(g_in_enc_fd);
|
||
|
g_in_enc_fd = TD_NULL;
|
||
|
}
|
||
|
|
||
|
if (g_out_enc_fd != TD_NULL) {
|
||
|
fclose(g_out_enc_fd);
|
||
|
g_out_enc_fd = TD_NULL;
|
||
|
}
|
||
|
#endif
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
#ifdef DUMP_AACDEC
|
||
|
static td_void init_decoder_dump_file(const ot_adec_attr_aac *attr)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
td_char name_in[DUMP_PATH_NAME_MAX_BYTES] = {'\0'};
|
||
|
td_char name_out[DUMP_PATH_NAME_MAX_BYTES] = {'\0'};
|
||
|
td_char name_out_l[DUMP_PATH_NAME_MAX_BYTES] = {'\0'};
|
||
|
|
||
|
ret = snprintf_s(name_in, DUMP_PATH_NAME_MAX_BYTES, DUMP_PATH_NAME_MAX_BYTES - 1,
|
||
|
"aacdec_sin_t%d.aac", attr->transport_type);
|
||
|
if (ret < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get decoder in dump name failed");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = snprintf_s(name_out, DUMP_PATH_NAME_MAX_BYTES, DUMP_PATH_NAME_MAX_BYTES - 1,
|
||
|
"aacdec_sout_t%d.raw", attr->transport_type);
|
||
|
if (ret < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get decoder out dump name failed");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = snprintf_s(name_out_l, DUMP_PATH_NAME_MAX_BYTES, DUMP_PATH_NAME_MAX_BYTES - 1,
|
||
|
"aacdec_sout_t%d_l.raw", attr->transport_type);
|
||
|
if (ret < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get decoder out left dump name failed");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
g_in_dec_fd = fopen(name_in, "w+");
|
||
|
if (g_in_dec_fd == TD_NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "open decoder in dump name failed");
|
||
|
}
|
||
|
|
||
|
g_out_dec_fd = fopen(name_out, "w+");
|
||
|
if (g_out_dec_fd == TD_NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "open decoder out dump name failed");
|
||
|
}
|
||
|
|
||
|
g_out_dec_left_fd = fopen(name_out_l, "w+");
|
||
|
if (g_out_dec_left_fd == TD_NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "open decoder out left dump name failed");
|
||
|
}
|
||
|
|
||
|
g_cnt_adec = DUMP_MAX_TIMES;
|
||
|
}
|
||
|
|
||
|
static td_void write_decoder_dump_file(td_u8 *inbuf, td_s32 in_len,
|
||
|
td_u16 *outbuf, td_u32 out_len, td_u32 chns)
|
||
|
{
|
||
|
if (g_cnt_adec > 0) {
|
||
|
if (g_in_dec_fd != TD_NULL) {
|
||
|
fwrite((td_u8 *)inbuf, 1, in_len, g_in_dec_fd);
|
||
|
}
|
||
|
if (g_out_dec_fd != TD_NULL) {
|
||
|
fwrite((td_u8 *)outbuf, 1, out_len * chns, g_out_dec_fd);
|
||
|
}
|
||
|
if (g_out_dec_left_fd != TD_NULL) {
|
||
|
fwrite((td_u8 *)outbuf, 1, out_len, g_out_dec_left_fd);
|
||
|
}
|
||
|
g_cnt_adec--;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
td_s32 open_aac_decoder(td_void *decoder_attr, td_void **pp_decoder)
|
||
|
{
|
||
|
adec_aac_decoder *decoder = NULL;
|
||
|
ot_adec_attr_aac *attr = NULL;
|
||
|
td_s32 ret;
|
||
|
|
||
|
aac_check_false_return(decoder_attr != NULL);
|
||
|
aac_check_false_return(pp_decoder != NULL);
|
||
|
|
||
|
attr = (ot_adec_attr_aac *)decoder_attr;
|
||
|
|
||
|
/* allocate memory for decoder */
|
||
|
decoder = (adec_aac_decoder *)malloc(sizeof(adec_aac_decoder));
|
||
|
if (decoder == NULL) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "no memory");
|
||
|
return OT_ERR_ADEC_NO_MEM;
|
||
|
}
|
||
|
ret = memset_s(decoder, sizeof(adec_aac_decoder), 0, sizeof(adec_aac_decoder));
|
||
|
if (ret != EOK) {
|
||
|
free(decoder);
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "memset_s fail");
|
||
|
return OT_ERR_ADEC_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
*pp_decoder = (td_void *)decoder;
|
||
|
|
||
|
/* create decoder */
|
||
|
decoder->aac_state = aac_init_decoder_adp((ot_aacdec_transport_type)attr->transport_type);
|
||
|
if (!decoder->aac_state) {
|
||
|
free(decoder);
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "aac_init_decoder failed");
|
||
|
return OT_ERR_ADEC_DECODER_ERR;
|
||
|
}
|
||
|
|
||
|
ret = memcpy_s(&decoder->aac_attr, sizeof(decoder->aac_attr), attr, sizeof(*attr));
|
||
|
if (ret != EOK) {
|
||
|
aac_free_decoder_adp(decoder->aac_state);
|
||
|
free(decoder);
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "memcpy_s failed");
|
||
|
return OT_ERR_ADEC_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
#ifdef DUMP_AACDEC
|
||
|
init_decoder_dump_file(attr);
|
||
|
#endif
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 decode_aac_frm(td_void *decoder, td_u8 **inbuf, td_s32 *left_byte,
|
||
|
td_u16 *outbuf, td_u32 *out_len, td_u32 *chns)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
adec_aac_decoder *decoder_tmp = NULL;
|
||
|
td_s32 samples, frm_len, sample_bytes;
|
||
|
ot_aacdec_frame_info aac_frame_info = { 0 };
|
||
|
|
||
|
aac_check_false_return(decoder != NULL);
|
||
|
aac_check_false_return(inbuf != NULL);
|
||
|
aac_check_false_return(left_byte != NULL);
|
||
|
aac_check_false_return(outbuf != NULL);
|
||
|
aac_check_false_return(out_len != NULL);
|
||
|
aac_check_false_return(chns != NULL);
|
||
|
|
||
|
*chns = 1; /* voice encoder only one channel */
|
||
|
|
||
|
decoder_tmp = (adec_aac_decoder *)decoder;
|
||
|
|
||
|
frm_len = aac_decode_find_sync_header_adp(decoder_tmp->aac_state, inbuf, left_byte);
|
||
|
if (frm_len < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "AAC decoder can't find sync header");
|
||
|
return OT_ERR_ADEC_BUF_LACK;
|
||
|
}
|
||
|
|
||
|
#ifdef DUMP_AACDEC
|
||
|
td_u32 pre_len = *left_byte;
|
||
|
#endif
|
||
|
|
||
|
/* notes: inbuf will updated */
|
||
|
ret = aac_decode_frame_adp(decoder_tmp->aac_state, inbuf, left_byte, (td_s16 *)outbuf);
|
||
|
if (ret) {
|
||
|
printf("aac decoder failed!, ret:0x%x\n", ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
ret = aac_get_last_frame_info_adp(decoder_tmp->aac_state, &aac_frame_info);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("aac get last frame info failed!\n");
|
||
|
return OT_ERR_ADEC_DECODER_ERR;
|
||
|
}
|
||
|
|
||
|
aac_frame_info.chn_num = ((aac_frame_info.chn_num != 0) ? aac_frame_info.chn_num : 1);
|
||
|
/* samples per frame of one sound track */
|
||
|
samples = aac_frame_info.output_samples / aac_frame_info.chn_num;
|
||
|
|
||
|
if ((samples != AACLC_SAMPLES_PER_FRAME) && (samples != AACPLUS_SAMPLES_PER_FRAME) &&
|
||
|
(samples != AACLD_SAMPLES_PER_FRAME)) {
|
||
|
printf("aac decoder failed!\n");
|
||
|
return OT_ERR_ADEC_DECODER_ERR;
|
||
|
}
|
||
|
|
||
|
sample_bytes = samples * sizeof(td_u16);
|
||
|
*chns = aac_frame_info.chn_num;
|
||
|
*out_len = sample_bytes;
|
||
|
|
||
|
#ifdef DUMP_AACDEC
|
||
|
write_decoder_dump_file(*inbuf, pre_len - (*left_byte), outbuf, *out_len, *chns);
|
||
|
#endif
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
td_s32 get_aac_frm_info(td_void *decoder, td_void *info)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
adec_aac_decoder *decoder_tmp = NULL;
|
||
|
ot_aacdec_frame_info aac_frame_info = { 0 };
|
||
|
aacdec_frame_info *aac_frm = NULL;
|
||
|
|
||
|
aac_check_false_return(decoder != NULL);
|
||
|
aac_check_false_return(info != NULL);
|
||
|
|
||
|
decoder_tmp = (adec_aac_decoder *)decoder;
|
||
|
aac_frm = (aacdec_frame_info *)info;
|
||
|
|
||
|
ret = aac_get_last_frame_info_adp(decoder_tmp->aac_state, &aac_frame_info);
|
||
|
if (ret != TD_SUCCESS) {
|
||
|
printf("aac_get_last_frame_info failed with ret = %d!\n", ret);
|
||
|
return OT_ERR_ADEC_DECODER_ERR;
|
||
|
}
|
||
|
|
||
|
aac_frm->sample_rate = aac_frame_info.sample_rate_out;
|
||
|
aac_frm->bit_rate = aac_frame_info.bit_rate;
|
||
|
aac_frm->profile = aac_frame_info.profile;
|
||
|
aac_frm->tns_used = aac_frame_info.tns_used;
|
||
|
aac_frm->pns_used = aac_frame_info.pns_used;
|
||
|
aac_frm->chn_num = aac_frame_info.chn_num;
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
td_s32 close_aac_decoder(td_void *decoder)
|
||
|
{
|
||
|
adec_aac_decoder *decoder_tmp = NULL;
|
||
|
|
||
|
aac_check_false_return(decoder != NULL);
|
||
|
decoder_tmp = (adec_aac_decoder *)decoder;
|
||
|
|
||
|
aac_free_decoder_adp(decoder_tmp->aac_state);
|
||
|
|
||
|
free(decoder_tmp);
|
||
|
|
||
|
#ifdef DUMP_AACDEC
|
||
|
if (g_in_dec_fd != TD_NULL) {
|
||
|
fclose(g_in_dec_fd);
|
||
|
g_in_dec_fd = TD_NULL;
|
||
|
}
|
||
|
|
||
|
if (g_out_dec_fd != TD_NULL) {
|
||
|
fclose(g_out_dec_fd);
|
||
|
g_out_dec_fd = TD_NULL;
|
||
|
}
|
||
|
|
||
|
if (g_out_dec_left_fd != TD_NULL) {
|
||
|
fclose(g_out_dec_left_fd);
|
||
|
g_out_dec_left_fd = TD_NULL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 reset_aac_decoder(td_void *decoder)
|
||
|
{
|
||
|
adec_aac_decoder *decoder_tmp = NULL;
|
||
|
|
||
|
aac_check_false_return(decoder != NULL);
|
||
|
decoder_tmp = (adec_aac_decoder *)decoder;
|
||
|
|
||
|
aac_free_decoder_adp(decoder_tmp->aac_state);
|
||
|
|
||
|
/* create decoder */
|
||
|
decoder_tmp->aac_state = aac_init_decoder_adp((ot_aacdec_transport_type)decoder_tmp->aac_attr.transport_type);
|
||
|
if (!decoder_tmp->aac_state) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "aac_reset_decoder failed");
|
||
|
return OT_ERR_ADEC_DECODER_ERR;
|
||
|
}
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 ss_mpi_aenc_aac_init(td_void)
|
||
|
{
|
||
|
td_s32 handle, ret;
|
||
|
ot_aenc_encoder aac;
|
||
|
ret = aac_init_enc_lib();
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
aac.type = OT_PT_AAC;
|
||
|
ret = snprintf_s(aac.name, OT_MAX_ENCODER_NAME_LEN, OT_MAX_ENCODER_NAME_LEN - 1, "aac");
|
||
|
if (ret < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get encoder name failed");
|
||
|
return ret;
|
||
|
}
|
||
|
aac.max_frame_len = MAX_AAC_MAINBUF_SIZE;
|
||
|
aac.func_open_encoder = open_aac_encoder;
|
||
|
aac.func_enc_frame = encode_aac_frm;
|
||
|
aac.func_close_encoder = close_aac_encoder;
|
||
|
ret = ss_mpi_aenc_register_encoder(&handle, &aac);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
g_aac_enc_handle = handle;
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 ss_mpi_aenc_aac_deinit(td_void)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
ret = ss_mpi_aenc_unregister_encoder(g_aac_enc_handle);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
aac_deinit_enc_lib();
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 ss_mpi_adec_aac_init(td_void)
|
||
|
{
|
||
|
td_s32 handle, ret;
|
||
|
ot_adec_decoder aac;
|
||
|
|
||
|
ret = aac_init_dec_lib();
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
aac.type = OT_PT_AAC;
|
||
|
ret = snprintf_s(aac.name, OT_MAX_DECODER_NAME_LEN, OT_MAX_DECODER_NAME_LEN - 1, "aac");
|
||
|
if (ret < 0) {
|
||
|
printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get decoder name failed");
|
||
|
return ret;
|
||
|
}
|
||
|
aac.func_open_decoder = open_aac_decoder;
|
||
|
aac.func_dec_frame = decode_aac_frm;
|
||
|
aac.func_get_frame_info = get_aac_frm_info;
|
||
|
aac.func_close_decoder = close_aac_decoder;
|
||
|
aac.func_reset_decoder = reset_aac_decoder;
|
||
|
ret = ss_mpi_adec_register_decoder(&handle, &aac);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
g_aac_dec_handle = handle;
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|
||
|
|
||
|
td_s32 ss_mpi_adec_aac_deinit(td_void)
|
||
|
{
|
||
|
td_s32 ret;
|
||
|
ret = ss_mpi_adec_unregister_decoder(g_aac_dec_handle);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
aac_deinit_dec_lib();
|
||
|
|
||
|
return TD_SUCCESS;
|
||
|
}
|