注:本教程默认您已经配置好vscode的C++开发环境,如果没有,请先看我的另一篇文章:https://blog.csdn.net/qq_45807140/article/details/112862592
选择ffmpeg4.4版本,这个版本似乎是一个承前启后的版本,兼容了旧的接口,能运行雷神的代码
下载方法:
进入官网,选择Windows builds by BtbN,从而进入git的release页面(如果点击其他下载链接,要么看不到版本号,要么就不是开发包而是仅有可执行文件)
展开Assets,选择最新的n4.4-shared版本,至于是选lgpl还是gpl看具体应用场景。(一定要选share版本,这个版本中才有开发库)
下载完成后,将bin、include、lib三个文件夹拷贝到自己的项目中去。bin中存放的是动态链接库(.dll)以及三个可执行文件(这三个对开发没用,可以删了);include中存放的是各种头文件(.h);lib中存放的是静态链接库(.lib,.a等)
进入官网,选择SDL releases,在development librarise下选择VC版的版本(我一开始下了MinGW的版本,发现始终无法在VScode上编译通过,换成VC版本后才成功。两者的区别应该在于链接库的格式,VC版中库文件是.lib格式,MinGW版中库文件是.a格式,这两种格式都是静态链接库,至于有什么不同我还没太搞懂,只知道似乎.a常用在linux系统中而.lib常用在win系统中)
下载完成后,先将include文件夹拷贝到自己的项目中去。然后进入lib文件夹,可以看到分成了x64和x86两个文件夹,这里似乎是要根据编译器的版本来选择的(我的MInGW以及操作系统都是64位的,故选择x64),将选好的文件作为lib文件夹拷贝到项目中。
在整个配置过程中,我使用了雷神的“最简单的基于FFMPEG+SDL的视频播放器 ver2”代码来排错,能跑通该程序则说明配置成功。
将代码拷贝到自己的VScode后,就能看到项目中出现”找不到头文件“的报错,由于include后并没有写全路径名,因此vscode并不知道去哪儿找这些头文件。进入c_cpp_properties.json配置文件,在includePath中添加ffmpeg与SDL的include文件夹路径("includePath"负责文本编辑器中代码的头文件查找)
我们还能看到如下报错
转到这些标识符的定义后,发现他们都是ffmpeg和SDL头文件中的宏定义。原因在于vscode不会递归地去检索头文件,需在settings.json配置文件中加入两个语句,强制intellisense使用Tag Parser,递归地检索头文件。(参考:https://blog.csdn.net/qq_43784626/article/details/111638186?spm=1001.2014.3001.5502)
至此,暂时没有报错了。但还是能看到一些警告
简单来说就是在你代码中使用的XXX函数已经被弃用了。因为雷神的代码比较早,现在的ffmpeg的接口已经发生了变化,不再适用。但好在这只是警告,也就是说,4.4版本的ffmpeg依旧支持旧的接口,只是提示我们应当用新接口替换这些接口。这里先无视警告。
尝试编译运行,发现编译失败,报错”fatal error: libavcodec/avcodec.h: No such file or directory“,即找不到头文件。原因在于c_cpp_properties.json的"includePath"只是告诉vscode插件在哪里找到头文件,便于进行源码查看和debug,但并没有告诉gcc编译器这个路径。所以vscode编辑器看起来没有错误但是gcc编译器找不到新增的"includePath",这个错实际上是编译器报出来的。tasks.json的"args"规定了编译器的编译指令中所带的参数,我们可以在指令中加入“-I include路径”参数,以此告知编译器头文件的位置。(参考:https://www.zhihu.com/question/373745969/answer/1581576356)
再次尝试运行,依旧编译失败,但此时”问题“区没有显示错误,代码中也不显示错误波形曲线,因为从vsocde编辑器的角度来说确实没有问题了,问题是出在编译过程中,因此此时的错误信息在”终端“中。对于这种情况,我们首先应该根据终端中gcc的错误信息来定位并解决错误,如果仅凭该错误信息无法定位错误(一般都能定位),还可以采用一种笨方法:把代码段全部注释,然后按模块逐步取消注释,看是那个模块出了问题。
这里,gcc给出了如下错误信息
回忆一下,除了头文件,我们还拷贝了动态链接库和静态链接库,而我们还没有针对这两者做任何配置,因此问题就出在它们身上。
静态库配置:
在c_cpp_properties.json中加入以下字段。(没搞懂什么作用,感觉是用来告诉vscode编辑器静态库的位置,但实际上经自己验证没有这个字段好像也没影响,不过姑且加上)
在tasks.json的“args”下增加如下参数。-L指向你要引入的静态库的存储位置,-l(小写的L)指向你要引入的静态库名称,-l会自动搜寻-L路径下的lib开头的文件,建议将 -l 和名称直接连用(即 -lxxx),此外使用-l选项指明静态库的名字时,既不需要lib前缀,也不需要.a后缀(gcc会自动补上前后缀),所以如果要匹配的文件是libavutil.lib,应写成”-lavutil“。另外,经试验,-L与lib路径不能合在一起写,-I(大写的I)与include路径也不能合在一起写。(参考(各参考了一部分,都不全对):https://blog.csdn.net/a1561067921/article/details/88796413;http://c.biancheng.net/view/8020.html;http://c.biancheng.net/view/7168.html)
动态库配置
在launch.json文件中增加如下字段。要将动态库load进来,Linux会查找LD_LIBRARY_PATH环境变量,而Windows会查找PATH环境变量。PATH环境变量用于在程序编译期间查找动态链接库时指定查找共享库的路径,例如,指定gcc编译需要用到的动态链接库的目录。为了方便(不知道怎么指定两个动态库目录),我将ffmpeg以及SDK的动态库复制到了同一个文件夹all_dll中。此外,也可以不做任何配置,直接把.dll文件放在与主程序相同的目录下,主程序运行时就会自动连接这些动态库。(参考:http://www.manongjc.com/detail/20-swxpwtbfzaoekzs.html;https://www.cnblogs.com/sinferwu/p/15176094.html;https://blog.csdn.net/fuck487/article/details/75089052)
{
"version": "0.2.0",
"configurations": [
{
"name": "g++.exe - 生成和调试活动文件",
"preLaunchTask": "C/C++: g++.exe build active file",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name": "PATH",
"value": "${workspaceFolder}/all_dll"
}
],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "D:\\mingw-w64\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
{
"cSpell.words": [
"stoi"
],
"C_Cpp.intelliSenseEngineFallback": "Disabled",
"C_Cpp.intelliSenseEngine": "Tag Parser"
}
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/ffmpeg4.4_lib/include",
"${workspaceFolder}/SDL2.0.22_lib/include"
],
"browse": {
"path": [
"${workspaceRoot}",
"${workspaceFolder}/ffmpeg4.4_lib/lib",
"${workspaceFolder}/SDL2.0.22_lib/lib"
]
},
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "gcc-x64",
"compilerPath": "D:\\mingw-w64\\mingw64\\bin\\g++.exe"
}
],
"version": 4
}
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe build active file",
"command": "D:\\mingw-w64\\mingw64\\bin\\g++.exe",
"args": [
"-g",
"${file}",
"-L", /*注意,这里指定库的lib目录,自动生成的默认配置文件没有此项*/
"${workspaceFolder}/ffmpeg4.4_lib/lib",
"-L",
"${workspaceFolder}/SDL2.0.22_lib/lib",
"-I", /*注意,这里指定库的include目录,自动生成的默认配置文件没有此项*/
"${workspaceFolder}/ffmpeg4.4_lib/include",
"-I",
"${workspaceFolder}/SDL2.0.22_lib/include",
"-lSDL2main", /*注意,这里指定要引入的静态库,自动生成的默认配置文件没有此项*/
"-lSDL2",
"-lSDL2test",
"-lavcodec",
"-lavdevice",
"-lavfilter",
"-lavformat",
"-lavutil",
"-lswresample",
"-lswscale",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "D:\\mingw-w64\\mingw64\\bin"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "compiler: D:\\mingw-w64\\mingw64\\bin\\g++.exe"
}
]
}