当前位置:网站首页>webrtc中视频采集实现分析(二) 视频帧的分发
webrtc中视频采集实现分析(二) 视频帧的分发
2022-08-04 05:25:00 【mo4776】
文章目录
需求
在上一篇介绍了webrtc中的视频采集模块的接口。视频采集模块抛出视频数据后,对视频帧的处理需求一般包括如下几种:
- 视频帧送到编码模块进行编码
- 视频帧送到渲染模块进行本地回显
- 视频帧先进行预处理(比如添加水印,字幕),再送去回显或编码
- 视频帧会送到多个编码器,产生多路不同分辨率,码率的码流
相当于一个“源头”有多个“支流”,通过回调拿到的视频帧数据就是“源头”,如上的各种需求就是“支流”。视频帧数据要按需分发,满足各个“支流”的需要。那么在代码中的体现就是一个source,多个sink。
分发框架涉及到类
webrtc中有一个对视频帧的分发框架,可以直接复用,包括videoSourceInterface,videoSinkInterface,VideoBroadcaster
videoSourceInterface
作为source的基类,指“源头”
- 主要接口是
AddOrUpdateSink()和RemoveSink(),videoSourceInterface可以添加多个sink AddOrUpdateSink接口的第二个参数是VideoSinkWants结构体,下面是它的定义
struct VideoSinkWants {
VideoSinkWants();
VideoSinkWants(const VideoSinkWants&);
~VideoSinkWants();
// Tells the source whether the sink wants frames with rotation applied.
// By default, any rotation must be applied by the sink.
bool rotation_applied = false;
// Tells the source that the sink only wants black frames.
bool black_frames = false;
// Tells the source the maximum number of pixels the sink wants.
int max_pixel_count = std::numeric_limits<int>::max();
// Tells the source the desired number of pixels the sinks wants. This will
// typically be used when stepping the resolution up again when conditions
// have improved after an earlier downgrade. The source should select the
// closest resolution to this pixel count, but if max_pixel_count is set, it
// still sets the absolute upper bound.
absl::optional<int> target_pixel_count;
// Tells the source the maximum framerate the sink wants.
int max_framerate_fps = std::numeric_limits<int>::max();
// Tells the source that the sink wants width and height of the video frames
// to be divisible by |resolution_alignment|.
// For example: With I420, this value would be a multiple of 2.
// Note that this field is unrelated to any horizontal or vertical stride
// requirements the encoder has on the incoming video frame buffers.
int resolution_alignment = 1;
};
主要就是描述sink期望的分辨率,帧率等,上面的注释也写的很明白了。
videoSinkInterface
作为sink的基类
主要接口是OnFrame()和OnDiscardeFrame()
这两个类就代表着source和sink,一个source中可以添加多个sink,source通过调用sink中的OnFrame方法,将视频帧数据传给sink
VideoBroadcaster 视频帧分发类
- VideoBroadcaster类,看名字就知道是视频帧分发类。上面的类图可以看到,VideoSourceBase既是一个source也是一个sink。
VideoBroadcaster可以放入对个sink,但它会对所有的sink集合的want做个合并,取的帧率帧率值是sink want中的最小值,分辨率的值也是sink want中的最小值但是source提供的视频帧不满足sink时就需要对视频帧数据做适配了,那么
VideoAdpater就是这样的作用了
VideoAdpater
VideoAdpater相当于一个filter,对source中的视频帧进行过滤,来满足sink的要求
VideoAdpater可以实现对帧率的过滤和对分辨率的缩放
基本框架
通过上面的这几个类的关系,就拼出了一个视频帧分发的框架

videocaputre代表视频采集模块,它到代表了总的数据“源头”,通过回调将视频帧数据给VideoBroadcaster,VideoBroadcaster再将视频帧分发到各个sink。
前一篇文章中 VideoCaptureModule有个回调注册接口void RegisterCaptureDataCallback(rtc::VideoSinkInterface<VideoFrame>* dataCallback),可以将VideoBroadcaster作为sink注册。
需要注意的是,VideoBoradcaster并没包含VideoAdpater类,它没有适配功能,只是单纯的分发。如果要对视频帧数据进行适配就需要在VideoBoradcaster得前面或后面加上VideoAdpater。
变化
webrtc中的VideoBoradcaster的用途是有局限的,它并不能实现不同帧率,不同分辨率的分发(上面提到它会对所有的sink wants做合并,取sink wants中的帧率,分辨率的最小值)。它适用于对帧的用途的分发,比如有的被送去编码,有的被送去本地回显,都是同一种分辨率和帧率。
所以上面的这个组合图,是并不能满足产生多路不同分辨率,帧率的码流场景。
考虑这样一个需求:
- 能产生三路码流,它们有不同的分辨率,帧率
- 能本地回显
所以需要像下面这种方式来进行组合了
videocatpure采集的视频是30fps,720P。需要产生三路码流(有三个编码器对象)和本地回显,VideoAapter不能放在VideoBroadcaster前面,因为VideoBroadcaster只能输出同样的帧率和分辨率。需要在video encoder前面放一个VideoAapter,满足帧率,分辨率的要求。
VideoAapter在满足帧率时,会进行丢帧处理,所以这三个VideoAapter+Video encoder应该是分别在一个线程中。
webrtc中的例子
在例子peer_conection_client的实现中,是通过TestVideoCapturer类集成了VideoAdapter和VideoBroadcaster,可以参考下如何实现将它们连接起来的。但是在浏览器的实现中应该不通过TestVideoCapturer实现的,因为它的实现是满足不了需求多路不同分辨率,帧率的码流的。
边栏推荐
- 4.1 JdbcTemplate for declarative transactions
- 即时通讯网 即时通讯音视频开发
- 7.18 Day23----标记语言
- string类简介
- Delphi-C端有趣的菜单操作界面设计
- Cannot read properties of null (reading ‘insertBefore‘)
- The Road to Ad Monetization for Uni-app Mini Program Apps: Full Screen Video Ads
- MySQL日志篇,MySQL日志之binlog日志,binlog日志详解
- MySQL日期函数
- Web Basics and Exercises for C1 Certification - My Study Notes
猜你喜欢

FLV格式详解

关于C#的反射,你真的运用自如嘛?

DP4398:国产兼容替代CS4398立体声24位/192kHz音频解码芯片

The symbol table

擎朗智能全国研发创新中心落地光谷:去年曾获2亿美元融资

Canal mysql data synchronization

C1认证之web基础知识及习题——我的学习笔记

The cost of automated testing is high and the effect is poor, so what is the significance of automated testing?

谷粒商城-基础篇(项目简介&项目搭建)

在被面试官说了无数次后,终于潜下心来整理了一下JVM的类加载器
随机推荐
PHP解决字符乱码问题(多种编码转换)
string类简介
Swoole学习(一)
JS basics - forced type conversion (error-prone, self-use)
npm init [email protected] 构建项目报错SyntaxError: Unexpected token ‘.‘解决办法
npm报错Beginning October 4, 2021, all connections to the npm registry - including for package installa
Can‘t connect to MySQL server on ‘localhost3306‘ (10061) 简洁明了的解决方法
7.15 Day21---MySQL----Index
3面头条,花7天整理了面试题和学习笔记,已正式入职半个月
Unity行为树AI分享
即时通讯网 即时通讯音视频开发
FLV格式详解
CentOS7 - yum install mysql
7.16 Day22---MYSQL (Dao mode encapsulates JDBC)
注意!软件供应链安全挑战持续升级
Gartner 权威预测未来4年网络安全的8大发展趋势
LCP 17. Quick Calculation Robot
12. Paging plugin
OpenRefine中的正则表达式
Handling List