FFmpeg vc 入门

来源:互联网 发布:java classloader使用 编辑:程序博客网 时间:2024/05/17 06:42
首先关于ffmpeg函数我们需要的文件,我是下载FFmpeg-full-SDK-3.2.rar,官网上一般都有。下载得到ffmpeg开发包,解压开发包得到三个文件夹:lib 、include 、bin。

   下面对于得到的文件如何处理:

   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 <limits.h>
 //#include "opt.h"
#include <assert.h>

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


原创粉丝点击