github:https://github.com/bigonelby/webrtcUml/tree/master/latest
这个图展示了webrtc中RTCP包的接收过程,整个过程涉及到的类很多
书接上文,这里的起点是WebrtcVideoChannel其OnPacketReceived方法,这个方法是rtp包流到媒体通道的入口
WebrtcVideoChannel有个非常关键的成员,就是webrtc::Call,这个结构体在PeerConnectionFactory创建PeerConnection的时候创建,因此是每个PC内部只有一个Call,这个Call保存在PeerConnection中,在创建VideoChannel的时候,从PC中取出,并传递给MediaChannel,这就是WebrtcVideoChannel中Call的由来
webrtc::Call的实现类是internal::Call,这个Call掌管底层的基本架构。首先通过webrtc::Call的Receiver()接口,得到PacketReceiver,实际上实现这个接口的依然是internal::Call,因此WebrtcVideoChannel拿到packet后,会通过Call的Receiver的DeliverPacket方法,将收到的packet,送给internal::Call
internal::Call在拿到Packet后,就要进行解析了,这里只是非常初步的解析,只要明白这个packet是rtp的还是rtcp的就可以了。我们以Rtcp的包为例,会进一步调用DeliverRtcp的方法。
Call拿到数据为何很重要呢?实在是因为Call是一个大管家,他负责辅助WebrtcVideoChannel创建发送流和接收流,并且内部维护了所有的发送,接收流。因此Call拿到Rtcp包后,就可以分发给其所有的发送接收流了
因此数据被送到了每个发送流里,即VideoSendStream。这个结构是一个包装类,其两个重要的成员,VideoStreamEncoderInterface负责编码,VideoSendStreamImpl负责数据包发送,层次分明。这里有个有意思的现象,VideoSendStreamImpl和VideoSendStream的关系并不是is-a的关系,而是has-a的关系。
VideoSendStreamImpl继续将数据向下游发送,由于是Rtp发送,因此数据送到了RtpVideoSender,这个RtpVideoSender是由RtpTransportControllerSendInterface创建的。RtpVideoSender维护了一个vector,不同的ssrc对应不同的RtpStreamSender,这样RTCP包进一步流到了RtpStreamSender中。
RtpStreamSender将数据送给ModuleRtpRtcpImpl2,这样数据到达了新的Module中,这个Module专门负责Rtp / Rtcp。这个Module有个关键的成员,是RTCPReceiver,这个类负责接收RTCP包,并进行解析。解析的步骤为:首先通过CommonHeader,解析出RTCP包的类型,再交由具体的类进行进一步解析,比如ReceiverReport,Remb。这些类都继承自RtcpPacket,并提供Parse方法对Rtcp包进行解析。
各解析后的关键数据被保存在PacketInformation中,并通过回调将最终的结果返回给上层。
这里就是通过RtcpBandwidthObserver,将数据回调,实现此接口的,又是RtpTransportControllerSend
最后一点需要说明的是,RtpTransportControllerSend是由Call创建出来的,也是每个PC只有一份,因此是所有的接收,发送码流所共享。因此也是一个大管家的地位,可以宏观调控各种资源。后面可以发现,带宽估算,码率分配,这些关键的步骤,都和这个类有非常大的联系