在Android中,编码器的具体实现会被封装在一个OpenMAX组件中,对于MP4的编码器,相应的组件为OmxComponentMpeg4EncAO,该组件被Mpeg4EncOmxComponentFactory、H263EncOmxComponentFactory等组件工厂共有,用来实现对H.263和MPEG-4的编码。提供给记录引擎的接口为OmxComponentMpeg4EncAO::ProcessData()方法,实际的编码工作在 Mpeg4Encoder_OMX::Mp4EncodeVideo()中实现。下面是该方法的具体实现:
        代码:视频的编码过程
        OMX_BOOL Mpeg4Encoder_OMX::Mp4EncodeVideo(OMX_U8*    aOutBuffer,
            OMX_U32*  aOutputLength,    //输出长度
            OMX_BOOL*  aBufferOverRun,    //运行缓冲
            OMX_U8**  aOverBufferPointer,	
            OMX_U8*  aInBuffer,    //输入缓冲
            OMX_U32  aInBufSize,
            OMX_TICKS  aInTimeStamp,   
 
            OMX_TICKS*  aOutTimeStamp,
            OMX_BOOL*  aSyncFlag)    // OMX_FALSE或者OMX_TRUE
    {
        *aSyncFlag=OMX_FALSE;
        if (OMX_FALSE==iModTimeInitialized)
        {
                iNextModTime=aInTimeStamp;
                iModTimeInitialized=OMX_TRUE;
        }
        if (OMX_COLOR_FormatYUV420Planar==iVideoFormat)  //YUV420元数据
        {
              if (aInBufSize<(OMX_U32)((iSrcWidth * iSrcHeight * 3) >> 1))
              {
                   *aOutputLength=0;
                   return OMX_FALSE;
              }
        }
        else if (OMX_COLOR_Format24bitRGB888==iVideoFormat) //RGB888元数据
        {
              if (aInBufSize<(OMX_U32)(iSrcWidth * iSrcHeight * 3))
              {
                   *aOutputLength=0;
                   return OMX_FALSE;
              }
        }
        else if (OMX_COLOR_Format12bitRGB444==iVideoFormat) //RGB444元数据
        {
              if (aInBufSize<(OMX_U32)(iSrcWidth * iSrcHeight * 2))
              {
                   *aOutputLength=0;
                   return OMX_FALSE;
              }
        }
        else if (OMX_COLOR_FormatYUV420SemiPlanar==iVideoFormat) //YUV420元数据
        {
              if (aInBufSize<(OMX_U32)((iSrcWidth * iSrcHeight * 3)>>1))
              {
                   *aOutputLength=0;
                   return OMX_FALSE;
              }
        }
        else if ((OMX_COLOR_FormatYCbYCr==iVideoFormat) ||
                     (OMX_COLOR_FormatYCrYCb==iVideoFormat) ||
                     (OMX_COLOR_FormatCbYCrY==iVideoFormat) ||
                     (OMX_COLOR_FormatCrYCbY==iVideoFormat))
        {
              if (aInBufSize<(OMX_U32)(iSrcWidth * iSrcHeight * 2))
              {
                   *aOutputLength=0;
                   return OMX_FALSE;
              }
        }
        //开始对输入缓冲解码
        VideoEncFrameIO vid_in, vid_out;
        Int Size;
        Bool status;
        ULong modTime;
        Int nLayer=0;
        if ((iNextModTime * 1000) <=aInTimeStamp)
        {
              Size=*aOutputLength;
    #if PROFILING_ON
              OMX_U32 Start=OsclTickCount::TickCount();
    #endif
              if (iVideoFormat==OMX_COLOR_FormatYUV420Planar)
              {
                   if (iYUVIn) 
                   {//对YUV元数据进行复制
                        CopyToYUVIn(aInBuffer, iSrcWidth, iSrcHeight,
                            ((iSrcWidth+15)>>4)<<4, ((iSrcHeight+15)>>4)<<4);
                        iVideoIn=iYUVIn;
                   }
                   else 
                   {
                        iVideoIn=aInBuffer;
                   }
              }
            else if ((iVideoFormat==OMX_COLOR_Format12bitRGB444) ||
     (iVideoFormat==OMX_COLOR_Format24bitRGB888) ||
                       (iVideoFormat==OMX_COLOR_FormatYUV420SemiPlanar) ||
     (iVideoFormat==OMX_COLOR_FormatYCbYCr) ||
                       (iVideoFormat==OMX_COLOR_FormatYCrYCb) ||
     (iVideoFormat==OMX_COLOR_FormatCbYCrY) ||
                       (iVideoFormat==OMX_COLOR_FormatCrYCbY))
              {/ /元数据格式转换
                   ccRGBtoYUV->Convert((uint8*)aInBuffer, iYUVIn); 
                   iVideoIn=iYUVIn;
              }
    #if PROFILING_ON
              OMX_U32 Stop=OsclTickCount::TickCount();
              iProfileStats.iColorConversionTime +=(Stop-Start);
              ++iProfileStats.iTotalNumFrames;
              OMX_U32 StartTime=OsclTickCount::TickCount();
    #endif
              *aOutTimeStamp=aInTimeStamp;
              vid_in.height=((iSrcHeight+15)>>4)<<4;
              vid_in.pitch=((iSrcWidth+15)>>4)<<4;
              vid_in.timestamp=(ULong)(aInTimeStamp / 1000);
              vid_in.yChan=(UChar*)iVideoIn;
              vid_in.uChan=(UChar*)(iVideoIn+vid_in.height * vid_in.pitch);
              vid_in.vChan=vid_in.uChan+((vid_in.height * vid_in.pitch) >> 2);
    //进行一帧YUV数据的编码
            status=PVEncodeVideoFrame(&iEncoderControl, &vid_in, &vid_out,&modTime, (UChar*)aOutBuffer,&Size, &nLayer);
    #if PROFILING_ON
              OMX_U32 EndTime=OsclTickCount::TickCount();
              iProfileStats.iTotalEncTime +=(EndTime-StartTime);
              if ((PV_TRUE==status) && (Size > 0))
              {
                   ++iProfileStats.iNumFramesEncoded;
                   iProfileStats.iDuration=vid_out.timestamp;
              }
    #endif
              if (status==PV_TRUE)
              {
                   iNextModTime=modTime; //以毫秒为单位
                   if ((nLayer >=0) && ((OMX_U32) Size > *aOutputLength))
                   {
                        *aOverBufferPointer=PVGetOverrunBuffer(&iEncoderControl);
                        *aBufferOverRun=OMX_TRUE;
                   }
                  *aOutputLength=Size;
                  if (Size > 0)
                  {
  			       //转换毫秒为微秒
                       *aOutTimeStamp=((OMX_TICKS) vid_out.timestamp * 1000);
                       PVGetHintTrack(&iEncoderControl, &iHintTrack);
                       if (0==iHintTrack.CodeType)
                       {
                            *aSyncFlag=OMX_TRUE;
                       }
                  }
                  return OMX_TRUE;
              }
              else
              {
                   *aOutputLength=0;
                   return OMX_FALSE;
              }
          }
          else
          {
               *aOutputLength=0;
               return OMX_TRUE;
          }
    }
        从编码过程可以看出,在进行编码时,首先要判断出元数据的格式,如果不是OMX_COLOR_FormatYUV420Planar格式,则调用ColorConvertBase:: Convert()方法对元数据格式进行转换,然后通过PVEncodeVideoFrame()方法针对当前一帧进行编码。
        对于MPEG-4,向组件库注册的注册函数为Mpeg4EncRegister(),组件名为“OMX.PV. mpeg4enc”;对于H263,向组件库注册的注册函数为H263EncRegister(),组件名为“OMX.PV.h263enc”。
        Mpeg4Encoder_OMX的编码模式为MODE_H263和MODE_MPEG4。