#include "system/includes.h" #include "source_node.h" #include "app_config.h" #include "reference_time.h" #include "ai_rx_player.h" /* #include "rcsp_translator.h" */ #if TCFG_AI_RX_NODE_ENABLE struct ai_rx_cb ai_rx_cb_t = {0}; extern const int OPUS_SRINDEX; //选择opus解码文件的帧大小,0代表一帧40字节,1代表一帧80字节,2代表一帧160字节 static int ai_fseek(void *_hdl, u32 fpos) { struct ai_rx_file_handle *hdl = (struct ai_rx_file_handle *)_hdl; if (!hdl->file) { return -1; } return hdl->file_ops->seek(hdl->file, fpos, SEEK_SET); } static int ai_fread(void *_hdl, u8 *data, int size) { u32 rets_addr; __asm__ volatile("%0 = rets ;" : "=r"(rets_addr)); struct ai_rx_file_handle *hdl = (struct ai_rx_file_handle *)_hdl; if (!hdl->file) { return 0; } return hdl->file_ops->read(hdl->file, data, size); } static int ai_ioc_get_fmt(struct ai_rx_file_handle *hdl, struct stream_fmt *fmt) { return hdl->file_ops->get_fmt(hdl->file, fmt); } static void ai_ioc_set_file(struct ai_rx_file_handle *hdl, struct stream_file_info *info) { hdl->file = info->file; hdl->file_ops = info->ops; } extern u32 bt_audio_conn_clock_time(void *addr); static enum stream_node_state ai_rx_get_frame(void *file, struct stream_frame **pframe) { struct ai_rx_file_handle *hdl = (struct ai_rx_file_handle *)file; if (ai_rx_cb_t.get_frame_event_cb != NULL) { // 用于ai应用的音频流播放 return ai_rx_cb_t.get_frame_event_cb(hdl, pframe); } struct stream_frame *frame; u8 fram_len = 0; switch (OPUS_SRINDEX) { case FRAME_LEN_40: fram_len = 40; break; case FRAME_LEN_80: fram_len = 80; break; case FRAME_LEN_160: fram_len = 160; break; default: break; } frame = jlstream_get_frame(hdl->node->oport, fram_len); if (frame == NULL) { *pframe = NULL; return NODE_STA_RUN; } int rlen = fread(frame->data, fram_len, 1, hdl->file); frame->len = rlen; *pframe = frame; return NODE_STA_RUN; } static void *ai_rx_file_init(void *priv, struct stream_node *node) { struct ai_rx_file_handle *hdl = (struct ai_rx_file_handle *)zalloc(sizeof(struct ai_rx_file_handle)); hdl->node = node; node->type |= NODE_TYPE_FLOW_CTRL;//NODE_TYPE_IRQ; return hdl; } static int ai_rx_file_set_bt_addr(struct ai_rx_file_handle *hdl, void *bt_addr) { hdl->bt_addr = (void *)bt_addr; return 0; } static void ai_rx_tick_handler(void *priv, u8 source) { struct ai_rx_file_handle *hdl = (struct ai_rx_file_handle *)priv; if (hdl->start && (hdl->node->state & NODE_STA_SOURCE_NO_DATA)) { jlstream_wakeup_thread(NULL, hdl->node, NULL); } } static int ai_rx_file_get_fmt(struct ai_rx_file_handle *hdl, struct stream_fmt *fmt) { #if 0 fmt->coding_type = AUDIO_CODING_OPUS; fmt->sample_rate = 16000; fmt->channel_mode = AUDIO_CH_MIX; #else extern const int CONFIG_OGG_OPUS_DEC_SUPPORT; #if TCFG_DEC_OGG_OPUS_ENABLE if (CONFIG_OGG_OPUS_DEC_SUPPORT) { fmt->sample_rate = 48000; } return hdl->file_ops->get_fmt(hdl->file, fmt); #else fmt->coding_type = hdl->param.coding_type; fmt->sample_rate = hdl->param.sample_rate; fmt->channel_mode = hdl->param.channel_mode; fmt->frame_dms = hdl->param.frame_dms; fmt->bit_rate = hdl->param.bit_rate; printf("%s 0x%x, %d, %d, %d, %d\n", __FUNCTION__, fmt->coding_type, fmt->sample_rate, fmt->channel_mode, fmt->frame_dms, fmt->bit_rate); #endif #endif return 0; } static int ai_rx_file_start(struct ai_rx_file_handle *hdl) { if (hdl->start) { return 0; } hdl->start = 1; return 0; } static int ai_rx_file_stop(struct ai_rx_file_handle *hdl) { if (!hdl->start) { return 0; } hdl->start = 0; if (hdl->reference) { audio_reference_clock_exit(hdl->reference); } return 0; } static int ai_rx_file_ioctl(void *file, int cmd, int arg) { int err = 0; struct ai_rx_file_handle *hdl = (struct ai_rx_file_handle *)file; switch (cmd) { case NODE_IOC_SET_BTADDR: ai_rx_file_set_bt_addr(hdl, (void *)arg); break; case NODE_IOC_SET_FMT: memcpy(&hdl->param, (struct ai_rx_player_param *)arg, sizeof(struct ai_rx_player_param)); break; case NODE_IOC_GET_FMT: ai_rx_file_get_fmt(hdl, (struct stream_fmt *)arg); break; case NODE_IOC_SET_FILE: ai_ioc_set_file(hdl, (struct stream_file_info *)arg); break; case NODE_IOC_START: ai_rx_file_start(hdl); break; case NODE_IOC_SET_PARAM: hdl->source = (u8)arg; break; case NODE_IOC_SUSPEND: case NODE_IOC_STOP: ai_rx_file_stop(hdl); break; } return 0; } static void ai_rx_file_release(void *file) { struct ai_rx_file_handle *hdl = (struct ai_rx_file_handle *)file; free(hdl); } REGISTER_SOURCE_NODE_PLUG(AI_RX_file_plug) = { .uuid = NODE_UUID_AI_RX, .init = ai_rx_file_init, #if TCFG_DEC_OGG_OPUS_ENABLE .read = ai_fread, .seek = ai_fseek, #else .get_frame = ai_rx_get_frame, #endif .ioctl = ai_rx_file_ioctl, .release = ai_rx_file_release, }; #endif /*TCFG_AI_RX_NODE_ENABLE*/