#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
extern "C"
{
#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>
#include <libavformat/avformat.h>
}
static AVFormatContext *input_fmt_ctx=NULL;
static int video_stream_idx=-1;
static AVStream *input_video_stream=NULL;
static AVCodecContext *video_dec_ctx = NULL;
static uint8_t *video_dst_data[4] = {NULL};
static int video_dst_linesize[4];
static int video_dst_bufsize;
static AVFrame *input_frame;
static AVPacket input_pkt;
/*video output*/
static AVFrame *frame;
static AVPicture src_picture, dst_picture;
static int frame_count;
static int open_codec_context(int *stream_idx,AVFormatContext *fmt_ctx, enum AVMediaType type)
{
int ret;
AVStream *st=NULL;
AVCodecContext *dec_ctx=NULL;
AVCodec *dec=NULL;
ret=av_find_best_stream(fmt_ctx,type,-1,-1,NULL,0);
if(ret<0)
{
return ret;
}
else
{
*stream_idx=ret;
st=fmt_ctx->streams[*stream_idx];
/*find decoded*/
dec_ctx=st->codec;
dec=avcodec_find_decoder(dec_ctx->codec_id);
if(!dec)
{
printf("avcodec_find_decoder fail\n");
return -1;
}
if((ret=avcodec_open2(dec_ctx,dec,NULL))<0)
{
printf("avcodec_open2 fail\n");
return -1;
}
}
return 0;
}
static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st)
{
int ret;
AVCodecContext *c=st->codec;
ret=avcodec_open2(c,codec,NULL);
if(ret<0)
{
printf("avcodec_open2 fail\n");
exit(-1);
}
frame=avcodec_alloc_frame();
if(!frame)
{
printf("avcodec_alloc_frame fail\n");
exit(-1);
}
/* Allocate the encoded raw picture. */
ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height);
if(ret<0)
{
printf("avpicture_alloc fail\n");
exit(-1);
}
if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
ret = avpicture_alloc(&src_picture, AV_PIX_FMT_YUV420P, c->width, c->height);
if(ret<0)
{
printf("avpicture_alloc fail\n");
exit(-1);
}
}
/* copy data and linesize picture pointers to frame */
*((AVPicture *)frame) = dst_picture;
}
int main()
{
const char* input_file="input.avi";
av_register_all();
avcodec_register_all();
int ret;
/*Reads the file header and stores information about the file format in the AVFormatContext structure*/
if(avformat_open_input(&input_fmt_ctx,input_file,NULL,NULL)<0)
{
printf("avformat_open_input fail\n");
exit(-1);
}
/*Check out the stream information in the file*/
if(avformat_find_stream_info(input_fmt_ctx,NULL)<0)
{
printf("avformat_find_stream_info fail\n");
exit(-1);
}
av_dump_format(input_fmt_ctx,0, input_file, 0);
if(open_codec_context(&video_stream_idx,input_fmt_ctx,AVMEDIA_TYPE_VIDEO)>=0)
{
input_video_stream=input_fmt_ctx->streams[video_stream_idx];
video_dec_ctx=input_video_stream->codec;
ret=av_image_alloc(video_dst_data,video_dst_linesize,video_dec_ctx->width,video_dec_ctx->height,video_dec_ctx->pix_fmt,1);
if (ret < 0)
{
printf("av_image_alloc fail\n");
}
video_dst_bufsize=ret;
}
else
{
printf("open_codec_context fail\n");
exit(-1);
}
/*配置一個AVframe空間 準備放待會要解的影像資料*/
input_frame =av_frame_alloc();
if (!input_frame) {
printf("av_frame_alloc fail\n");
exit(-1);
}
/*========================================*/
/*==========output media==================*/
/*========================================*/
/*配置outputfile的參數*/
AVOutputFormat *fmt;
AVFormatContext *oc;
AVStream *video_st=NULL;
AVCodec *video_codec;
const char *outputfile;
outputfile="output.mp4";
/* allocate the output media context */
avformat_alloc_output_context2(&oc,NULL,NULL,outputfile);
if(!oc)
{
avformat_alloc_output_context2(&oc,NULL,"mpeg",outputfile);
}
if(!oc)
{
printf("avformat_alloc_output_context2 fail\n");
exit(-1);
}
fmt=oc->oformat;
/*Mp4 format為H264*/
fmt->video_codec=AV_CODEC_ID_H264;
/*Find the encoder*/
video_codec=avcodec_find_encoder(fmt->video_codec);
if(!(video_codec))
{
printf("avcodec_find_encoder fail\n");
exit(-1);
}
/*配置output stream*/
video_st=avformat_new_stream(oc,video_codec);
if(!(video_st))
{
printf("avformat_new_stream fail\n");
exit(-1);
}
video_st->id=oc->nb_streams-1;
video_st->codec->codec_id=fmt->video_codec;
video_st->codec->bit_rate=400000;
/*frame rate*/
video_st->codec->time_base.den=25;
video_st->codec->time_base.num=1;
/*every 12 frame must have I frame*/
video_st->codec->gop_size=12;
video_st->codec->pix_fmt=AV_PIX_FMT_YUV420P;
/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
{
video_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
video_st->codec->width=video_dec_ctx->width;
video_st->codec->height=video_dec_ctx->height;
av_dump_format(oc,0,outputfile,1);
/*Try to open output file*/
if((fmt->flags&AVFMT_NOFILE))
{
ret=avio_open(&oc->pb,outputfile,AVIO_FLAG_WRITE);
if(ret<0)
{
fprintf(stderr,"Could not open\n");
exit(-1);
}
}
open_video(oc, video_codec, video_st);
/*Write the stream header*/
//ret=avformat_write_header(oc,NULL);
/*========================================*/
/*========================================*/
/*========================================*/
/*Av_read_frame*/
int index=0;
int frameFinished=0;
while(av_read_frame(input_fmt_ctx,&input_pkt)>=0)
{
if(input_pkt.stream_index==video_stream_idx)
{
/* decode video frame */
ret=avcodec_decode_video2(video_dec_ctx,input_frame,&frameFinished,&input_pkt);
if(ret<0)
{
printf("avcodec_decode_video2 fail\n");
exit(-1);
}
/*Aready get a video frame*/
if(frameFinished)
{
/*do something*/
printf("HI ");
}
}
av_free_packet(&input_pkt);
}
/*Close codec*/
avcodec_close(video_st->codec);
av_free(src_picture.data[0]);
av_free(dst_picture.data[0]);
av_free(frame);
if(!(fmt->flags&AVFMT_NOFILE))
avio_close(oc->pb);
avformat_free_context(oc);
av_free(input_frame);
av_free(video_dst_data[0]);
avcodec_close(video_dec_ctx);
system("pause");
return 0;
}