在Ubuntu和Android中使用ffmpeg全格式解码视频文件(2)

1、如何在ffmpeg中加入对on2 api的调用    
  1.1 、ON2 Decoder在ffmpeg的修改位置及与CODEC_ID的对应关系  
  表2 

ON2 Decoderffmpeg fileCODEC_IDDIFFMark
H264h264.cCODEC_ID_H264  
DIVXDIVX3~6h263dec.cCODEC_ID_MPEG4DIVX 
   DI50 
  CODEC_ID_MSMPEG4V3 DIVX3
MPEG4h263dec.cCODEC_ID_MPEG4MP4V 
H263h263dec.cCODEC_ID_H263  
Sorenson Sparkversion0,1h263dec.cCODEC_ID_FLV1FLV1 
MPEG2mpeg12.cCODEC_ID_MPEG2VIDEO  
MPEG1mpeg12.cCODEC_ID_MPEG1VIDEO  
VC-1vc1dec.cCODEC_ID_VC1  
  CODEC_ID_WMV3  
RVRV8~10rv34.cCODEC_ID_RV30 RV8
  CODEC_ID_RV40 RV9&10
VP6vp6.cCODEC_ID_VP6  
  CODEC_ID_VP6F  
  CODEC_ID_VP6A  

  1.2 如何从ffmpeg的AVFrame中组装on2各种视频格式需要的frame/slice      
    1.2.1    H264    
      有两种方式为on2 decoder提供正确的raw data.      
      1.2.1.1    把每一个Nal数据分别传给on2   
        ffmpeg在提取nal数据的时候,会由变量is_avc做不同的判断来获得nal的长度

        if (extradata && *extradata == 1)                      
            is_avc = 1;                     
        else                       
            is_avc = 0;                     
        if (is_avc)                      
            search start code prefix:[0][0][1]                     
        else                       
            读AVPacket.data的第一个字节作为nal_size,以此循环 

      1.2.1.2   把每一个AVPacket的data转化为符合标准的一帧后传给on2                    
        这个具体可以参见h264_mp4toannexb_bsf.c的h264_mp4toannexb_filter函数                      
    1.2.2   MPEG1&2                     
      AVPacket.data的数据不需要额外的处理即可被on2的解码。                       
    1.2.3   MPEG4                     
      1.2.3.1   MPEG4                    
        对于mpeg4文件,header信息存放在extradata里面,所以在解码AVPacket的data前,我们应该先把extradata传给on2解码以获得该mpeg4流的头信息。因为ffmpeg在init的时候就要调用一次decode_frame,但此时on2不需要解码任何一帧,所以on2解码extradata的时期如下表:
                                                             表3 

 需要解extradata需要解数据帧
初始化的时候YESNO
解第一帧的时候YESYES
解其他帧的时候NOYES

        1.2.3.2   DIVX3 
          1.2.3.2.1    Divx3不属于mpeg4标准         
          1.2.3.2.2    Divx3没有startcode         
          1.2.3.2.3    解码前需要调用on2的api MP4DecSetinfo来设置视频流的宽高         
          1.2.3.2.4    解码Divx3时,没有DEC_HDRS_RDY这种状态,只有PIC_Decoded.         
        1.2.3.3   DIVX4~6           
          1.2.3.3.1    Divx4~6没有extradata         
          1.2.3.3.2    Divx4~6的CodecID与MPEG4一样,所以需要FourCC来区分         
        1.2.3.4   H263&Sorenson Spark           
        ​​​​​​​  1.2.3.4.1    Sorenson Spark被认为H263(Sorenson Spark)         
        ​​​​​​​  1.2.3.4.2    H263没有extradata         
      1.2.4   RV            
        1.2.4.1   RV各种版本说法的对应关系           
                                        表4             

Video 版本Player 版本wiki Codecs视频编码标准FourCC
Real VideoReal PlayerRealVideoH.263rv10 / rv 13
Real Video 2Real Player 6 / Real Player G2RealVideo G2H.263rv20
Real Video 3Real Player 8RealVideo 3Eearly Version of H.264rv30
Real Video 4Real Player 9~10RealVideo 4H.264rv40

        1.2.4.2   RV数据组成结构      
        一帧rv数据,前20个字节,存储的是整帧的信息,其中前4个存储的是帧的长度,最后4个存储的是该帧slice的个数,比如n个。随后紧接着的n*8个字节存储的便是每个slice的头信息,每8个字节的前四个是标识该帧的合法性,后四个是该slice在整个frame的偏移量,如下图:        
 图5        

        1.2.4.3   MPlayer与Ffmpeg解析rm有所不同,并且在传给on2时帧数据需要处理    
          1.2.4.3.1    mplayer与ffmpeg在解析rm文件用的不是一套代码  
        ​​​​​​​  1.2.4.3.2    mplayer与ffmpeg读出的rv数据不完全一致  
        ​​​​​​​  1.2.4.3.3    mplayer送给decoder的数据,头信息比ffmpeg少一个slice的信息。  
        ​​​​​​​  1.2.4.3.4    mplayer送给decoder的数据,尾部比ffmpeg多一部分信息。  
        ​​​​​​​  1.2.4.3.5    mplayer能解析rv,需要把最后16个字节的数据删除  
        ​​​​​​​  1.2.4.3.6    ffmpeg能解析rv8,必须把第一帧的最后一个slice去掉,包括slice的偏移和合法性。  
        ​​​​​​​  1.2.4.3.7    ffmpeg中slice_count都是从AVPacket的data读的,不是从avctx获得的  
        ​​​​​​​  1.2.4.3.8    ffmpeg一帧的数据(并不是所有帧)比On2 test解码出的数据多一个slice,包括头信息与data  
        ​​​​​​​  1.2.4.3.9    ffmpeg已经解过frame info,并把它去掉,然后才发给decoder,我们需要利用ffmpeg已经获得的信息把slice infos传送给On2  
      1.2.5   VP6    
        从ffmpeg获得CodecID,如果是CODEC_ID_VP6A,则去掉AVPacket.data前三个字符后,On2才能解码。      
      1.2.6   VC1    
        1.2.6.1   对于profile为advanced的VC1视频,on2需要解码extradata   
        1.2.6.2   对于profile为advanced的VC1视频,每一帧的头部必须加上0x00,0x00,0x01,0x0d。
        1.2.6.3   不能直接把ffmpeg中的profile传给on2,因为ffmpeg与on2的profile枚举值不同。   
        1.2.6.4   对于profile为simple&main的VC1视频,on2不能解码extradata,on2需要的metadata需要从avctx中获得。   
        1.2.6.5   simpler&main的文件,目前不能完全支持。   
2、如何在Android中加入对on2 api的调用   
  2.1  CodecID与OMX_CODEC等的映射关系 
                     表5  

CODEC_IDMIMETYPEOMX_CODECON2 DEC
CODEC_ID_H264MEDIA_MIMETYPE_VIDEO_AVCOMX_VIDEO_CodingAVCH264
CODEC_ID_H263MEDIA_MIMETYPE_VIDEO_H263OMX_VIDEO_CodingH263MPEG4
CODEC_ID_FLV1MEDIA_MIMETYPE_VIDEO_FLV1OMX_VIDEO_CodingMPEG4 
CODEC_ID_MPEG4MEDIA_MIMETYPE_VIDEO_MPEG4  
CODEC_ID_MSMPEG4V3   
CODEC_ID_MPEG1VIDEOMEDIA_MIMETYPE_VIDEO_MPEG1OMX_VIDEO_CodingMPEG2MPEG2
CODEC_ID_MPEG2VIDEOMEDIA_MIMETYPE_VIDEO_MPEG2  
CODEC_ID_VC1MEDIA_MIMETYPE_VIDEO_VC1OMX_VIDEO_CodingWMVVC1
CODEC_ID_WMV3   
CODEC_ID_RV30MEDIA_MIMETYPE_VIDEO_RV30OMX_VIDEO_CodingRVRV
CODEC_ID_RV40MEDIA_MIMETYPE_VIDEO_RV40  
CODEC_ID_VP6MEDIA_MIMETYPE_VIDEO_VP6OMX_VIDEO_CodingVP6VP6
CODEC_ID_VP6FMEDIA_MIMETYPE_VIDEO_VP6F  
CODEC_ID_VP6AMEDIA_MIMETYPE_VIDEO_VP6A  

    2.2  新增一个OMX_CODEC步骤,以OMX_VIDEO_CodingRV为例         
      2.2.1   注册Decoder名称       

omx/system/src/openmax_il/omx_core/src/OMX_Core.c         
   {"OMX.NU.Video.Decoder", "video_decoder.rv"},  

      2.2.2   增加Decoder参数       

  omx/system/src/openmax_il/omx_core/inc/OMX_Video.h         
   typedef struct OMX_VIDEO_PARAM_RVTYPE {…}        
   typedef enum VIDDEC_DEFAULT_INPUT_INDEX        
    VIDDEC_DEFAULT_INPUT_INDEX_RV,       
   typedef enum VIDDEC_INIT_VALUE        
    VIDDEC_INIT_RV,       
   typedef struct VIDDEC_COMPONENT_PRIVATE        
    OMX_VIDEO_PARAM_RVTYPE* pRV;       
   #define VIDDEC_COMPONENTROLES_RV        
   #define VIDDEC_DEFAULT_RV_PORTINDEX        
   #define VIDDEC_DEFAULT_RV_VERSION 

      2.2.3   增加对Decoder的初始化       

  omx/video/src/openmax_il/video_decode/src/OMX_VideoDecoder.c         
   OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE hComponent)        
    OMX_MALLOC_STRUCT(pComponentPrivate->pRV, OMX_VIDEO_PARAM_RVTYPE,...);   

      2.2.4   增加Decoder参数的初始化       

  omx/video/src/openmax_il/video_decode/src/OMX_VideoDec_Utils.c         
   OMX_ERRORTYPE VIDDEC_Load_Defaults         
    case VIDDEC_INIT_RV:   

      2.2.5   增加Decoder参数的设置       

  omx/video/src/openmax_il/video_decode/src/OMX_VideoDecoder.c         
   static OMX_ERRORTYPE VIDDEC_GetParameter (OMX_IN OMX_HANDLETYPE hComponent,        
    case OMX_IndexParamVideoPortFormat:       
     case VIDDEC_DEFAULT_INPUT_INDEX_RV:      
   static OMX_ERRORTYPE VIDDEC_SetParameter (OMX_HANDLETYPE hComp,        
    case OMX_IndexParamVideoPortFormat:       
     case OMX_VIDEO_CodingRV:      

      2.2.6   增加Decoder解码所需资源的分配       

  omx/video/src/openmax_il/video_decode/src/OMX_VideoDecoder.c         
   static OMX_ERRORTYPE VIDDEC_Allocate_DSPResources        
    if (nPortIndex == pComponentPrivate->pInPortFormat->nPortIndex) {       
     else if (pPortDefIn->format.video.eCompressionFormat == OMX_VIDEO_CodingRV) {      
    else if (nPortIndex == pComponentPrivate->pOutPortFormat->nPortIndex) {       
     else if (pPortDefIn->format.video.eCompressionFormat == OMX_VIDEO_CodingRV) { 

      2.2.7   增加Decoder对Command的处理       

  omx/video/src/openmax_il/video_decode/src/OMX_VideoDec_Utils.c         
   OMX_ERRORTYPE VIDDEC_HandleCommand        
    if (pComponentPrivate->pInPortDef->format.video.eCompressionFormat == OMX_VIDEO_CodingRV) {  

      2.2.8   增加Decoder对资源的释放       

  omx/video/src/openmax_il/video_decode/src/OMX_VideoDecoder.c         
   static OMX_ERRORTYPE VIDDEC_FreeBuffer        
    else if (pPortDefIn->format.video.eCompressionFormat == OMX_VIDEO_CodingRV) { 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值