最近开始弄WebRtc与网页端传输视频的项目了,现在进入测试阶段,故而记录一下开发过程中遇到的坑。
首先先吐槽一波,WebRtc的项目对于c++开发来说实在是不太友好,文档也不全,弄懂全靠读代码注释,除了封装的Interface API的注释以外,具体实现的代码大多数要靠自己去领悟。相对于封装的很好,文档也很好,网上解决方案一搜一大把的JS和Android,真是让人心里不平衡。不过好处就是,可以随时去改WebRtc的源码,来满足自己特定的需求,比如说假冒摄像头向另一端发送视频之类的。
言归正传,先来总结一下WebRtc在Ubuntu下的编译过程及将其应用于Qt中遇到的坑。希望对于刚刚入手WebRtc的c++开发小伙伴有帮助。
编译及编译开关的使用
源码的下载及编译推荐一个github上作者写的小脚本,链接在这里:WebRtc编译脚本
去下载下来,按照作者说明,把翻墙工作做好,运行脚本就会自动帮你下载了,不过要注意的是,如果翻墙的服务器网络波动很大的话,多半会失败,由于git代码是没有失败重传机制的,所以一旦失败又要重新下载,很坑爹,我是直接拜托同事下好了需要的编译工具depot_tools文件夹和源码文件夹,拷贝过来以后运行脚本进行编译的。看到网上有推荐做法是在境外租主机,在主机上下好源码和工具以后,再从主机上下载到本地,感觉是可行的,不过没试过。
完成下载步骤以后,通过修改github下载下来的脚本,可以控制编译选项、编译开关以及编译输出目录,在build_apprtc函数中,包含了如下多个类似语句:
export WEBRTC_DEBUG=false
export WEBRTC_ARCH=x86_64
prepare_gyp_defines $1 &&
execute_build
由于我只需要编译出ubuntu64位的release版WebRtc静态库,因此我只保留了上面这一段,其他的都注释掉了,如果有需要的话,可以自行选择。输出目录我忘记在哪里了,不过自己读一下代码找一找可以改的,不过我个人感觉没什么必要,默认是输出到src/out-linux-x86_64,不同的编译版本,输出文件夹名字也不同,看一看就知道了。
然后是最坑的编译开关环节,要把WebRtc导入Qt并使用,坑还是很多的,这就是其中之一。搜索脚本里面的代码,只有一行有如下字样“gn gen”,这一句是执行gn工具,生成ninja文件,以用于下一步执行ninja编译。因此,编译开关是在这一句后面加的,下面是我修改以后的语句,有需要的小伙伴可以拷贝过去直接用或者根据自己的需要进行修改:
gn gen "$ARCH_OUT/$BUILD_TYPE" --args="$DEBUG_ARG symbol_level=1 target_os=\"linux\" target_cpu=\"${ARCH}\" use_custom_libcxx=false proprietary_codecs=true use_custom_libcxx_for_host=false ffmpeg_branding=\"Chrome\"" --ide="qtcreator"
稍微解释一下这里的意思,--args参数顾名思义,就是编译开关的各种参数设置,--ide是为了方便在qtcreator下阅读和修改源码,毕竟谁都不想用文本编辑器去一个一个打开源码文件,然后肉眼各种查看吧(虽然我这样干了挺长一段时间)。
先说--args的内容,前面几项直到target_cpu都不用太解释了,自己都能猜出一两分意思。use_custom_libcxx=false和use_custom_libcxx_for_host=false这是用来控制编译WebRtc时使用的c++库的。原因很简单,如果不加这个编译开关的话,WebRtc编译默认使用libc++来编译,而Qt使用GCC编译的时候使用的是libstdc++,这样在编译的过程中就会导致用到std::string的地方,就会编译报错。proprietary_codecs=true ffmpeg_branding=\"Chrome\"这两个是用来控制打开h264编解码的编译开关,至于为什么会用到这个,还不都是因为苹果系统的网页端,只支持用Safari来运行WebRtc,并且编解码只支持h264,不支持vp8。当然,并不是说这里打开了就能用h264编解码了,还要去在Qt项目中添加宏定义,并且源码也需要做少量修改才能使用h264编解码。Qt中的添加后面会提到,源码修改因为时间太久了有些忘记了,网上有很多教程,可以自行搜索,在这里就不写了。
然后是--ide的内容,添加这个以后,会在输出目录多出一个qt_creator的目录,在Qt中打开项目,进到这个文件夹,打开就可以很方便的读代码了,函数跳转什么的超方便,不过由于WebRtc对各个类层层封装,再加上大多数代码注释少的可怜,代码也不是这么好读懂的就是了。
正常来说,执行完这一步就可以在Qt中,将输出目录下的obj/libwebrtc.a添加进去了。这个静态库整合了整个WebRtc项目的所有静态库,因此,包含这一个就可以了。如果只需要静态库里面的部分功能,想要精简库的话,去修改.gn文件就可以做到,不过我没精力去做这个,但是是绝对可行的。另外,我不知道是不是只有我遇到了这种情况,在我使用静态库的过程中,编译找不到解码工厂的实现。去每一层查看了.gn文件,发现没有把解码工厂的静态库整合进libwebrtc.a,修改以后解决了这个问题,这个会在之后第三部分去谈一谈gn和ninja,现在就先按着开发的顺序说到这里。
下一部分会提到,如何编辑Qt的.pro文件,以及WebRtc和Qt冲突遇到的坑,以便使用WebRtc库在Qt项目中进行开发。