vs版本:2017
操作系统:win10
webrtc版本:4577
成果物要求: x64的可被vs引入的webrtc库
第一:找个
公司有提供客户端工具,工具启动的端口号是10080
第二:webrtc下载
1.首先打开cmd,输入如下内容
set http_proxy=http://127.0.0.1:10080
set https_proxy=http://127.0.0.1:10080
set DEPOT_TOOLS_UPDATE=0
set DEPOT_TOOLS_WIN_TOOLCHAIN=0
set GYP_MSVS_OVERRIDE_PATH=D:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise
set GYP_MSVS_VERSON=2017
set GYP_GENERATORS=msvs-ninja,ninja
注意:代理是一定要设置的,否则webrtc无法下载。
2.下载depot_tools
cmd中输入下面内容:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
下载成功后,设置环境变量PATH,因为这里面有不少的编译需要的工具,比如著名的ninja.exe
设置环境变量后,重启cmd,重新输入以下内容:
set http_proxy=http://127.0.0.1:10080
set https_proxy=http://127.0.0.1:10080
set DEPOT_TOOLS_UPDATE=0
set DEPOT_TOOLS_WIN_TOOLCHAIN=0
set GYP_MSVS_OVERRIDE_PATH=D:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise
set GYP_MSVS_VERSON=2017
set GYP_GENERATORS=msvs-ninja,ninja
3.下载webrtc
在e盘下,新建一个git目录,git目录下建立webrtc目录,webrtc目录下再建立webrtc_wins目录。
cmd中执行cd E:\git\webrtc\webrtc_wins,切换到对应的目录。
然后在cmd中执行fetch --nohooks webrtc,这大概要等一段时间,中途会遇到很多Still working on的提示。
下载完成后,再执行gclient sync
说明下,gclient sync建议多执行几次,主要是内地的原因,一次可能下载的不够彻底,鄙人就遇到过这种情况。
然后cmd中执行下面的命令,定位到4577分支
git checkout -b m4577 refs/remotes/branch-heads/4577
接着继续gclient sync,gclient sync依然建议多执行几次
4.编译webrtc
下载webrtc后,E:\git\webrtc\webrtc_wins下面会多个src目录,cmd中执行cd src,切换到此目录。
然后执行下面命令
gn gen out/Release_h264 --args=“is_clang=false use_lld=false treat_warnings_as_errors=false rtc_include_tests=false is_component_build=false is_debug=false rtc_use_h264=true proprietary_codecs=true ffmpeg_branding=\“Chrome\”” --ide=vs2017
这个会自动生成ninja文件,然后执行下面的命令,进行ninja编译
注意use_lld=false是一定要设置的,早起的webrtc版本只需要设置is_clang=false就行了,此处如果没设置use_lld=false,则最终生成的peerconnection_client.exe无法运行起来。
ninja -C out/Release_h264
这个要等待一段时间,具体要看机器性能,我的台式机,16G的内容,大概要等30多分钟。
相关参数解析:
is_debug 是否是Debug版,默认true,false:表示编译Release版。
target_os: 平台类型,可以取值win、android、ios、linux等,这里取win,表示Windows平台。
target_cpu: cpu类型,Windows下可以取x86、x64
is_component_build :是否使用动态运行期库,这里取false,使用静态运行期库,Release版本将对应MT,Debug版将对应MTd。
proprietary_codecs: 是否使用版权编码,也就是H264,这里取true。
rtc_use_h264: 是否使用H264,这里取true,注意Windows平台编码使用OpenH264,解码使用ffmpeg。
ffmpeg_branding: ffmpeg的分支名,这里采用Chrome的分支。
is_clang: 是否采用clang编译器编译,默认设置为true
rtc_include_tests:自动编译单元测试test文件,默认是true,webrtc的单元测试文件很多,设置为false,可以节省不少编译时间。
5.编译中遇到的问题
编译中会遇到各种各样的问题,下面列举几条
5.1
…/…/modules/audio_processing/agc2/rnn_vad/features_extraction.cc(84): error C2398: 元素“2”: 从“const int”转换到“size_t”需要收缩转换
很明显,vs编译器检查是比较严格的,is_clang如果设置成true,就没这种问题。
我们进行下手动强制转换即可。
5.2
e:\git\webrtc\webrtc_wins\src\third_party\ffmpeg\libavcodec\error_resilience.h(23): fatal error C1083: 无法打开包括文件: “stdatomic.h”: No such file or directory
我们在webrtc目录下搜索stdatomic.h,发现third_party\ffmpeg下面存在几个stdatomic.h,将其中的一个放置于third_party\ffmpeg下即可。
5.3
…/…/third_party/ffmpeg/libavcodec/pcm.c(52): error C2065: “CONFIG_PCM_VIDC_ENCODER”: 未声明的标识符
…/…/third_party/ffmpeg/libavcodec/pcm.c(634): error C2059: 语法错误:“字符串”
直接将对应的行代码注释掉
5.4
E:\git\webrtc\webrtc_wins\src\modules/video_coding/codecs/h264/h264_decoder_impl.h(21): fatal error C1189: #error: “See: bugs.webrtc.org/9213#c13.”
直接注释掉
5.5
ffmpeg_internal.lib(pcm.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm(不影响最终webrtc库的生成)
这个问题是最难解决的,其他的问题跟这相比,有点毛毛雨的感觉,尽管此种情况下webrtc.lib可以生成,但是很多exe都无法生成,比如peerconnection_server.exe,并且将生成的webrtc.lib放置于其他vs工程,会报如下的链接错误:
1>webrtc.lib(pcm.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm
1>webrtc.lib(encode.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm
1>webrtc.lib(h264_picture.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm
1>webrtc.lib(avcodec.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm
1>webrtc.lib(decode.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm
1>webrtc.lib(h264dec.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm
1>webrtc.lib(vp3.obj) : error LNK2001: 无法解析的外部符号 avpriv_emms_asm
所以这个问题必须解决
解决方法:替换ffmpeg文件,x86版本无此问题,x64才会出现,原因是x64不支持大多数汇编指令,ffmpeg里面有汇编代码,用clang就没那个问题,但是clang编译的vc不能引用
现在来讲讲如何替换ffmpeg文件,这里说的ffmpeg指的是third_party\ffmpeg这个目录。
我是这样替换的,我们之前用的webrtc是72版本的,72版本的64位lib库很容易编译通过
编译通过后,我们将72版本的third_party\ffmpeg替换过来,然后接着生成ninja文件,在生成ninja文件的过程中,会出现两个错误。
第一:需要将72版本的third_party\yasm替换过来
第二:需要更改build\config\compiler目录下的BUILD.gn,里面需要在指定位置添加黄色区域的一段内容,这段内容其实是从72版本里面拷贝过来的。
除此外,编译的时候,注意用MD而不是MT,为此,我修改了文件
build\config\win下面的BUILD.gn,修改内容如下:
这里,我将原来的static_crt改成了dynamic_crt。
6.运行效果
运行的时候,发现peerconnection_client.exe无法播放视频,然后采用is_clang=true的方式进行编译,结果编译出的peerconnection_client.exe依然无法播放视频,故中间有放弃此版本,改用4484版本编译,4484版本的问题解决后,后边又改回到了4577版本,发现4577的成果物放置到自己工程下,发现可以播放视频了。。
7.4484版本编译
4484版本也是比较新的版本,直接编译64位时,最终还是会出现avpriv_emms_asm这样无法识别的符号错误,这里,我并没有采取替换72的ffmpeg的方式,而是事先编译好64位版本的ffmpeg,然后将头文件和lib库替换进去,这样webrtc本身就不需要对ffmpeg进行编译,只需要链接ffmpeg库即可。
64位ffmpeg库的编译,我采取的是以下链接里面的方式:
https://www.cnblogs.com/wanggang123/p/9896564.html
如下图所示,其中ffmpeg_x64_result是编译出的成果物
进入到文件夹ffmpeg_x64_result里面,如下图所示:
其中bin文件夹里面的内容如下:
include文件夹里面的内容如下:
将整个ffmpeg_x64(其实只需要拷贝里面的ffmpeg_x64_result)目录拷贝到webrtc下面,拷贝后,webrtc的third_party目录如下图所示:
可以看出,对于ffmpeg,我32和64位的都进行编译了下,然后编辑\src\modules\video_coding下的BUILD.gn
打开后,进行修改,修改共有两处,第一处如下:
其中左侧是原来的,右侧是修改后的。
第二处:注释掉下面这部分。
为方便以后粘贴,故将修改的文本放置如下:
rtc_library("webrtc_h264") {
visibility = [ "*" ]
sources = [
"codecs/h264/h264.cc",
"codecs/h264/h264_color_space.cc",
"codecs/h264/h264_color_space.h",
"codecs/h264/h264_decoder_impl.cc",
"codecs/h264/h264_decoder_impl.h",
"codecs/h264/h264_encoder_impl.cc",
"codecs/h264/h264_encoder_impl.h",
"codecs/h264/include/h264.h",
]
if (!is_clang) {
#设置头文件路径
include_dirs = [ "//third_party/ffmpeg_x64/ffmpeg_x64_result/include" ]
libs = [
# 设置引用库
"//third_party/ffmpeg_x64/ffmpeg_x64_result/bin/avcodec.lib",
"//third_party/ffmpeg_x64/ffmpeg_x64_result/bin/avdevice.lib",
"//third_party/ffmpeg_x64/ffmpeg_x64_result/bin/avfilter.lib",
"//third_party/ffmpeg_x64/ffmpeg_x64_result/bin/avformat.lib",
"//third_party/ffmpeg_x64/ffmpeg_x64_result/bin/avutil.lib",
"//third_party/ffmpeg_x64/ffmpeg_x64_result/bin/swresample.lib",
"//third_party/ffmpeg_x64/ffmpeg_x64_result/bin/swscale.lib",
]
}
defines = []
deps = [
":video_codec_interface",
":video_coding_utility",
"../../api/video:video_frame",
"../../api/video:video_frame_i010",
"../../api/video:video_rtp_headers",
"../../api/video_codecs:video_codecs_api",
"../../common_video",
"../../media:rtc_h264_profile_id",
"../../media:rtc_media_base",
"../../rtc_base",
"../../rtc_base:checks",
"../../rtc_base/system:rtc_export",
"../../system_wrappers:field_trial",
"../../system_wrappers:metrics",
"//third_party/libyuv",
]
absl_deps = [
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
if (rtc_use_h264) {
deps += [
#"//third_party/ffmpeg",
"//third_party/openh264:encoder",
]
然后开启编译,编译结果比较顺利,peerconnection_client.exe能够播放视频
后面将webrtc.lib放到项目中时,碰到一个链接错误,
webrtc.lib(auto_correlation.obj) : error LNK2019: unresolved external symbol __std_reverse_copy_trivially_copyable_4
这个我通过符号__std_reverse_copy_trivially_copyable_4在百度和谷歌上都没搜索到结果,最后采取了微软的bing搜索,此问题已经有人提出,如下网址:
https://github.com/Unity-Technologies/com.unity.webrtc/issues/441
根据里面所说,cmake存在一定的问题,当电脑上安装两个微软编译器的时候。
我电脑上安装有vs2017和vs2019,我卸载了vs2019,重新编译后,就好了。
上面ffmpeg是以动态库的方式提供的,当然也可以以静态库的方式提供,静态库方式编译的好处是最终的成果物里面不需要包含 avcodec-59.dll这样的文件,ffmpeg的静态库编译要比动态库编译麻烦些,为此,本人专门写了一篇博客,如下:
ffmpeg 64位静态库编译
后来我又重新编译了ffmpeg4577,也可以播放视频。