97干视频,99国产精品懂色,亚洲精品99久久久久中文字幕,伊人五月丁香综合AⅤ,国产精品成人免费999

  您的位置:華清遠(yuǎn)見教育科技集團(tuán) >> 新聞動(dòng)態(tài) >> Android資料 >> Android視頻解碼過程詳解  
 
Android視頻解碼過程詳解
分享到:

在《Android視頻編碼源碼分享》一文中,我們主要學(xué)習(xí)的是Android視頻編碼的實(shí)現(xiàn)方法,本文要給大家講述的則是Android中視頻的解碼過程。

在Android中,解碼器的具體實(shí)現(xiàn)會(huì)被封裝在一個(gè)OpenMAX組件中,對(duì)于視頻的編碼器,相應(yīng)的組件為OpenmaxMpeg4AO,該組件被Mpeg4OmxComponentFactory、H263OmxComponentFactory等組件工廠共有,用來實(shí)現(xiàn)對(duì)H.263和MPEG-4的解碼。提供給記錄引擎的接口為OpenmaxMpeg4AO::ProcessData()方法,實(shí)際的解碼工作在 Mpeg4 Decoder_OMX::Mp4DecodeVideo ()方法中實(shí)現(xiàn)。下面是該方法的具體實(shí)現(xiàn):

代碼:視頻的解碼過程

MX_BOOL Mpeg4Decoder_OMX::Mp4DecodeVideo(OMX_BUFFERHEADERTYPE* aOutBuffer, OMX_U32*
    aOutputLength,OMX_U8** aInputBuf, OMX_U32* aInBufSize,
    OMX_PARAM_PORTDEFINITIONTYPE* aPortParam, OMX_BOOL aDeBlocking,
    OMX_S32* aFrameCount, OMX_BOOL aMarkerFlag, OMX_BOOL *aResizeFlag)
    {
      OMX_BOOL Status=OMX_TRUE;
      OMX_S32 OldWidth, OldHeight;
      OldWidth=aPortParam->format.video.nFrameWidth;
      OldHeight=aPortParam->format.video.nFrameHeight;
      *aResizeFlag=OMX_FALSE;
      #ifdef _DEBUG
      static OMX_U32 FrameCount=0;
      #endif
      uint UseExtTimestamp=0;
      uint32 TimeStamp;
      OMX_S32 InputSize, InitSize;
      if ((Mpeg4InitCompleteFlag==OMX_FALSE) && (MPEG4_MODE==CodecMode))
      {
        if (!aMarkerFlag)
        {
          InitSize=GetVideoHeader(0, *aInputBuf, *aInBufSize);
        }
        else
        {
          InitSize=*aInBufSize;
        }
      //初始化解碼
      if (PV_TRUE!=InitializeVideoDecode(&iDisplay_Width, &iDisplay_Height,aInputBuf, (OMX_S32*)aInBufSize, MPEG4_MODE, aDeBlocking))
      return OMX_FALSE;
      Mpeg4InitCompleteFlag=OMX_TRUE;
      aPortParam->format.video.nFrameWidth=iDisplay_Width;
      aPortParam->format.video.nFrameHeight=iDisplay_Height;
      OMX_U32 min_stride=((aPortParam->format.video.nFrameWidth+15) & (~15));
      OMX_U32 min_sliceheight=((aPortParam->format.video.nFrameHeight+15) & (~15));
      aPortParam->format.video.nStride=min_stride;
      aPortParam->format.video.nSliceHeight=min_sliceheight;
      //解碼器組件總是輸出YUV420格式
      aPortParam->nBufferSize=(aPortParam->format.video.nSliceHeight*aPortParam->
      format.video.nStride * 3)>>1;
      iFrameSize=(aPortParam->format.video.nSliceHeight * aPortParam->format. video.nStride);
      if ((iDisplay_Width !=OldWidth) || (iDisplay_Height !=OldHeight))
      {
        *aResizeFlag=OMX_TRUE;
      }
      else if (NULL !=aOutBuffer)
      {
        PVSetReferenceYUV(&VideoCtrl, (uint8*)(aOutBuffer->pBuffer));
        BufferCtrlStruct *pBCTRL=(BufferCtrlStruct *)(aOutBuffer-> pOutputPortPrivate);
        pBCTRL->iRefCount++;
        ipRefCtrPreviousReferenceBuffer=&(pBCTRL->iRefCount);
        iReferenceYUVWasSet=OMX_TRUE;
      }
      *aFrameCount=1;
      *aInBufSize -=InitSize;
      return OMX_TRUE;
      }
      if ((*(OMX_S32*)aInBufSize) <=0)
      {
        return OMX_FALSE;
      }
      TimeStamp=0xFFFFFFFF;
      InputSize=*aInBufSize;
      if ((OMX_FALSE==Mpeg4InitCompleteFlag) && (H263_MODE==CodecMode))
      {
      int32 aligned_width, aligned_height;
      int32 display_width, display_height;
      //獲取配置信息
      if (iGetM4VConfigInfo(*aInputBuf, *aInBufSize, &aligned_width, &aligned_height,&display_width, &display_height))
      {
        return OMX_FALSE;
      }
      Mpeg4InitCompleteFlag=OMX_TRUE;
      iDisplay_Width=display_width;
      iDisplay_Height=display_height;
      aPortParam->format.video.nFrameWidth=iDisplay_Width; // use non 16byte aligned values (display_width) for H263
      aPortParam->format.video.nFrameHeight=iDisplay_Height; // like in the case of M4V (PVGetVideoDimensions also returns display_width/height)
      OMX_U32 min_stride=((aPortParam->format.video.nFrameWidth+15) & (~15));
      OMX_U32 min_sliceheight=((aPortParam->format.video.nFrameHeight+15) & (~15));
      aPortParam->format.video.nStride=min_stride;
      aPortParam->format.video.nSliceHeight=min_sliceheight;
      aPortParam->nBufferSize=(aPortParam->format.video.nSliceHeight * aPortParam->format.video.nStride * 3) >> 1;
      iFrameSize=(aPortParam->format.video.nSliceHeight * aPortParam->format.video.nStride);
      if ((iDisplay_Width !=OldWidth)||(iDisplay_Height !=OldHeight))
      {
        *aResizeFlag=OMX_TRUE;
      }
      else if (NULL !=aOutBuffer)
      {
        PVSetReferenceYUV(&VideoCtrl, (uint8*)(aOutBuffer->pBuffer));
        BufferCtrlStruct *pBCTRL=(BufferCtrlStruct *)(aOutBuffer->pOutputPortPrivate);
        pBCTRL->iRefCount++;
        ipRefCtrPreviousReferenceBuffer=&(pBCTRL->iRefCount);
        iReferenceYUVWasSet=OMX_TRUE;
      }
      *aFrameCount=1;
      return OMX_TRUE;
      }
      if (iReferenceYUVWasSet==OMX_FALSE)
      {
        PVSetReferenceYUV(&VideoCtrl, (uint8*)(aOutBuffer->pBuffer));
        BufferCtrlStruct *pBCTRL=(BufferCtrlStruct *)(aOutBuffer-> pOutputPortPrivate);
        pBCTRL->iRefCount++;
        ipRefCtrPreviousReferenceBuffer=&(pBCTRL->iRefCount);
        iReferenceYUVWasSet=OMX_TRUE;
        return OMX_TRUE;
      }
      #if PROFILING_ON
      OMX_U32 StartTime=OsclTickCount::TickCount();
      #endif
      //針對(duì)一幀進(jìn)行解碼
      Status=(OMX_BOOL) PVDecodeVideoFrame(&VideoCtrl, aInputBuf,&TimeStamp,(int32*)aInBufSize,&UseExtTimestamp,(OMX_U8*)(aOutBuffer->pBuffer));
#if PROFILING_ON
      OMX_U32 EndTime=OsclTickCount::TickCount();
      iTotalTicks +=(EndTime-StartTime);
      #endif
      if (Status==PV_TRUE)
      {
        #ifdef _DEBUG
        #endif
        *aInputBuf +=(InputSize-*aInBufSize);
        (*ipRefCtrPreviousReferenceBuffer)--;
        if ((*ipRefCtrPreviousReferenceBuffer)==0)
        {
          ipOMXComponent->iNumAvailableOutputBuffers++;
        }
        BufferCtrlStruct *pBCTRL=(BufferCtrlStruct *)(aOutBuffer-> pOutputPortPrivate);
        pBCTRL->iRefCount++;
        ipRefCtrPreviousReferenceBuffer=&(pBCTRL->iRefCount);
        *aOutputLength=(iFrameSize * 3)>>1;
        (*aFrameCount)++;
      }
      else
      {
        *aInBufSize=InputSize;
        *aOutputLength=0;
      }
      return Status;
    }

在進(jìn)行解碼時(shí),會(huì)首先判斷編碼格式是MPEG4_MODE還是H263_MODE,如果是MPEG4_MODE,則首先通過GetVideoHeader()方法讀取視頻的頭信息,然后通過InitializeVideoDecode()方法初始化視頻解碼器,終將數(shù)據(jù)解碼為YUV420格式的元數(shù)據(jù)。如果編碼格式為H263_MODE,則首先通過iGetM4VConfigInfo()方法獲取M4V文件的配置信息,終將數(shù)據(jù)解碼為YUV420格式的元數(shù)據(jù)。

 更多相關(guān)文章

·Android 視頻編碼源碼分享
·Android 雙緩沖局部渲染
·Android Overlay硬件加速
·Android OpenGL ES渲染方式
·Android Skia UI控件架構(gòu)