传输协议
- 扩展头
在原audio, video screen等流stream的sequnce number的基层上, 增加传输层的sequence number, 即所有的流都会有统一的transportSeq.
uint16_t transportSeq;
- 反馈报文
- 反馈报文定义
struct ControlPacket_TransportFeedback {
uint16_t baseSeq;
uint16_t packetStatusCount;
uint24_t baseTime;
uint8_t feedbackCount;
uint16_t packetStatus[n];
uint16_t recvDeltas[n];
};
字段名 | 含义 | 长度(bit) | 值 |
---|---|---|---|
baseSeq | 这次反馈的头一个包的transportSeq | 16 | 0 - 65535 |
packetStatusCount | 总共反馈多少个包的状态 | 16 | 0 - 65535 |
baseTime | 收端的时间,可用baseSeq收到的时间 | 24 | 绝对时间的后24位,单位ms, 做64ms的倍数 |
feedbackCount | feedback序号,便于知道丢失transportfeedback | 8 | 0 - 255 |
packetStatus[n] | 每个包的状态,具体每一位含义见下表 | 16 * n | |
recvDeltas[n | ]收到包的时间差值,具体每一位含义见下表 | 16 * n |
- packetStatus定义
共两种, 其一:
struct PacketStatus_Repeat {
uint8_t type : 1;
uint8_t status : 2;
uint13_t count ;
};
字段名 | 含义 | 长度(bit) | 值 |
---|---|---|---|
type | 两种packetStatus中哪一种 | 1 | 0 |
status | 包的状态 | 2 | 0x00 -- 未收到 ; 0x01 -- 收到,且recv delta较小; 0x02 --收到,且recv delta 较大; 0x03保留 |
count | 有多个连续的包处于这种状态 | 13 | 1 - 8095 |
其二:
struct PacketStatus_Continue {
uint8_t type : 1;
uint8_t symbol : 1;
uint14_t symbolVector;
};
字段名 | 含义 | 长度(bit) | 值 |
---|---|---|---|
type | 两种packetStatus中哪一种 | 1 | 1 |
symbol | 包的状态的分类 | 1 | 0 -- 只有“收到”, “未收到”两种状态; 1 -- 有以上三种状态 |
symbolVector | 如果symbol = 0, 则可包含14个包的状态; 如果symbol = 1, 则包含7个包的状态。 | 14 |
- recvDeltas定义
Recv delta 较小 : [-128, 127] ms
Recv delta 较大 : [-2048, 2047] ms, 并去掉较小部分
注:这个定义同参考draft不同。
struct RecvDeltas_Small {
uint8_t delta1;
uint8_t delta2;
};
字段名 | 含义 | 长度(bit) | 值 |
---|---|---|---|
delta1 | 接收到的包的时间差 | 8 | 如果recvDeltas的第一个包,则是recvtime - baseTime (ms),否则是,recvtime - lastRecvTime, 即跟前一个包的时间差; |
delta2 | 接收到的包的时间差 | 8 | 如果recvDeltas的第一个包,则是recvtime - baseTime (ms);否则是,recvtime - lastRecvTime, 即跟前一个包的时间差; |
struct RecvDeltas_Large {
uint8_t delta;
};
字段名 | 含义 | 长度(bit) | 值 |
---|---|---|---|
delta | 接收到的包的时间差 | 16 | 如果recvDeltas的第一个包,则是recvtime - baseTime (ms);否则是,recvtime - lastRecvTime, 即跟前一个包的时间差; |
- 反馈报文频率
draft建议: 一个rtt或是30 - 50ms。
实践: 先定为400ms, 基于多次实验测试数据调节。
基于传输反馈的拥塞控制
- TCC算法
- trendline计算:
根据反馈的recv delta计算delay(同rtcp jitter):
然将delay做累加和平滑:
smoothingCoef是个经验值, 在webrtc trendline_estimator.cc中取0.9。
另外还有一个recvTime = recvTime(i) - firstRecvTime;
接着将recvTime, accumulatedDelay和smoothedDelay保存到一个固定窗口大小的队列HistoryQueue中,
然后按以下公式计算线性斜率:
得到的slope即是我们需要的带宽变化趋势。
为了限制slope不让它跑偏了,
在HistoryQueue中取前80%的包中最小的accumlatedDelay(k), 以及这个包对应的recvTime(k),
在HistoryQueue中取后80%的包中最大的accumlatedDelay(m), 以及这个包对应的recvTime(k)
slope不能大于slope(max)。
基于slope判断出网络带宽的使用状态: overuse, underuse, normal。
最后,基于新的网络带宽状态, 通过AIMD调整带宽。
- trendline计算带来的优势:
- 算法简洁,易于实现和改进
- 平滑jitter