目录
1、多媒体处理开源库FFmpeg
2、实时音视频处理开源库WebRTC
3、Chrome浏览器内核开源库Chromium
4、Chromium嵌入式框架开源库CEF
5、多协议网络传输开源库libcurl
6、开源操作系统ReactOS
7、开源多媒体播放器VLC
8、最后
在开源软件盛行的今天,很多知名的C++国产软件都用到了一些大型C/C++开源库,比如暴风音影使用了多媒体处理开源库FFmpeg、腾讯会议使用了实时音视频处理开源库Webrtc、PC版微信使用了Chromium嵌入式框架开源库CEF等。今天我们就来介绍一下日常工作中常用的C/C++开源库,给大家提供一个借鉴和参考。
享有盛名的音视频多媒体处理开源库FFmpeg,做过音视频编解码开发的同学基本都用过,即便没做过这方面开发,也会听说过这个开源库。
FFmpeg是目前最全面的开源音视频编解码库,包括常用的音视频编码协议 H265、H264、MPEG4、H263、G.721、G.726、G.729等,并且它提供了一整套的音视频处理解决方案,包括音视频采集与编码、音视频解码、视频格式转换、视频抓图、给视频加水印等。
FFmpeg虽然是基于Linux的开源项目,但可以通过交叉编译的方式在多个系统下运行,包括Windows、Mac、iOS、Android等,其对外提供的有一套可执行程序和一套sdk以及相关的库。通过sdk接口可以看出FFmpeg非常强大,可以直接接收和发送码流,读取文件和写入文件,对码流做编解码操作,修改解码数据格式等等。
FFmpeg是用C语言实现的,在执行效率上是接近汇编语言的(C/C++在执行效率上是最接近汇编语言的),可以很好地满足对实时性有很高要求的音视频处理场景,此外,项目中添加了很多优化效率的代码,如采用汇编替代C/C++代码,大大提高了代码的运行效率。在音视频处理的代码中,插入部分汇编代码去提高代码的运行效率,是常有的事!
有时为了提升代码执行的速度,我们会直接在源代码中嵌入一段汇编代码,比如在一些算法代码中,比如音视频编解码算法。
有人可能会问,经过IDE编译出来的二进制文件中也都是汇编指令,你人为的添加一段汇编代码,都是汇编代码,为啥会有执行速度上的差别呢?
因为源代码经过编译器的处理生成的汇编代码在实现上可能不是最优的,这要依赖于通用的编译器,而我们人为添加的汇编代码,编译器不会做任何修改,所以我们可以直接在汇编代码中直接去控制操作,保证汇编代码是最优的,不再依赖编译器去生成。
几乎所有的视频播放器都使用到了FFmpeg的音视频解码功能,比如国内知名的暴风影音、QQ影音、腾讯视频、爱奇艺视频、优酷视频等。
对于播放器,将视频文件中经过压缩的视频图像帧解成一张张图片,然后将图片显示到窗口上,每秒钟连续显示多张图片,这样人眼就看到了动态的效果了,即我们观看视频时动态的显示效果,其实是一张一张图片连续显示出来的效果。
每秒钟播放的视频图片的个数叫做帧率,一般帧率达到15帧后,人眼看到的就是连续动态的播放效果了!
内部支持多种音视频格式之间的相互转换,很多音视频转化软件都用到了FFmpeg的音视频转换功能,比如大家常用的格式工厂、暴风转码(暴风影音自带的工具)、QQ音影自带的视频格式转换工具、狸窝视频转换器、迅捷视频转换器等。
FFmpeg项目源码的相关说明:
(1)根目录各文件夹说明:
libavcodec:一个包含了所有ffmpeg音视频编解码器的库。
libavformat:一个包含了所有的普通音视频格式的解析器和产生器的库。
libavdevice: 用于采集设备相关。
libavutil:用于内存操作等辅助性模块。
libpostproc:用于视频前处理的库。
libswscale: 用于图像缩放等处理的库。
libavfilter: the filtering API of ffmpeg。
其中最重要的就是libavcodec库。它被mplayer,xine使用作为解码器。还有,国内比较流行的播放器影音风暴,QQ影音都用到此解码库。(2)另外有两个.c文件:ffmpeg.c,ffplay.c,编译后会生成两个可执行文件:
WebRTC(Web Real-Time Communication)是一个由Google发起的实时音视频通讯C++开源库,其提供了音视频采集、编码、网络传输,解码显示等一整套音视频解决方案,我们可以通过该开源库快速地构建出一个音视频通讯应用。
一个实时音视频应用软件一般都会包括这样几个环节:音视频采集、音视频编码(压缩)、前后处理(美颜、滤镜、回声消除、噪声抑制等)、网络传输、解码渲染(音视频播放)等。每一个细分环节,还有更细分的技术模块。
WebRTC的起源,要从2010年Google以6820万美元收购VoIP软件开发商Global IP Solutions的 GIPS引擎谈起,在经过收购之后没多久,Google将该引擎改名为“WebRTC”,并宣布向全球开发者开源。
Global IP Solution (GIPS) ,是瑞典一家全球顶级的专业从事IP多媒体编解码引|擎的技术公司,专为包交换网络开发世界级的语音和视频处理解决方案。其产品主要包括两大类:
(1)媒体引擎
VoiceEngine:全功能语音处理框架。包括PC、Mobile、Conference、SDK ( 集成SIP信命)等各版本。
VideoEngine:完整高质量的语音和视频解决方案。同样包括PC、Conference、SDK
等各版术。
(2)组件
NetEQ:单向嵌入式解决力案,即使在语音网络条件不佳的情况下仍能提供先进的抖动缓冲和丢包掩盖功能。NetEQ 是 WebRTC 音视频核心技术之一,对于提高 VoIP 质量有明显的效果,
Voice Quality Enhancement(VQE):通过去除回声和噪音,以及调整音阶来改善VoIP的通话质量,以达到一一个稳定和l舒适的收听水平。GIPS的音频和视频编解码器套件包括了宽带和窄带,即在严重丢包的情况下都能输途有健壮性的,清晰的声音。和GIPS NetEQ结合在一起时,可有效控制延迟与抖动。音频codec有iLBC, Enhanced G.711JSAC, iPCM-wb和超过20种标准编解码器。视频codec有LSVX, H.264, H.264 SVC。
WebRTC项目最开始是让Web开发者能够基于浏览器(Chrome\FireFox\...)轻易快捷开发出丰富的实时音视频应用,而无需下载安装任何插件,Web开发者也无需关注音视频的处理过程,只需编写简单的Javascript程序即可实现。WebRTC库底层是用C/C++实现的,具有良好的跨平台性能,当前已提供对Windows、MAC、iOS和Andriod等多系统的支持,我们只需要调用对应系统的SDK即可完成这些系统上音视频应用的构建。
虽然其名为WebRTC,但是实际上它不光支持Web之间的音视频通讯,还支持Windows、Android以及iOS等移动平台。WebRTC底层是用C/C++开发的,具有良好的跨平台性能。
WebRTC因为其较好的音视频效果及良好的网络适应性,目前已被广泛的应用到视频会议、实时音视频直播等领域中。在视频会议领域,腾讯会议、华为WeLink、字节飞书、阿里钉钉、科达、ZOOM、小鱼易连均提供了基于WebRTC方案的视频会议。
大家熟知的音视频专业服务商声网(Agora),更是基于开源WebRTC库,提供了社交直播、教育、游戏电竞、IoT、AR/VR、金融、保险、医疗、企业协作等多个行业的音视频互动解决方案。使用声网服务的企业包括小米、陌陌、斗鱼、哔哩哔哩、新东方、小红书、HTC VIVE 、The Meet Group、Bunch、Yalla等遍布全球的巨头、独角兽及创业企业。
除了头部公司声网之外,也陆续有多家公司基于开源的WebRTC,开发出了多个音视频应用,提供了多个领域的音视频通信解决方案。
WebRTC项目源码的相关说明:
(1)根目录各文件夹说明:
api:WebRTC接口层,浏览器都是通过该接口调用WebRTC,包括 DataChannel, MediaStream, SDP相关的接口
call:数据流的管理层,Call代表同一个点的所有数据的流入流出,存放的是 WebRTC “呼叫(Call)” 相关逻辑层的代码。
video:与视频相关的逻辑,视频逻辑层及视频引擎层的相关的代码。视频数据逻辑上的发送,接收等代码。
audio:与音频相关的逻辑,音频数据逻辑上的发送,接收等代码。
common_audio:音频算法相关,存放一些音频的基本算法。包括环形队列,博利叶算法,滤波器等。
common_video:视频算法相关,存放了视频算法相关的常用工具,如libyuv, sps/pps分析器,I420缓冲器等。media:主要是媒体流的接口抽象。为媒体引擎和 codec 层提供桥接。这里说的媒体流是 RTP 流。pc 层也抽象了媒体流,那是编码前、或者解码后。
logging:WebRTC 的 log 库。
media:媒体引擎层,包括音频、视频引擎实现。
modules:WebRTC 把一些逻辑比较独立的抽象为 Module,利于扩展维护。
ortc:媒体描述协议,类似 sdp 协议。
out:build 输出目录,这是 webrtc 官方编译指导中示范目录。
p2p:主要是实现 candidate 收集,NAT 穿越。
pc:实现 jsep 协议。
resources:测试数据
rtc_base:包括 Socket、线程、锁等 OS 基础功能实现。
rtc_tools:网络监测工具、音视频分析工具。很多工具都是脚本实现。
sdk:主要是移动端相关实现。
stats:WebRTC 统计模块实现。
style-guide:编码规范说明
system_wrappers:OS 相关功能的封装,比如 cpu、clock 等。
test:单元测试代码实现,用 gmock
testing:gmock、gtest等源码,属于整个 Chromium 项目。
third_party:第三方库依赖。比如,boringssl,abseil-cpp,libvpx等
tools:公共工具集,整个 Chromium 项目依赖的。
tools_webrtc:WebRTC 用到的工具集。比如代码检查 valgrind 的使用。
video:视频 RTP 流的抽象接口,属于视频引擎的一部分。(2)重要模块module对应的目录结构
这个目录是 WebRTC 代码中最重要的一个目录。里面包括了音视频的采集,处理,编解码器,混音等,该目录中文件夹说明如下:
audio_coding:音频编解码相关代码 audio_coding,是和编解码逻辑相关的,会用编解码,这里的audio_coding它是编解码器,都是放在audio_coding这个目录下。
audio_device:视频采集与音频播放相关代码 audio_device它是和设备相关的,它做了一个区分,安卓和IOS放在sdk下面了,它相应的一些代码移到sdk里面了,在以前的webrtc版本 ,所有的设备都是 放在audio_device里面 ,包括我们的windows和MAC下的以及Linux下的,都是在audio_device这个目录下。audio_mixer:混音相关代码 audio_mixer,就是混音相关的,混音就好比开会时多人实时互动,比如四个人同时在说话,就要给它混在一起,这样在传输的时候就比较方便,这个减少了音频流,所以这个混音相关的就放在audio_mixer里面。
audio_processing:音频前后处理相关代码 audio_processing就是音频的前处理后处理,音频的前处理后处理就好比回音消除、降噪、增益等,都是放在audio_processing里面。这个目录里面又分了很多子目录,在后面你就 大体的知道这个相关的在这个目录下。以及在这个目录下再找子目录
bitrate_controller:码率控制相关代码 bitrate_controller,这个是码流控制的,比如说控制这个码流,视频的码流是500k还是1M。这个码流的控制。如果想知道相关的码流他是怎么控制的 ,那么可以到这里去看。
congestion_controller:流控制相关代码 -congestion_controller,就是流量控制,当我能检测到网络流量比较高的时候,我们要做一些流量控制,防止这个网络包将带宽打死,具体怎么控制就是在这里做的相关的逻辑。所以如果我要 了解流量控制相关的,就到这个目录下面去找。
desktop_capture:桌面采集相关代码 –
pacing:码率探测及平滑处理相关代码 pacing的作用是码率的侦测和平滑处理,我首先要检测到音频视频的码率是怎样的,做到之后我们要做到一个平滑的处理,我们不能让他一下子就发送出去,应该对他做一下平滑,比如有时候是10k有时候是500k,我们让他平均一下。
remote_bitrate_estimator:远端码率估算相关的代码 emote_bitrate_estimator的作用是远程码率评估,我远端能接收的带宽是多少,一个是我本地的带宽,一个是远端的带宽,不光我能发多少还有对方能收多少,所以要有一个远端的码率的评估,这是放在remote_bitrate_estimator目录下。
rtc_rtcp:rtp/rtcp协议相关代码 –
video_capture:视频采集相关代码 video_capture我捕获视频的相关的代码,放在video_capture里面。
video_coding:视频编解码相关代码 视频的编码,如H264,VP 8,VP 9,等,这个编码器都是放在video_coding里面。
video_processing:视频前后处理相关的代码 video_processing,就是视频的前处理和后处理,如视频帧的增强,检测,如果我们增加人脸识别可以放到video_processing这个目录下。
随着 c++11,c++14,c++17 新标准的推出,WebRTC 在新版本中逐渐支持了新标准中的语法功能,可能会有些晦涩难懂。
Chromium是Google的一个久负盛名的浏览器C++开源项目,它是Google的Chrome浏览器背后的引擎,其目的是为了创建一个安全、稳定和快速的通用浏览器。
Chromium的设计思想基于简单、高速、稳定、安全等理念,在架构上使用了Apple发展出来的WebKit渲染引擎,并采用Google独家开发出的用于提升JavaScript解译效率的V8引擎,以提升JavaScript的效率,而且设计了“沙盒”、“黑名单”、“无痕浏览”等功能,来实现稳定与安全的网页浏览环境。
Chrome浏览器与Chromium的关系:
Chromium是google的开源项目,Chome是google维护的基于Chromium的浏览器,在Chromium的基础上添加了一些额外的功能并做了一些优化。这两个浏览器面向的用户是不一样的,一般来说使用Chrome的用户是普通用户,用它来浏览网页使用,而使用Chromium大部分是极客、开发人员和体验新功能的的用户。
很多浏览器使用的都是Chromium开源内核,比如微软Win10系统中推出的Edge浏览器抛弃了IE内核,转而使用Chromium内核。国内知名的360浏览器、QQ浏览器、傲游浏览器,它们用的都是Chromium内核,只是开发了各自的UI皮肤和界面,增加了一些额外的用户功能。接下来说到的CEF嵌入式浏览器框架也是基于Chromium内核实现的。
Chromium项目根目录下的各文件夹介绍:
android_webview:Android WebView 实现,封装 Content 层以集成进 Android 平台。android 重要的支持。
apps:Chrome 打包的应用
base:子项目共享的通用代码。 其中包含诸如字符串操作,通用实用程序等内容。
breakpad:崩溃报告,我checkout出的并没有这个
build:所有项目共享的编辑构建相关的配置
cc:Chromium合成器的实现
chrome:Chromium 浏览器
chrome/test/data:用于运行某些测试的数据文件
components:上层组件所依赖的内容模块的组件目录
content:多进程沙盒浏览器所需的核心代码
device:常见的底层硬件API的跨平台抽象。mojo:类似于 Android 的 AIDL,提供了跨语言(C++ / Java / JavaScript)跨平台的进程间对象(Object)通信机制;对比 ipc ,后者提供的是单语言(C++)的进程间消息(Message)通信机制。这是chromium最新设计的IPC架构,会逐渐替换掉老的IPC。
net:为Chromium开发的网络库。
sandbox:沙盒项目,该项目试图防止被黑的渲染器修改系统。
skia+third_party/skia:谷歌的Skia图形库
sql:包装了 sqlite
testing:包含我们用于单元测试的Google开源GTest代码。
third_party:200多个小型和大型“外部”库,例如图像解码器,压缩库和Web引擎Blink(此处是因为它继承了WebKit的许可证限制)。
.../blink/renderer: 负责将HTML,CSS和脚本转换为绘画命令和其他状态更改的Web引擎。
tool:工具。
ui/gfx:共享的图形类。 这些构成了Chromium UI图形的基础。
ui/views:一个简单的框架,用于进行UI开发,提供呈现,布局和事件处理。 大多数浏览器UI在此系统中实现。 该目录包含基础对象。 其他一些特定于浏览器的对象位于chrome / browser / ui / views中。
url:Google的开源URL解析和规范化库。
V8:V8 Javascript库。 这是直接从Google Code的Subversion存储库中提取的。
Chrome浏览器采用多进程架构,运行时会启动多个chrome进程,不同的进程执行不同的任务,比如render渲染进程、异常处理进程、GPU加速进程、网络服务进程、数据存储进程,可以通过Chromium源码的学习,可以学到多进程多线程通信的技术实现细节。
CEF的全称是Chromium Embedded Framework(Chromium嵌入式框架),是一个基于Google Chromium的开源浏览器“控件”,也是用C++实现的。Google Chromium项目主要是为Google Chrome浏览器开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器(控件)的支持。
CEF是作为浏览器控件嵌入到应用程序的窗口中,以实现在应用窗口中打开网页的功能。CEF隔离了底层Chromium和Blink的复杂代码,并提供一套产品级稳定的API,并发布跟踪具体Chromium版本的CEF版本。CEF的大部分特性都提供了丰富的默认实现,让使用者做尽量少的定制即可满足需求。
CEF支持Windows、Linux、Mac等多个平台,除了提供C/C++接口外,也有其他语言的移植版。因为基于Chromium,所以CEF支持Webkit渲染引擎和Chrome中实现的HTML5的特性,在性能上也比较接近Chrome浏览器。CEF还提供了自定义插件、自定义协议、自定义JavaScript对象和扩展,以及可控制的resource loading,、navigation、context menus等。
CEF的典型应用场景包括:
(1)嵌入一个兼容HTML5的浏览器控件到一个已经存在的本地应用,实现在应用程序中打开网页,这是CEF最常用的一个场景。
(2)创建一个轻量化的壳浏览器,用以托管主要用Web技术开发的应用。
(3)有些应用有独立的绘制框架,使用CEF对Web内容做离线渲染。
(4)使用CEF做自动化Web测试。
现在很多C/S架构的PC桌面程序中都内嵌了CEF浏览器控件,直接在应用程序的窗口中打开指定的web页面,就像在浏览器中打开web页面一样。内嵌的浏览器控件可以直接使用Windows中的IE浏览器内核的控件,但是IE浏览器内核在渲染界面时需要使用到adobe flash控件,而flash控件不稳定,经常会导致IE浏览器崩溃,所以大家都会选择稳定高效的CEF浏览器控件的方式。比如我们常用的桌面软件QQ、PC版微信、企业微信、钉钉、飞书、迅雷、爱奇艺视频客户端、优酷视频客户端、有道词典、有道云笔记、MindMaster思维导图软件等都使用了内嵌CEF浏览器控件。
libcurl是一个免费开源的网络传输库(the multiprotocol file transfer library),该库是使用C语言实现的,支持ftp、ftps、http、https、telnet、ldap、pop3、smtp、rtmp、rtsp、smb等多种协议。libcurl中封装了支持这些协议的网络通信模块,支持跨平台,支持Windows,Unix,Linux等多个操作系统。libcurl提供了一套统一样式的API接口,我们不用关注各种协议下网络通信的实现细节,只需要调用这些API就能轻松地实现基于这些协议的数据通信。
我们在实际项目多次使用libcurl库,使用库中的HTTP/HTTPS协议发起http/https请求,使用SMTP协议实现邮件的发送。对于libcurl开源库的编译,可以参见之前写的一篇文章:
详解C++开源网络传输库libcurl的编译过程https://blog.csdn.net/chenlycly/article/details/125135667
ReactOS是一款基于 Windows NT 架构的类似于Windows XP系统的免费开源操作系统,旨在实现和 NT 与 Windows 操作系统二进制下的完全应用程序和驱动设备的兼容性,使用类似的系统构架,提供完全类似的系统API接口及内部接口。该开源项目是用C语言实现的,项目中各dll模块的名称,模块中接口的名称、接口的参数类型、接口的内部实现,都是非常接近Windows操作系统的,所以可以通过查看ReactOS的源码去了解Windows系统的内部实现。
ReactOS一直在持续维护中,可以到ReactOS官网上找到ReactOS源码的下载地址,使用svn将ReactOS源码下载下来。
ReactOS开源代码对于Windows软件开发人员来说非常有用,可以到ReactOS代码中查看系统API函数的内部实现,可以去查看系统模块的内部接口实现,可以去查看ReactOS系统内部任意模块的实现代码。Windows只提供了系统API接口的详细说明,未提供系统模块内部的接口说明,ReactOS是比较接近Windows系统的,可以通过查看ReactOS的代码去大概地了解Windows系统模块的内部接口声明及内部实现,对我们排查Windows软件的问题是很有好处的!
我们在项目中多次参考ReactOS的代码,解决了开发过程中遇到的多个问题,具体实例可以参考下面的文章:
通过查看ReactOS开源代码,解决完整路径dll加载失败问题(附源码)https://blog.csdn.net/chenlycly/article/details/124360104
VLC全称是Video Lan Client,是一款自由、开源的跨平台多媒体播放器及框架,它是用C语言实现的,可以播放来自网络、摄像头、磁盘、光驱的文件,支持包括MPEG4、H264、H265、DivX、WMV、Vorbis、AC3等多种音视频协议。VLC最为突出的就是流媒体文件的功能,VLC支持各种流媒体协议,能直接播放远端的流媒体视频,只要输入一个视频文件的网址即可,无需下载到本地。此外,VLC还可以直接播放没有下载完成的文件。
VideoLanServer(VLS)的功能已经合并到VLC中,所以VLC不仅仅是一个音视频播放器,它也可以作为小型的视频服务器或流媒体服务器使用,可以一边播放一边转码,把视频流发送到网络上。
在Windows和Linux上的VLC是使用C++/Qt编写的,提供了一致的用户体验。同时VLC还专门为OS X提供了原生版本,OS X版的 VLC的用户界面使用Cocoa框架编写,在OS X下拥有卓越的原生体验。
VLC原先是几个法国的大学生做的项目,后来他们把VLC作为了一个开源的项目,吸引了来自世界各国的很多优秀程序员来共同编写和维护VLC,才逐渐变成了现在这个样子。
上述几大著名的C/C++开源库,都能在github上均能搜索到,也可以到它们的官网上下载开源代码。感兴趣的朋友,可以把开源代码下载下来去研究学习!通过阅读开源代码去了解这些开源库中的实现机制及细节,学习库中的编程思想。比如我们可以去学习开源库中进程间、线程间的通信机制,了解底层协议及网络通信模块的内部实现。