在visual studio 2010中调用ffmpeg

来源:互联网 发布:端口映射端口号 编辑:程序博客网 时间:2024/05/16 19:27

在visual studio 2010中调用ffmpeg

(2012-07-31 16:57:12)
转载
标签:

编程

visual

studio

2010

ffmpeg

 
   最近几天一直在折腾ffmpeg,在网上也查了许多资料,费了不少劲,现在在这里和大家分享一下。
一、准备工作
   本来是想自己在windows下编译ffmpeg生成lib、dll等库文件的,但是折腾好久总是出错,于是果断放弃。幸好网上已经有了编译好的版本,可以拿过来直接用,网址为http://ffmpeg.zeranoe.com/builds/。我们需要的是32-bitBuilds (Shared)和32-bit Builds (Dev),版本号要相对应。32-bit Builds(Shared)主要包含了所要用到的dll文件,32-bit Builds(Dev)主要包含了所要用的头文件和lib文件。其实这些lib并不是传统的静态库文件(真正的静态库文件是在lib目录下的*.a文件),他们是dll的导出文件。dll文件在32-bitBuilds (Shared)的bin目录下,lib文件在32-bit Builds(Dev)的lib目录下,头文件在32-bitBuilds (Dev)的include目录下。
   另外,C99中添加了几个新的头文件,VisualStudio中没有,所以需要你自己下载。并放至相应目录。对于VS2010来说通常是:C:\Program Files(x86)\Microsoft Visual Studio 10.0\VC\include。
二、Visual Studio配置
   在准备好库文件之后,便可以进行VisualStudio简单的编译工作了,下面给出一份当前可以编译运行的代码,并以此为示例。
// ffmpeg-example.cpp : Defines the entry point for theconsole application.
//
//#include "stdafx.h"
 
#define inline _inline
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
   
#include<libavformat/avformat.h>
#include<libavcodec/avcodec.h>
#include<libswscale/swscale.h>
#ifdef __cplusplus
}
#endif
 
#include <stdio.h>
 
 
static void SaveFrame(AVFrame *pFrame, int width, int height,int iFrame);
 
int main (int argc, const char * argv[])
{
    AVFormatContext*pFormatCtx;
    int           i, videoStream;
    AVCodecContext *pCodecCtx;
    AVCodec       *pCodec;
    AVFrame       *pFrame; 
    AVFrame       *pFrameRGB;
    AVPacket      packet;
    int           frameFinished;
    int           numBytes;
    uint8_t       *buffer;
 
    // Register all formatsand codecs
    av_register_all();
 
    // Open video file
   //if(avformat_open_input(&pFormatCtx, argv[1],NULL, NULL)!=0)
if(avformat_open_input(NULL, argv[1], NULL, NULL)!=0)
       return -1; // Couldn't open file
 
    // Retrieve streaminformation
   if(av_find_stream_info(pFormatCtx)<0)
       return -1; // Couldn't find streaminformation
 
    // Dump informationabout file onto standard error
   av_dump_format(pFormatCtx, 0, argv[1], false);
 
    // Find the first videostream
    videoStream=-1;
    for(i=0;i<pFormatCtx->nb_streams; i++)
      if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
       {
          videoStream=i;
          break;
       }
       if(videoStream==-1)
           return -1;// Didn't find a video stream
 
       // Get a pointer to the codec context for thevideo stream
      pCodecCtx=pFormatCtx->streams[videoStream]->codec;
 
       // Find the decoder for the video stream
      pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
       if(pCodec==NULL)
           return -1;// Codec not found
 
       // Open codec
       if(avcodec_open(pCodecCtx,pCodec)<0)
           return -1;// Could not open codec
 
       // Hack to correct wrong frame rates that seemto be generated by some codecs
      if(pCodecCtx->time_base.num>1000&&pCodecCtx->time_base.den==1)
          pCodecCtx->time_base.den=1000;
 
       // Allocate video frame
       pFrame=avcodec_alloc_frame();
 
       // Allocate an AVFrame structure
       pFrameRGB=avcodec_alloc_frame();
       if(pFrameRGB==NULL)
           return-1;
 
       // Determine required buffer size and allocatebuffer
       numBytes=avpicture_get_size(PIX_FMT_RGB24,pCodecCtx->width,
          pCodecCtx->height);
 
       //buffer=malloc(numBytes);
       buffer=(uint8_t*)av_malloc(numBytes*sizeof(uint8_t));
 
       // Assign appropriate parts of buffer to imageplanes in pFrameRGB
       avpicture_fill((AVPicture *)pFrameRGB, buffer,PIX_FMT_RGB24,
          pCodecCtx->width,pCodecCtx->height);
 
       // Read frames and save first five frames todisk
       i=0;
       while(av_read_frame(pFormatCtx,&packet)>=0)
       {
           // Is thisa packet from the video stream?
          if(packet.stream_index==videoStream)
           {
              // Decode video frame
             avcodec_decode_video2(pCodecCtx, pFrame,&frameFinished, &packet);
 
              // Did we get a videoframe?
              if(frameFinished)
              {
                 static struct SwsContext *img_convert_ctx;
 
#if 0
                 // Older removed code
                 // Convert the image from its native format toRGB swscale
                 img_convert((AVPicture *)pFrameRGB,PIX_FMT_RGB24, 
                    (AVPicture*)pFrame, pCodecCtx->pix_fmt,pCodecCtx->width, 
                    pCodecCtx->height);
 
                 // function template, for reference
                 int sws_scale(struct SwsContext *context,uint8_t* src[], int srcStride[], int srcSliceY,
                     intsrcSliceH, uint8_t* dst[], int dstStride[]);
#endif
                 // Convert the image into YUV format that SDLuses
                 if(img_convert_ctx == NULL) {
                     int w =pCodecCtx->width;
                     int h =pCodecCtx->height;
 
                    img_convert_ctx = sws_getContext(w, h, 
                       pCodecCtx->pix_fmt, 
                        w, h, PIX_FMT_RGB24,SWS_BICUBIC,
                        NULL, NULL, NULL);
                    if(img_convert_ctx == NULL) {
                        fprintf(stderr, "Cannotinitialize the conversion context!\n");
                        exit(1);
                     }
                 }
                 int ret = sws_scale(img_convert_ctx,pFrame->data, pFrame->linesize,0, 
                    pCodecCtx->height, pFrameRGB->data,pFrameRGB->linesize);
#if 0 
                 // this use to be true, as of 1/2009, butapparently it is no longer true in 3/2009
                 if(ret) {
                    fprintf(stderr, "SWS_Scale failed [%d]!\n", ret);
                    exit(-1);
                 }
#endif
                 // Save the frame to disk
                 if(i++<=5)
                    SaveFrame(pFrameRGB, pCodecCtx->width,pCodecCtx->height, i);
              }
           }
 
           // Freethe packet that was allocated by av_read_frame
          av_free_packet(&packet);
       }
 
       // Free the RGB image
       //free(buffer);
       av_free(buffer);
       av_free(pFrameRGB);
 
       // Free the YUV frame
       av_free(pFrame);
 
       // Close the codec
       avcodec_close(pCodecCtx);
 
       // Close the video file
       av_close_input_file(pFormatCtx);
 
       return 0;
}
 
static void SaveFrame(AVFrame *pFrame, int width, int height,int iFrame)
{
    FILE *pFile;
    charszFilename[32];
    int y;
 
    // Open file
    sprintf(szFilename,"frame%d.ppm", iFrame);
    pFile=fopen(szFilename,"wb");
    if(pFile==NULL)
       return;
 
    // Write header
    fprintf(pFile, "P6\n%d%d\n255\n", width, height);
 
    // Write pixeldata
    for(y=0;y<height; y++)
      fwrite(pFrame->data[0]+y*pFrame->linesize[0],1, width*3, pFile);
 
    // Close file
    fclose(pFile);
}
首先在VisualStudio中新建工程,并将代码添加到工程的.cpp文件中。其次,就要配置工程的库文件和链接器。
1. 设置ffmpeg头文件位置
鼠标右键点击工程名,选择属性
在visual <wbr>studio <wbr>2010中调用ffmpeg
然后选择 配置属性 -> C/C++ -> 常规-> 附加包含目录,添加目录为你下载的32-bit Builds (Dev)中的头文件目录。
在visual <wbr>studio <wbr>2010中调用ffmpeg

2.设置ffmpeg的lib文件位置 
鼠标右键点击工程名,选择属性,然后选择 配置属性 -> 链接器-> 常规 ->附加库目录,添加目录为你下载的32-bitBuilds (Dev)中的lib文件目录。 
在visual <wbr>studio <wbr>2010中调用ffmpeg

3.设置ffmpeg的所引用的lib文件 
鼠标右键点击工程名,选择属性, 然后选择 配置属性 -> 链接器-> 输入 ->附加依赖项,添加的文件为你下载的32-bitBuilds (Dev)中的lib文件。 
在visual <wbr>studio <wbr>2010中调用ffmpeg

如果一切正常,这时你便可以编译成功。

三、可能出现的问题
1. 虽然编译通过,但是并不表示就可以运行,当你运行代码时会出现以下错误
在visual <wbr>studio <wbr>2010中调用ffmpeg

原因是,你虽然引用了LIB文件,但这并不是真正的静态库文件,而是对DLL的引用,所以当你调用ffmpeg库函数时,需要DLL文件在场。你可以用dumpbin(VS自带工具)来查看你生成的exe中引用了哪些DLL文件。你在命令行输入:
>dumpbin D:\test\test.exe /imports
然后根据显示的文件名,将下载的32-bit Builds(Shared)的bin文件夹下的dll文件拷贝到你新建的工程的源文件目录下。
在visual <wbr>studio <wbr>2010中调用ffmpeg

2. 上段代码中的变量argv[1],如果你没有指定参数,则会报错。所以如果不指定,则需要将其改为一个const char*的字符串变量,字符串内容为你想读入的视频的全路径,例如
const char* filename ="D:\\work\\code\\VideoConference\\test\\IMGP1816.AVI";

上述都配置完毕就可以运行了,暂时先写这么多吧,后面我会继续总结的。
0 0
原创粉丝点击