视频分发器- VideoBroadcaster

511 阅读2分钟

VideoBroadcaster属于vcm capture中的一个成员, 通过vcm capture 获取到采集的数据之后,再通过VideoBroadcaster分发出去.

这里主要讲解一下视频是如何被VideoBroadcaster分发给不同的对象的.

再以上函数中, for循环遍历sink_pairs,

注:

  • 每一个sink代表一个输出对象;

  • 每一个sink_pair是一个输出对象的key-value值;

  • 所有需要接收视频数据的对象都会被组装成sink_pair插入到sink_pairs列表中;

if(是否需要一帧黑帧){

} else if (!上一帧发送给了sinks中的所有目标&&这一帧的宽高发生了变化) {
      //由于上一帧没有发送到一些接收器,没有可靠的更新信息可用,所以我们需要清除更新rect。
} else {
      sink_pair.sink->OnFrame(frame); //将数据分发个该对象
}


那么sink_pairs中的成员从何而来?

  • main_wnd_->StartLocalRenderer(video_track_) : 将main_wnd_作为sink插入到列表中, 通过video_track拿到VCMcapture, 再通过vcmCapture拿到broadcaster, 将main_wnd_ 插入列表中.

  • pc_->SetRemoteDescription() : 将视频编码器插入到列表中.

调用本地渲染将sink插入到broadcaster的调用栈:

addrender() 
VideoTrack::AddOrUpdateSink()
VideoTrackSource::AddOrUpdateSink()
TestVideoCapture::AddOrUpdateSink()
VideoBroadcaster::AddOrUpdateSink()
VideoSourceBase::AddOrUpdateSink()

将视频编码器插入到broadcaster的调用栈:

PeerConnection::SetRemoteDescription()
...
PeerConnection::DoSetRemoteDescription()
PeerConnection::AppliRemoteDescription()
PeerConnection::UpdateSessionState()
PeerConnection::PushdownMediaDescription()
BaseChannel::SetRemoteContent()
... // 信令线程切换到工作线程
VideoChannel::SetRemoteContent_w()
WebRtcVideoChannel::SetSendParameters()
WebRtcVideoChannel::ApplyChangedParams()
WebRtcVideoChannel::WebRtcVideoSendStream::SetSendParameters()
WebRtcVideoChannel::WebRtcVideoSendStream::SetCodec()
WebRtcVideoChannel::WebRtcVideoSendStream::RecreateWebRtcStream()
internal::VideoSendStream::SetSource()
VideoStreamEncoder::SetSource()
VideoSourceSinkController::SetSource()
WebRtcVideoChannel::WebRtcVideoSendStream::AddUpdateSink()
...
VideoTrack::AddOrUpdateSink()
VideoTrackSource::AddOrUpdateSink()
test::TestVideoCapture::AddOrUpdateSink()
VideoBroadcaster::AddOrUpdateSink()
VideoSourceBase::AddOrUpdateSink()

WebRtcVideoChannel::

WebRtcVideoSendStream::

视频分发架构

通过上层api可以直接在session层创建VideoTrack, VideoTrack内部包含VideoTrackSource;

引擎层是在媒体协商(setLocalDescription、setRemoteDescription)的时候进行构造的, 同时也会根据需要去访问设备层, 例如VCMCapture初始化的时候就会访问设备层;

VideoBroadcaster是在VCMCapture创建的时候构造出来的;

插入sink_pair到broadcaster中的流程:

  • set local Renderer的时候,将视频渲染器对象插入broadcaster中

  • 媒体协商调用setRemoteDescription时, 将VideoStreamEncoder对象插入broadcaster中

  • video Capture采集到视频的时候通过OnFrame函数交给broadcaster去分发给不同的接收者.

  • 编码好的数据会交给PacedSender进行平滑处理,然后交给网络层发送出去

总结

  1. broadcaster是在创建capture的时候被构造出来,此时里面没有要接收视频的接收者.

  2. 上层调用接口设置本地渲染器的时候, 本地渲染器作为一个接收者被加入到broadcaster中, 调用过程大致是 track->source->capture->broadcaster.

  3. 当进行媒体协商调用setRemoteDescription时, 将VideoStreamEncoder对象作为视频接收者插入到broadcaster中.

  4. videoCapture通过On Frame 函数将视频数据传给broadcaster, broadcaster在分发给接收者列表中的所有接收者.

  5. 编码器将编码后的数据交给PacedSender进行平滑处理后,再通过网络层发送出去.