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;

}

  

 

你可能感兴趣的:(ffmpeg)