您好,欢迎来到61ic! | [登录] [注册] 忘记密码 | 设为首页 帮助
 . 网站首页 . 业界新闻 . 设计中心 . 移动技术 . TI专栏 . ADI专栏 . FPGA专栏 . 代码工厂 . 官方商城 . 
 . 活动专区 . 新品快递 . 解决方案 . 前沿科技 . TI资源 . ADI资源 . FPGA资源 . 下载中心 . 产品展示 . 
加入收藏
付款方式
联系我们
您现在的位置: 61IC电子在线 >> TI专栏 >> TI DaVinci >> OMAP3x >> 正文
  [图文]Android开发之OMAP平台OpenMax IL的硬件实现           ★★★ 【字体:
Android开发之OMAP平台OpenMax IL的硬件实现
作者:tigerly    文章来源:tigerly    点击数:    更新时间:2014-4-29    

一:  TI OpenMax IL实现的结构和机制

Android的开源代码中,已经包含了TI的OpenMax IL层的实现代码,其路径如下所示:

hardware/ti/omap3/omx/

其中包含的主要目录如下所示。

  system:OpenMax核心和公共部分

  audio:音频处理部分的OpenMax IL组件

  video:视频处理部分OpenMax IL组件

  image:图像处理部分OpenMax IL组件

TI OpenMax IL实现的结构如图18-7所示。

在TI OpenMax IL实现中,最上面的内容是OpenMax的管理者用于管理和初始化,中间层是各个编解码单元的OpenMax IL标准组件,下层是LCML层,供各个OpenMax IL标准组件所调用。

TI OpenMax IL实现的公共部分在system/src/openmax_il/目录中,主要的内容如下所示。

  omx_core/src:OpenMax IL的核心,生成动态库libOMX_Core.so

  lcml/:LCML的工具库,生成动态库libLCML.so

TI OpenMax IL的视频(Video)相关的组件在video/src/openmax_il/目录中,主要的内容如下所示。

  prepost_processor:Video数据的前处理和后处理,生成动态库libOMX.TI.VPP.so

  video_decode:Video解码器,生成动态库libOMX.TI.Video.Decoder.so

  video_encode:Video编码器,生成动态库libOMX.TI.Video.encoder.so

图18-7  TI OpenMax IL实现的结构

TI OpenMax IL的音频(Audio)相关的组件在audio/src/openmax_il/目录中,主要的内容如下所示。

  g711_dec:G711解码器,生成动态库libOMX.TI.G711.decode.so

  g711_enc:G711编码器,生成动态库libOMX.TI.G711.encode.so

  g722_dec:G722解码器,生成动态库libOMX.TI.G722.decode.so

  g722_enc:G722编码器,生成动态库libOMX.TI.G722.encode.so

  g726_dec:G726解码器,生成动态库libOMX.TI.G726.decode.so

  g726_enc:G726编码器,生成动态库libOMX.TI.G726.encode.so

  g729_dec:G729解码器,生成动态库libOMX.TI.G729.decode.so

  g729_enc:G720编码器,生成动态库libOMX.TI.G729.encode.so

  nbamr_dec:AMR窄带解码器,生成动态库libOMX.TI.AMR.decode.so

  nbamr_enc:AMR窄带编码器,生成动态库libOMX.TI.AMR.encode.so

  wbamr_dec:AMR宽带解码器,生成动态库libOMX.TI.WBAMR.decode.so

  wbamr_enc:AMR宽带编码器,生成动态库libOMX.TI.WBAMR.encode.so

  mp3_dec:MP3解码器,生成动态库libOMX.TI.MP3.decode.so

  aac_dec:AAC解码器,生成动态库libOMX.TI.AAC.decode.so

  aac_enc:AAC编码器,生成动态库libOMX.TI.AAC.encode.so

  wma_dec:WMA解码器,生成动态库libOMX.TI.WMA.decode.so

TI OpenMax IL的图像(Image)相关的组件在image/src/openmax_il/目录中,主要的内容如下所示。

  jpeg_enc:JPEG编码器,生成动态库libOMX.TI.JPEG.Encoder.so

  jpeg_dec:JPEG解码器,生成动态库libOMX.TI.JPEG.decoder.so

二:  TI OpenMax IL的核心和公共内容

LCML的全称是“Linux Common Multimedia Layer”,是TI的Linux公共多媒体层。在OpenMax IL的实现中,这个内容在system/src/openmax_il/lcml/目录中,主要文件是子目录src中的LCML_DspCodec.c文件。通过调用DSPBridge的内容, 让ARM和DSP进行通信,然DSP进行编解码方面的处理。DSP的运行还需要固件的支持。

TI OpenMax IL的核心实现在system/src/openmax_il/omx_core/目录中,生成TI OpenMax IL的核心库libOMX_Core.so。

其中子目录src中的OMX_Core.c为主要文件,其中定义了编解码器的名称等,其片断如下所示:

char *tComponentName[MAXCOMP][2] = {

    {"OMX.TI.JPEG.decoder", "image_decoder.jpeg"},  /* 图像和视频编解码器 */ 

    {"OMX.TI.JPEG.Encoder", "image_encoder.jpeg"},

    {"OMX.TI.Video.Decoder", "video_decoder.avc"},

    {"OMX.TI.Video.Decoder", "video_decoder.mpeg4"},

    {"OMX.TI.Video.Decoder", "video_decoder.wmv"},

    {"OMX.TI.Video.encoder", "video_encoder.mpeg4"},

    {"OMX.TI.Video.encoder", "video_encoder.h263"},

    {"OMX.TI.Video.encoder", "video_encoder.avc"},

    /* ......省略 ,语音相关组件*/

#ifdef BUILD_WITH_TI_AUDIO                              /* 音频编解码器 */

    {"OMX.TI.MP3.decode", "audio_decoder.mp3"},

    {"OMX.TI.AAC.encode", "audio_encoder.aac"},

    {"OMX.TI.AAC.decode", "audio_decoder.aac"},

    {"OMX.TI.WMA.decode", "audio_decoder.wma"},

    {"OMX.TI.WBAMR.decode", "audio_decoder.amrwb"},

    {"OMX.TI.AMR.decode", "audio_decoder.amrnb"},

    {"OMX.TI.AMR.encode", "audio_encoder.amrnb"},

    {"OMX.TI.WBAMR.encode", "audio_encoder.amrwb"},

#endif

    {NULL, NULL},

};

tComponentName数组的各个项中,第一个表示编解码库内容,第二个表示库所实现的功能。

其中,TIOMX_GetHandle()函数用于获得各个组建的句柄,其实现的主要片断如下所示:

OMX_ERRORTYPE TIOMX_GetHandle( OMX_HANDLETYPE* pHandle, OMX_STRING cComponentName,

    OMX_PTR pAppData, OMX_CALLBACKTYPE* pCallBacks)

{

    static const char prefix[] = "lib";

    static const char postfix[] = ".so";

    OMX_ERRORTYPE (*pComponentInit)(OMX_HANDLETYPE*);

    OMX_ERRORTYPE err = OMX_ErrorNone;

    OMX_COMPONENTTYPE *componentType;

    const char* pErr = dlerror();

// ...... 省略错误处理内容

    int i = 0;

    for(i=0; i< COUNTOF(pModules); i++) {       // 循环查找

        if(pModules[i] == NULL) break;

    }

// ...... 省略错误处理内容

    int refIndex = 0;

    for (refIndex=0; refIndex < MAX_TABLE_SIZE; refIndex++) {            

// 循环查找组件列表

        if (strcmp(componentTable[refIndex].name, cComponentName) == 0) {

            if (componentTable[refIndex].refCount >= MAX_CONCURRENT_INSTANCES) { 

// ...... 省略错误处理内容

            } else {

                char buf[sizeof(prefix) + MAXNAMESIZE + sizeof(postfix)];

                strcpy(buf, prefix);

                strcat(buf, cComponentName);

                strcat(buf, postfix);

                pModules[i] = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);

            // ...... 省略错误处理内容

            // 动态取出初始化的符号

                pComponentInit = dlsym(pModules[i], "OMX_ComponentInit");  

                pErr = dlerror();

            // ...... 省略错误处理内容

                *pHandle = malloc(sizeof(OMX_COMPONENTTYPE));

            // ...... 省略错误处理内容

                pComponents[i] = *pHandle;

                componentType = (OMX_COMPONENTTYPE*) *pHandle;

                componentType->nSize = sizeof(OMX_COMPONENTTYPE);

                err = (*pComponentInit)(*pHandle);   // 执行初始化工作

            // ...... 省略部分内容

            }

        }

    }

    err = OMX_ErrorComponentNotFound;

    goto UNLOCK_MUTEX;

// ...... 省略部分内容

    return (err);

}

在TIOMX_GetHandle()函数中,根据tComponentName数组中动态库的名称,动态打开各个编解码实现的动态库,取出其中的OMX_ComponentInit符号来执行各个组件的初始化。

三:  一个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 OMX_ComponentInit (OMX_HANDLETYPE hComp)

{

    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等实现写操作,在线程中读取其内容。

文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    Android OMAP4 Ducati 和 Op…
    Android WL1271 wifi驱动移植
    F2812上电顺序 防止烧掉
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    站长:61 湘ICP备13001086号-2