从零开始,VS2010中ffmpeg中samples代码的成功运行

来源:互联网 发布:ubuntu 16.04 apache2 编辑:程序博客网 时间:2024/05/07 16:53

从http://ffmpeg.zeranoe.com/builds/  下得ffmpeg的windows的builds

里面有3个版本,

Static:   只有*.exe文件

Shared: 有*.exe与*.dll

Dev:      有*.lib、*.def、还有mingw用的*.a

但是vs同时需要lib,与dll,所以把Shared与Dev都下载下来(Dev提供的是动态链接库的lib文件,Shared提供了dll文件)

1、在vs2008新建工程,

2、将ffmpeg-20130217-git-b8bb661-win32-dev\doc\examples下的编解码samples代码

decoding_encoding.c内容复制到工程中新建的decode_encode.cpp中

然后将ffmpeg-20130217-git-b8bb661-win32-dev下的include和lib文件夹都复制到工程目录下

3、将ffmpeg-20130217-git-b8bb661-win32-shared\bin下的dll文件也拷贝到工程目录下

剪贴板20131322134612111.jpgv

4、在工程属性中添加  附加工程目录:include 附加库目录:lib

在链接器输入中加入

avcodec.lib;avformat.lib;avutil.lib;swscale.lib;swresample.lib;avfilter.lib;

5、编译,发现找不到<stdint.h>,原因貌似是vs2008之前的编译器都不是c99的,所以没有这个文件

有网友提供了解决办法,如注释再添加定义:

剪贴板20131322133837075.jpg

http://blog.csdn.net/lights_joy/article/details/3500570

或者定义宏来绕过该文件,http://www.cnblogs.com/verygis/archive/2012/04/22/2465561.html

或者从别的地方拷贝来对应文件,如官方提供的方案

http://ffmpeg.org/platform.html#Linking-to-FFmpeg-with-Microsoft-Visual-C_002b_002b

本质都是一样的方法。

考虑到后面可能会出现另外的麻烦,所以就直接换了vs2010来编译

按照上面1-4的步骤新建vs2010的工程,然后

5、编译,会有些错误,如

(1)void*转uint16_t*的错误,强制转换即可

samples = (uint16_t*)av_malloc(buffer_size);

(2)video_encode_example的第二个参数codec_id 是枚举不能是int,改为AVCodecID codec_id即可

(3)  c->time_base = AVRational {1,25} 初始化结构体语法错误,不能那样写,要改成

AVRational avrational;
avrational.num=1;
avrational.den=25;
 c->time_base= avrational;

(4)比较麻烦的错误是,编译成功后链接错误,这个问题是因为我们这里采用的是CPP文件的原因,

剪贴板20131322135432196.jpg

改成c文件,应该可以链接成功,但是会出现新的编译错误,如inline的定义,要改ffmpeg的头文件 而且不能用c++的东西了,这个代价太大 ,理想的办法还是使用cpp

其实这个问题的根源还是在于ffmpeg是用c语音编写的库,在c++编译的时候会有函数重命名(函数重载的关键实现技术),所以链接的时候自然找不到对应的函数了,解决办法很简单,给所有ffmpeg头文件加入extern "C"声明,如下

#ifdef __cplusplus
extern "C" {
#endif

#include "libavformat/avformat.h"
#include <math.h>
#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>

#ifdef __cplusplus
}
#endif

这样就可以链接通过,在debug下能运行,如下

剪贴板20131322135844282.jpg

还有一个问题就是在release模式下,生成的exe不能运行,调试的时候发现在main中调用外部库的函数avcodec_register_all();时就出错了,使用vc的dumpbin工具也可以发现,release版本的exe缺少对导入函数位置的声明

dumpbin testCodec.exe /imports 得到下面两个对比结果(左边是debug版本,右边是release版本)

剪贴板20131422140143497.jpg

后来在Zernaoe FFmpeg网站的论坛上找到解决方法

http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=5&t=888&p=3481&hilit=vs2010#p3481

即从Shared中的dll重新导出lib文件,

步骤是先把dll文件和Dev中的def拷贝在一起,运行下面的批处理即可生成新的lib文件

call "C:\tool\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
lib /MACHINE:X86 /DEF:avcodec-54.def
lib /MACHINE:X86 /DEF:avdevice-54.def
lib /MACHINE:X86 /DEF:avfilter-3.def
lib /MACHINE:X86 /DEF:avformat-54.def
lib /MACHINE:X86 /DEF:avutil-52.def
lib /MACHINE:X86 /DEF:postproc-52.def
lib /MACHINE:X86 /DEF:swresample-0.def
lib /MACHINE:X86 /DEF:swscale-2.def
pause