KT24-1110_65E-HA-651B/cpu/br25/localtws/localtws_dec.c
2024-11-10 18:44:17 +08:00

660 lines
19 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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