CedarX是全志科技开源的多媒体SDK,其解码的调用基于自研的解码器接口,向上可对接MediaPlayer接口。本文记录与分析其源代码中对于C语言方面的代码技术的应用,仅作记录与借鉴。
源码参考于https://github.com/FREEWING-JP/OrangePi_CedarX
player.c中对VideoDecComponent设置回调。
p是定义在player.c中的私有结构体对象。类型为PlayerContext。
//player.c
VideoDecCompSetCallback(p->pVideoDecComp, CallbackProcess, (void*)p);
而CallbackProcess是定义在player.c的私有的消息处理函数,用于处理下一层模块VideoDecComponent回调的消息。
//player.c
static int CallbackProcess(void* pSelf, int eMessageId, void* param)
{
PlayerContext* p;
p = (PlayerContext*)pSelf;
switch(eMessageId)
{
case PLAYER_VIDEO_DECODER_NOTIFY_EOS://收到视频解码结束的消息,后续有叙述
{
if(p->pVideoRender != NULL)
VideoRenderCompSetEOS(p->pVideoRender);
return 0;
}
case PLAYER_AUDIO_RENDER_NOTIFY_AUDIO_INFO:
if(p->callback != NULL)
{
int nAudioInfo[4];
nAudioInfo[0] = p->nAudioStreamSelected;
//对于传递上来的参数作转型,以取得各个所需要的参数
nAudioInfo[1] = ((int *)param)[0];
nAudioInfo[2] = ((int *)param)[1];
nAudioInfo[3] = ((int *)param)[2] > 0 ? ((int *)param)[2] : 320*1000;
p->callback(p->pUserData, PLAYBACK_NOTIFY_AUDIO_INFO, (void *)nAudioInfo);
}
break;
//省略其他case
default:
break;
}
return 0;
}
该VideoDecCompSetCallback回调设置函数声明在cedarx\libcore\playback\videoDecComponent.h中。
//cedarx\libcore\playback\videoDecComponent.h
typedef int (*PlayerCallback)(void* pUserData, int eMessageId, void* param);
int VideoDecCompSetCallback(VideoDecComp* v, PlayerCallback callback, void* pUserData);
定义如下:
//cedarx\libcore\playback\videoDecComponent.c
int VideoDecCompSetCallback(VideoDecComp* p, PlayerCallback callback, void* pUserData)
{
p->callback = callback;
p->pUserData = pUserData;//传递实际类型为PlayerContext的任意指针对象是为了player层回调处理函数能接收到自身对象
return 0;
}
接下来看VideooDecComponent的回调调用实例,这是一个解码调用函数,收不到码流后回调解码结束消息。
//cedarx\libcore\playback\videoDecComponent.c
static void doDecode(AwMessage *msg, void *arg)
{
VideoDecComp *p = arg;
(void)msg;
int ret = DecodeVideoStream(p->pDecoder,
p->bEosFlag,
p->bConfigDecodeKeyFrameOnly,
p->bConfigDropDelayFrames,
nCurTime);
logv("DecodeVideoStream return = %d, p->bCrashFlag(%d)", ret, p->bCrashFlag);
if(ret == VDECODE_RESULT_NO_BITSTREAM)
{
if(p->bEosFlag)
{
logv("video decoder notify eos.");
//如果解码没有码流了,而且收到了EOS的标志,则说明解码结束,回调通知上层,不携带数据。
p->callback(p->pUserData, PLAYER_VIDEO_DECODER_NOTIFY_EOS, NULL);
return;
}
}
//省略其他
}