• webrtc源码阅读理解一


    webrtc是一个比较成熟的实时音视频处理开源项目,一上来老大就扔给我一本webrtc native实践,虽然狠下心“翻”完了一遍,但是还是云里雾里的,在经过几个月的摸索之后,我大概知道原因了,归根到底,是基础不在一个层次,理解不了的,所以我决定,尝试写一个接近我这种零基础入门实时音视频的记录系列,希望能帮到一些同学

    基础概念的理解

    实时音视频是一个很长的流程,从采集-编码-传输-接收-解码-渲染,每一个步骤都是很大的模块,所以我们一个一个来,我们先从采集相关的设计开始,我们先看一些概念,否则直接看代码会有点懵

    stream(流):包含音频轨和视频轨的编码流

    track(轨道):音频轨或者视频轨

    音视频同异点-我的理解

    先说几个点

    • 音频和视频还是很多地方不一样的
      • 音频采集了,自己不不要同时听到自己,一般只需要传输给对方;一般只有一个采集的地方;即使有多个采集的地方,对方希望听到是合流之后的一个声音;
      • 视频采集了,一般需要同时在己方和对方都渲染显示出来;可能要多个采集源;一般希望每个视频源独立展示(甚至是不同的设备展示)
    • 音频和视频有很多地方是一致的
      • 是同级的概念;整体的处理流程几乎一致
    • 音频和视频输入和输出的过程不一样

    整体感觉是视频的逻辑要比音频复杂一些,所以下面我主要也是围绕视频展开,音频也会顺便说下

    视频代码设计

    其实这个地方很难真正从零开始,我这里也是从中间某个点开始说(对着代码说自己的理解);结合上面的同异点,我们来看下webrtc里面的代码设计

    source和sink

    这是我觉得第一个坑的设计,但你理解了之后,觉得这样设计也没有问题

    联系实际场景,摄像头采集到图像之后,保存视频,成为视频源,编码和本地渲染需要消费图像做处理,类似于生产和消费的概念

    对于消费者,也就是sink来说,如果我想要增加一个消费者,我继承sink接口,塞到保存视频源的实例里面去,让实例不断给我塞数据给我消费即可(onFrame),所以sink的接口定义比较好理解;

    source的接口定义里面只有对sink的操作,这是我觉得一开始不好理解的地方,source并没有存储视频图像(为什么叫source呢?);我现在的理解是,相对于sink,这样的接口就可以理解为source(摄像头采集图像之后,调用source的某个接口,这这个接口里面,对图像数据进行分发给sink,对于sink来说,这个实例就可以理解为source);

    videoBroadcaster

    broadcaster做的就是我们上面那段话想做的事情

    source的接口太简单了,下面是videoSourceBase的函数定义,还增加了一个sinks的成员来保存所有的sink成员;

    而broadcaster同时继承了sink和source,这就是我们想做的事情:初始化一个broadcaster实例,增加一个消费者sink的时候,把sink通过broadcaster的source接口存入sinks即可;当采集到图像的时候,把图像按照既定的逻辑调用所有sink的接口即可;

    webrtc里面同时是sink又是source的实例还有很多,例如

    这是第一个实际概念到代码设计的实践,可以看到,简单的物理概念想真正用代码设计构架起来,还是需要很多抽象设计和构架思考的

     source、track、stream

     上面说完了整体一个大概念的图像采集之后,采集分发的小流程,这些图像数据source要变成track最后要形成 stream,我们看下这里的设计,在这些之前,有些更细节的概念也要考虑到,例如音视频发生了变化需要通知观察者

    所以首先定义了观察者接口和通知者接口,都是很纯粹的接口定义

    而通知者的继承关系则很长,通知接口有三个继承者MediaSourceInterface,MediaStreamTrackInterface,MediaStreamInterface,基本source、track、stream都是通知者

    MediaSourceInterface

    定义了媒体源的基本状态,媒体大类有两个,音频和视频,所以有两个继承者VideoTrackSourceInterface,AudioSourceInterface,上面也说到过,音视频细节上有些差异,从这里的接口设计可以看到一些

    AudioSourceInterface

    AudioSourceInterface的接口,例如音量这些,都是音频独有的

    VideoTrackSourceInterface

    因为之前已经定义了VideoSourceInterface,所以这里直接到了videoTrackSource的定义

    从audio和video两个继承来看,这里的分化挺明显的

    MediaStreamTrackInterface

    track的定义和继承如下,定义了trackState和必要接口;同时可以看到有音视频track两个子接口

     

    videoTrack

    audioTrack和VideoTrack有一个不一样的地方是,audioTrack只是组合了audioSource,videoTrack还继承了videoSource,我理解这是因为视频的来源和分发比音频复杂,因为所有的音频可能最后会汇聚成一个,是多个视频源可能需要分发和处理到不同的地方;

    MediaStreamInterface

    最后继承Notifier的是MediaStreamInterface,可以看到,stream是videoTrack和audioTrack的组合

     

    好了,今天就先写到这里,后面应该会持续更新

    p

  • 相关阅读:
    Spring中的@Transactional以及事务的详细介绍
    Shiro缓存使用Redis、Ehcache、自带的MpCache实现的三种方式实例
    使用shiro缓存用户身份信息的时候报:java.io.NotSerializableException: org.apache.shiro.util.SimpleByteSource
    rocketmq 延时消息
    用区块链技术做一个 不可被修改的 恋爱记录 app 我叫<<誓言>>
    java 调用区块链 发布和调用智能合约
    centos 以太坊多节点私链搭建
    数据库的死锁原因 和 处理办法
    聚簇索引
    Java 容易疑惑的一些杂记录
  • 原文地址:https://www.cnblogs.com/qwj-sysu/p/15335619.html
Copyright © 2020-2023  润新知