当前位置: 首页 > news >正文

6.6.编解码器信息的收集之二

在上节课中呢,我向你介绍了编辑码信息收集的第一部分,那在那一部分中呢?我们本来是要将所有内容通过一节课全部讲出来。但是呢,由于时间的关系,我们只能讲其中的一部分,那今天呢,我们继续讲第二部分。那在上节课中,我们归到了通过create peer connection factory,我们就开始收集音视频编解码器的信息了。

其中用到的四个重要的函数呢,就是create buildin audio encoder factory create buildin audio encoder factory。以及video encoder factory和video decoder factory这四个API,那其中呢,我们举了一个典型的例子,就是audio encoder factory。在其内部呢,会通过可变参数模板递归的方式,将每一个音频的编码器遍历出来,将这些信息保存到specs中。那上节课中我们介绍的这些内容呢,实际只是我们收集音视频编解码器中的第一步。那我们要完成音视频编辑码器的收集,实际需要好几个步骤,那第一步,

刚才我们已经介绍了,就是在创建peer connection factory的时候。我们就开始收集音视频编解码器了。那涉及到的音视频编辑码器只是暂存到了一个位置上,那后边呢?我们还需要将暂存的这些数据进行整合。那整合的时机呢,就是创建并初始化peer connection的时候,那一会儿我们再进行代码的阅读的时候,你就会看到它具体是怎么做的。这是第二步。那第三步呢,就是将整合后的信息最终存放到media session description factory。这个类中那这个类我们通过它的名字啊,就可以知道它呢,

就是创建session description对象的一个工厂方法。最后呢,通过它来将session description创建出来,那通过这个类,我们就可以构造出sdp的类关系图。之后再通过这个类关系图,我们就可以获取到sdp信息了OK,那这个呢,就是编解码器信息收集的一个完整的步骤。好,那在我们今天的课程中呢?我们会介绍整个步骤中的前三步,那第一步呢?实际我们主要的内容已经介绍完了。我们再来看一下它在外边tc中的调用过程是什么就OK了。

重点呢,是介绍第二步和第三步,至于第四步呢,我们会留作后边的课程,再给大家做介绍OK,那下面呢,我们就来看一下。我们第一步收集音视频编辑码器的时机。那这个过程呢,就是对我们上节课所介绍内容的一个总结,在上节课中,我们知道在创建peer connection factory的时候呢?会进行音视频编解码器的收集,那具体它是如何做的呢?实际就是按照这张图中所展示的这个步骤。

那首先呢,在创建完peer connection factory对象之后,在其内部会进行初始化,initialize。在初始化中呢,又会调用China manager的nit函数,对China manager进行初始化。在China manager的I it函数中,会进行一次线程切换。那在切换之后,它会创建media engine,也就是媒体引擎。那这个媒体引擎呢,包括了音频媒体引擎和视频媒体引擎。这两个媒体引擎是web rtc中最重要的两个引擎,

那它用于处理整个音视频的编辑码。好当创建完media engine之后呢,它会调用它的I it方法,再对它进行初始化。那紧接着在其内部会对音频引擎进行初始化,在音频引擎里边儿呢,它会调用audio encoder factory t。这个类的get supported encoders这个方法,那通过这个方法来获取它所支持的音频编码器。就包括了oprah sg 7幺幺g七二等等,这些编码器。好在其内部呢,又会调用helper append supported encoders调用这个方法。来最终将所支持的音频编码器的信息保存起来,那这个呢?

就是在audio encoder factory t。这个类中的get supported encoders中所做的事情,那当这个函数执行完成之后呢?会调用collect products。通过这个API,最终呢,将收集到的音频编码器放入到send codex victor中。而解码器呢,会存放到recv q dex victor中。此时就完成了音视频编解码器的收集工作。那在这个调用过程中啊,我们可以通过这个箭头的长短来区分它是在哪个函数之内?比如在这里边儿,那这个三个箭头儿指明的就是get supported encoders这个API是在。v安检nit这个函数中执行的。

而append supported encoders呢,是在get supported encoders中执行的collect codex与get supported encoder。它俩是平级关系。这两个函数呢,都是在voice engine n it这个函数中执行的,那这个呢,就是我们对上节课所介绍内容的一个总结。当然,此时只是完成了音视频编解码器收集的初级阶段。那之后还有一个重要的步骤,就是在我们创建peer connection的时候,就是我们这张图所展示的整个调用过程呢。是从peer connection client进入的之后呢?创建peer connection最终将我们前面收集的信息。进行一次整理。

那最后将整理内容呢,存放到了media session description factory,这个对象中,那我们来看一下整个的调用过程啊。那对于peer connection cl and来说,当我们与对端进行连接的时候,也就是调用connect to peer这个方法的时候。在其内部呢,就会调用initialized peer connection。那在这个函数中呢,又会调用conductor的create peer connection。那就这样一步一步向里调用,最终调到哪儿呢?就会调用peer connection factory的create peer connection。通过peer connection factory来创建一个peer connection对象,

那有了peer connection对象之后。会调用它的initialized方法对它进行初始化。在初始化的过程中,会创建web rtc session description factory。那在这里边儿呢,又会创建media session description factory,这个对象在这个对象的构造函数中就会对。因视频编辑码器的信息啊,进行整合,那整合之后呢,它得到了很多信息,这些信息包括什么呢?包括audio send codex。audio receive codex audio rtp extensions,video codex,

video rtp extensions.那这些信息都是在media session description factory,在构造函中获得的。那在这里呢,我也做了一些解释。对于audios and codecs,它是通过China manager获取到的音频编码器。当然,在China manager中呢?它就会调用底层的方法,最终呢,获取到音频的编码器和音频的解码器。那同样的,后边儿的这个三个呢,也是类似的情况OK,

那下面呢,我们就按照这个步骤来看一下外部rtc代码是如何实现的,那我们切到Windows系统下。好,那在我们分析代码之前呢?实际你应该按照我们刚才介绍的这个步骤,在每一个关键点处做一些断点。那这个工作呢,你底下去做就OK了,那在我这里这些断点呢,已经是设置好的,我现在只要直接执行就OK了。好,那现在呢?程序已经运行起来了,

我们执行。我们先连接心理服务器。在新订服务器中呢,选择一个我们要通讯的对象。好,这样它就进入到了connect to peer这个方法中。我们继续执行。好,现在我们就进入到create peer connection factory,这个函数调用的断点处,那在这里呢,我们可以看到。四个非常关键的API。第一个是create buildin audio encoder factory,第二个呢是decoder factory,

第三个是video encoder factory。第四个是video decoder factory,那我们可以看一下audio encoder factory里,它是怎么?定义的那在create building audio encoder factory中呢?它又调用了create audio encoder factory。在这里边,我们就可以将支持的所有的音频的编码器给它列出来。那对于表达tc来说,它所支持的音频编码器都列在这里了,包括了opus multi China opus等等,这些编码器。我们都可以看到那通过C加加幺幺的可变参数模板y8 rtc就实现了一个非常巧妙的。音频编码器工厂。我们可以在这儿设一个断点,

让它进入到这里。好进入到这儿之后呢?我们进入到这个函数内部,那在这个函数中呢?它又创建了一个新的对象。在这个新对象的内部,就是audio encoder factory t。它也使用了可变参数模板,我们在进入到audio encoder factory器中。在这个函数中呢,就会通过递归便利的方式,将每一个支持的音频编码器获取出来。最终呢,把对应的编码器信息保存到一个固定的位置,那一会儿呢,

我们来看一下它具体是怎么做的?那我们继续执行啊。这时候呢,我们就来到了China manager I it这个函数中,它就是在创建peer connection factory之后。调用了peer connection factory的initialize方法,在initialize方法中呢,又调用了China manager in it方法。那这个过程我们是如何知道的呢?我们可以看一下它的并行堆栈。那它是一个图形化的啊,可以看到现在我们执行的位置呢,就是channel manager in it。我们往下找,你就会看到它是从哪儿调过来的呢?

就是从peer connection factory中的initialize调过来的。而peer connection factory的initialize又是从哪调用的呢?它是从create model peer connection factory。这个方法是我们调用过来的。那我们进入到这个函数中,我们就可以看到它是怎么调过去的,可以看到在这一块呢,有一个小箭头。那这个箭头的上一行就是它真正执行的这个代码。也就是说,在创建peer connection factory的时候呢,会创建一个临时的对象method code。那在method code构造函数中就会调用peer connection factory的initialize。最终呢,就来到了China manager n it这个方法中。

好,那在China manager I it中啊,做了很多事情,我们可以单步执行,那首先呢,它会对网络线程和工作线程啊做检查。之后呢,如果判断它不是网络线程,那它会通过invoke调用网络线程的disallow blocking code这个方法。那这个方法呢?我们不太关心,我们就继续执行就OK了,那再下来它会判断现在media engine是否已经构造成功了。如果构造成功了,它会调用media engine的int方法。

那media engine是什么时候创建的呢?一会儿我们就会介绍到我们现在先不管,总之呢,它是在China manager初始化之前构造好了。那有了媒体引擎之后,它就要调用媒体引擎的I it方法,我们继续执行。好,那现在呢?我们就进入了voice engine I it这个方法中。那它是怎么调用过来的呢?我们还是要看这个并行站。我们现在执行的位置就是voice engine int,那它的上边儿呢?是media engine int,

它就是从这儿来的。那在这个方法中呢,它首先做了一些逻辑,这些逻辑呢,我们暂时不太关心,我们就不做介绍了。那后边比较关键的一个逻辑呢,就是238行。会调用collect codex,这个方法在这个方法中呢?它的输入参数就是encoder factory的概念。get supported encoder方法。那我们继续执行啊,现在呢,我们就进入到了audio encoder factory t中的get supported encoder方法中。

那在这个方法中呢,又会调用hyper的呃pad supported encoder方法,我们继续执行。在helper的append supported encoder方法中呢,它会调用某个具体音频编码器的append supported encoders。这个方法之后呢,又会通过递归的方法再次调用append supported encoder方法。那这样呢,就不停的在这个函数中运行。每次运行的时候都会调用一个具体的编码器的呃pad supported encoder方法,这样将所有的音频编码器的信息呢?最终保存到specs这个参数中,这就是它的一个具体含义,那么可以继续执行啊。好,

那在这里呢?由于我们第一个是opus音频编码器,所以它就会调用opus的append supported encoders。这个方法。那么,在这个方法中呢?它又会调用具体的opus的实现类。调用这个类中的append supported encoder。那最终将这个信息保存到space中。好,由于它是一个递归的调用,所以这个方法呢,会调用很多次,我们一直执行就OK了,那通过get supported encoder方法,

我们获取到。所有的音频编码器的列表之后。最终呢,就会进入到collect codex这个方法中,那在这个方法中呢,它首先定义了一个payload type MA PR。那么这个对象啊,非常的关键,我们可以进入到这个类中,看它是怎么定义的?好在这个类的构造函数中啊,每个字段啊都非常关键。第一个字段呢,就是未使用的pillow type是九六。那最大的pillow type呢是幺二七,

这两个值是为我们后边儿再插入新的。pillow type是使用的。那么,已经存在的这些pillow type呢,是通过一个mappings给它构造出来的。比如说p cum这个编码器,它的采样率呢,是8000单通道。所对应的pillow type是零。这七二三它的采样率也是8000单通道,那它的payload type呢?是四。我们可以往下翻。那在这里啊,我们看到一个熟悉的身影,

这就是opus opus的采样率呢,是48000。双通道那对于这个编码器呢?它还有一些其他参数,比如说采样的最小时间是十毫秒。使用袋内fec。那对于opus的palo type呢,这里指明了是幺幺幺。那所以我们在看sdp的时候,在auto类型的m行呢payload type幺幺幺指的就是opus。这样我们就能找到这个对应关系了。那我们知道了payload type map之后呢?我们继续往下走啊,那再后边的这些内容呢,就是对一些参数的不同设置。

比如,对产生的舒适噪音的这个设置,以及dtmf音频的这个设置。在这里都做了相关的设置。那这些呢,都不是我们的重点,我们就不做介绍了。好,我们重点看一下633行那633行这个for循环呢?实际就是便利。我们刚才通过get supported encoder方法获取到的音频编码器。对获取到的这些音频编码器的信息呢进行便利,那每次便利呢都获取其中一项信息。对这项信息呢,进行格式化。

最终呢,生成audio codex形成对象,那之后我们翻到658行将生成对象保存到alt中。最终呢,将out返回,返回之后呢,我们就得到了send codex victor。那在这个victor中呢?我们可以看到它包括了14项,从零到13。那其中的每一项呢?就是一个音频编码器,第一项就是opus配额tab是幺幺幺采样率48000。双通道等等,这一系列的信息都有了。

那第二项呢?是is ec 16000,其他参数没有,那这样呢?我们就获取到了send codex。那这个cent codex属于谁呢?就属于voice enge ine,也就是说在ve nge in e中保存了音频编码器信息和音频解码器信息。那上面呢是音频编码,我们看到了。后边呢,是音频解码,那这个内容呢,我们就不做介绍了,大家自己去跟着代码去看一下就OK了。

好,那由于时间的关系呢,我们不可能将所有的代码啊都给大家一一走一遍,那大家呢,只要按照我们。之前PPT中的一些关键的步骤给它打上断点,你就可以开始调试了,在调试过程中呢,一边看着代码一边。去对照着视频去看,那这样呢,就可以使PPT中所讲内容与你的代码形成一个对应关系,你就可以很容易理解这部分代码它做了什么事儿了。OK,那下面呢?

我们再切回来。好,那原文版分析完之后呢?我们做一下小结,那在我们前面的课程中啊,我们可以知道。在我们调用create peer connection factory这个方法的时候呢,它会创建video encoder factory。video decoder factory audio encoder factory以及audio decoder factory。那同时呢,在这个方法中还会创建media engine。那这就回答了,我们前面的问题media engine是什么时候创建的?就是在create peer connection factory这个方法中创建的。那当这个方法执行完成之后,

就产生了一个peer connection factory对象,在这个对象中包括了两个重要的方法。第一个方法呢,就是initialize方法进行初始化。那第二个方法呢,是create a peer connection,那通过它呢,可以创建peer connection对象,也就是这里的这个对象。好,那当我们得到peer connection factory对象之后呢?在它内部又会调用它的initialize方法进行初始化,那在进行初始化的时候呢,它会创建China manager。那对于China manager来说呢,

它包括了几个方法,第一个方法呢,是get supported audio send codex。第二个呢,是get supported audio receive codecs。第三个方法呢,是get supported video codex,那通过这个名字啊,我们就可以知道它们每个函数的含义了。那第一个函数的含义是获得音频的编码器,第二个呢是获得音频的解码器,那第三个呢是视频的编辑码器。OK,那这里呢?我们可以看出音频的编解码器是单独的两个API,

而视频呢?只有一个API。这是我们需要注意的好,那当peer connection factory初始化完成之后。在应用层呢,你就可以调用peer connection的,create peer connection方法来创建peer connection对象了。这是它的一个大体的过程,那下面呢?我们再来看看,对于每一个方法中它做了哪些事情?那首先呢,我们来看create a peer connection factory。那在我们前面的例子中呢?我们重点向你介绍了audio encoder factory,

它的创建。当audio encoder factory创建好之后呢,它里边包含了一个方法,就是get supported encoders。那这个方法呢?刚才我们已经看到了。这是属于audio encoder factory对象的,这是第一个,我们要知道的,也就是说一开始创建create peer connection factory的时候。我们知道了整个的一个过程是怎么样的,之后我们再来看第二步就是在创建factory对象的时候呢,同时还会创建。密地安镇。那在调用create media engine这个方法之后呢,

会构造出comp size media engine,那这个对象呢,就是音频引擎和视频引擎的一个联合体。所以呢,它就包括了voice engine和video engine。那同时呢,它也包含了一个in it方法OK,在我们前面介绍代码中呢,我们重点介绍了voice engine。那在voice安装中呢?包括了send codex和receive codex这两个属性,分别用于存储音频的编码器信息和音频的解码器信息。那它呢,又包括两个重要的方法,一个呢是I it方法,

第二个呢是collect codex方法。也就是用于收集音频的编辑码器,最终呢,将收集的结果存放到send codec中以及receive codec中。所以在我们调用create a peer connection这个方法之后呢,就将上面的这一堆东西构造出来了。但是构造出这一堆东西之后呢,所有的事情并没有产生什么化学反应,就是无法通过这一堆东西产生,最终我们想要的结果。这个结果呢,就是构造stp的编解码器信息。那真正产生化学反应呢?是从哪儿开始的呢?是从第三步也就是调用peer connection factory的initialized方法之后。

它会构造出China manager。在构造完China manager对象之后,它会调用它的in it方法,那在China manager的in it方法中呢,又会调用。media engine的in it方法。那可以想到,在这个I it方法中,肯定会调用voice安的I it方法。在voice安装中的nit方法呢?又会调用它自己类的collect codex方法来收集音频的编辑码器。具体的过程呢,就是调用audio encoder factory中的get supported encoder方法以及。audio decoder factory中的get supported decoder方法来获得音频所支持的所有编辑码器的信息。那这个peer connection factory的nit方法就是一个催化剂,

它使得我们上面构造的所有的对象之间。产生了关联关系,并且呢,通过这个触发,拿到了我们想要的音频的编码器信息以及音频的解码器信息。OK,这是peer connection factory initialize函数的一个重要作用。好,那当peer connection factory全部初始化OK之后呢,又会执行第四步调用create peer connection方法来创建peer connection对象。那当这个对象构造好之后呢,也会调用它的initialize方法,在这个方法中会构造web rtc。session description factory.那紧接着构造出media session description factory好,

那在这个对象的构造函数中呢?会调用China manager中的get supported video codecs audio send codecs以及audio receive codecs这三个方法。来获取音视频的编辑码器。那对这三个不同的方法啊,它们分别会调用不同的函数,对于video codex来说,它会调用video engine中的codex方法。那这个方法中呢,又会调用pillow type and default codex,那么最终呢,调用到video encoder factory中的。get supported format方法拿到VP 8和VP 9这两个编解码器,而对于音频来说呢?那它们呢,都会从voice engine中获取信息,

也就是说从voice engine中的send codex以及receive codex中。获取音视频的编辑码器信息,那最终的结果呢?就是这个结果。那在media session description factory中就会保存。audio send codecs audio receive codecs audio send receive codecs or audio codecs.video codex等等一系列的信息,那这些信息呢?最终都是用于生成与对端进行媒体交换的sdp信息。OK,那以上呢,就是我们这节课所介绍的内容,那在这节课中呢,我首先向你介绍了。获取音视频编辑码器信息的一个调用过程之后呢,

带你简单阅读了一下原码。最后呢,我们做了一下小结,那通过这张图呢,让你知道了整个信息获取的具体的步骤以及获取的方式是什么?好,那我们今天的课呢?就到这里,谢谢。

相关文章:

  • 【Ubuntu】Windows访问Ubuntu时“需要认证”界面卡住
  • CRUD-SQL
  • 微服务基础,分布式核心,常见微服务框架,SpringCloud概述,搭建SpringCloud微服务项目详细步骤,含源代码
  • 怎么恢复删除的数据? 8个有效的数据恢复方法
  • 力扣--268丢失的数字(三种解法)
  • 基于SSM的校园服务平台管理系统设计与实现
  • java初探之代理模式
  • 如何在interface中处理DUT中的inout信号
  • DatePicker与DatePickerDialog
  • Ubuntu创建新用户
  • ElementPlus el-switch开关页面初始化时,change事件自动触发
  • Python使用Mechanize库完成自动化爬虫程序
  • 窗口管理工具 Mosaic mac中文版功能特点
  • 屏蔽机房与普通机房有什么不同?
  • Unity地面交互效果目录
  • C语言笔记(第一章:C语言编程)
  • eclipse的离线汉化
  • Java方法详解
  • markdown编辑器简评
  • vue2.0项目引入element-ui
  • webpack项目中使用grunt监听文件变动自动打包编译
  • Zsh 开发指南(第十四篇 文件读写)
  • 读懂package.json -- 依赖管理
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 机器学习学习笔记一
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 时间复杂度与空间复杂度分析
  • 实现菜单下拉伸展折叠效果demo
  • 数据结构java版之冒泡排序及优化
  • 思维导图—你不知道的JavaScript中卷
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 新书推荐|Windows黑客编程技术详解
  • 正则与JS中的正则
  • 自制字幕遮挡器
  • 阿里云服务器购买完整流程
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • (+4)2.2UML建模图
  • (2.2w字)前端单元测试之Jest详解篇
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (pojstep1.3.1)1017(构造法模拟)
  • (初研) Sentence-embedding fine-tune notebook
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (九)c52学习之旅-定时器
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (转)视频码率,帧率和分辨率的联系与区别
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET4.0并行计算技术基础(1)
  • .Net7 环境安装配置
  • .Net各种迷惑命名解释
  • .NET下的多线程编程—1-线程机制概述
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题