一个TI OpenMax IL组件的实现
TI OpenMax IL中各个组件都是通过调用LCML来实现的,实现的方式基本类似。主要都是实现了名称为OMX_ComponentInit的初始化函数,实现OMX_COMPONENTTYPE类型的结构体中的各个成员。各个组件其目录结构和文件结构也类似。
以MP3解码器的实现为例,在audio/src/openmax_il/mp3_dec/src目录中,主要包含以下文件。
OMX_Mp3Decoder.c:MP3解码器组件实现
OMX_Mp3Dec_CompThread.c:MP3解码器组件的线程循环
OMX_Mp3Dec_Utils.c:MP3解码器的相关工具,调用LCML实现真正的MP3解码的功能
OMX_Mp3Decoder.c中的OMX_ComponentInit()函数负责组件的初始化,返回的内容再从参数中得到,这个函数的主要片断如下所示:
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_COMPONENTTYPE *pHandle = (OMX_COMPONENTTYPE*) hComp;
OMX_PARAM_PORTDEFINITIONTYPE *pPortDef_ip = NULL, *pPortDef_op = NULL;
OMX_AUDIO_PARAM_PORTFORMATTYPE *pPortFormat = NULL;
OMX_AUDIO_PARAM_MP3TYPE *mp3_ip = NULL;
OMX_AUDIO_PARAM_PCMMODETYPE *mp3_op = NULL;
MP3DEC_COMPONENT_PRIVATE *pComponentPrivate = NULL;
MP3D_AUDIODEC_PORT_TYPE *pCompPort = NULL;
MP3D_BUFFERLIST *pTemp = NULL;
int i=0;
MP3D_OMX_CONF_CHECK_CMD(pHandle,1,1);
/* ......省略,初始化OMX_COMPONENTTYPE类型的指针pHandle */
OMX_MALLOC_GENERIC(pHandle->pComponentPrivate,MP3DEC_COMPONENT_PRIVATE);
pComponentPrivate = pHandle->pComponentPrivate; /* 私有指针互相指向 */
pComponentPrivate->pHandle = pHandle;
/* ......略,初始化似有数据指针pComponentPrivate */
/* 设置输入端口(OMX_PARAM_PORTDEFINITIONTYPE类型)的默认值 */
pPortDef_ip->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
pPortDef_ip->nPortIndex = MP3D_INPUT_PORT;
pPortDef_ip->eDir = OMX_DirInput;
pPortDef_ip->nBufferCountActual = MP3D_NUM_INPUT_BUFFERS;
pPortDef_ip->nBufferCountMin = MP3D_NUM_INPUT_BUFFERS;
pPortDef_ip->nBufferSize = MP3D_INPUT_BUFFER_SIZE;
pPortDef_ip->nBufferAlignment = DSP_CACHE_ALIGNMENT;
pPortDef_ip->bEnabled = OMX_TRUE;
pPortDef_ip->bPopulated = OMX_FALSE;
pPortDef_ip->eDomain = OMX_PortDomainAudio;
pPortDef_ip->format.audio.eEncoding = OMX_AUDIO_CodingMP3;
pPortDef_ip->format.audio.cMIMEType = NULL;
pPortDef_ip->format.audio.pNativeRender = NULL;
pPortDef_ip->format.audio.bFlagErrorConcealment = OMX_FALSE;
/* 设置输出端口(OMX_PARAM_PORTDEFINITIONTYPE类型)的默认值 */
pPortDef_op->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
pPortDef_op->nPortIndex = MP3D_OUTPUT_PORT;
pPortDef_op->eDir = OMX_DirOutput;
pPortDef_op->nBufferCountMin = MP3D_NUM_OUTPUT_BUFFERS;
pPortDef_op->nBufferCountActual = MP3D_NUM_OUTPUT_BUFFERS;
pPortDef_op->nBufferSize = MP3D_OUTPUT_BUFFER_SIZE;
pPortDef_op->nBufferAlignment = DSP_CACHE_ALIGNMENT;
pPortDef_op->bEnabled = OMX_TRUE;
pPortDef_op->bPopulated = OMX_FALSE;
pPortDef_op->eDomain = OMX_PortDomainAudio;
pPortDef_op->format.audio.eEncoding = OMX_AUDIO_CodingPCM;
pPortDef_op->format.audio.cMIMEType = NULL;
pPortDef_op->format.audio.pNativeRender = NULL;
pPortDef_op->format.audio.bFlagErrorConcealment = OMX_FALSE;
/* ......省略,分配端口 */
/* 设置输入端口的默认格式 */
pPortFormat = pComponentPrivate->pCompPort[MP3D_INPUT_PORT]->pPortFormat;
OMX_CONF_INIT_STRUCT(pPortFormat, OMX_AUDIO_PARAM_PORTFORMATTYPE);
pPortFormat->nPortIndex = MP3D_INPUT_PORT;
pPortFormat->nIndex = OMX_IndexParamAudioMp3;
pPortFormat->eEncoding = OMX_AUDIO_CodingMP3;
/* 设置输出端口的默认格式 */
pPortFormat = pComponentPrivate->pCompPort[MP3D_OUTPUT_PORT]->pPortFormat;
OMX_CONF_INIT_STRUCT(pPortFormat, OMX_AUDIO_PARAM_PORTFORMATTYPE);
pPortFormat->nPortIndex = MP3D_OUTPUT_PORT;
pPortFormat->nIndex = OMX_IndexParamAudioPcm;
pPortFormat->eEncoding = OMX_AUDIO_CodingPCM;
/* ......省略部分内容 */
eError = Mp3Dec_StartCompThread(pHandle); // 启动MP3解码线程
/* ......省略部分内容 */
return eError;
}
这个组件是OpenMax的标准实现方式,对外的接口的内容只有一个初始化函数。完成OMX_COMPONENTTYPE类型的初始化。输入端口的编号为MP3D_INPUT_PORT(==0),类型为OMX_PortDomainAudio,格式为OMX_AUDIO_CodingMP3。输出端口的编号是MP3D_OUTPUT_PORT(==1),类型为OMX_PortDomainAudio,格式为OMX_AUDIO_ CodingPCM。
OMX_Mp3Dec_CompThread.c中定义了MP3DEC_ComponentThread()函数,用于创建MP3解码的线程的执行函数。
OMX_Mp3Dec_Utils.c中的Mp3Dec_StartCompThread()函数,调用了POSIX的线程库建立MP3解码的线程,如下所示:
nRet = pthread_create (&(pComponentPrivate->ComponentThread), NULL,
MP3DEC_ComponentThread, pComponentPrivate);
Mp3Dec_StartCompThread()函数就是在组件初始化函数OMX_ComponentInit()最后调用的内容。MP3线程的开始并不表示解码过程开始,线程需要等待通过pipe机制获得命令和数据(cmdPipe和dataPipe),在适当的时候开始工作。这个pipe在MP3解码组件的SendCommand等实现写操作,在线程中读取其内容。