github:https://github.com/bigonelby/webrtcUml/tree/master/latest
这张图介绍了pacing过程中的入队列情况
既然提到了pacing,显然会把之前的RtpPacketToSend缓存在某个队列里,然后再以某种方式从队列里取出数据然后发送到网络中。这里介绍的就是缓存入队列的过程
probe并不是这张图的重点,这里先不介绍,后面再具体研究
之前已经知道数据流是如何从编码器产生并最终送到了pacing模块,因此这里主要关注的是PacingController的packet_queue_,也就是RoundRobinPacketQueue
这个packet_queue_可不一般,因为这里的入队列情况一定是有优先级只说的,packet的发送也不是简单的先进先出的,而是按照优先级来的,即优先级最高的那些包,会被最先发送到网络中去。因此首先看看优先级,优先级从大到小的顺序为audio > retransmission > video > fec > padding
来看看RoundRobinPacketQueue的基本结构。这个RoundRobinPacketQueue是由Stream构成的,key为ssrc,即每个ssrc对应一个Stream,Stream有个成员packet_queue,为PriorityPacketQueue,这个结构体是继承自std::priority_queue的,因此这个Queue的入栈会根据优先级排序,优先级高的在前面,优先级低的在后面。优先级之前已经介绍了,这里补充一点,当优先级相同时,重传包的优先级最高;如果都不是重传包或都是重传包,则根据入队列的次序决定优先级,入队列的次序即为每个包所对应的packet_counter_
PriorityPacketQueue这个按照优先级大小入队列的结构体,其成员为QueuedPacket,此结构体的成员owned_packet_即为之前打包好的RtpPacketToSend
梳理一下RtpPacketToSend的入队列的过程:首先从RoundRobinPacketQueue的streams中找到对应的Stream,然后按照优先级插入到Stream的成员PriorityPacketQueue中,这个Queue中的每个成员QueuedPacket中的owned_packet_即为RtpPacketToSend
最后看看RtpPacketToSend的出队列的过程。我们需要找到优先级最高的Stream,然后从这个Stream中Pop优先级最高的那个RtpPacketToSend。从指定的Stream中找到优先级最高的RtpPacketToSend并非难事。因为本身,PriorityPacketQueue即为有序的容器,因此其top()元素,即为优先级最高。因此要解决的问题是如何找到优先级最高的Stream。
比较容易想到的方案就是遍历所有的streams,然后找到每个PriorityPacketQueue的top(),比较其优先级值,从而得到优先级最高的Stream。但是这个操作过于繁琐。由于每个RtpPacketToSend在出队列时均要进行这个操作,因此考虑用空间换时间。因此在RoundRobinPacketQueue中还维护着另一个有序容器,即StreamPrioKey,这个有序容器是std::multimap,其中key为StreamPrioKey,值为ssrc。我们知道std::multimap是有序容器,其元素在入队列时,会根据key值进行排序,由此结构体,我们就可以找到优先级最高的ssrc,也就是stream_priorities_.begin(),而值ssrc,就是我们要找的优先级最高的那个ssrc。我们通过这个ssrc,就可以在streams中找到所对应的Stream了,这样就非常快速的找到了当前优先级最高的Stream