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

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM