• 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;
    }
    

      

  • 相关阅读:
    WinForm DotNetBar 动态添加DataGridView
    调用Excel宏批量处理文件
    jquery datatables+MVC+WCF
    DataTables warning : Requested unknown parameter '0' from the data source for row 0错误
    数据库中判断内容中是否包含中文
    TerraGate SFS Manager配置时权限设置问题
    AutoCAD开发5--批量修改dwg文件
    关闭浏览器时提示的javascript事件
    ArcGIS for JS 离线部署
    [转]ArcGIS for Silverlight:关于尝试连接到REST端点时发生安全异常的解决方案
  • 原文地址:https://www.cnblogs.com/mlj318/p/3057305.html
Copyright © 2020-2023  润新知