在VC2010下编译ffmpeg.c(版本2.1.4)

来源:互联网 发布:cos女装官网旗舰店淘宝 编辑:程序博客网 时间:2024/05/16 18:38

经过N天的折腾,今天终于把ffmpeg.c这个文件编译过了,经试验与官方的一致。下面总结一些要点如下:


1、从 http://www.ffmpeg.org/download.html
下载官方的ffmpeg原文件,这一堆原文件本质上是for linux的,而我并不是想编译整个ffmpeg,我想要的只是其中的某些头文件,以及步骤3中的那些源文件。


2、从http://ffmpeg.zeranoe.com/builds/ 
下载官方提供的for win32的头文件和lib和dll。这里我有点不解的是,此处的头文件不全,这也是为什么我们需要第一步的原因。


3、 生成 config.h
这一步其实很折腾的,需要安装mingw,msys,yasm等工具软件,然后进入到mingw命令行下执行./configure命令,参数有点复杂要讲就讲远了,看客需要自己百度。执行后会生成一个config.h文件。这个文件中定义了一堆开关宏用于指示你编译时打开什么选项。把下面两个选项关闭:

#define CONFIG_AVDEVICE 0
#define CONFIG_AVFILTER 0


在config.h里面加上
#define PRIu64       "I64u"
#define PRId64       "I64d"


4、新建vc2010 console空工程,把ffmpeg.h,ffmpeg.c,cmdutils.c,cmdutils.h,cmdutils_common_opts.h,ffmpeg_filter.c,ffmpeg_opt.c加到工程。因为vc2010的c编译器是老掉牙的C89标准,而ffmpeg用的是较新的C99标准,所以很多地方需要我们手工改代码。
在工程中建一个include目录,把第二步下载的那些头文件放到这里。在工程中建一个lib目录,把第二步下载的那些lib文件放到这里。还有dll文件,放到编译时生成的debug和release目录下


5、从mingw下复制inttypes.h到系统目录下:C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include。如果你用的是VC2010以下的版本,还需要拷贝stdint.h这个文件。




6、 把.h里的inline换成__inline

#if defined(WIN32) && !defined(__cplusplus)
#define inline __inline
#endif

project->[setting]->[c/c++]->Preprocessor definitions:编辑框里输入inline=__inline
解释:inline在C99标准中是一个关键字,但是在C89中还不是,VC采用的是__inline,所以。。。。。。


7、试着编译一次,会有很多错误,不急,我们慢慢来搞定它们。最低级的错误是找不到XXX.h文件,那么你就到第一步下载的那一堆原码中去找,然后拷贝到include下对应的目录。


8、如果遇到winstock.h与win2def.h重定义报错,说明你头文件顺序有错,windows.h文件要放到winstock.h后面。


9、遇到有些函数找不到,可能是config.h中的开关宏的问题,试着打开或关闭之,比如
#define HAVE_LOG2 0
刚开始是1,导致找不到log2函数,改为0就好了。


10、宏AV_TIME_BASE_Q是一个烦人的东西,它在avutil.h文件中,ffmpeg中太多地方使用它了,我们看看它的定义:
#define AV_TIME_BASE_Q          (AVRational){1, AV_TIME_BASE}
这显然不符合VC的写法,我采用这个办法:在用到AV_TIME_BASE_Q 的地方,手写AVRational r = {1,AV_TIME_BASE };,再用上这个r.


11、在文件ffmpeg_opt.c中,有const OptionDef options[] 这个数组的初值处理,主要是里面的函数,参考ffmpeg_vc5的代码,把每一行改成这样:{ "f",  HAS_ARG | OPT_STRING | OPT_OFFSET,   { (void*)OFFSET(format) },
就是把原来函数的地方{.fun = xxx}改成 {(void*)xxx}。编译通过了,常规的一些输入参数都好用。
文件cmdutils_common_opts.h文件也一样


12、还有一个在timestamp.h文件中定义了两个C99标准的宏:
#define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts)
#define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb)
这两个宏在VC2010中都是无法使用的,我尝试了几种变种的宏都没搞定,最后我笨办法,修改ffmpeg.c中所有用到的地方,把他们改为先定义char数组,再直接使用av_ts_make_string函数或av_ts_make_time_string函数。


13、在ffmpeg_filter.c文件中也有一处难懂的C99语法,就是第一个函数choose_pixel_fmt,里面有一个enum指针:
p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE };
从没见过这种用法,怎么办,改:
在函数开关定义:
const enum AVPixelFormat avp1[5] = { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE };

const enum AVPixelFormat avp2[8] = { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P,
 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE };
然后在使用的时候赋值:
p = avp1;


14、最后是引用lib文件:
#pragma comment(lib,"../lib/avutil.lib")  
#pragma comment(lib,"../lib/avcodec.lib")  
#pragma comment(lib,"../lib/avformat.lib")  
#pragma comment(lib,"../lib/avfilter.lib") 
#pragma comment(lib,"../lib/swscale.lib") 
//#pragma comment(lib, "../lib/SDL.lib") //编译ffplay时需要
//#pragma comment(lib, "../lib/SDLmain.lib") //编译ffplay时需要
#pragma comment(lib, "../lib/swresample.lib")
#pragma comment(lib, "../lib/postproc.lib")
#pragma comment(lib, "../lib/unistdd.lib")
#pragma comment(lib,"Psapi.lib")


15、到此,ffmpeg.exe应该可以编译出来了。顺便多讲两句,如果要编译ffplay也差不多,但记得下载SDL的1.2.15版,我开始下载最新的2-2.0.1版本发现用不了。


先写这么多,以后想到了再添加。有问题请联系QQ4991464

0 0