JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
JCHub
Code as My Sword, Lost in Obsession
Beauty of Programming

Nodejs C++ addon开发简介

目前OWT服务端使用了两种方式开发C++ addon: 使用内部的V8、libuv 和 Node.js 库 第三方NAN库 OWT服务端更新最频繁的数WebRTC agent代码了,目前WebRTC agent用的是NAN方式开发C++ addon,其他agent用的是内部的V8、libuv 和 Node.js 库开发C++ addon,开发起来会比较复杂,需要熟悉Nodejs各个组件的知识以及libuv、V8相关API调用。所以对于新开发的C++ addon,推荐使用NAN方式开发,简单,而且不用考虑Nodejs升级后的兼容性问题。 1. NAN简介 NAN的全称为**Native Abstraction for Node.js** , 其表现上是一个Node.js包。安装后,就得到一堆C++头文件,里面是一堆宏。它主要为Node.js和V8跨版本提供了封装的宏,使得开发者不用关心各个版本之间的API的差异。 NAN官方地址为:https://github.com/nodejs/nan。 NAN的优势在于可以屏蔽不同版本Node的API,使得C++ addon可以wirte once, compile anywhere,一份C++ addon可以适用于不同版本的Nodejs。 接下来我们以WebRTC agent中的代码简单讲解下如何使用NAN开发一个C++ addon。 2. NAN C++ addon开发 这里我们以WebRTC agent中的rtcConn addon作为示例,代码位于source/agent/webrtc/rtcConn中。 2.1 使用 安装NAN包: [crayon-69cbc6099ec3b110483709/] 编写binding.gyp,将NAN路径添加到binding.gyp中: [crayon-69cbc6099ec4a938506941/] NAN的路径会通过node -e "require('nan')"获取。 2.2 目录结构 如下是rtcConn addon的目录结构: [crayon-69cbc6099ec4e868786110/] 在每个C++ addon中都包含:binding.gyp,addon.cc。 binding.gyp。使用JSON风格,包含当前addon的编译配置,例如用到的文件以及库 addon.cc。类似于main函数入口,调用包含的各个C++类的Init接口 binding.gyp 如下是rtcConn addon中,binding.gyp部分内容。 首先通过target_name定义了该C++ addon名称,这样会在build目录下生成target_name.node文件。接着包含相关源码文件以及链接用到的第三方库。 [crayon-69cbc6099ec51812051288/] addon.cc 调用用到的各个C++类的Init方法,这些C++类都是按照NAN规定的方式进行wrap,这样我们就可以将这些C++类导出,以addon.cppclass方式调用各个C++类。 [crayon-69cbc6099ec56292672397/] 目录中除了binding.gyp,addon.cc,剩下的都是用到的各个C++类NAN方式wrap后的文件。 OWT服务端不同agent代码文件命名,以及代码规范比较乱。这里规定新代码中wrap后的文件名最好加上Wrapper修饰,便于区分。可以参照WebRTC agent中最新的rtcFrame addon(基于WebRTC SDK 实现的一个C++ addon)。 2.3 NAN wrap C++类 我们的C++类都要按照NAN规定的方式wrap,这样Nodejs层才可以调用。 我们有个licode中的erizo::WebRtcConnection(third_party/licode/erizo/src/erizo/WebRtcConnection.h)类,用于处理WebRTC连接相关的配置信息,我们要将它提供给Nodejs层调用。我们可以通过如下方式进行wrap,这里看下wrap后的类头文件大概内容。 [crayon-69cbc6099ec59870742415/] 对于C++类要导出的接口使用NAN_METHOD进行修饰。我们要wrap的类作为me成员。 2.3.1 NAN_MODULE_INIT 用于定义该模块的入口函数。在这里注册要使用的C++类接口,这样Nodejs层才可以调用。当Nodejs层执行require('path/xxx.node')的时候,就会执行该函数。 [crayon-69cbc6099ec5c678054252/] 2.3.2 NAN_METHOD(New) 构造函数入口,在Nodejs层New一个该C++ wrap类时,就会进入这里。在这里可通过判断Nodejs层传入的参数个数,调用不同的构造函数。 我们通过info.Length()判断传入的参数个数。 2.3.3 NAN_METHOD(setRemoteSdp) 通过这个函数讲下怎么传递参数到C++。这个函数主要传递Nodejs层的字符串参数到C++底层。 [crayon-69cbc6099ec5f624297077/] 2.3.4 NAUV_WORK_CB 通过这个函数讲下怎么将C++底层的数据回调到Nodejs层。大概函数调用层次如下: [crayon-69cbc6099ec63792747667/] 首先按NAN方式定义一个回调 [crayon-69cbc6099ec66425610006/] 定义一个抽象类,在这里定义回调接口,其实就是常见的观察者模式 [crayon-69cbc6099ec69306334712/] NAN方式wrap后的类继承前一步定义的抽象类 [crayon-69cbc6099ec6c215071411/] 实现抽象类的回调接口 [crayon-69cbc6099ec6f519438731/] NAN_METHOD(New)中构造对象时,将wrap的类对象传递进去 [crayon-69cbc6099ec72794062335/] 看下erizo::WebRtcConnection中的实现: [crayon-69cbc6099ec75628533628/] 通过conn_event_listener_进行各种事件回调: [crayon-69cbc6099ec78172240913/] 这样回调的信息就会传到NAN这一层,NAN这一层再调用Nodejs层的回调函数,即可将信息回调到Nodejs层。 Nodejs层回调 函数这里我们通过调用定义的init接口获取Nodejs层的回调函数 [crayon-69cbc6099ec7b295804334/] 这里看下Nodejs层代码调用: [crayon-69cbc6099ec7e701462297/] 回调事件队列处理 [crayon-69cbc6099ec81734171831/] eventsCallback与libuv的绑定在NAN_METHOD(WebRtcConnection::New)中: [crayon-69cbc6099ec84783512936/] 这样调用uv_async_send(&async_)就会异步执行eventsCallback。 退出时关闭处理 [crayon-69cbc6099ec87210381941/] 2.4 Nodejs层调用 编译后如下方式引入: [crayon-69cbc6099ec8a106839957/] 构造: [crayon-69cbc6099ec8d865629769/] 传入回调函数: [crayon-69cbc6099ec90625897548/] 相关接口调用: [crayon-69cbc6099ec93175619761/] 3. 总结 本文简单介绍了目前服务端Nodejs c++ addon开发,通过列举的参数传递,回调例子,对着相关代码过一遍,基本能快速上手。

2020年9月25日 0comments 10hotness 1likes Jeff Read all
WebRTC

WebRTC研究:BBR拥塞控制被移除了

本来想写篇文章分析下WebRTC拥塞控制中的BBR算法代码,不过更新最新代码后发现BBR相关代码已经被移除了,所以也没必要了。WebRTC中对应的代码提交如下: [crayon-69cbc609a06e7868437828/] 给出的理由是WebRTC中性能表现很糟糕,BBR得等到以后我研究完QUIC协议再专门分析了。

2020年8月22日 5comments 6256hotness 10likes Jeff Read all
WebRTC

WebRTC安卓编译

系统要求 系统:Ubuntu 18.04 磁盘空间:至少16GB磁盘空间 安装工具 [crayon-69cbc609a19ea911857093/] 安装depot tools [crayon-69cbc609a19f3651903316/] 获取代码 [crayon-69cbc609a19f7962778481/] gclient sync也可以拆分为如下两步执行: [crayon-69cbc609a19fb521914031/] 依赖安装 [crayon-69cbc609a19fe885105894/] 编译 直接使用aar编译工具编译,这里我们指定编译armeabi-v7a与arm64-v8a两种架构。 [crayon-69cbc609a1a01106334353/] 生成的libwebrtc.aar文件文件位于src目录下,编译过程产生的文件,例如libjingle_peerconnection_so.so位于src/out目录下。 崩溃问题排查 使用addr2line定位WebRTC底层崩溃代码位置。 [crayon-69cbc609a1a04694605497/] 编译特定版本 这里我们以更新到m79版本为例。 [crayon-69cbc609a1a08359020709/] 更新WebRTC代码到m79版本: [crayon-69cbc609a1a0b710336879/] 同时也要更新对应的depot_tools,通过git log查看m79版本对应日期,然后进入depot_tools目录,也使用git log查看与m79版本日期相近的某个版本,并更新到该版本。 [crayon-69cbc609a1a0d627032138/] 最后进入WebRTC目录: [crayon-69cbc609a1a11281151121/] 然后参照前面步骤重新编译即可。

2020年8月17日 2comments 3927hotness 7likes Jeff Read all
A/V

音视频开发入门:视频基础

数字图像 平时我们看到的视频其实是由一幅幅图像组成,所以先来了解下数字图像。 数字图像由一个个像素组成,是二维图像用有限数字数值像素的表示。如下路所示,我们放大一个图像后,能明显看到一个个像素块: 图像分辨率 水平分辨率指的一幅图像的宽,垂直分辨率指的一幅图像的高。一般说的分辨率用水平分辨率(宽)X 垂直分辨率(高)表示。 常见分辨率有: QVGA:320x240 CIF:352×288 VGA:640x480 HD:1360x768 FHD:1920x1080 WQHD:2560x1440 4K UHD:3840x2160 数字图像编码方法 指的是图像中每一个像素点在计算机中用什么编码方法表示。 RGB 人的眼睛是根据所看见的光的波长来识别颜色的。可见光谱中的大部分颜色可以由三种基本色光按不同的比例混合而成,这三种基本色光的颜色就是红(Red)、绿(Green)、蓝(Blue)三原色光。这三种光以相同的比例混合、且达到一定的强度,就呈现白色(白光);若三种光的强度均为零,就是黑色(黑暗)。这就是加色法原理,加色法原理被广泛应用于电视机、监视器等主动发光的产品中。 RGB存储表示 每个像素至少包含R、G、B分量,逐个像素存储。 RGB16:每像素占2字节,R、G、B分别用5bit,6 bit,5 bit表示。 RGB24:每像素占3字节,R、G、B各占一字节。 RGB32:每像素占4字节,A(Alpha)、R、G、B各占一字节。 YUV "Y"表示明亮度(Luminance),"U"和"V"则是色度、浓度(Chrominance、Chroma)。之所以使用YUV编码方法,主要有这些原因: R、G、B三个分量的相关性很强,存在冗余,使用YUV后可进行数据压缩 人眼对亮度信号较敏感,对色度信号较不敏感,可通过较少UV分量进行数据压缩 彩色信号能很好兼容黑白电视,黑白视频只有Y分量 YUV、YCbCr YUV解决彩色信号对黑白电视的兼容,黑白电视也能接收彩色电视信号。 Y:亮度(黑白图像) UV:彩度 YUV针对模拟信号。YCbCr模型针对数字信号,是YUV压缩和偏移的版本。一般俗称的YUV大多是指YCbCr。如下是某YCbCr图像的三个分量组成,其中其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。 YUV与RGB的转换 YUV与RGB可以按公式进行互相转换,具体可参考文末的参考[1]。 YUV采样 YUV 4:4:4采样,每一个Y对应一组UV分量。24 Bits per Pixel。 YUV 4:2:2采样,每两个Y共用一组UV分量。16 Bits per Pixel。 YUV 4:2:0采样,每四个Y共用一组UV分量。12 Bits per Pixel。 上图中黑点表示采样该像素点的Y分量,以空心圆圈表示采用该像素点的UV分量。 YUV 存储格式 YUV的存储格式有两大类: 紧缩格式(packed formats):将Y、U、V值存储成Macro Pixels数组,和RGB的存放方式类似。YUV4:4:4格式而言,用紧缩格式最合适。大概格式为:YUVYUVYUVYUV 平面格式(planar formats):将Y、U、V的三个分量分别存放在不同的矩阵中。大概格式为:YYYYUV。 YUV常见表示方法 根据采样方式和存储格式的不同,就有了多种 YUV 格式。这些格式主要是基于 YUV 4:2:2 和 YUV 4:2:0 采样。 常见的几乎都是基于YUV4:2:0: YU12。先存储 Y 分量,再存储 U、V 分量。例如:YYYYYYYYUUVV。 YV12 ,又称作 I420 格式。它的存储格式就是把 V 和 U 反过来了。例如:YYYYYYYYVVUU。 NV12。先存储了Y分量,但接下来并不是再存储所有的U或者V分量,而是把UV分量交替连续存储。例如:YYYYYYYYUVUV。NV12在硬件编解码中用的比较多。 如下图所示,为YUV420的存储格式,每4个Y对应一组UV: 视频 连续的图像变化每秒超过24帧(frame)画面以上时,根据视觉暂留原理,人眼无法辨别单幅的静态画面,看上去是平滑连续的视觉效果,这样连续的画面叫做视频。视频里面的每一幅图像称为一帧。 视频图像扫描 包括显示器扫描和摄像机视频捕获扫描两个环节。分为逐行扫描和隔行扫描两种扫描方式。 隔行扫描(Interlace Scanning) 每帧分为两场:奇数行组成奇数场,偶数行组成偶数场。 在显示器扫描中,隔行扫描指在显示一幅图像时,先扫描奇数行,再扫描偶数行,因此每幅图像需扫描两次才能完成。 摄像机在进行视频捕获时,例如对于25帧视频,每秒钟扫描50场,每一场只有半幅图像,意味着我们看到的图像的每一帧都是由两个采集时间不同的“半幅”图像合并而成的。当我们观看隔行扫描的视频时,会出现行间闪烁、运动模糊、垂直边缘锯齿等现象,从而影响画面清晰度。一般比较早期的视频是隔行扫描采集的。如下是一个隔行扫描视频截图,可以看到人物运动时有明显的锯齿。 该视频链接如下,大家可以认真看下人物运动时的边缘: https://music.163.com/#/mv?id=5309079 逐行扫描(Progressive Scanning) 每次扫描完所有行,从上到下逐行扫描。在显示器扫描中,逐行扫描指从上到下的扫描每一行图像。摄像机在进行视频捕获时,例如对于25帧视频,每秒钟扫描25场,每一场是完整一副图像。画面平滑干净、细节清晰、没有闪烁感、也不会产生运动模糊与锯齿现象。 1080P和1080i的区别 1080i:就是1920x1080分辨率。不过这种高清图像是隔行扫描(Interlace Scanning)的。每一个奇数行图像都在每一偶数行图像后面显示出来,当然图像就不会那么平滑。1080i适于表现纪录片和野生动物等题材,但是不是那么适合播放运动和电影类的内容。 1080p:也是1920x1080分辨率。和1080i的区别就在于1080p不是隔行扫描的,而是逐行扫描(Progressive Scanning)。每一线都同时表现在画面上,因此比隔行扫描更加得平滑。这是更高的高清标准。 视频时间戳(Timestamp) 每一帧的采样时间tn(相对)为时间戳。时间单位为采样频率或具体时间单位(如毫秒)。 RTP timestamp是用采样频率表示时间的。两帧之间RTP timestamp的增量 = 采样频率 / 帧率 例如:90kHz作为视频采样频率,视频帧率为25fps,相邻帧间RTP timestamp增量值 = 90000/25 = 3600。 视频帧率(Frame rate) 每秒播放的图像帧数量(Frames per Second,简:fps)。目前常见帧率:25fps、30fps、60fps、90fps、120fps。 视频码率(Bitrate) 单位时间传送的数据bit数,一般我们用的单位是kbps,也就是数据bit数除以1000(不是1024,发现很多人这个很容易搞错)。 码率越大,单位时间包含的数据越多,视频质量越好。目前有如下两种码率类型: 可变码率(Variable bitrate,简称VBR),指编码码率会随图像的复杂程度的不同而变化。 固定码率(Constant bitrate,简称CBR),指编码码率是固定的。 视频压缩的必要性 1920x1080@30fps视频的每秒数据量: RGB:1920x1080x3x30 = 186624000B = 186M YUV420:1920x1080x1.5x30 = 93M 可以看到数据量非常大。所以为了存储以及网络带宽要求,需要对视频数据进行压缩。 视频压缩原理 利用了视频数据的冗余。例如如空间冗余、时间冗余、结构冗余、信息熵冗余等,即图像的各像素之间存在着很强的相关性。通过消除这些冗余信息实现视频数据的压缩。 时间上的冗余信息(temporal redundancy)。在视频数据中,相邻的帧(frame)与帧之间通常有很强的关连性,这样的关连性即为时间上的冗余信息。 空间上的冗余信息(spatial redundancy)。在同一张帧之中,相邻的像素之间通常有很强的关连性,这样的关连性即为空间上的冗余信息。 统计上的冗余信息(statistical redundancy)。统计上的冗余信息指的是欲编码的符号(symbol)的几率分布是不均匀(non-uniform)的。 视觉冗余。人眼的一些特性比如亮度辨别阈值,视觉阈值,对亮度和色度的敏感度不同,使得在编码的时候引入适量的误差,也不会被察觉出来。可以利用人眼的视觉特性,以一定的客观失真换取数据压缩。 如下图为视频相邻帧间时间上的冗余信息,可以看到只有头部对应的像素发生了变化: 下图为利用空间上的冗余信息进行帧内压缩(后面提到的I帧压缩原理): 下图为利用时间上的冗余信息进行数据压缩(后面提到的P帧压缩原理),参考了前面的视频帧: 下图为利用时间上的冗余信息进行数据压缩(后面提到的B帧压缩原理),参考了前面以及后面的视频帧: 视频编解码器(Codec) 能够对数字视频进行压缩或者解压缩的程序或者设备。下图为一个典型的视频编码器。在进行当前信号编码时,编码器首先会产生对当前信号做预测的信号,称作预测信号(predicted signal),预测的方式可以是时间上的预测(inter prediction),亦即使用先前帧的信号做预测,或是空间上的预测(intra prediction),亦即使用同一张帧之中相邻像素的信号做预测。得到预测信号后,编码器会将当前信号与预测信号相减得到残余信号(residual signal),并只对残余信号进行编码,如此一来,可以去除一部分时间上或是空间上的冗余信息。接着,编码器并不会直接对残余信号进行编码,而是先将残余信号经过变换(通常为离散余弦变换)然后量化以进一步去除空间上和感知上的冗余信息。量化后得到的量化系数会再透过熵编码,去除统计上的冗余信息。在解码端,透过类似的相反操作,可以得到重建的视频数据。 对于编解码器,有硬件以及软件类型,硬件一般基于显卡或者FPGA设备,性能较高,能耗低,软件编解码器一般是指通过CPU进行视频编解码。 I帧、B帧、P帧 详细压缩原理在前面小节分析过了。 I帧:帧内编码图像帧(关键帧),帧内压缩。不依赖其它帧就可以解码还原出完整一帧图像。 P帧:预测编码图像帧,帧间压缩。依赖前面的I帧或P帧进行解码 B帧:双向预测编码图像帧,帧间压缩。提供最高的压缩比,它既需要之前的图像帧(I帧或P帧),也需要后来的图像帧(P帧),采用运动预测的方式进行帧间双向预测编码。 Note:对于实时视频(如摄像头),一般不产生B帧,因为用B帧,意味着会导致一定的帧延时 关键帧 VS 参考帧 GOP(Group of picture) GOP指画面组,一个GOP就是一组连续的画面。I帧表示一个GOP的开始。GOP大小指两个I帧之间的距离(两I帧之间的帧数量)。例如如下帧序列: IBBPBBPBBPBBI GOP大小为12。在视频直播中,为了秒开,GOP大小不宜设置过大。 DTS、PTS DTS:Decoder Timestamp,用来表示图像的解码时间 PTS:Presentation Timestamp,用来表示图像的显示时间 引入这两变量主要是因为,在存在双向参考帧(B帧)时,图像在编码图像的顺序和编码输出的顺序不同,而对于audio 来说,audio没有双向的预测, DTS 和 PTS 可以看成是一个顺序的,因此可一直采用一个,即可只采用 PTS。 如下是一个含有B帧的码流,在解码器端,对于前面4帧来说,得先解码B帧参考的I帧以及P帧,才能解码后续的B帧,所以解码顺序为IPBB,但是实际显示顺序为IBBP,所以DTS与PTS就不一样。 视频编码格式 目前主要有如下几种视频编码格式: H264/AVC。迄今为止业界最为成功的音视频编解码标准。 H265/HEVC。H.264官方的继任者。进一步的工业化目前受到了专利授权费用的显著影响,未来仍不明朗。 VP9。HEVC的一个不可忽视的竞争对手。人气不够高,Google在使用。性能没有受到业界的广泛认可。 AV1(AOMedia Video 1)。针对HEVC的专利问题,Google为首的多家公司成立了AOM(Alliance of Open Media,http://aomedia.org/)组织,专门研发的替代HEVC的免费开放视频编解码标准。 下图是视频编解码器发展历史。 视频容器 也叫封装格式,把已经编码好的视频、音频裸流按照一定的规范放到一起。里面可能还有元信息(metadata)、字幕、脚本之类。 常见容器格式有:MP4,AVI,FLV,MKV。如下是一个MP4容器文件包含的内容: 参考 [1] YUV.https://en.wikipedia.org/wiki/YUV. [2] 视频.https://baike.baidu.com/item/%E8%A7%86%E9%A2%91/321962?fr=aladdin. 本文已收录到大话WebRTC专栏,更多精彩请访问《大话WebRTC》。

2020年8月16日 5comments 4687hotness 28likes Jeff Read all
WebRTC

WebRTC研究:FEC之RED封装

首先看下webrtcglossary中的定义。 RED stands for REDundant coding and it is a RTP payload format defined in RFC 2198 for encoding redundant audio or video data. The primary motivation of sending redundant data is to be able to recover packets lost under lossy network conditions. If a packet is lost then the missing information may be reconstructed at the receiver from the redundant data that arrives in the following packet(s). The use of RED is negotiated in the SDP as an additional payload type and when used the audio/video RTP packets are packaged using RED format with a 6 bytes header, before the primary and secondary payloads conveying the actual audio/video packet and the redundant information. RED封装简介 RED指冗余编码,并且依据RFC 2198定义了一种RTP有效载荷格式,用于携带冗余编码的音视频数据。RED封装的数据作为payload跟在RTP报头后面。RED封装的数据有自己的Header。在一个RTP包中,会包含多个RED Header,指定了后面携带的编码数据信息。这些RED Header依次跟在RTP报头后面,在这些RED Header后就是各个RED Header对应的冗余编码数据。 如下是一个携带两个RED Header的RTP包结构: |RTP header| RED header | RED headr | RED encoding data | RED encoding data| RED Header结构如下: [crayon-69cbc609a2c3a667000379/] F: 1 bit长度,说明后面是否还有其他RED Header跟着。为1说明还有其他RED Header跟着,为0说明这是最后一个RED Header blcok PT:7 bits长度,表示该RED Header对应的冗余编码类型 timeoffset: 14 bits长度,表示无符号长度时间戳偏移,该偏移是相对于RTP Header的时间戳。用无符号长度做偏移意味着冗余编码数据必须在发送完原始数据后才能发送 block length: 10 bits长度,表示该RED Header对应编码数据块长度,该长度包含RED Header字段 对于RTP包中最后一个RED Header,可以忽略block length以及timestamp。因为它们可以从RTP Fixed Header以及整个RTP包长度计算得到。最后一个RED Header结构如下: [crayon-69cbc609a2c44705775180/] 其中F-bit位始终为0。 如下是一个完整RTP包示例,包含两个编码数据块:DVI4编码块,以及一个LPC冗余编码块。可以看到有两个RED Header跟在RTP Fixed Header后,第一个RED header F-bit为1,第二个RED Header由于是最后一个,所以F-bit为0,不包含时间戳偏移以及数据块长度信息。在RED Headrs后就是对应的编码数据块。 [crayon-69cbc609a2c49089540375/] 视频RED封装代码 这里我们以视频FEC为例,在WebRTC中音频的带外FEC也用到了RED编码。 UlpfecGenerator::GetUlpfecPacketsAsRed WebRTC视频相关RED封装代码位于UlpfecGenerator类中。RED封装主要配合UlpFEC使用。这里我们看下UlpFEC编码数据封装为RED包的过程: [crayon-69cbc609a2c4d549528319/] RedPacket::CreateHeader 对于视频,WebRTC中RED HeaderF-bit总是为0,不包含时间戳偏移等信息,也就是说一个RTP包只包含一个RED header: [crayon-69cbc609a2c51393620104/] 视频RED解析代码 相关处理位于UlpfecReceiverImpl类中,我们看下主要的代码: [crayon-69cbc609a2c56671381863/] 参考 [1] RED (REDundant coding).https://webrtcglossary.com/red/. [2] RTP Payload for Redundant Audio Data.https://tools.ietf.org/html/rfc2198. 本文已收录到大话WebRTC专栏,更多精彩请访问《大话WebRTC》。

2020年8月16日 10comments 6464hotness 6likes Jeff Read all
WebRTC

WebRTC研究:带宽估计中的稳定估计值

WebRTC带宽估计后,得到的结果会存到TargetTransferRate结构体中,然后回调给上层。TargetTransferRate定义如下: [crayon-69cbc609a40d8547340618/] 可以看到该结构体有两个估计码率值,本文我们介绍下其中的stable_target_rate,该值在后续的码率分配中有用到,配合target_rate进行相关判断。 在GoogCcNetworkController中,TargetTransferRate结果值按如下得到: [crayon-69cbc609a40e2716023133/] 其中pushback_target_rate为我们实际的带宽估计值,stable_target_rate取带宽估计值与EstimatedLinkCapacity小的一个。 SendSideBandwidthEstimation 如下代码可知,LinkCapacity通过LinkCapacityTracker(link_capacity_)计算得到,接下来我们看看这个LinkCapacityTracker究竟是什么东东。 [crayon-69cbc609a40e6524689504/] LinkCapacityTracker LinkCapacityTracker类比较简单,接口不多,这里我们介绍下主要的两个接口,通过这两个接口进行LinkCapacity的更新。 UpdateDelayBasedEstimate 主要两个输入参数如下: at_time: 当前时间 delay_based_bitrate:当前基于时延的带宽估计值 这里我们分析下该函数代码: [crayon-69cbc609a40e9659688489/] OnRateUpdate 主要有如下三个输入参数: acknowledged:根据接收端反馈的信息计算的接收码率(通过Transport-CC报文,该报文详细分析可去我博客搜索下) target:当前综合时延以及丢包信息得到的带宽估计值 at_time:当前时间 该函数具体分析如下: [crayon-69cbc609a40ed801544469/] 通过前面两个函数,得到的capacity_estimate_bps_即为我们前面说的稳定估计值stable_target_rate。由前面分析可知,该stable_target_rate综合了当前带宽估计值以及实际接收码率,从计算过程可知比较保守。从实际测试效果看,该估计值也正如其名,相对实际带宽估计值target_rate会更平稳,值也会相对小些。

2020年8月12日 2comments 3117hotness 5likes Jeff Read all
WebRTC

Windows平台WebRTC编译(持续更新)

在音视频领域,想深入研究的话,必定会接触WebRTC。WebRTC是一个庞大的工程,就像是音视频领域的百科全书,音视频采集,编解码,传输,渲染等一条龙在WebRTC里都有,而且WebRTC还有很多先进的音视频处理算法。由于WebRTC代码过于庞大,所以最好单步调试跟踪代码运行,这样才可以更好地学习WebRTC,否则很难有头绪。工欲善其事必先利其器,作为调试神器,宇宙第一IDE Visual Studio必不可少。所以本篇文章主要讲下如何在Windows上编译WebRTC,同时得到VS工程,然后调试。 很早以前写过VS2017上的编译,不过那篇文章有点跟不上时代,因为WebRTC用到的编译工具以及版本总是变化的,所以另开此文章,同步更新Windows平台最新编译步骤。 本文内容截止2025.08.18,最新代码测试编译通过 系统要求 Win10及以上64位系统。 内存至少8G,当然越大越好。 至少100G磁盘空间(NTFS格式),不能是FAT32,因为会生成大于4G的文件。 Visual Studio安装 要求 Visual Studio 2022 (>=17.0.0)。这里我们选择VS2022的社区版。安装VS2022时选择自定义安装,必须勾选如下几项: Desktop development with C++组件中10.0.26100.3323或以上的Win11 SDK(如果没看到该版本,去左侧Individual components那里勾选) Desktop development with C++组件中MFC以及ATL这两项 Desktop development with C++组件中适用于Windows的C++ Clang工具,这个很重要,新版WebRTC已经不支持MSVC编译器了 安装完VS2022后,必须安装SDK调试工具。打开控制面板->程序与功能,找到刚才安装的最新Windows Software Development Kit,鼠标右键->change。 勾选Debugging Tools For Windows,然后点击change。 depot_tools安装 下载depot_tools然后解压到某个目录,比我的解压到E盘根目录。接着将该depot_tools目录的路径加到系统环境变量Path里,然后把该路径移到最前面(避免已安装的python与git造成影响)。 或者直接通过如下命令行快速安装设置: [crayon-69cbc609a524d460622968/] 获取WebRTC源码 由于WebRTC的源码地址被墙了,所以需要通过科学工具访问才能得到源码。后面都是命令行操作,打开cmd窗口,例如我用的是Clash代理,在cmd窗口设置如下: [crayon-69cbc609a5256678744970/] 设置当前cmd窗口代理上网,如果cmd窗口关闭了重开得重新设置。 接着执行gclient命令,更新depot_tools。一般我们刚下载的都是最新的,可以跳过这一步。 [crayon-69cbc609a5259429155148/] 后续如果不希望执行gclient有关命令时候自动更新浪费时间,可以通过如下命令设置: [crayon-69cbc609a525d656514019/] 再接着设置一些环境变量,设置下我们的VS安装路径以及Windows SDK路径,这里我是安装在C盘。由于我用的社区版,所以路径名后缀是Community,其他VS版本可按实际修改。 [crayon-69cbc609a5260078061530/] 然后cd到要放源码的地方,执行: [crayon-69cbc609a5263956565022/] 这一过程是个漫长的等待,包括源码,第三方库,以及一些测试的音视频文件资源等,同时自动执行一些hook任务。如果因为网络等原因中断了,就再执行gclient sync。如果这一步一直卡着不动,可以执行ctrl+c,然后执行gclient sync。 这里为了避免中途中断,重新执行gclient sync时间太久,可以将gclient sync分两步执行: [crayon-69cbc609a5267607662524/] 编译工程 生成VS工程文件 首先需要生成工程文件。WebRTC默认使用Ninja作为编译系统,Ninja工程文件通过GN生成,由于我们需要使用VS进行代码编辑调试等,所以使用GN生成Ninja工程时需要配置--ide=vs生成VS的工程文件。通过如下命令生成工程文件(Debug编译,工程文件位于out\Default目录下): [crayon-69cbc609a526a210323605/] 我们可以在src\out\Default下得到 VS2022的all.sln解决方案文件。 如果需要Release编译,通过如下命令生成工程文件: [crayon-69cbc609a526e976960675/] 如果不想使用默认编译参数,可以使用gn args out/Default --list查看当前编译参数,通过类似如下方式设置: [crayon-69cbc609a5271179692450/] 编译 生成工程文件后,就可以在src目录下执行编译命令: [crayon-69cbc609a5274469211494/] 用VS2022打开: 可以看到众多工程,到此算是完成了。找到我们感兴趣的,就可以用VS单步调试,跟踪代码运行了。 代码更新 后续如需要更新代码,按照如下步骤: [crayon-69cbc609a5277716402366/] 然后参考前面步骤重新生成工程文件,编译即可。 引用WebRTC库 WebRTC编译后会在src\out\Default\obj目录下生成整个WebRTC工程的静态库:webrtc.lib,链接下这个就可以了。 PS:最新版只支持Clang编译器。如果VS应用没配置Clang编译器,链接这个webrtc.lib,生成工程文件时需要配置如下参数: gn gen --ide=vs out/Default --args="is_clang=false use_lld=false" 禁用clang与lld 由于最新版只支持Clang编译器,同时WebRTC也带有自己的Clang编译器(third_party\llvm-build目录下),所以可能跟VS前面配置下载的Clang编译器版本不同,导致出现webrtc.lib链接错误,所以需要配置WebRTC使用Visual Studio的Clang编译器。 拷贝Visual Studio的Clang编译器目录Llvm到webrtc-checkout目录下,当然也可以直接覆盖替换WebRTC自带的。Clang编译器目录位置举例:C:\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm gn gen参数增加:clang_base_path = "..\..\..\..\Llvm",告诉WebRTC使用的Clang编译器目录。也可以修改out\Default\args.gn,增加clang_base_path gn gen参数增加:use_custom_libcxx=false,告诉WebRTC构建系统gn不使用WebRTC 源码中自带的C++标准库(libcxx),而是使用系统或工具链提供的标准C++库,不配置为false,使用Clang编译的会报链接错误 最后修改我们的Visual Studio应用属性配置,使用Clang编译。修改位置:General->Platform Toolset->LLVM (clang-cl) 总结 总之WebRTC在Windows上的编译很考验耐心,只要你的科学上网工具够好,编译就会顺畅很多。 如果遇到问题,可以多看下文章,是不是哪里漏了,或者看下评论,不要一上来就问为什么编译不了。 参考 [1] WebRTC Native code Development.https://webrtc.github.io/webrtc-org/native-code/development/. [2] Chromium’s build instructions for Windows.https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md.

2020年8月11日 85comments 33682hotness 56likes Jeff Read all
WebRTC

Google C++ style Guide图解

Google C++ Style Guide的官方完整文本可在GitHub博客上获取。由于从事WebRTC开发,所以代码规范遵循这个,个人觉得很简洁紧凑,还好看。 如下图片是该代码规范的总结图,收藏用:

2020年7月11日 0comments 7hotness 0likes Jeff Read all
12345…26
Copyright Statement

Unauthorized reproduction or plagiarism in any form is strictly prohibited. For reprint requests, please contact via email.

Recent Comments
Muraknuh Published at 1 hours ago(03 03202633107 31 31pm26) Shiresse Nobel, age 7, was having minimal seizures...
MurakLierpef Published at 1 days ago(03 03202633105 30 30pm26) Sometimes simple visual hallucinations may also oc...
snail Published at 4 days ago(03 03202633105 27 27pm26) 多谢,大佬。醍醐灌顶!
Bramsnawl Published at 4 days ago(03 03202633110 27 27am26) Proper blood collection playing cards are measure ...
NasibDepdrotte Published at 5 days ago(03 03202633110 26 26pm26) Inf ect isC linNo rth A m viiiix, Sm ets o urgo is...
Ad

COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang