ffmpeg对avs,h264编解码的支持

http://www.cnblogs.com/mlj318/archive/2013/05/03/3057305.html


ffmpeg对avs编解码的支持

输出的avs码流是.cavs格式的。

编码:ffmpeg -s 640x480 -i test.yuv -b 300k -vcodec libxavs test.cavs

解码:ffmpeg -i test.cavs test.yuv

http://xavs.sourceforge.net/xavs_ffmpeg.html  

http://ffmpeg.zeranoe.com/builds/

 

ffmpeg提供的encoding-example有不少问题,解码正确的h264比特流文件时,报错信息如下:
error while decoding MB 5 4, bytestream (-11).

原因是avcodec_decode_video2传进来的是要完整的一帧,在此之前调用av_parser_parse2来取一帧。 之前低版本的avcodec_decode_video不需要传进来完整的一帧,升级之后还不如以前了。。。

 

参考http://bbs.chinavideo.org/viewthread.php?tid=14008&extra=page%3D1 的解码过程,以下代码可以正确解码264和avs码流了。

使用的是zeranoe 提供的共享库,ffmpeg版本应该是  ffmpeg-1.2-win32-shared.7z 。

avs编码使用-vcodec libxavs 选项,解码的AVCodecID 是 AV_CODEC_ID_CAVS.

解码的结果与ffmpeg-1.2-win32-static.7z  静态版ffmpeg.exe解码的结果基本一样,中间会有几帧有区别。

#include <math.h>
 
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
 
#define INBUF_SIZE 4096
  
FILE  *fp =  NULL;
 
AVFrame * m_pFrame;
 
//AVFormatContext *m_pFormatCtx;
 
AVCodecParserContext * m_parser;
 
AVCodec *m_pCodec;
AVCodecContext *m_pCodecContext;
 
//初始化
int  Decode_init(unsigned int  width,unsigned int  height)
{
     int  iRet ;
     /* register all the codecs */
     avcodec_register_all();
     m_pCodec=avcodec_find_decoder(AV_CODEC_ID_CAVS); 
         if (m_pCodec==NULL)
         {
                 printf ( "Error avcodec_find_decoder" );
                 return  0;
         }
         m_pCodecContext=avcodec_alloc_context3(m_pCodec);
         if (m_pCodecContext==NULL)
         {
                 printf ( "Error avcodec_alloc_context" );
                 return  0;
         }
         //m_pCodecContext->width = width;   //不用初始化图像尺寸一样可以解
        // m_pCodecContext->height = height;
         //m_pCodecContext->codec_id  = CODEC_ID_H264;
         m_pCodecContext->pix_fmt = PIX_FMT_YUV420P;
         iRet = avcodec_open2(m_pCodecContext,m_pCodec,NULL);
         if (iRet<0)
         {
                 printf ( "Error avcodec_open" );
                 return  0;
         }
         m_pFrame=avcodec_alloc_frame();
         if (m_pFrame==NULL)
         {
                printf ( "Error avcodec_alloc_frame" );
                 return  0;
         }
   //下面的内容,示例中没有
         //m_pFormatCtx=avformat_alloc_context();
         //if (!m_pFormatCtx)//分配内存失败
         //{
         //        printf("avformat_alloc_context error\n");      
         //        return 0;    
         //}
         m_parser = av_parser_init(AV_CODEC_ID_CAVS);
         if (!m_parser)
                 return  0;
return  1;
}
//释放
int  Decode_uninit()
{
av_free(m_pFrame);
avcodec_close(m_pCodecContext);
     av_free(m_pCodecContext);
return  1;
}
  
static  int  DecodeFrame(uint8_t *data , int  size,unsigned char  *yuvOutBuffer)
{
         int  got_picture=0;
         int  iRet;
         AVPacket avp;
         av_init_packet(&avp);
 
         avp.data=data;
         avp.size=size;
 
        iRet  = avcodec_decode_video2(m_pCodecContext,m_pFrame,&got_picture,&avp);
 
         if (iRet>=0)
         {
                 if (got_picture)
                 {
                     int  i;
                         for ( i=0; i<m_pCodecContext->height; i++)
                                 fwrite (m_pFrame->data[0] + i * m_pFrame->linesize[0], 1, m_pCodecContext->width, fp);
                         for ( i=0; i<m_pCodecContext->height/2; i++)
                                 fwrite (m_pFrame->data[1] + i * m_pFrame->linesize[1], 1, m_pCodecContext->width/2, fp);
                         for ( i=0; i<m_pCodecContext->height/2; i++)
                                 fwrite (m_pFrame->data[2] + i * m_pFrame->linesize[2], 1, m_pCodecContext->width/2, fp);
 
                 }
         }
         
         return  got_picture;
}
//调用入口函数
void  DecodeVideo(uint8_t * pInBuffer, int  size,unsigned char  *yuvOutBuffer)
{
         int  pos=0;
         int64_t pts=AV_NOPTS_VALUE;
         int64_t dts=AV_NOPTS_VALUE;
         do
         {
                 uint8_t *pout;
                 int  pout_len;
                 int  len= av_parser_parse2(m_parser,m_pCodecContext,&pout,&pout_len, pInBuffer+pos,size-pos,pts,dts,AV_NOPTS_VALUE);
 
                 pos +=len;
 
                 if (pout_len >0 )
                 {
                         DecodeFrame(pout,pout_len,yuvOutBuffer);
                 }
         } while  (pos<size);
 
 
         if (size<=0)
         {
                 while (DecodeFrame(NULL,0,yuvOutBuffer));
 
         }
 
}
 
 
int  main( int  argc, char  **argv)
{
     const  char  *output_type;
     FILE  *f;
         f = fopen ( "test.cavs" , "rb" );
     if  (!f) {
         fprintf (stderr, "Could not open %s\n" , "test.264" );
         exit (1);
     }
     fp= fopen ( "out.yuv" , "wb" );
 
 
     Decode_init(704,480);
     {
     uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
      
     /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
     memset (inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
 
     for (;;) {
         int  size = fread (inbuf, 1, INBUF_SIZE, f);
         if  (size== 0)
             break ;
         DecodeVideo(inbuf,size,NULL);
     }
     }
     fclose (f);
     fclose (fp);
     Decode_uninit();
     return  0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值