doubao_chat/lib/net/tencent/tvs_adapter/tvs_mediaplayer_impl.c

500 lines
12 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.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "tvs_api/tvs_api.h"
#include "tvs_mediaplayer_impl.h"
#include "tvs_api_config.h"
#include "tvs_api_config.h"
#include "os/os_api.h"
#include "server/audio_server.h"
#include "server/server_core.h"
#include "server/ai_server.h"
#include "network_download/net_audio_buf.h"
#define AUDIO_PLAYER_DBG 1
#define LOG(flags, fmt, arg...) \
do { \
if (flags) \
TVS_ADAPTER_PRINTF(fmt, ##arg); \
} while (0)
#define AUDIO_PLAYER_DEBUG(fmt, arg...) \
LOG(AUDIO_PLAYER_DBG, "[tvs_audio] "fmt, ##arg)
typedef enum {
PLAYER_URL_PLAYING = 4001,
PLAYER_URL_PAUSED,
PLAYER_URL_FINISHED,
PLAYER_URL_STOPPED,
PLAYER_URL_SEEKING,
PLAYER_URL_ERROR,
PLAYER_URL_UNSUPPORTED_FORMAT,
PLAYER_URL_RESUME,
} PLAYER_STATUS_E;
// 网络流媒体Url
static char *g_player_url = NULL;
// 网络流媒体唯一标识
static char *g_player_token = NULL;
// 下发的seek进度
static uint32_t g_player_offset_sec = 0;
//新url标志位
static u8 new_url_flag = 0;
//yii:引用tencent平台api
extern const struct ai_sdk_api tc_tvs_api;
extern u8 alarm_rings;
static int g_total_tts_size = 0;
static bool g_tts_play_start = false;
u8 tts_start_play_flag; //用与tts与播歌互斥
#define DEC_CBUF_SIZE (1024 * 10)
static struct tvs_dec_t {
void *dec_server;
OS_SEM end_sem;
void *net_buf;
int state;
} dec_hdl;
__attribute__((weak)) int get_app_music_prompt_dec_status(void)
{
return 0;
}
__attribute__((weak)) int get_app_music_playtime(void)
{
return 0;
}
__attribute__((weak)) int get_app_music_playtime1(void)
{
return 0;
}
__attribute__((weak)) int get_app_music_total_time(void)
{
return 0;
}
__attribute__((weak)) int get_app_music_volume(void)
{
return 100;
}
__attribute__((weak)) int get_listen_flag()
{
return 0;
}
static void dec_server_event_handler(void *priv, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_SERVER_EVENT_ERR:
puts("tvs_tts: AUDIO_SERVER_EVENT_ERR\n");
case AUDIO_SERVER_EVENT_END:
puts("tvs_tts: AUDIO_SERVER_EVENT_END\n");
os_sem_post(&((struct tvs_dec_t *)priv)->end_sem);
break;
default:
break;
}
}
static int tts_vfs_flen(void *priv)
{
return -1;
}
static int tts_vfs_fread(void *file, void *data, u32 len)
{
int rlen = net_buf_read(data, len, file);
if (rlen == -2) {
return rlen; //暂时读不到数
} else if (rlen < 0) {
return 0;
}
return rlen;
}
static int tts_vfs_fseek(void *priv, u32 offset, int orig)
{
int ret = net_buf_seek(offset, orig, priv);
if (ret == -2) { //暂时读不到数
return ret;
}
return 0;
}
static int tts_vfs_fclose(void *file)
{
return 0;
}
static const struct audio_vfs_ops tts_vfs_ops = {
.fread = tts_vfs_fread,
.fclose = tts_vfs_fclose,
.fseek = tts_vfs_fseek,
.flen = tts_vfs_flen,
};
static int tvs_api_impl_media_player_init()
{
return 0;
}
static void do_release_music()
{
if (g_player_url != NULL) {
TVS_FREE(g_player_url);
g_player_url = NULL;
}
if (g_player_token != NULL) {
TVS_FREE(g_player_token);
g_player_token = NULL;
}
}
static int mediaplayer_adapter_set_source(const char *url, const char *token, uint32_t offset_sec)
{
if (NULL == url || NULL == token) {
return -1;
}
if (!g_player_url || (g_player_url && strcmp(url, g_player_url))) { //如果是新的url,则标志位置1
new_url_flag = 1;
}
// 后台下发了新的媒体
do_release_music();
g_player_url = strdup(url);
g_player_token = strdup(token);
g_player_offset_sec = offset_sec;
AUDIO_PLAYER_DEBUG("set new music %s, token %s, seek %d seconds\n", g_player_url == NULL ? "null" : g_player_url,
g_player_token == NULL ? "null" : g_player_token, g_player_offset_sec); //yii:歌曲格式不支持快进快退,所以这里的offset没用
return 0;
}
static int mediaplayer_adapter_start_play(const char *token)
{
if (g_player_url == NULL) {
return 0;
}
// 开始播放后台下发的媒体
AUDIO_PLAYER_DEBUG("start play music %s, token %s, seek %d seconds\n", g_player_url == NULL ? "null" : g_player_url,
g_player_token == NULL ? "null" : g_player_token, g_player_offset_sec);
//调用播放器播放流媒体
if (!new_url_flag && g_player_offset_sec) {
ai_server_event_url(&tc_tvs_api, NULL, AI_SERVER_EVENT_RESUME_PLAY); //yii:若有offset(只有同一个歌曲才有offset) 则继续播放
} else {
new_url_flag = 0;
ai_server_event_url(&tc_tvs_api, g_player_url, AI_SERVER_EVENT_URL);
}
//网络流媒体开始播放的时候,接入方需要主动调用
tvs_mediaplayer_adapter_on_play_started(token);
return 0;
}
static int mediaplayer_adapter_stop_play(const char *token)
{
if (g_player_url == NULL) {
return 0;
}
// 后台下发了结束播放命令
AUDIO_PLAYER_DEBUG("stop play music %s, token %s\n", g_player_url == NULL ? "null" : g_player_url,
g_player_token == NULL ? "null" : g_player_token);
//调用播放器停止播放流媒体
ai_server_event_url(&tc_tvs_api, NULL, AI_SERVER_EVENT_PAUSE);
//网络流媒体停止或者播放出错的时候,接入方需要主动调用
tvs_mediaplayer_adapter_on_play_stopped(0, token);
return 0;
}
static int mediaplayer_adapter_resume_play(const char *token)
{
if (g_player_url == NULL) {
return 0;
}
AUDIO_PLAYER_DEBUG("resume play music %s, token %s\n", g_player_url == NULL ? "null" : g_player_url,
g_player_token == NULL ? "null" : g_player_token);
//调用播放器继续播放流媒体
ai_server_event_url(&tc_tvs_api, NULL, AI_SERVER_EVENT_RESUME_PLAY);
//网络流媒体开始播放的时候,接入方需要主动调用
tvs_mediaplayer_adapter_on_play_started(token);
return 0;
}
static int mediaplayer_adapter_pause_play(const char *token)
{
if (g_player_url == NULL) {
return 0;
}
AUDIO_PLAYER_DEBUG("pause play music %s, token %s\n", g_player_url == NULL ? "null" : g_player_url,
g_player_token == NULL ? "null" : g_player_token);
ai_server_event_url(&tc_tvs_api, NULL, AI_SERVER_EVENT_PAUSE);
//网络流媒体暂停播放的时候,接入方需要主动调用
tvs_mediaplayer_adapter_on_play_paused(token);
return 0;
}
bool mediaplayer_adapter_is_player_valid()
{
return true;
}
char *mediaplayer_adapter_get_url_token()
{
return g_player_token;
}
static int mediaplayer_adapter_get_offset(const char *token)
{
//获取网络流媒体的播放进度
int offset = get_app_music_playtime1();
printf("------------%s------------%d offset = %d", __func__, __LINE__, offset);
return offset;
}
/*********************************播放mp3格式音频****************************/
int tts_volume_change(void)
{
if (!g_tts_play_start) {
return -1;
}
int err = -1;
union audio_req req = {0};
req.dec.cmd = AUDIO_DEC_SET_VOLUME;
req.dec.volume = get_app_music_volume();
err = server_request(dec_hdl.dec_server, AUDIO_REQ_DEC, &req);
return err;
}
int on_play_tts_start(int type)
{
//TTS mp3数据开始下发,在此处开始进行MP3解码和播放
AUDIO_PLAYER_DEBUG("*******tts start play mp3********\n");
tts_start_play_flag = 1;
union audio_req req = {0};
while (get_app_music_prompt_dec_status()) {
os_time_dly(10);
}
dec_hdl.dec_server = server_open("audio_server", "dec");
if (!dec_hdl.dec_server) {
return -1;
}
server_register_event_handler_to_task(dec_hdl.dec_server, &dec_hdl, dec_server_event_handler, "tc_tvs_task");
os_sem_create(&dec_hdl.end_sem, 0);
dec_hdl.state = 0;
u32 bufsize = DEC_CBUF_SIZE;
dec_hdl.net_buf = net_buf_init(&bufsize, NULL);
if (!dec_hdl.net_buf) {
server_close(dec_hdl.dec_server);
dec_hdl.dec_server = NULL;
return -1;
}
net_buf_set_time_out(0, dec_hdl.net_buf);
net_buf_active(dec_hdl.net_buf);
g_total_tts_size = 0;
g_tts_play_start = true;
return 0;
}
void record_sem_post(void)
{
if (os_sem_valid(&dec_hdl.end_sem)) {
os_sem_post(&dec_hdl.end_sem);
}
}
void on_play_tts_stop(bool force_stop)
{
// force_stop为false,代表TTS mp3数据下发结束
// force_stop为true,代表SDK需要强制停止TTS的播放,此时不管mp3数据是否解码播放完毕,都要立即停止
if (!g_tts_play_start) {
return;
}
AUDIO_PLAYER_DEBUG("*******tts end, total %d bytes********\n", g_total_tts_size);
tts_start_play_flag = 0;
union audio_req req = {0};
if (!force_stop) {
net_buf_set_file_end(dec_hdl.net_buf);
os_sem_pend(&dec_hdl.end_sem, 0);
}
g_tts_play_start = false;
if (dec_hdl.dec_server != NULL) {
net_buf_set_file_end(dec_hdl.net_buf);
req.dec.cmd = AUDIO_DEC_STOP;
server_request(dec_hdl.dec_server, AUDIO_REQ_DEC, &req);
server_close(dec_hdl.dec_server);
dec_hdl.dec_server = NULL;
}
if (dec_hdl.net_buf != NULL) {
net_buf_uninit(dec_hdl.net_buf);
dec_hdl.net_buf = NULL;
}
}
int on_play_tts_recv_data(char *data, int data_len)
{
//解码并播放mp3数据
//AUDIO_PLAYER_DEBUG("*******tts playing, recv %d bytes, total %d bytes********\n", data_len, g_total_tts_size);
if (!g_tts_play_start) {
return -1;
}
int err = 0;
union audio_req req = {0};
if (dec_hdl.state == 0 && g_total_tts_size >= 4 * 1024) { //yii:需要一定大小的数据检测格式
dec_hdl.state = 1;
req.dec.cmd = AUDIO_DEC_OPEN;
req.dec.volume = get_app_music_volume();
req.dec.output_buf_len = 4 * 1024;
req.dec.sample_source = "dac";
req.dec.dec_type = "mp3";
req.dec.file = (FILE *)dec_hdl.net_buf;
req.dec.vfs_ops = &tts_vfs_ops;
err = server_request(dec_hdl.dec_server, AUDIO_REQ_DEC, &req);
if (err) {
g_tts_play_start = 0;
server_close(dec_hdl.dec_server);
dec_hdl.dec_server = NULL;
net_buf_uninit(dec_hdl.net_buf);
dec_hdl.net_buf = NULL;
return -1;
}
req.dec.cmd = AUDIO_DEC_START;
err = server_request(dec_hdl.dec_server, AUDIO_REQ_DEC, &req);
}
err = net_buf_write((u8 *)data, data_len, dec_hdl.net_buf);
g_total_tts_size += data_len;
return err;
}
/*************************************************************/
bool tvs_tts_adapter_play_inner()
{
// 设置是否由适配层接管TTS的播放
return CONFIG_DECODE_TTS_IN_SDK;
}
void tvs_init_mediaplayer_adapter_impl(tvs_mediaplayer_adapter *ad)
{
if (ad == NULL) {
return;
}
// adapter实现
ad->get_offset = mediaplayer_adapter_get_offset;
ad->set_source = mediaplayer_adapter_set_source;
ad->stop_play = mediaplayer_adapter_stop_play;
ad->start_play = mediaplayer_adapter_start_play;
ad->pause_play = mediaplayer_adapter_pause_play;
ad->resume_play = mediaplayer_adapter_resume_play;
ad->play_inner = tvs_tts_adapter_play_inner;
ad->tts_start = on_play_tts_start;
ad->tts_end = on_play_tts_stop;
ad->tts_data = on_play_tts_recv_data;
// 初始化媒体播放器
tvs_api_impl_media_player_init();
}
// TO-DO 监听播放器状态,调用此函数
void notify_player_status_change(const char *url, PLAYER_STATUS_E status)
{
if (g_player_url == NULL || strlen(g_player_url) == 0 || url == NULL) {
return;
}
int len = strlen(url);
if (len == 0) {
return;
}
len = strlen(g_player_url) > len ? len : strlen(g_player_url);
if (strncmp(g_player_url, url, len) != 0) {
return;
}
switch (status) {
case PLAYER_URL_FINISHED:
tvs_mediaplayer_adapter_on_play_finished(g_player_token);
do_release_music();
break;
case PLAYER_URL_PLAYING:
tvs_mediaplayer_adapter_on_play_started(g_player_token);
break;
case PLAYER_URL_PAUSED:
tvs_mediaplayer_adapter_on_play_paused(g_player_token);
break;
case PLAYER_URL_STOPPED:
case PLAYER_URL_ERROR:
tvs_mediaplayer_adapter_on_play_stopped(-1, g_player_token);
break;
default:
break;
}
}