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