电子说
介绍 FreeRTOS 下如何使用 rtplayer 的接口来开发播放器应用程序,方便播放器开发人员快速正确地开发,以及播放器测试人员如何根据该文档对 rtplayer 播放器进行验证测试。
这张状态转换图清晰地描述了 rtlayer 的各个状态,也列举了主要的方法的调用时序,每种方法只能在一些特定的状态下使用,否则会出错。另外,只有在 Prepared、Started、Paused、Play‑backCompleted 这四种状态下可以进行 seekTo() 操作,并且 seekTo() 之后,状态不变。
Idle 状态:当调用 player_init() 创建一个 rtplayer 或者调用了其 reset() 方法时,rtplayer 处于 idle状态。
这个状态比较简单,调用 setDateSource_url() 方法就进入 Initialized 状态,表示此时要播放的文件已经设置好了
调用 prepare() 函数还没返回或者是调用 prepareAsync() 并且还没收到 RTPLAYER_NOTIFY_PREPARED 这个回调消息的时候就处于 Preparing 状态
调用 prepare() 函数已经返回或者是调用 prepareAsync() 并且已经收到 RTPLAYER_NOTIFY_PREPARED 这个回调消息之后的状态就处于 Prepared 状态。在这个状态下说明所有的资源都已经就绪了,调用 start() 函数就可以播放了。
rtplayer 一旦 prepare 完成,就可以调用 start() 方法,这样 rtplayer 就处于 Started 状态,这表明 rtplayer 正在播放文件过程中。可以使用 XPlayerIsPlaying() 测试 rtplayer 是否处于了 Started 状态。如果播放完毕,而又设置了循环播放,则 rtplayer 仍然会处于 Started 状态。
Started 状态下可以调用 pause_l() 方法暂停 rtplayer,从而进入 Paused 状态,rtplayer 暂停后再次调用 start() 则可以继续 TPlayer 的播放,转到 Started 状态。
Started 或者 Paused 状态下均可调用 stop() 停止 rtplayer,而处于 Stop 状态的 rtplayer 要想重新播放,需要通过 prepareAsync() 和 prepare() 回到先前的 Prepared 状态重新开始才可以。
文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并且会通过 RTPLAYER_NOTIFY_PLAYBACK_COMPLETE 这个消息回调给应用。此时可以调用 start() 方法重新从头播放文件,也可以 stop() 停止 rtplayer,或者也可以 seekTo() 来重新定位播放位置。
由于某种原因 rtplayer 出现了错误,就会进入该状态,并且会通过 RTPLAYER_NOTIFY_MEDIA_ERROR 这个消息回调给应用。如果 rtplayer 进入了 Error 状态,可以通过调用 reset() 来恢复,使得 rtplayer 重新返回到 Idle 状态。
通过 plater_deinit() 的方法可以进入 End 状态,只要 rtplayer 不再被使用,就应当尽快将其 destroy 掉。
函数原型
uint32_t player_init(void)
参数:
返回值:
函数原型
void player_deinit(void* handle)
参数:
返回值:
函数原型
void registerCallback(void* handle, void* userData, player_callback_t fn)
参数:
返回值:
创建完 rtplayer 播放器之后,就要调用该函数设置回调消息处理函数。
可以是本地文件也可以是网络源
函数原型
status_t setDataSource_url(void* handle,void* userData, const char * url, int id)
参数:
返回值:
函数原型
status_t prepare(void* handle)
参数:
返回值:
函数原型
status_t prepareAsync(void* handle)
参数:
返回值:
该函数是非阻塞函数,需要等到 RTPLAYER_NOTIFY_P‑ REPARED 消息回调之后才能调 start() 函数进行播放,而且 start() 函数不能在回调函数中调用
函数原型
status_t start(void* handle)
参数:
返回值:
函数原型
status_t pause_l(void* handle)
参数:
返回值:
函数原型
status_t stop(void* handle)
参数:
返回值:
函数原型
status_t reset(void* handle)
参数:
返回值:
在任何状态下都可以调用该函数,每次播放不同的音频之前,都需要调用该函数重置播放器,另外,一般收到 RTPLAYER_NOTIFY_MEDIA_ERROR 这个消息的时候,也需要通过调用该函数来重置播放器。但是不能在回调函数中调用该函数,否则会出现死锁
函数原型
status_t seekTo(void* handle, int sec)
参数:
返回值:
函数原型
status_t getCurrentPosition(void* handle, int * sec)
参数:
返回值:
函数原型
status_t getDuration(void* handle, int * sec)
参数:
返回值:
需要在 prepared 状态之后才可以调用该函数
函数原型
MediaInfo* getMediaInfo(void* handle)
参数:
返回值:
需要在 prepared 状态之后才可以调用该函数
函数原型
status_t setLooping(void* handle, int loop)
参数:
返回值:
函数原型
XPlayer* XPlayerCreate()
参数:
返回值:
函数原型
int XPlayerSetNotifyCallback(XPlayer* p, XPlayerNotifyCallback notifier, void* pUserData)
参数:
返回值:
Xplayer 将接收来自下层的回调通知,进行相应的操作
函数原型
SoundCtrl* RTSoundDeviceCreate(int card)
参数:
返回值:
函数原型
int XPlayerSetDataSourceUrl(XPlayer* p, const char* pUrl, void* httpService, const CdxKeyedVectorT* pHeaders)
参数:
返回值:
调用说明: 发送 SetDataSource 命令,获取需要播放的音频数据内容
函数原型
int XPlayerPrepare(XPlayer* p)
参数:
返回值:
该函数是阻塞函数,调用完返回之后就进入了 Prepared 状态,此时可调 XPlayerStart() 函数进行播放
函数原型
int XPlayerPrepareAsync(XPlayer* p)
参数:
返回值:
网络播放源一般采用 PrepareAsync,而不是 Prepare 命令,PrepareAsync 命令的返回值为 0 时说明响应成功,播放器准备工作已经完成可以开始播放,为‑1 时说明响应失败
函数原型
int XPlayerStart(XPlayer* p)
参数:
返回值:
Start 命令的返回值为 0 时说明响应成功,为‑1 时说明响应失败
函数原型
int XPlayerPause(XPlayer* p)
参数:
返回值:
在 XPlayer 处于 start 状态时可调用此接口,Pause 命令的返回值为 0 时说明响应成功,为‑1 时说明响应失败
函数原型
int XPlayerStop(XPlayer* p)
参数:
返回值:
将相关变量复位,并销毁各模块,如音频解码模块、音频解码数据接收模块等
函数原型
int XPlayerReset(XPlayer* p)
参数:
返回值:
Reset 命令的返回值为 0 时说明响应成功,为‑1 时说明响应失败
函数原型
int XPlayerGetDuration(XPlayer* p, int *msec)
参数:
返回值:
在 XPlayer 处于 PREPARED、STARTED、PAUSED、STOPPED 或 COMPLETE 状态下才可调用此接口,否则操作无效
函数原型
int XPlayerSeekTo(XPlayer* p, int nSeekTimeMs)
参数:
返回值:
如果跳转前播放处于暂停状态,则跳转后将保持在暂停状态
函数原型
int XPlayerGetDuration(XPlayer* p, int *msec)
参数:
返回值:
需要在 prepared 状态之后才可以调用该函数
在 XPlayer 处于 PREPARED、STARTED、PAUSED、STOPPED 或 COMPLETE 状态下才可调用此接口,否则操作无效,在 complete 状态下,可能会调用 prepare 方法并更改媒体信息,获取的播放时间以 ms 为单位
函数原型
int XPlayerGetCurrentPosition(XPlayer* p, int* msec)
参数:
返回值:
函数原型
MediaInfo* XPlayerGetMediaInfo(XPlayer* p)
参数:
返回值:
需要在 prepared 状态之后才可以调用该函数
函数原型
int XPlayerSetLooping(XPlayer* p, int loop)
参数:
返回值:
函数原型
int XPlayerIsPlaying(XPlayer* p)
参数:
返回值:
函数原型
void XPlayerDestroy(XPlayer* p)
参数:
返回值:
player_init() 创建一个播放器
registerCallback() 设置消息回调函数
setDataSource_url() 设置 url
prepare() 或 prepareAsync() 解析头部信息,获取元数据,并根据元数据的信息初始化对应的解码器
start() 播放 (注: 如果是用 prepareAsync() 函数,则需要等到 RTPLAYER_NOTIFY_PREPARED 消息回调之后才可以调用 start() 函数进行播放)
如果需要跳播,则可以调用 seekTo() 函数
如果需要暂停,则调用 pause_l() 函数进行暂停
如果需要停止,则可以调用 stop() 或 reset() 函数进行停止 (注:建议用 reset() 函数进行停止,因为任何状态下都可以调用 reset() 函数)
如果需要播放下一个或其他的,则可以先调用 reset() 函数使播放器进入 idle 状态,然后再重复 (3)(4)(5) 的步骤
typedef struct DemoPlayerContext
{
RTPlayer* mRTplayer;
sem_t mPreparedSem;
mqd_t mRTplayerMq;
pthread_t mThreadId;
char *pUrl;
int mSeekable;
char isPlayingFlag;
char mError;
int inputMode;
int isSetLoop;
char quitFlag;//no_shell_input mode quitFlag
int testMode;
MediaInfo* mMediaInfo;
int SoundCard;
}DemoPlayerContext;
typedef struct DemoPlayerMsg
{
int msg;
int data;
}DemoPlayerMsg;
static const char *pcRTplayerMqName = "/rtplayerMq";
static volatile mqd_t mRTplayerMq = INVALID_MQD;
static int mRTplayerUserInput = 0;
static struct mq_attr xRTplayerMqAttr =
{
.mq_flags = 0,
.mq_maxmsg = 3,
.mq_msgsize = sizeof(DemoPlayerMsg),
.mq_curmsgs = 0
};
static void showHelp(){
printf("n");
printf("**************************n");
printf("* This is a simple audio player, when it is started, you can input commands to telln");
printf("* what you want it to do.n");
printf("* Usage: n");
printf("* tplayer_demo /data/test.mp3 : this means play test.mp3n");
printf("* P :this will Pause if in playing status,or Play in paused status n");
printf("* S :this means Stop n");
printf("* s :this means seek to 10s n");
printf("* B :show buffer n");
printf("* b :this means player will run in the background n");
printf("* q :this means quit the player n");
printf("* l :this means loop play n");
printf("* G :this means Get duration n");
printf("* g :this means get position n");
printf("* i :this means show media info n");
printf("* h :this means show the help information n");
printf("* r : replay the current audion");
printf("**************************n");
}
static int rtplayer_clear_cmd(mqd_t mq){
struct timespec cur, delay, abstime;
clock_gettime( CLOCK_REALTIME, &cur );
delay.tv_sec = 0;
delay.tv_nsec = 5*1000*1000;
UTILS_TimespecAdd(&cur, &delay, &abstime);
DemoPlayerMsg msg;
while(mq_timedreceive(mq, (char *)&msg, sizeof(msg), NULL, &abstime)!=-1);
return 0;
}
static int rtplayer_send_cmd(mqd_t mq, int msg, int data){
DemoPlayerMsg pmsg = {msg, data};
struct timespec tsn, ts;
clock_gettime(CLOCK_REALTIME, &tsn);
UTILS_TimespecAddNanoseconds(&tsn, 20*1000*1000, &ts);
int status = mq_timedsend(mq, (char *)&pmsg, sizeof(pmsg), 0, &ts);
if(status)
LOGE("send cmd %c,%d failed!", pmsg.msg, pmsg.data);
return status;
}
static int rtplayer_send_cmd_force(mqd_t mq, int msg, int data){
int try_times = 0;
DemoPlayerMsg pmsg = {msg, data};
struct timespec tsn, ts;
int status;
try_send:
clock_gettime(CLOCK_REALTIME, &tsn);
UTILS_TimespecAddNanoseconds(&tsn, 20*1000*1000, &ts);
status = mq_timedsend(mq, (char *)&pmsg, sizeof(pmsg), 0, &ts);
if(status){
try_times++;
if(try_times< 5){
LOGE("send cmd %c,%d failed, retry...", pmsg.msg, pmsg.data);
goto try_send;
}
else if(try_times< 10){
DemoPlayerMsg tmp;
LOGE("send cmd %c,%d failed, retry...", pmsg.msg, pmsg.data);
clock_gettime(CLOCK_REALTIME, &tsn);
UTILS_TimespecAddNanoseconds(&tsn, 20*1000*1000, &ts);
status = mq_timedreceive(mq, (char *)&tmp, sizeof(tmp), NULL, &ts);
if(status< 0){
LOGE("mq_receive fail %d", status);
goto fail_exit;
}
LOGW("drop: %c, %d", tmp.msg, tmp.data);
goto try_send;
}
goto fail_exit;
}
return status;
fail_exit:
LOGE("send cmd %c,%d failed!n", pmsg.msg, pmsg.data);
return status;
}
static void callbackFromRTplayer(void* userData,int msg, int id, int ext1, int ext2);
static void* RTplayerThread(void* arg){
DemoPlayerContext* demoPlayer = (DemoPlayerContext*)arg;
char quitFlag = 0;
if(demoPlayer- >inputMode)
{
while(1)
{
if(demoPlayer- >quitFlag)
{
if(demoPlayer- >mRTplayer != NULL)
{
printf("player finsh, quit the rtplayern");
mRTplayerMq = INVALID_MQD;
sem_destroy(&demoPlayer- >mPreparedSem);
player_deinit(demoPlayer- >mRTplayer);
free(demoPlayer- >pUrl);
free(demoPlayer);
}
break;
}
usleep(50*1000);
}
return NULL;
}
while(!quitFlag){
int cRxed = 0;
int data = 0;
DemoPlayerMsg msg;
ssize_t status;
if(demoPlayer- >mRTplayerMq!=INVALID_MQD){
usleep(50*1000);
ssize_t status = mq_receive(demoPlayer- >mRTplayerMq, (char *)&msg, sizeof(msg), NULL);
if(status<=-1){
LOGE("mq_receive fail %d", status);
usleep(1*1000*1000);
continue;
}
printf("receive %c,%dn", msg.msg, msg.data);
cRxed = msg.msg;
data = msg.data;
}
else{
cRxed = QUIT_CMD;
}
switch(cRxed){
case PAUSE_CMD:
{
if(demoPlayer- >isPlayingFlag){
printf("pause the rtplayern");
pause_l(demoPlayer- >mRTplayer);
demoPlayer- >isPlayingFlag = 0;
}else{
printf("play the rtplayern");
start(demoPlayer- >mRTplayer);
demoPlayer- >isPlayingFlag = 1;
}
break;
}
case STOP_CMD:
{
printf("stop the rtplayern");
stop(demoPlayer- >mRTplayer);
demoPlayer- >isPlayingFlag = 0;
break;
}
case SEEK_TO_CMD:
{
printf("rtplayer seek to 10 secondn");
seekTo(demoPlayer- >mRTplayer,10);
break;
}
case SEEK_TO_CMD2:
{
printf("rtplayer seek to %d secondn", data);
seekTo(demoPlayer- >mRTplayer,data);
break;
}
case QUIT_CMD:
{
printf("quit the rtplayern");
mRTplayerMq = INVALID_MQD;
//mq_close(demoPlayer- >mRTplayerMq);
sem_destroy(&demoPlayer- >mPreparedSem);
player_deinit(demoPlayer- >mRTplayer);
free(demoPlayer- >pUrl);
free(demoPlayer);
quitFlag = 1;
break;
}
case LOOP_CMD:
{
printf("let the rtplayer loop playn");
demoPlayer- >isSetLoop = 1;
setLooping(demoPlayer- >mRTplayer,1);
break;
}
case GET_DURATION_CMD:
{
printf("get the audio durationn");
int duration;
getDuration(demoPlayer- >mRTplayer,&duration);
printf("duration:%d sn",duration);
break;
}
case GET_POSITION_CMD:
{
printf("get the current positionn");
int position;
getCurrentPosition(demoPlayer- >mRTplayer,&position);
printf("current position:%d sn",position);
break;
}
case HELP_CMD:
{
printf("show the help informationn");
showHelp();
break;
}
case INFO_CMD:
{
printf("**************************n");
printf("* show media information:n");
MediaInfo* mi = NULL;
demoPlayer- >mMediaInfo = getMediaInfo(demoPlayer- >mRTplayer);
if(demoPlayer- >mMediaInfo != NULL){
mi = demoPlayer- >mMediaInfo;
printf("* file size = %lld KBn",mi- >nFileSize/1024);
printf("* duration = %lld msn",mi- >nDurationMs);
printf("* bitrate = %d Kbpsn",mi- >nBitrate/1024);
printf("* container type = %dn",mi- >eContainerType);
printf("* audio stream num = %dn",mi- >nAudioStreamNum);
if(mi- >pAudioStreamInfo != NULL){
printf("* audio codec tpye = %dn",mi- >pAudioStreamInfo- >eCodecFormat);
printf("* audio channel num = %dn",mi- >pAudioStreamInfo- >nChannelNum);
printf("* audio BitsPerSample = %dn",mi- >pAudioStreamInfo- >nBitsPerSample);
printf("* audio sample rate = %dn",mi- >pAudioStreamInfo- >nSampleRate);
}
printf("**************************n");
}
break;
}
case SHOW_BUFFER_CMD:
{
printf("**************************n");
printf("* show buffer information:n");
player_show_buffer();
printf("**************************n");
break;
}
case REPLAY_CMD:
{
printf("replay %sn", demoPlayer- >pUrl);
int ret;
if(demoPlayer- >testMode){
printf("test mode: destroy & create instead of resetn");
player_deinit(demoPlayer- >mRTplayer);
usleep(50*1000);
demoPlayer- >mRTplayer = (RTPlayer*)(uintptr_t)player_init();
printf("demoPlayer.mRTplayer = %pn",demoPlayer- >mRTplayer);
if(!demoPlayer- >mRTplayer){
printf("init rtplayer failn");
free(demoPlayer- >pUrl);
free(demoPlayer);
quitFlag = 1;
continue;
}
registerCallback(demoPlayer- >mRTplayer, demoPlayer, callbackFromRTplayer);
}
else
reset(demoPlayer- >mRTplayer);
ret = setDataSource_url(demoPlayer- >mRTplayer, demoPlayer, demoPlayer- >pUrl, 0);
if(ret){
printf("setDataSource_url failedn");
break;
}
ret = prepare(demoPlayer- >mRTplayer);
if(ret){
printf("prepare failedn");
break;
}
start(demoPlayer- >mRTplayer);
demoPlayer- >isPlayingFlag = 1;
if(demoPlayer- >isSetLoop)
{
setLooping(demoPlayer- >mRTplayer,1);
}
break;
}
case RETRY_CMD:
{
int position = data;
if(data==-1)
getCurrentPosition(demoPlayer- >mRTplayer,&position);
printf("retry %sn", demoPlayer- >pUrl);
int ret;
if(demoPlayer- >testMode){
printf("test mode: destroy & create instead of resetn");
player_deinit(demoPlayer- >mRTplayer);
usleep(50*1000);
demoPlayer- >mRTplayer = (RTPlayer*)(uintptr_t)player_init();
printf("demoPlayer.mRTplayer = %pn",demoPlayer- >mRTplayer);
if(!demoPlayer- >mRTplayer){
LOGE("init rtplayer fail");
free(demoPlayer- >pUrl);
free(demoPlayer);
quitFlag = 1;
continue;
}
registerCallback(demoPlayer- >mRTplayer, demoPlayer, callbackFromRTplayer);
}
else
reset(demoPlayer- >mRTplayer);
ret = setDataSource_url(demoPlayer- >mRTplayer, demoPlayer, demoPlayer- >pUrl, 0);
if(ret){
LOGE("setDataSource_url failed");
rtplayer_send_cmd_force(demoPlayer- >mRTplayerMq, RETRY_CMD, position);
usleep(500*1000);
break;
}
ret = prepare(demoPlayer- >mRTplayer);
if(ret){
LOGE("prepare failed");
rtplayer_send_cmd_force(demoPlayer- >mRTplayerMq, RETRY_CMD, position);
usleep(500*1000);
break;
}
start(demoPlayer- >mRTplayer);
demoPlayer- >isPlayingFlag = 1;
//seekTo(demoPlayer- >mRTplayer, position);
if(demoPlayer- >isSetLoop)
setLooping(demoPlayer- >mRTplayer,1);
break;
}
default:
{
LOGW("warning: unknown command,cmd = %d",cRxed);
break;
}
}
if(quitFlag){
return NULL;
}
}
return NULL;
}
static void callbackFromRTplayer(void* userData,int msg, int id, int ext1, int ext2){
LOGI("call back from RTplayer,msg = %d,id = %d,ext1 = %d,ext2 = %dn",msg,id,ext1,ext2);
DemoPlayerContext* pDemoPlayer = (DemoPlayerContext*)userData;
switch(msg)
{
case RTPLAYER_NOTIFY_PREPARED:
{
printf("RTPLAYER_NOTIFY_PREPARED:has prepared.n");
#if USE_PREPARE_ASYNC
sem_post(&pDemoPlayer- >mPreparedSem);
pDemoPlayer- >mPreparedFlag = 1;
#endif
break;
}
case RTPLAYER_NOTIFY_PLAYBACK_COMPLETE:
{
printf("RTPLAYER_NOTIFY_PLAYBACK_COMPLETE:play completen");
pDemoPlayer- >isPlayingFlag = 0;
if(pDemoPlayer- >inputMode)
{
pDemoPlayer- >quitFlag = 1;
}
break;
}
case RTPLAYER_NOTIFY_SEEK_COMPLETE:
{
printf("RTPLAYER_NOTIFY_SEEK_COMPLETE:seek okn");
break;
}
case RTPLAYER_NOTIFY_MEDIA_ERROR:
{
switch (ext1)
{
case RTPLAYER_MEDIA_ERROR_UNKNOWN:
{
printf("erro type:TPLAYER_MEDIA_ERROR_UNKNOWNn");
break;
}
case RTPLAYER_MEDIA_ERROR_UNSUPPORTED:
{
printf("erro type:TPLAYER_MEDIA_ERROR_UNSUPPORTEDn");
break;
}
case RTPLAYER_MEDIA_ERROR_IO:
{
printf("erro type:TPLAYER_MEDIA_ERROR_IOn");
break;
}
}
printf("RTPLAYER_NOTIFY_MEDIA_ERRORn");
pDemoPlayer- >mError = 1;
if(pDemoPlayer- >mPreparedFlag == 0){
printf("recive err when preparingn");
sem_post(&pDemoPlayer- >mPreparedSem);
}
if( pDemoPlayer- >mRTplayerMq!=INVALID_MQD ){
rtplayer_send_cmd_force(pDemoPlayer- >mRTplayerMq, RETRY_CMD, -1);
}
else{
printf("io error, mqueue not existn");
}
break;
}
case RTPLAYER_NOTIFY_NOT_SEEKABLE:
{
pDemoPlayer- >mSeekable = 0;
printf("info: media source is unseekable.n");
break;
}
case RTPLAYER_NOTIFY_DETAIL_INFO:
{
int flag = *(int *)(uintptr_t)ext2;
//printf("detail info: %dn", flag);
break;
}
default:
{
printf("warning: unknown callback from RTplayer.n");
break;
}
}
}
int cmd_rtplayer_test(int argc, char ** argv)
{
int inputMode = 0;
int testMode = 0;
/*
printf("argc = %dn",argc);
for(int i=0; i < argc;i++){
printf("argv[%d]=%sn",i,argv[i]);
}
*/
printf("rtplayer source:%sn", argv[1]);
if(argc == 3){
if( !strncmp("no_shell_input", argv[2], sizeof("no_shell_input")-1) ){
argc--;
inputMode = 1;
}
else if( !strncmp("test_mode", argv[2], sizeof("test_mode")-1) ){
argc--;
testMode = 1;
}
}
if(argc != 2){
LOGW("the parameter is error,usage is as following:");
showHelp();
goto rtp_failed;
}
int waitErr = 0;
DemoPlayerContext* demoPlayer = (DemoPlayerContext*)malloc(sizeof(DemoPlayerContext));
if(demoPlayer == NULL){
LOGE("malloc DemoPlayerContext fail");
goto rtp_failed;
}
memset(demoPlayer, 0, sizeof(DemoPlayerContext));
demoPlayer- >mSeekable = 1;
demoPlayer- >mRTplayerMq = INVALID_MQD;
demoPlayer- >inputMode = inputMode;
demoPlayer- >testMode = testMode;
demoPlayer- >quitFlag = 0;
demoPlayer- >mMediaInfo = NULL;
if(strlen(argv[1])<=0){
LOGE("url error");
goto rtp_url_failed;
}
demoPlayer- >pUrl = malloc(strlen(argv[1])+1);
if(!demoPlayer- >pUrl){
LOGE("pUrl malloc fail");
goto rtp_url_failed;
}
memset(demoPlayer- >pUrl, 0, strlen(argv[1]));
strcpy(demoPlayer- >pUrl, argv[1]);
sem_init(&demoPlayer- >mPreparedSem, 0, 0);
demoPlayer- >mRTplayer = (RTPlayer*)(uintptr_t)player_init();
LOGI("demoPlayer.mRTplayer = %p",demoPlayer- >mRTplayer);
if(!demoPlayer- >mRTplayer){
LOGE("init rtplayer fail");
goto rtp_init_failed;
}
registerCallback(demoPlayer- >mRTplayer, demoPlayer, callbackFromRTplayer);
status_t ret = setDataSource_url(demoPlayer- >mRTplayer,demoPlayer,demoPlayer- >pUrl, 0);
if(ret){
LOGE("set DataSource url fail");
goto rtp_prepare_failed;
}
demoPlayer- >mPreparedFlag = 0;
if(prepareAsync(demoPlayer- >mRTplayer) != 0)
{
printf("TPlayerPrepareAsync() return fail.n");
}else{
printf("preparing...n");
}
struct timespec t;
t.tv_nsec = 0;
t.tv_sec = 30;
waitErr = sem_timedwait(&demoPlayer- >mPreparedSem, &t);
if(waitErr == -1){
printf("prepare timeout,has wait %d sn",t.tv_sec);
sem_destroy(&demoPlayer- >mPreparedSem);
goto rtp_prepare_failed;
}else if(demoPlayer.mError == 1){
printf("prepare failn");
sem_destroy(&demoPlayer- >mPreparedSem);
goto rtp_prepare_failed;
}
printf("prepared okn");
ret = prepare(demoPlayer- >mRTplayer);
if(ret){
LOGE("prepare fail");
goto rtp_prepare_failed;
}
start(demoPlayer- >mRTplayer);
demoPlayer- >isPlayingFlag = 1;
if( mRTplayerMq==INVALID_MQD ){
mRTplayerMq = mq_open( pcRTplayerMqName, O_CREAT | O_RDWR, DEFAULT_MODE, &xRTplayerMqAttr );
if(mRTplayerMq==INVALID_MQD){
LOGE("mq_open fail");
}
}
demoPlayer- >mRTplayerMq = mRTplayerMq;
rtplayer_clear_cmd(demoPlayer- >mRTplayerMq);
pthread_attr_t attr;
pthread_attr_init(&attr);
struct sched_param sched;
sched.sched_priority = 4;
pthread_attr_setschedparam(&attr, &sched);
pthread_attr_setstacksize(&attr, 32768);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if( pthread_create(&demoPlayer- >mThreadId, &attr, RTplayerThread, demoPlayer) ){
LOGE("pthread_create failed, quit the rtplayer");
mRTplayerMq = INVALID_MQD;
//mq_close(demoPlayer- >mRTplayerMq);
sem_destroy(&demoPlayer- >mPreparedSem);
goto rtp_prepare_failed;
}
pthread_setname_np(demoPlayer- >mThreadId, "RTplayerThread");
if(demoPlayer- >inputMode)
goto rtp_succeed;
while(1){
char cRxed = getchar();
if(cRxed==BACKGROUND_CMD){
printf("shell input exit, rtplayer will run in the backgroundn");
break;
}
rtplayer_send_cmd(demoPlayer- >mRTplayerMq, cRxed, 0);
if(cRxed==QUIT_CMD)
break;
usleep(50*1000);
}
rtp_succeed:
return 0;
rtp_prepare_failed:
player_deinit(demoPlayer- >mRTplayer);
rtp_init_failed:
free(demoPlayer- >pUrl);
rtp_url_failed:
free(demoPlayer);
rtp_failed:
return -1;
}
FINSH_FUNCTION_EXPORT_CMD(cmd_rtplayer_test, rtplayer_test, test the rtplayer);
static int cmd_rtplayer_controller(int argc, char ** argv){
if(mRTplayerMq==INVALID_MQD){
printf("mRTplayerMq = INVALID_MQD!n");
return -1;
}
if( (argc!=2) && (argc!=3) ){
printf("usage:rtpc < cmd > [data]n");
return -1;
}
int data = 0;
if(argc==3)
data = atoi(argv[2]);
rtplayer_send_cmd(mRTplayerMq, argv[1][0], data);
return 0;
}
FINSH_FUNCTION_EXPORT_CMD(cmd_rtplayer_controller, rtpc, control the rtplayer);
void registerCallback(void* handle, void* userData, player_callback_t fn)
函数必须要调用,而且 fn 不能为 NULL。全部0条评论
快来发表一下你的评论吧 !