- 博客(97)
- 资源 (4)
- 收藏
- 关注
原创 webrtc中的Track,MediaChannel,MediaStream
Audio/Video track,MediaChannel,MediaStream是Webrtc的业务核心,对媒体的操作都是围绕着这三个对象进行,弄清出它们见的关系及作用,就等于弄清了Webrtc的骨架,对阅读Webrtc的代码大有益处。根据本地sdp或sdp的协商结果,来产生MediaChannel,MediaChannel代表一个Video或Audio通道,里面会有多个不同方向的MediaStream。sdp中的媒体信息需要转化为具体的编解码器,rtp流的信息。这些信息最终会分别变成为。
2024-04-14 21:30:06 1535
原创 C++ 模板基础知识(二)
可以是函数,函数指针,函数对象,lambad。),将会返回一个数据结构包含一个类型成员,指示得到的类型,推导出返回值的类型,推导是编译期完成。模板参数除了类型参数,可以使用非类型参数,如下,类模板。通过下面三种方法可以使编译器确定模板函数的返回值类型。下面是C++ 14及之后标准的写法,写法更简单些。它可以推导两种或多种不同类型的共同类型(如下定义了一个非类型参数的函数模板,结合。可以看到推导出来的类型为double。内的表达式不同了,这里要注意。上面是C++ 11的写法,用于获取表达式的类型,通过。
2024-03-24 19:24:28 1042
原创 C++模板基础知识
为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义。因此,与非模板代码不同,模板的头文件通常即包括声明也包括定义。函数模板和类模板成员函数的定义通常放在头文件中。像常规的头文件和源文件分离编译的情况,在模板情况下行不通。如下模板类Blob,在文件中public:public:T getA();U getB();U _b;如果将Blob类中的构造函数及getA()和getB()函数,定义在文件return _a;return _b;那么在。
2024-03-09 09:43:15 970
原创 webrtc native api的几个要点
sdp中核心的信息就是描述媒体信息的内容,简称m行或媒体行。通过pc对象的AddTrack或AddTransceiver方法添加track,会直接反映到sdp中。一个PC对象表示一次P2P会话,它包括sdp handle,call。如下代码,添加了两个VideoTrack,最终反映到sdp中为两个sendrecv的m行。整个过程本质就是获取本地sdp信息和远端sdp信息,再进行协商,流程可以概括为如下图。,前者是告知sdp创建,协商的状态。,是webrtc native的pc对象封装示例代码。
2024-02-06 20:15:49 1660
原创 ZLMediaKit 切换用于源的RingBuffer
那么把它抽象为技术实现,就是web同时会与ZLMediaKit建立4个pc对象,这个4个pc对象建立后,就不会销毁(直到web播放器关闭),由ZLMediaKit根据web请求的rtsp摄像头标识,将不同摄像头的流转给web。有这样一个需求,基于webrtc实现的web实时流播放器,有4分屏,最大同时显示4个图像rtsp摄像头的图像。对象的生命周期只与任务对象一样长,这样显然不是原始要表达的意图,应该改成如下,在外部定义。中切换源,但是它并未提供这样的功能,根据上面的分析,可以加一个。上连了多少个连流端。
2024-01-08 21:46:30 1086
原创 通过ZLMediaKit来说说流媒体服务的实现
rtc中的流媒体服务主要目标是保证高效的转发,在基于udp/rtp协议的系统中,直接转发rtp包,不会转协议,不涉及到组帧,拆包,音视频同步。现在有很多开源事件库实现,比如libevet,libuv,asio等,不同的实现,主要是在性能,功能,和跨平台上做文章来突出差异化。现在服务器的实现大多采用了多线程模式,即多进程多线程或单进程多线程,ZLMediaKit是单进程多线程服务,虽然它有两个进程,但是其中一个是守护进程,并不处理业务。会出现多进程多线程,单进程多线程,单进程单线程,多进程单线程的各种模式。
2024-01-04 08:06:50 1086
原创 webrtc中的接口代理框架
模块提供接口,外部代码通过接口来使用模块功能。业务应用通过一层proxy来使用webrtc通过功能,也就是应用层与webrtc通过proxy隔离。在webrtc中通过一种接口代理的方式,来封装了对外的接口。(类图中我列出了类所在的文件名,方便查看代码,它的接口太多,这里就不列出了)(类图中我列出了类所在的文件名,方便查看代码,列出了几个核心的接口)文件中,这里就不展开叙述了,可以直接看看代码,是怎么使用的。在webrtc中需要导出的接口,采用的是如上的类体系。方法,它将产生接口类的实例类,供应用使用。
2024-01-01 12:03:06 1348
原创 我的2023年,平淡中寻找乐趣
我很满意的是我坚持了下来,虽然在很长的一段时间里,每天只背十个单词,这一年英语水平并没有大的提高。学习言语重要的是听与说,我也改变了背单词的策略,重点是听,是熟悉它的读音,而不是光记怎么写。要听到音后,知道是什么意思,怎么拼写,也就是记住了。经过一个月的练习,换气也顺畅了,划水也掌握了要领。剩下就是练习熟练度了,反复练。以这样的标准,反复练习,如果在水中感觉到了滑翔的感觉,就表示练成了。换气比较顺畅了,划水没掌握要领,前进基本靠腿打水,搞的小腿经常抽筋。开始无法顺畅换气,憋上一口气,游个20米,就不行了。
2023-12-28 22:41:26 423
原创 ZLMediaKit的转流流程(二)
中的suorce作为源时,此时就涉及到了组帧,拆包的过程了。中,通过信令协商产生了对应的音视频的Track,视频对应的Track为。,它是一个各种协议的muxer类,将视频帧按不同的协议进行拆包。**如果有rtmp的拉流端则会直接使用这个源,以。类型,数据将由它们转发。下面Frame的牛转图。类型的成员变量,存放的就是Frame的消费者。,视频帧又被拆分为各协议对应的包。类型,作为一个Rtmp的源。视频帧的转发的被抽象为一个。在以Rtsp为源的情况下,方法传入的是rtp包,经过。
2023-12-27 08:04:42 1365
原创 优秀的流媒体服务器ZLMediaKit
它适用于视频监控系统的转流服务或作为RTC系统的边缘媒体网关。而不太适合于高实时要求的RTC SFU转流服务。ZLMediaKit 是国人写的优秀的流媒体服务器,它支持的协议多,稳定,性能优秀。它的可以作为音视频开发的百宝箱,特别是对协议的实现,可以直接复用。
2023-12-24 20:38:28 631
原创 ZLMediaKit中的RingBuffer
前面的文章讲到ZLMediaKit转流,提到过RingBuffer,它是比较核心的数据结构。这篇文章就来讲讲RingBuffer的用法。
2023-12-24 20:09:02 1213
原创 40岁的堂哥从华为“退休“了
堂哥刚40出头,他说持续了十几年的高强度工作,现在有点力不从心了,心里总是想着工作,都不知道怎么生活了,思想无法放松,睡觉都在想工作的事。跟身边的同学,朋友聊起来,大家都有这样的顾虑,普遍都比较焦虑,但是人到中年,选择面越来越少,现在市场活力降低,就业学历歧视,年龄歧视的状态下,也很难有所改变。反观我呢,在二线城市普通的中年程序员,在私企上班。他学历背景不好,04年计算机应用专科毕业,毕业那年去深圳参加了软件测试的培训班,第二年进入了华为外包公司慧通,干了没多久,慧通被华为兼并,他也转成了华为的正式员工。
2023-12-21 10:21:07 1034
原创 ZLMediaKit的转流流程(一)
zlmediakit的优势就是支持多种媒体容器和媒体协议。我从推流和拉流的两个角度,梳理出了转流的核心骨架。
2023-12-20 07:43:38 2098
原创 ZLMediaKit中的线程
EventLoop在众多的开源网络库都有实现。ZLMediaKit的实现非常适合用于多线程模型。这种方式非常适用于对线程职责的划分,将特定的业务通过消息队列分到固定的线程。就是EventLoop,为一个事件循环。它还包括了计算CPU负载的功能(在。以上为ZLMediaKit中线程池类图,通过。方法来取一个线程(EventPoller)。方法获取一个CPU负责最小的线程。时,线程都已创建并绑定到了核上,通过。优先取一个CPU负载小的线程。设置线程数,当产生线程池对象。对象就代表了一个线程。
2023-12-14 07:43:06 412
原创 webrtc 支持H265(三) 总结
有音频流最大的难点是要做音视频同步,也意味着web端不再只是单纯的解码,渲染,回放。在这样的场景中,视频流是单向的,码流从摄像头到ZLMediaKit到浏览器并且没有音频。关于延迟,对于webrtc datachannel通道的延迟我并没有专门进行测试,但是在后续的播放器整体测试时,webrtc datachannel通道并没有引入不可接受的延迟。浏览器通过ffmpeg软解码,对于分辨率大,码流大的情况或多路视频时,还是会出现性能不足的情况。浏览器已经可以支持对H265的硬解码,但是有浏览器的版本限制。
2023-07-26 07:24:07 2905 3
原创 webrtc 支持H265(二) ZLMediaKit通过datachannel通道转发视频流
ZLMediaKit中的datachannel的实现也是基于usrsctp库,所以首先需要编译安装usrsctp,步骤比较简单这里就不列举。usrsctp的IO模式被设置成非阻塞IO,默认的发送缓存的大小为262144。中缓存的GOP大小可能远远大于262144,在一开始转流时就填满了发送缓冲区,造成图像卡顿。rtp包的长度不会大于mute,一般是在1500个字节一下,远远小于这个大小。,在offer的sdp中有一个表示可以发送最大发送消息长度的属性行。在只有datachannel通道时,才从src的。
2023-06-28 07:53:57 3555 10
原创 webrtc支持H265(一)webrtc datachannel的特性
但是这种缓存机制又无法优化,http-flv基于tcp协议,播放器的实现必然需要引入缓存来兼容tcp 协议流的特性,因为应用层无法预测什么时候有数据,数据有多少,所以必须有个缓存处理tcp协议上抛数据的抖动性,来保证播放的流畅。但是有这样一个问题:web 播放器通过http-flv拉h264或h265的流进行播放,有明显的延迟,即使在内网延迟也有2s,通过调试发现,主要是web播放器的缓存的机制导致。datachannel基于sctp协议,sctp协议是与udp,tcp同级的协议,属于传输层协议。
2023-06-21 20:41:25 4893 5
原创 连接器处理重复符号(二)具体不同地址的全局对象
方法,它将输出单例对象的地址。最终输出的结果是每个对象的地址都不相同。这显然不符合我们的预期。就好比原本有一个封装了日志功能的静态,被多个动态库链接使用,本意是都使用同一个日志全局对象输出日志,结果缺产生了多个日志对象,这显然是不符合业务需求的。,它会包含静态库中的所有符号,默认情况下这些静态库都会标示为导出符号,通过连接器脚本。在动态库,可执行程序中都调用了单例对象。,输出如下,全局对象的地址各不同。将这些静态库符号隐藏,只导出符号。在下面这个例子中,可执行程序。,把它编译为一个静态库。
2023-05-02 11:26:10 740 1
原创 连接器重复符号处理(一)动态库重复符号处理规则
在日常开发工作中,经常会遇到符号重复定义的问题,这篇文章主要描述的是链接器在处理重复符号时的规则。在解析引用的过程中,最常发生的问题就是会出现重复符号,该问题发生在链接的最后阶段,具体为在所有可用符号列表中包含两个甚至更多同名符号,连接器就会报错,一般如下错误:./libsecond.a(secondfile.o):在函数‘duplicateFunction(int)’中:/root/test/cf/secondfile.cpp:6: duplicateFunction(int) 的多重定义。
2023-04-24 16:12:31 1630
原创 webrtc中的线程(二)ProcesThread
所以它也是一个异步任务队列。它也是一个接口,具体实现类为。在Pacing,audio 模块都有用到,主要用法就是注册。不同,它并没有直接封住操作系统的线程类API,而是使用了。主要功能方法,就是往Module list中插入或删除。实现还是比较简单,就是依次执行几个任务队列中的任务。在webrtc中另外一个用的比较多的线程对象是。就是驱动队列的事件:当队列为空时,线程阻塞在。因为它是一个异步任务队列,它内部的队列就是。,它主要用于执行定时任务。是定时任务队列,执行定时任务队列是。
2023-03-13 08:02:21 365
原创 C/C++程序编译与链接(四) 创建动态库
其实站在开发者的角度,认为API与ABI是应该等价的,代码里的接口匹配,难道编译后,二进制文件中的接口对应的符号还不匹配吗?是的,对C++来说是要需要关注这些问题。
2023-03-11 10:01:58 1679
原创 C/C++程序编译与链接(三) 动态库的概念
对一些核心动态库(比如libc.so,libstd++.so等),这些都不是问题,因为这些库的位置,都已经被预先内置到系统中。但是对我们自己依赖动态库的程序,要想运行必须有两点:1. 操作系统中有程序需要的动态库。构建动态库生成的二进制文件本质上与可执行文件是相同的,唯一的区别在与动态库缺少了让其独立执行的启动程例程。运行时需要将可执行程序的符号正确解析到正确的地址上,这个地址是动态库所映射到进程内存映射中的地址。与路径一样,对操作系统自身的功能动态库,版本都是适配于操作系统的最合适的版本。
2023-03-06 08:22:45 461
原创 webrtc中的线程(一) rtc::Thread
是webrtc中最重要的线程类型。它与WebRtc库的实现深度结合。线程类型,主要是用作执行一些定时任务。这篇文章将介绍rtc::Thread及它在WebRtc中的使用。的线程模型如下:不仅仅是只产生一个线程,它还包含一个队列**(message list)**,将它称为异步任务队列更适合。它的基本功能就是在线程中执行任务队列中的任务。它靠事件驱动,也就是说当中没有任务()时,它会阻塞在事件等待上,当有事件唤醒时后会继续在队列中去任务执行。在图中可以看到它可以处理IO事件,这里的IO事件就是网络数据的收发
2023-03-04 08:26:32 1216
原创 C/C++程序编译与链接(二) 静态库的概念及使用
静态库和动态库是我们都非常熟悉的概念,它们的产生根本目的就是为了代码重用。我们平常在工作中也会使用各种库,有静态库,动态库。虽然它们的目的都一致的,但是两种形式的库还是有本质上的区别,静态库是一种比较原始,简单的代码复用方式,而动态库相对就复杂些。所以如果静态库中某个方法或变量变动,意味着整个客户程序都需要重新链接,不管客户程序是否有改动(即使只是实现方式的变动,而不是方法名字,签名参数的变动)。我们有时需要在传递给链接器的静态库多次添加同一个静态库。参数是指定库的路径,静态库是在当前目录下,所以是。
2023-02-28 08:28:46 588
原创 C/C++程序编译与链接(一) 编译与链接的概念
编译器本质上是将源代码中的高级语言翻译成低级语言,比如翻译成intel x86平台的汇编代码。上面简单的描述编译器的主要工作后,可以体会到编译器的复杂性,通常一个大型的C/C++项目有成千上万上个源文件,源文件间的调用关系错中复杂,编译器生成正确的汇编代码,要理解这些调用关系产生正确符号地址等,再生成正确的执行文件,还要讲究速度。这样简单的想想都很复杂。平常我们认为C/C++复杂,认为它们是比较低级的语言,但是在它们背后,编译器还是做了大量的工作。那么对python,java这样简洁,高效的语言。
2023-02-27 09:52:28 2030
原创 手把手教你实现buffer(四)——webrtc中的CopyOnWriteBuffer
的实现基于Buffer,在功能上强于Buffer。我们也可以根据业务的需求,基于Buffer封装自己的Buffer类。
2022-11-02 10:07:50 534
原创 手把手教你实现buffer(三)——接口及自动扩容
但是buffer还是有特定的使用场景,也需要一些基本的,通用的,易用的接口。的中内容,就需要提供这样的接口,所以使用时一点要注意不要破坏内存,比如写了大于容量的数据量等。定义在buffer.h文件中,在前一篇文章已经贴出,下面是buffer.cpp的代码。内容管理机制的接口,可以直接往内存中读写数据,权限太大。写入数据时,如果当前的容量不够,则会再次分配内存,扩大容量。重载了两种不同形式的下标操作符,前面一个是返回。位置的引用,可以直接更改数据。内部内存的地址,并且可以直接读写数据。指针,只可读,不可写。.
2022-08-08 09:33:24 960
原创 手把手教你实现buffer(二)——内存管理及移动语义
禁止拷贝,通过是构造函数,复制构造函数,赋值操作符号来实现。类,它是一个非常典型的基础buffer封装,我们来通过分析它的实现,来学习要如何实现一个buffer。多引用几次,引用关系就会混乱了,很容易造成问题,比如内存无法释放;在C++中最直观的语义就是引用语义,因为它代表一块内存空间。但是这种引用语义,很难区分所有权,即是谁需要对这块内存负责(负责分配,负责释放),这种语义的。移动赋值运算符的逻辑跟移动构造函数的相同,将资源转移,将原对象置为无效。给到了所构造的对象,而原对象的。时,内存会自动释放。...
2022-08-01 18:57:19 1113
原创 手把手教你实现buffer(一) —— C++中buffer的概念及需求
buffer的概念很庞大,根据不同场景,有各种各样功能的buffer,比如双缓冲buffer,jitterbuffer。这篇文章说的buffer,是指一段用于存取数据的内存空间,这是最基础的buffer。然而就是这种最基础的buffer,在C++中标准库也没有提供很通用,完善的buffer类(-_-!)。这一系列文章,将参照webrtc中的,一步步介绍如何实现这样的buffer。......
2022-08-01 18:55:15 8275
原创 将自定义类型作为关联容器的key
如下一个结构体structS{intn;boolf;floatd;};作为关联容器的key,需要定义operator
2022-07-26 10:12:52 179
原创 webrtc中的视频编码(一) 视频编码模块轮廓
关于webrtc视频编码的分析,这将是一系列文章,主要从代码结构和设计思路两个方面去分析视频编码模块,不会进入代码细节,目的是在自己实现视频编码时可以从中借鉴。这篇文章是这个系列的第一篇,主要是介绍视频编码模块轮廓。整个视频编码功能包括下面几个功能类:视频编码接口类,是一个抽象接口类。它有多个实例,编码h264 encoder,vp8/9 encoder工厂类,用于创建的具体实例 h264编码接口类,有个方法用于创建h264的编码类实例(好绕-_-!) h264编码的具体实现,的实例包括,, 它们之间的关系
2022-07-08 11:54:45 2278
原创 大龄程序员的心理建设
我的IT职业生涯从2010到2021年,已经11年,换了三家公司。现在在第四家公司待了将近两年。我已经36岁了,按照程序员35岁定理,我在职场上是没竞争力了。在年龄上35岁是青中年,正式人生的巅峰期,但是在程序员的职业年龄上,已步入“晚年”。后面的几十年的职业路,我该怎么走?年龄越大在职场上就越不受欢迎,除非你是公认的牛人。可能三十五岁的程序员百分之九十都自认为是人才(包括我),但是其实很少符合“公认”的标准。你是某个著名开源库的作者,你参与了某个非常著名产品设计研发,你是教授,你发了重要的论文,这些都是
2022-02-24 08:21:50 252
原创 webrtc中视频采集实现分析(一) 采集及图像处理接口封装
文章目录webrtc中视频采集类DeviceInfoGetBestMatchedCapabilityVideoCaptureModuleVideoCaptureFactory示例视频帧处理I420Buffer视频采集是媒体库最基础功能。但是它的实现与操作系统有强相关性,因为不同的操作系统提供的视频采集接口不一样。视频采集模块也具有通用性,不同媒体库的视频采集模块实现的功能是相同的,主要包括如下几个功能:检索视频采集设备指定视频采集设备进行采集根据指定的采集参数(包括分辨率,帧率,图像格式)来初始化
2022-02-08 11:52:10 3850 1
原创 webrtc中视频采集实现分析(二) 视频帧的分发
视频采集模块,抛出视频数据后,对视频帧的处理需求一般包括如下几种:视频帧送到编码模块进行编码视频帧送到渲染模块进行本地回显视频帧先进行预处理(比如添加水印,字幕),再送去回显或编码视频帧会送到多个编码器,产生多路不同分辨率,码率的码流所以从采集模块获取的视频帧是需要分发的,也是只有一个source,但是有多个sinkwebrtc中的实现webrtc中有一个对视频帧的分发框架,可以直接借用相关实现videoSourceInterface作为source的基类主要接口是 AddOrU
2022-01-13 16:07:48 2646
原创 webtrc 中VideoAdapter类中的作用及局限
需求在媒体库中,是要求能动态改变编码的分辨率和帧率的,思路是重启编码器,设置编码器新的分辨率,帧率参数来满足要求。所以输入到编码器中的视频流分辨率,帧率应该与设置的分辨率参数是一致的。但是不能通过改变视频采集的分辨率来实现,否则可能会造成摄像头重启,导致图像会黑一下。往往是在送入编码器之前应该有专门进行分辨率,码率适配的功能类。输入的是视频采集的原始分辨率和帧率,输出的是满足于编码器的编码分辨率和帧率。VideoAdapter类分辨率的适配webrtc中VideoAdapter类就是实现这里的功能
2022-01-11 15:13:16 1229
原创 webrtc中的引用计框架
webrtc中的引用计框架文章目录webrtc中的引用计框架基本框架类scoped_refptr实现用法使用示例基本框架类webrtc中通过RefCounter,RefCountedObject,RefCountInterface类提供了一个引用计数框架。RefCounter是计数器类,实现了线程安全的计数功能;RefCountedObject对RefCounter进行了封装;RefCountInterface是接口类,要求实现AddRef()和Release()接口。它们可以单独使用,可以结合使用。
2022-01-10 19:15:03 669
原创 C++ 11中的移动语义
移动语义文章目录移动语义拷贝与移动拷贝移动左值与右值左值引用和右值引用移动语义移动构造函数和移动赋值函数移动对象后为可析构状态编译器生成移动操作移动操作的匹配std::move函数STL中的移动语义拷贝与移动一个形象的比喻如何把一个冰箱里的大象放到另一个冰箱中?打开冰箱1的门,打开冰箱2的门,将冰箱1里的大象移动冰箱2中,关上冰箱门。这是一个很自然的方法,那么还有一种方法,将冰箱2里的大象复制一头,将复制的大象放到冰箱1中,再让冰箱2里的大象消失掉。这种方法是不是感觉似曾相识,这个就是C ++
2021-09-15 10:06:54 404
Directshow视频采集,支持图像预览,支持根据策略设置分辨率及帧率
2018-03-20
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人