KT24-1110_65E-HA-651B/cpu/br25/localtws/localtws_dec.c

660 lines
19 KiB
C
Raw Permalink Normal View History

2024-11-10 10:44:17 +00:00
/***********************************Jieli tech************************************************
File : localtws_dec.c
By : Huxi
brief:
Email: huxi@zh-jieli.com
date : 2020-07
********************************************************************************************/
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "classic/tws_api.h"
#include "classic/tws_local_media_sync.h"
#include "localtws/localtws.h"
#include "clock_cfg.h"
#include "app_config.h"
#include "audio_config.h"
#include "audio_dec.h"
#include "media/audio_eq_drc_apply.h"
#include "audio_effect/audio_eq_drc_demo.h"
#if TCFG_DEC2TWS_ENABLE
#define LOCALTWS_LOG_ENABLE
#ifdef LOCALTWS_LOG_ENABLE
#define LOCALTWS_LOG log_i //y_printf
#define LOCALTWS_LOG_CHAR putchar
#else
#define LOCALTWS_LOG(...)
#define LOCALTWS_LOG_CHAR(...)
#endif
//////////////////////////////////////////////////////////////////////////////
//
struct localtws_dec_hdl {
struct audio_stream *stream; // 音频流
struct localtws_decoder local_dec; // local解码句柄
struct audio_res_wait wait; // 资源等待句柄
struct audio_eq *eq; //eq drc句柄
struct audio_drc *drc; // drc句柄
struct convert_data *convert;
struct audio_mixer_ch mix_ch; // 叠加句柄
u32 id; // 唯一标识符,随机值
u32 media_value; // localtws媒体信息
struct audio_wireless_sync *sync;
};
static struct localtws_dec_hdl *localtws_dec = NULL;
//////////////////////////////////////////////////////////////////////////////
//
extern struct audio_decoder_task decode_task;
#if TCFG_DEC2TWS_TASK_ENABLE
extern struct audio_decoder_task localtws_decode_task;
#define LOCALTWS_TASK localtws_decode_task
#else /*TCFG_DEC2TWS_TASK_ENABLE*/
#define LOCALTWS_TASK decode_task
#endif /*TCFG_DEC2TWS_TASK_ENABLE*/
extern void tws_api_local_media_trans_clear_no_ready(void);
extern int tws_api_local_media_trans_get_total_buffer_size(void);
extern void bt_drop_a2dp_frame_start(void);
extern int a2dp_media_clear_packet();
extern struct audio_wireless_sync *audio_localtws_sync_open(int sample_rate, int output_sample_rate, u8 channels);
extern void audio_localtws_sync_close(struct audio_wireless_sync *localtws_sync);
extern u8 is_tws_active_device(void);
extern void sys_auto_shut_down_disable(void);
///////////////////////////////////////////////////////////////////////////////////
struct local_dec_type {
u32 type;
u32 clk;
};
const struct local_dec_type local_dec_clk_tb[] = {
{AUDIO_CODING_SBC, DEC_TWS_SBC_CLK},
{AUDIO_CODING_MP3, DEC_MP3_CLK},
{AUDIO_CODING_WMA, DEC_WMA_CLK},
{AUDIO_CODING_M4A, DEC_M4A_CLK},
};
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**@brief localtws解码时钟添加
@param type:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void local_dec_clock_add(u32 type)
{
LOCALTWS_LOG("local_dec_clock_add : 0x%x \n", type);
int i = 0;
for (i = 0; i < ARRAY_SIZE(local_dec_clk_tb); i++) {
if (type == local_dec_clk_tb[i].type) {
clock_add(local_dec_clk_tb[i].clk);
return;
}
}
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码时钟移除
@param type:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void local_dec_clock_remove(u32 type)
{
LOCALTWS_LOG("local_dec_clock_remove : 0x%x \n", type);
int i = 0;
for (i = 0; i < ARRAY_SIZE(local_dec_clk_tb); i++) {
if (type == local_dec_clk_tb[i].type) {
clock_remove(local_dec_clk_tb[i].clk);
return;
}
}
}
/*----------------------------------------------------------------------------*/
/**@brief localtws激活前级解码/编码
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
#if 0
void localtws_decoder_resume_pre(void)
{
audio_stream_resume(&g_localtws.push.entry);
#ifdef TCFG_PCM_ENC2TWS_ENABLE
localtws_enc_resume();
#endif
}
#endif
/*----------------------------------------------------------------------------*/
/**@brief localtws解码输出重启
@param ms:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void localtws_decoder_output_reset(u32 ms)
{
app_audio_output_reset(ms);
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码激活
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void localtws_dec_resume(void)
{
if (localtws_dec && localtws_dec->local_dec.status) {
audio_decoder_resume(&localtws_dec->local_dec.decoder);
}
}
/*----------------------------------------------------------------------------*/
/**@brief localtws已经打开
@param
@return true:
@return false:
@note
*/
/*----------------------------------------------------------------------------*/
u8 localtws_dec_is_open(void)
{
if (localtws_dec) {
return true;
}
return false;
}
/*----------------------------------------------------------------------------*/
/**@brief localtws抛弃数据
@param
@return true:
@return false:
@note
*/
/*----------------------------------------------------------------------------*/
int localtws_media_dat_abandon(void)
{
if ((localtws_dec) && (localtws_dec->local_dec.status) && (localtws_dec->local_dec.tmp_pause)) {
// 从机,暂停,抛弃中间数据包
return true;
}
return false;
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码释放
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void localtws_dec_release()
{
audio_decoder_task_del_wait(&LOCALTWS_TASK, &localtws_dec->wait);
clock_remove(DEC_TWS_SBC_CLK);
local_irq_disable();
free(localtws_dec);
localtws_dec = NULL;
g_localtws.tws_send_pause = 0;
local_irq_enable();
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码事件回调
@param *decoder:
@param argc:
@param *argv:
@note
*/
/*----------------------------------------------------------------------------*/
static void localtws_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
LOCALTWS_LOG("AUDIO_DEC_EVENT_END\n");
localtws_dec_close(1);
//audio_decoder_resume_all(&LOCALTWS_TASK);
break;
}
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码数据流激活
@param *p:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void localtws_dec_out_stream_resume(void *p)
{
struct localtws_dec_hdl *dec = p;
audio_decoder_resume(&dec->local_dec.decoder);
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码开始
@param
@return 0
@note
*/
/*----------------------------------------------------------------------------*/
static int localtws_dec_start()
{
int err;
struct localtws_dec_hdl *dec = localtws_dec;
if (!dec) {
return -EINVAL;
}
struct audio_fmt fmt = {0};
localtws_media_get_info((u8 *)&dec->media_value, &fmt);
dec->local_dec.dec_type = fmt.coding_type;
dec->local_dec.sample_rate = fmt.sample_rate;
dec->local_dec.ch_num = fmt.channel;
LOCALTWS_LOG("localtws_dec_start: in, type:0x%x \n", dec->local_dec.dec_type);
LOCALTWS_LOG("sr:%d, ch:%d, outch:%d \n", dec->local_dec.sample_rate, dec->local_dec.ch_num, dec->local_dec.output_ch_num);
// 打开file解码器
err = localtws_decoder_open(&dec->local_dec, &LOCALTWS_TASK);
if (err) {
goto __err1;
}
audio_decoder_set_event_handler(&dec->local_dec.decoder, localtws_dec_event_handler, dec->id);
audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_LOCALTWS);
// 设置叠加功能
audio_mixer_ch_open_head(&dec->mix_ch, &mixer); // 挂载到mixer最前面
audio_mixer_ch_set_src(&dec->mix_ch, 1, 0);
audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数
audio_mixer_ch_sample_sync_enable(&dec->mix_ch, 1);
audio_mixer_ch_set_sample_rate(&dec->mix_ch, dec->local_dec.sample_rate);
dec->sync = audio_localtws_sync_open(dec->local_dec.sample_rate, audio_mixer_get_sample_rate(&mixer), dec->local_dec.output_ch_num);
localtws_decoder_stream_sync_enable(&dec->local_dec, dec->sync->context, 200, is_tws_active_device);
if (dec->local_dec.dec_type != AUDIO_CODING_SBC) {
#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE
dec->eq = music_eq_open(dec->local_dec.sample_rate, dec->local_dec.output_ch_num);// eq
#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE
dec->drc = music_drc_open(dec->local_dec.sample_rate, dec->local_dec.output_ch_num);//drc
#endif/*TCFG_MUSIC_MODE_DRC_ENABLE*/
if (dec->eq && dec->eq->out_32bit) {
dec->convert = convet_data_open(0, 512);
}
#endif
}
// 数据流串联
struct audio_stream_entry *entries[8] = {NULL};
u8 entry_cnt = 0;
entries[entry_cnt++] = &dec->local_dec.decoder.entry;
if (dec->sync) {
entries[entry_cnt++] = dec->sync->entry;
}
if (dec->eq) {
entries[entry_cnt++] = &dec->eq->entry;
if (dec->drc) {
entries[entry_cnt++] = &dec->drc->entry;
}
if (dec->convert) {
entries[entry_cnt++] = &dec->convert->entry;
}
}
if (dec->sync) {
entries[entry_cnt++] = dec->sync->resample_entry;
}
entries[entry_cnt++] = &dec->mix_ch.entry;
dec->stream = audio_stream_open(dec, localtws_dec_out_stream_resume);
audio_stream_add_list(dec->stream, entries, entry_cnt);
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
dec->local_dec.status = 1;
if (is_tws_active_device()) {
/*audio_decoder_set_run_max(&dec->local_dec.decoder, 10);*/
}
err = audio_decoder_start(&dec->local_dec.decoder);
if (err) {
goto __err3;
}
localtws_drop_frame_stop();
bt_drop_a2dp_frame_start();
local_dec_clock_add(dec->local_dec.decoder.dec_ops->coding_type);
clock_set_cur();
return 0;
__err3:
dec->local_dec.status = 0;
#if TCFG_EQ_ENABLE &&TCFG_BT_MUSIC_EQ_ENABLE
music_eq_close(dec->eq);
#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE
music_drc_close(dec->drc);
#endif
convet_data_close(dec->convert);
#endif
audio_mixer_ch_close(&dec->mix_ch);
if (dec->stream) {
audio_stream_close(dec->stream);
dec->stream = NULL;
}
localtws_decoder_close(&dec->local_dec);
__err1:
localtws_dec_release();
return err;
}
static void localtws_dec_res_put(struct localtws_dec_hdl *dec)
{
if (!dec->local_dec.status) {
return;
}
os_mutex_pend(&g_localtws.mutex, 0);
g_localtws.drop_frame_start = 1;
dec->local_dec.status = 0;
localtws_decoder_close(&dec->local_dec);
#if TCFG_EQ_ENABLE &&TCFG_BT_MUSIC_EQ_ENABLE
music_eq_close(dec->eq);
#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE
music_drc_close(dec->drc);
#endif
convet_data_close(dec->convert);
#endif
if (dec->sync) {
audio_localtws_sync_close(dec->sync);
dec->sync = NULL;
}
audio_mixer_ch_close(&dec->mix_ch);
if (dec->stream) {
audio_stream_close(dec->stream);
dec->stream = NULL;
}
local_dec_clock_remove(dec->local_dec.decoder.dec_ops->coding_type);
/* g_localtws.media_value = 0; */
if (g_localtws.tmrout) {
sys_hi_timeout_del(g_localtws.tmrout);
g_localtws.tmrout = 0;
}
tws_api_local_media_trans_clear();
localtws_drop_frame_start();
os_mutex_post(&g_localtws.mutex);
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码资源等待
@param *wait:
@param event:
@return 0
@note
*/
/*----------------------------------------------------------------------------*/
static int localtws_dec_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
struct localtws_dec_hdl *dec = localtws_dec;
#if 0
if (event == AUDIO_RES_GET) {
if (dec->local_dec.status == 0) {
tws_api_local_media_set_limit_size(LOCALTWS_MEDIA_BUF_LIMIT_LEN);
err = localtws_dec_start();
} else if (dec->local_dec.tmp_pause) {
tws_api_local_media_set_limit_size(LOCALTWS_MEDIA_BUF_LIMIT_LEN);
localtws_drop_frame_stop();
dec->local_dec.tmp_pause = 0;
/* audio_mixer_ch_open(&dec->mix_ch, &mixer); */
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
/*audio_output_start(dec->src_out_sr, 1);*/
if (dec->local_dec.status) {
err = audio_decoder_start(&dec->local_dec.decoder);
}
}
} else if (event == AUDIO_RES_PUT) {
/* LOCALTWS_LOG("localtws AUDIO_RES_PUT\n"); */
if (dec->local_dec.status) {
dec->local_dec.tmp_pause = 1;
err = audio_decoder_pause(&dec->local_dec.decoder);
os_time_dly(2);
// 先暂停再清数据避免清了数据后dec还在output
tws_api_local_media_trans_clear();
localtws_drop_frame_start();
/* audio_mixer_ch_close(&dec->mix_ch); */
}
}
#else
y_printf("%s,%d, evt:%d \n", __func__, __LINE__, event);
if (event == AUDIO_RES_GET) {
tws_api_local_media_set_limit_size(LOCALTWS_MEDIA_BUF_LIMIT_LEN);
err = localtws_dec_start();
localtws_decoder_resume_pre();
} else if (event == AUDIO_RES_PUT) {
if (dec->local_dec.status) {
localtws_dec_res_put(dec);
}
}
#endif
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 打开localtws解码
@param :
@return
@note
*/
/*----------------------------------------------------------------------------*/
int localtws_dec_open(u32 value)
{
if (localtws_dec && (localtws_dec->media_value != value)) {
localtws_dec_close(0);
}
os_mutex_pend(&g_localtws.mutex, 0);
if (!localtws_dec) {
localtws_dec_close(0);
localtws_dec = zalloc(sizeof(struct localtws_dec_hdl));
ASSERT(localtws_dec);
} else {
os_mutex_post(&g_localtws.mutex);
return 0;
}
int err;
struct localtws_dec_hdl *dec = localtws_dec;
LOCALTWS_LOG(" ****** localtws_dec_open: in, \n");
sys_auto_shut_down_disable();
if (!dec) {
os_mutex_post(&g_localtws.mutex);
return -EPERM;
}
#if 1
a2dp_dec_close();
esco_dec_close();
g_localtws.drop_frame_start = 0;
#endif
dec->id = rand32();
dec->media_value = value;
dec->local_dec.ch_type = AUDIO_CH_MAX;
dec->local_dec.output_ch_num = audio_output_channel_num();
dec->local_dec.output_ch_type = audio_output_channel_type();
dec->wait.priority = 1;
#if DEC_MIX_ENABLE
dec->wait.preemption = 0;
dec->wait.protect = 1;
#else
dec->wait.preemption = 1;
#endif//DEC_MIX_ENABLE
dec->wait.handler = localtws_dec_wait_res_handler;
err = audio_decoder_task_add_wait(&LOCALTWS_TASK, &dec->wait);
os_mutex_post(&g_localtws.mutex);
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 关闭localtws解码
@param drop_frame_start:
@return 0
@note
*/
/*----------------------------------------------------------------------------*/
int localtws_dec_close(u8 drop_frame_start)
{
os_mutex_pend(&g_localtws.mutex, 0);
/* LOCALTWS_LOG("localtws_dec_close start\n"); */
if (!localtws_dec) {
os_mutex_post(&g_localtws.mutex);
return 0;
}
if (drop_frame_start) {
g_localtws.drop_frame_start = 1; // 关闭过程中可能刚好会有数据过来
}
if (localtws_dec->local_dec.status) {
localtws_dec->local_dec.status = 0;
localtws_decoder_close(&localtws_dec->local_dec);
#if TCFG_EQ_ENABLE &&TCFG_BT_MUSIC_EQ_ENABLE
music_eq_close(localtws_dec->eq);
#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE
music_drc_close(localtws_dec->drc);
#endif
convet_data_close(localtws_dec->convert);
#endif
audio_mixer_ch_close(&localtws_dec->mix_ch);
if (localtws_dec->sync) {
audio_localtws_sync_close(localtws_dec->sync);
localtws_dec->sync = NULL;
}
if (localtws_dec->stream) {
audio_stream_close(localtws_dec->stream);
localtws_dec->stream = NULL;
}
local_dec_clock_remove(localtws_dec->local_dec.decoder.dec_ops->coding_type);
}
/* g_localtws.media_value = 0; */
if (g_localtws.tmrout) {
sys_hi_timeout_del(g_localtws.tmrout);
g_localtws.tmrout = 0;
}
localtws_dec_release();
tws_api_local_media_trans_clear();
if (drop_frame_start) {
g_localtws.drop_frame_start = 1;
localtws_drop_frame_start();
} else {
localtws_drop_frame_stop();
g_localtws.drop_frame_start = 0;
}
clock_set_cur();
LOCALTWS_LOG("***** localtws_dec_close: exit\n");
os_mutex_post(&g_localtws.mutex);
return 1;
}
/*----------------------------------------------------------------------------*/
/**@brief localtws暂停
@param :
@return
@note
*/
/*----------------------------------------------------------------------------*/
void localtws_dec_pause(void)
{
g_localtws.tws_send_pause = 1;
#ifdef TCFG_PCM_ENC2TWS_ENABLE
localtws_enc_clear();
#endif
localtws_media_send_pause(100);
g_localtws.tws_send_pause = 2;
}
/*----------------------------------------------------------------------------*/
/**@brief localtws已经开始解码
@param
@return true:
@return false:
@note
*/
/*----------------------------------------------------------------------------*/
int localtws_dec_out_is_start(void)
{
if ((!localtws_dec) || (!localtws_dec->local_dec.status)) {
return false;
}
if (localtws_dec->local_dec.read_en) {
return true;
}
return false;
}
/*----------------------------------------------------------------------------*/
/**@brief localtws解码idle判断
@param
@return 1: idle
@return 0: busy
@note
*/
/*----------------------------------------------------------------------------*/
static u8 localtws_dec_idle_query()
{
if (localtws_dec) {
return 0;
}
return 1;
}
REGISTER_LP_TARGET(localtws_dec_lp_target) = {
.name = "local_dec",
.is_idle = localtws_dec_idle_query,
};
#endif /*(defined(TCFG_DEC2TWS_ENABLE) && (TCFG_DEC2TWS_ENABLE))*/