FFmpeg-out1.h264文件解码成out1.yuv文件(代码实现)

#include <iostream>
using namespace std;
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include <stdio.h>
}
#define VIDEO_INBUF_SIZE 20480
#define VIDEO_REFILL_THRESH 4096

static void decode(AVCodecContext *dec_ctx,AVPacket *pkt,AVFrame *frame,FILE *outfile)
{
    int ret=avcodec_send_packet(dec_ctx,pkt);   //发送给解码器
            while(ret>=0)
            {
                ret=avcodec_receive_frame(dec_ctx,frame);   //接收解码后的帧
                if(ret==AVERROR(EAGAIN)||ret==AVERROR_EOF)
                    return;

                for(int j=0;j<frame->height;j++)
                    fwrite(frame->data[0]+j*frame->linesize[0],1,frame->width,outfile);
                for(int j=0;j<frame->height/2;j++)
                    fwrite(frame->data[1]+j*frame->linesize[1],1,frame->width/2,outfile);
                for(int j=0;j<frame->height/2;j++)
                    fwrite(frame->data[2]+j*frame->linesize[2],1,frame->width/2,outfile);
            } 
}
int main()
{
    const char *outfilename="out1.yuv";
    const char *filename="out1.h264";
    const AVCodec *codec;
    AVCodecContext *codec_ctx=NULL;
    AVCodecParserContext *parser=NULL;
    int len=0;
    int ret=0;
    FILE *infile=NULL;
    FILE *outfile=NULL;
    uint8_t inbuf[VIDEO_INBUF_SIZE+AV_INPUT_BUFFER_PADDING_SIZE];
    uint8_t *data=NULL;
    size_t data_size=0;
    AVPacket *pkt=NULL;
    AVFrame *decoded_frame=NULL;

    pkt=av_packet_alloc();
    enum AVCodecID video_codec_id=AV_CODEC_ID_H264;
    if(strstr(filename,"264")!=NULL){               //  根据文件后缀名给audio_codec_id赋值
        video_codec_id=AV_CODEC_ID_H264; //char *strstr( const char *str1, const char *str2 ); 
    }                                                                                //  strstr函数是在字符串str1中查找是否含有字符串str2,如果存在,返回str2在str1中第一次出现的地址;否则返回NULL。
    else if(strstr(filename,"mpeg2")!=NULL){
        video_codec_id=AV_CODEC_ID_MPEG2VIDEO;
    }
    else{
        printf("default codec id:%d\n",video_codec_id);
    }
    codec=avcodec_find_decoder(video_codec_id);      //查找解码器
    parser=av_parser_init(codec->id);  //获取裸流的解析器AVCodecParserContext(数据)+AVCodecParser(方法)
    codec_ctx=avcodec_alloc_context3(codec);    //分配codec上下文
    avcodec_open2(codec_ctx,codec,NULL);    //将解码器和解码器上下文进行关联
    infile=fopen(filename,"rb");    //打开输入文件
    outfile=fopen(outfilename,"wb");    //打开输出文件
    data=inbuf;
    data_size=fread(inbuf,1,VIDEO_INBUF_SIZE,infile);   读取文件进行解码
    while(data_size>0)
    {
        decoded_frame=av_frame_alloc();
        ret=av_parser_parse2(parser,codec_ctx,&pkt->data,&pkt->size,
                                                       data,data_size,AV_NOPTS_VALUE,AV_NOPTS_VALUE,0);
        data+=ret;  //跳过已经解析的数据
        data_size-=ret;  //对应的缓存大小也做相应减小

        if(pkt->size)
        {
            decode(codec_ctx,pkt,decoded_frame,outfile);
       }
        if(data_size<VIDEO_REFILL_THRESH)   //如果数据少了则再次读取
        {
            memmove(inbuf,data,data_size);    //把之前剩的数据拷贝到buffer的起始位置
            data=inbuf;
            //读取数据长度:AUDIO_INBUF_SIZE-data_size
           len=fread(data+data_size,1,VIDEO_INBUF_SIZE-data_size,infile);
            if(len>0)
                data_size+=len;
        }
    }

    /*冲刷解码器*/
    pkt->data=NULL;
    pkt->size=0;
    decode(codec_ctx,pkt,decoded_frame,outfile);

    fclose(outfile);
    fclose(infile);

    avcodec_free_context(&codec_ctx);
    av_parser_close(parser);
    av_frame_free(&decoded_frame);
    av_packet_free(&pkt);

    printf("main finish,please enter Enter and exit\n");
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值