WebRTC视频 01 - 视频采集整体架构

WebRTC视频 01 - 视频采集整体架构(本文)
WebRTC视频 02 - 视频采集类 VideoCaptureModule
WebRTC视频 03 - 视频采集类 VideoCaptureDS 上篇
WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇
WebRTC视频 05 - 视频采集类 VideoCaptureDS 下篇

一、前言:

我们从1对1通信说起,假如有一天,你和你情敌使用X信进行1v1通信,想象一下画面是不是一个大画面中有一个小画面?这在布局中就叫做PIP(picture in picture);这个随手一点,看似在1s不到就完成的动作,里面却经过了很多复杂的操作,我们今天开始写一系列文章介绍下这俩帅哥的图片怎么显示的。

二、宏观流程:

在这里插入图片描述

  1. 首先开始呼叫的时候会对摄像头和显示屏幕进行初始化。
  2. 摄像头采集完数据之后会进行分发,一路给本地进行渲染(你自己就画出来了),另外一路送给编码器进行编码。
  3. 编码后的数据通过网络模块发送(这里面其实非常复杂,后续专题分析)。
  4. 接收端通过网络模块接收数据,并进行一些排序,去掉RTP头等操作,得到编码后的视频帧。
  5. 视频帧送给解码模块进行解码。
  6. 将解码后的数据进行渲染(你女票也画出来了)。

三、类图:

在这里插入图片描述

  • 里面最重要的就是VideoCaptureModule,这是一个抽象类,不同平台有自己的实现。
  • VideoTrack是负责将整个链路创建起来。并不负责处理具体数据,数据由VideoCaptureModule、VcmCapture、VideoBroadcaster处理。
  • VcmCapture是PeerConnectionClient这个demo实现的一个类,里面包含了vcm_,又实现了TestVideoCapture(里面有broadcaster),所以这个类是左手连接数据源vcm,右手连接broadcaster;
  • VcmCapture包含的成员(其实是父类包含)VideoBroadCaster,负责分发给本地渲染器和Encoder;
  • 上面就是核心类,接下来看其他类,也就是看看怎么使用上面的核心类的。
    • 采集视频流的时候,首先会创建CaptureTrackSource。这个类里面会有capture(也就是VcmCapture);
    • 然后就是创建VideoTrack,里面有个成员变量video_source,就是上面创建的CaptureTrackSource的接口类指针,也就是说创建的收入接收了入参CaptureTrackSource,拥有了它;
    • 在PeerConnectionClient这个demo中,调用StartLocalRenderer的时候,就会调用VideoTrack(还记得吗,它是专门负责建立链路的)的AddOrUpdateSink,然后就会调用CaptureTrackSource的AddOrUpdateSink,接着调用VideoBroadCaster的AddOrUpdateSink。这个时候VideoBroadCaster就会将本地渲染器添加到自己的列表中,由于之前VideoCaptureModule****已经将采集模块启动起来了,因此,数据就源源不断的从VideoCaptureModule进入到VcmCapture,然后再进入VideoBroadCaster当中。
    • VideoBroadcaster收到数据,发现目标列表中有数据的时候,就会将数据转发给这些目标。也就是本地渲染器,这个时候本地就可以看到自己视频了;
    • 同样,在媒体协商进行到最后一步的时候,就会将编码器添加到VideoBroadCaster的目标列表当中,这样给本地渲染器分发数据的时候,同时也给编码器分发。

四、代码走读:

前面说了VideoTrack主要职责是建立数据链路,将数据源和数据消费者串起来,我们现在看看这条通道是怎么建立起来的。

我们先按照经验猜一下(其实我是看了代码的,假装猜一下):

  1. 首先,创建VcmCapture,因为它持有数据源VideoCaptureModule和分发器VideoBroadcaster,就可以把数据生产者和消费者连起来,形成通路;
  2. 有了VcmCapture,先给它创建数据源source,由于数据源CaptureTrackSource需要通过VideoTrack管理,因此,我们创建CaptureTrackSource之后,需要再创建一个VideoTrack,再将CaptureTrackSource交给VideoTrack持有,具体步骤:
    • 将上面的CaptureTrackSource对象video_device作为参数传入,创建VideoTrack,这样VideoTrack就持有了CaptureTrackSource(看上面类图);
  3. 至此,VcmCapture中就有了源,源产生的数据需要交给消费者,也就是VideoBroadcaster,然后VideoBroadcaster可以分发给本地渲染器和视频编码器;
  4. 三个重要对象创建好,就可以通过:VideoTrack -> CaptureTrackSource -> VcmCapture -> VideoBroadcaster 完成的链路搭建;

看代码:

代码入口:

// 代码路径:examples\peerconnection\client\conductor.cc
bool Conductor::InitializePeerConnection() {
   
   
  // 创建PeerConnection部分省略...
    
  // 添加track到PeerConnection中
  AddTracks();

  return peer_connection_ != nullptr;
}

AddTracks里面会:

  • 创建VcmCapture;
  • 创建数据生产者;
  • 创建数据消费者;
  • 并将生产者到消费者的链路建立起来;
  • 将VideoTrack这个管理者加入到PeerConnection当中;

已经删除非关键代码。

// 代码路径:examples\peerconnection\client\conductor.cc
void Conductor::AddTracks() {
   
   
  if (!peer_connection_->GetSenders().empty()) {
   
   
    return;  // Already added tracks.
  }
  
  // 1、构建一个数据源 CaptureTrackSource (里面会创建 VcmCapturer )
  rtc::scoped_refptr<CapturerTrackSource> video_device = CapturerTrackSource::Create();
  if (video_device) {
   
   
    // 2、构建一个 VideoTrack , 返回其代理类
    rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track_(
        peer_connection_factory_->CreateVideoTrack(kVideoLabel, video_device));
    // 3、开始本地渲染
    main_wnd_->StartLocalRenderer(video_track_);
    // 4、将VideoTrack添加到PeerConnection当中管理
    result_or_error = peer_connection_->AddTrack(video_track_, {
   
   kStreamId});
    if (!result_or_error.ok()) {
   
   
      RTC_LOG(LS_ERROR) << "Failed to add video track to PeerConnection: "
                        << result_or_error.error().message();
    }
  }

  main_wnd_->SwitchToStreamingUI();
}

分开看下上面几个关键步骤:

1)创建CapturerTrackSource:

// 代码路径:examples\peerconnection\client\conductor.cc
  static rtc::scoped_refptr<CapturerTrackSource> Create() {
   
   
    const size_t kWidth = 640;
    const size_t kHeight = 480;
    const size_t kFps = 30;
    std::unique_ptr<webrtc::test::VcmCapturer> capturer;
    // 创建一个DeviceInfo对象,里面包含视频采集设备的属性信息
    std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(
        webrtc::VideoCaptureFactory::CreateDeviceInfo());
    if (!info) {
   
   
      return nullptr;
    }
    // 获取采集设备数量(因为有些设备有多个摄像头),并遍历每个采集设备
    int num_devices = info->NumberOfDevices();
    for (int i = 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值