下面对于得到的文件如何处理:
1.1新建工程,在vc6.0下新建了一个工程。取名为MPG。
1.2搭建ffmpeg运行环境
将include,lib文件拷贝到MPG工程目录下,然后将bin文件夹中的 所有的dll文件拷贝到MPG工程下的Debug文件夹下。
接下来就是对工程的一些设置,以便让工程能够在运行时找到这些文件。
1.2.1 设置lib
在VC6.0中project->setting->link 下的object/library modules:
添加以下lib库: avcodec.lib avdevice.lib avformat.lib avutil.lib swscale.lib avfilter.lib
1.2.2设置头文件和库文件路径
在VC6.0下 Tools->options->Directories
对于 show directory 选择“inlcude files”
并在下面添加include文件路径
例如:C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\MYPROJECTS\MPG_IOTEST_SDL_SHOW\MPG_IOTEST\INCLUDE
C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\MYPROJECTS\MPG_IOTEST_SDL_SHOW\MPG_IOTEST\INCLUDE\LIBAVCODEC
......依次将include下的文件夹添加进去
在show directory 下 选择“library files”添加lib文件夹路径
例如:C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\MYPROJECTS\MPG_IOTEST_SDL_SHOW\MPG_IOTEST\LIB
下面配置好路径之后,接下来就是运用ffmpeg
有很多例子,比如output_sample.c
现在这个例子是自己根据这些例子综合起来,
在写例子之前,因为ffmpeg是用c编译的,如果在c++下面编译的话,最重要的一个设置就是
#ifdef __cplusplus
extern "C" {
#endif
#include "avcodec.h"
#include "avformat.h"
#include "mathematics.h"
#include "avutil.h"
#include "swscale.h"
//#include "fifo.h"
#include
//#include "opt.h"
#include
#ifdef __cplusplus
}
#endif
该设置一开始困扰自己很久,所以希望贴出来,给大家一些建议 :-)
以下是自己写的程序
int main()
{
const char *filename="aa.mpg";
//输入部分
av_register_all();//注册库中所有可能有用的文件格式和编码器
AVFormatContext *ic;
//输入文件处理部分
ic=av_alloc_format_context();
//打开文件
if (av_open_input_file(&ic,filename,NULL,0,NULL)!=0)
{
printf("can not open file%s\n",filename);
exit(1);
}
//取出流信息
if (av_find_stream_info(ic)<0)
{
printf("can not find suitable codec parameters\n");
exit(1);
}
//列出输入的文件相关流信息
dump_format(ic,0,filename,0);
int i;
int videoindex=-1;
int audioindex=-1;
for (i=0;i
{
if (ic->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
{
videoindex=i;
}
else if (ic->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
{
audioindex=i;
}
}//检查是否存在视频流和音频流
if (videoindex==-1)
{
printf("can not find video stream\n");
exit(1);
}
AVCodecContext *vCodeCtx;
vCodeCtx=ic->streams[videoindex]->codec;//取得视频编码的上下文指针
AVCodec *vCodec;
vCodec=avcodec_find_decoder(vCodeCtx->codec_id);//寻找合适编码器
if (vCodec==NULL)
{
printf("cannot find suitable video decoder\n");
exit(1);
}
//打开该视频编码器
if (avcodec_open(vCodeCtx,vCodec)<0)
{
printf("cannot open the video decoder\n");
exit(1);
}
//查找是否有音频
if (audioindex==-1)
{
printf("cannot open audio srteam\n");
exit(1);
}
//音频上下文
AVCodecContext *aCodecCtx;
aCodecCtx=ic->streams[audioindex]->codec;
AVCodec *aCodec;
aCodec=avcodec_find_decoder(aCodecCtx->codec_id);
//找到合适的音频编码器
if (aCodec==NULL)
{
printf("cannot find suitable audio decoder\n");
exit(1);
}
//打开音频解码器
if (avcodec_open(aCodecCtx,aCodec)<0)
{
printf("cannot open the audio decoder\n");
exit(1);
}
AVPicture *pt;
//img_convert(pt,1,pt,1,22,22);
/* initialize libavcodec, and register all codecs and formats */
const char* filename_out="aa1.mpg";
AVOutputFormat *fmt;
AVFormatContext *oc;
AVCodecContext *oVcc,*oAcc;
AVCodec *oVc,*oAc;
AVStream *video_st,*audio_st;
AVFrame *oVFrame,*oAFrame;
double video_pts;
oVFrame=avcodec_alloc_frame();
fmt=guess_format(NULL,filename_out,NULL);
if (!fmt)
{
printf("could not deduce output format out file extension\n");
exit(0);
}
oc=av_alloc_format_context();
if (!oc)
{
printf("memmory error!\n");
exit(0);
}
oc->oformat=fmt;
strncpy(oc->filename,filename_out,sizeof(oc->filename));
video_st=av_new_stream(oc,0);
if (!video_pts)
{
printf("can not alloc video stream\n");
exit(0);
}
oVcc=avcodec_alloc_context();
oVcc=video_st->codec;
oVcc->codec_id=vCodeCtx->codec_id;
oVcc->codec_type=vCodeCtx->codec_type;
oVcc->bit_rate=vCodeCtx->bit_rate;
oVcc->width=vCodeCtx->width;
oVcc->height=vCodeCtx->height;
oVcc->time_base=vCodeCtx->time_base;
oVcc->gop_size=vCodeCtx->gop_size;
oVcc->pix_fmt=vCodeCtx->pix_fmt;
oVcc->max_b_frames=vCodeCtx->max_b_frames;
video_st->r_frame_rate=ic->streams[videoindex]->r_frame_rate;
audio_st=av_new_stream(oc,oc->nb_streams);
if (!audio_st)
{
printf("could not alloc audio stream");
exit(0);
}
avcodec_get_context_defaults2(audio_st->codec,CODEC_TYPE_AUDIO);
oAcc=avcodec_alloc_context();
oAcc=audio_st->codec;
oAcc->codec_id=aCodecCtx->codec_id;
oAcc->codec_type=aCodecCtx->codec_type;
oAcc->bit_rate=aCodecCtx->bit_rate;
oAcc->sample_rate=aCodecCtx->sample_rate;
oAcc->channels=2;
//设置输出的必要参数
if (av_set_parameters(oc,NULL)<0)
{
printf("invalid output format parameters\n");
exit(0);
}
strcpy(oc->title,ic->title);
strcpy(oc->author,ic->author);
strcpy(oc->copyright,ic->copyright);
strcpy(oc->album,ic->album);
oc->bit_rate=ic->bit_rate;
oc->year=ic->year;
oc->track=ic->track;
oc->timestamp=ic->timestamp;
strcpy(oc->genre,ic->genre);
//列出输出文件的相关信息
dump_format(oc,0,filename_out,1);
//查找编码器
oVc=avcodec_find_encoder(vCodeCtx->codec_id);
if (!oVc)
{
printf("cannot find suitable video codec\n");
exit(0);
}
//打开视频编码器
if (avcodec_open(oVcc,oVc)<0)
{
printf("can not open the output video codec\n");
exit(0);
}
//查找音频解码器
oAc=avcodec_find_encoder(aCodecCtx->codec_id);
if (!oAc)
{
printf("can not find suitable audio encoder\n");
exit(1);
}
//打开音频解码器
if (avcodec_open(oAcc,oAc)<0)
{
printf("cannot open the output audio codec\n");
exit(0);
}
if (!oc->nb_streams)
{
fprintf(stderr,"output file does not contain any stream\n");
exit(1);
}
if (!(oc->flags&AVFMT_NOFILE))
{
if (url_open((struct URLContext**)&oc->pb,filename_out,URL_WRONLY)<0)
{
fprintf(stderr,"can not open output file %s\n",filename_out);
exit(0);
}
}
//写文件的头
if (av_write_header(oc)<0)
{
fprintf(stderr,"could not write header for output file\n");
exit(1);
}
//分配输出视频和音频空间
AVPacket pack;
uint8_t *ptr;
short *out_buf;
int out_size;
static short*samples=NULL;
static unsigned int sample_size=0;
uint8_t *video_outbuf,*audio_outbuf;
int video_outbuf_size,audio_outbuf_size;
video_outbuf_size=400000;
video_outbuf=(unsigned char *)malloc(video_outbuf_size);
audio_outbuf_size=10000;
audio_outbuf=(uint8_t*)av_malloc(audio_outbuf_size);
int flag;
int frameFinished,len,frame_index=0,ret;
//
// Allocate an AVFrame structure
AVFrame *pFrameRGB=avcodec_alloc_frame();
AVFrame *pFrameEnc;
pFrameEnc= avcodec_alloc_frame();
if(pFrameRGB==NULL)
return -1;
// Determine required buffer size and allocate buffer
int numBytes=avpicture_get_size(PIX_FMT_RGB24, oVcc->width,
oVcc->height);
unsigned char* bufferRGB=(unsigned char *)malloc(numBytes);
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)pFrameRGB, bufferRGB, PIX_FMT_RGB24,
oVcc->width, oVcc->height);
/* auto detect the output format from the name. default is
mpeg. */
fmt = guess_format(NULL, filename_out, NULL);
if (!fmt) {
printf("Could not deduce output format from file extension: using MPEG.\n");
fmt = guess_format("mpeg", NULL, NULL);
}
if (!fmt) {
fprintf(stderr, "Could not find suitable output format\n");
exit(1);
}
/* allocate the output media context */
oc = av_alloc_format_context();
if (!oc) {
fprintf(stderr, "Memory error\n");
exit(1);
}
oc->oformat = fmt;
_snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
/* add the audio and video streams using the default format codecs
and initialize the codecs */
video_st = NULL;
audio_st = NULL;
if (fmt->video_codec != CODEC_ID_NONE) {
video_st = add_video_stream(oc, fmt->video_codec);
}
if (fmt->audio_codec != CODEC_ID_NONE) {
audio_st = add_audio_stream(oc, fmt->audio_codec);
}
/* set the output parameters (must be done even if no
parameters). */
if (av_set_parameters(oc, NULL) < 0) {
fprintf(stderr, "Invalid output format parameters\n");
exit(1);
}
dump_format(oc, 0, filename_out, 1);
/* now that all the parameters are set, we can open the audio and
video codecs and allocate the necessary encode buffers */
if (video_st)
open_video(oc, video_st);
if (audio_st)
open_audio(oc, audio_st);
/* open the output file, if needed */
if (!(fmt->flags & AVFMT_NOFILE)) {
if (url_fopen(&oc->pb, filename_out, URL_WRONLY) < 0) {
fprintf(stderr, "Could not open '%s'\n", filename_out);
exit(1);
}
}
/* write the stream header, if any */
av_write_header(oc);
i=0;
/
//读取输入视频,进行处理再输出
/
while (av_read_frame(ic,&pack)>=0)//从输入文件读取一个包
{
if (pack.stream_index==videoindex)//判断是否为当前视频流中的包
{
len=avcodec_decode_video(vCodeCtx,oVFrame,&frameFinished,pack.data,pack.size);
//
if (len<0)
{
printf("error while decoding\n");
exit(0);
}
if (frameFinished)
{
pFrameEnc->data[0] = oVFrame->data[0];
pFrameEnc->data[1] = oVFrame->data[1];
pFrameEnc->data[2] = oVFrame->data[2];
pFrameEnc->linesize[0] = oVFrame->linesize[0];
pFrameEnc->linesize[1] = oVFrame->linesize[1];
pFrameEnc->linesize[2] = oVFrame->linesize[2];
if (oc->oformat->flags & AVFMT_RAWPICTURE)
{
/* raw video case. The API will change slightly in the near
futur for that */
AVPacket pkt;
av_init_packet(&pkt);
pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= video_st->index;
pkt.data= (uint8_t *)pFrameEnc->data;
pkt.size= sizeof(AVPicture);
//write_video_frame(oc,video_st);
// av_write_frame(oc, &pkt);
}
else {
// encode the image
// Convert the image into YUV format that SDL uses
static struct SwsContext *img_convert_ctx;
if(img_convert_ctx == NULL) {
int w = oVcc->width;
int h = oVcc->height;
img_convert_ctx = sws_getContext(w, h,
oVcc->pix_fmt,
w, h, PIX_FMT_RGB24, SWS_BICUBIC,
NULL, NULL, NULL);
if(img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
}
}
int ret = sws_scale(img_convert_ctx, oVFrame->data, oVFrame->linesize, 0,
oVcc->height, pFrameRGB->data, pFrameRGB->linesize);
#if 0 // this use to be true, as of 1/2009, but apparently it is no longer true in 3/2009
if(ret) {
fprintf(stderr, "SWS_Scale failed [%d]!\n", ret);
exit(-1);
}
#endif
//GetVesselConter(pFrameRGB, oVcc->width, oVcc->height, i++);
//该函数是对pFrameRGB一帧图像进行处理的函数,读者可以根据自己的意愿进行修改~
//将RGB转回YUV进行显示
static struct SwsContext *rgb_convert_yuv_ctx=NULL;
if(rgb_convert_yuv_ctx == NULL) {
int w = oVcc->width;
int h = oVcc->height;
rgb_convert_yuv_ctx = sws_getContext(w, h,
PIX_FMT_RGB24, w, h, PIX_FMT_YUV420P, SWS_BICUBIC,NULL, NULL, NULL);
if(rgb_convert_yuv_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
}
}
sws_scale(rgb_convert_yuv_ctx,pFrameRGB->data, pFrameRGB->linesize, 0, oVcc->height,
oVFrame->data, oVFrame->linesize);
out_size = avcodec_encode_video(oVcc, (unsigned char*)video_outbuf, video_outbuf_size, pFrameEnc);
pack.data=video_outbuf;
pack.size=out_size;
// if zero size, it means the image was buffered
if (out_size != 0) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.pts= oVcc->coded_frame->pts;
if(oVcc->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= video_st->index;
pkt.data= (unsigned char*)video_outbuf;
pkt.size= video_outbuf_size;
// write the compressed frame in the media file
// write_video_frame(oc,video_st);
// av_write_frame(oc, &pkt);
// av_write_frame(oc, &pkt);
av_write_frame(oc,&pack);
}
}//if videoindex
}
}
av_free_packet(&pack);
}
/* write the trailer, if any. the trailer must be written
* before you close the CodecContexts open when you wrote the
* header; otherwise write_trailer may try to use memory that
* was freed on av_codec_close() */
av_write_trailer(oc);
/* close each codec */
if (video_st)
close_video(oc, video_st);
if (audio_st)
close_audio(oc, audio_st);
/* free the streams */
for(i = 0; i < oc->nb_streams; i++) {
av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]);
}
if (!(fmt->flags & AVFMT_NOFILE)) {
/* close the output file */
url_fclose(oc->pb);
}
/* free the stream */
av_free(oc);
return 0;
}