傳輸協(xié)議
- 擴(kuò)展頭
在原audio, video screen等流stream的sequnce number的基層上, 增加傳輸層的sequence number, 即所有的流都會(huì)有統(tǒng)一的transportSeq.
uint16_t transportSeq;
- 反饋報(bào)文
- 反饋報(bào)文定義
struct ControlPacket_TransportFeedback {
uint16_t baseSeq;
uint16_t packetStatusCount;
uint24_t baseTime;
uint8_t feedbackCount;
uint16_t packetStatus[n];
uint16_t recvDeltas[n];
};
| 字段名 | 含義 | 長(zhǎng)度(bit) | 值 |
|---|---|---|---|
| baseSeq | 這次反饋的頭一個(gè)包的transportSeq | 16 | 0 - 65535 |
| packetStatusCount | 總共反饋多少個(gè)包的狀態(tài) | 16 | 0 - 65535 |
| baseTime | 收端的時(shí)間,可用baseSeq收到的時(shí)間 | 24 | 絕對(duì)時(shí)間的后24位,單位ms, 做64ms的倍數(shù) |
| feedbackCount | feedback序號(hào),便于知道丟失transportfeedback | 8 | 0 - 255 |
| packetStatus[n] | 每個(gè)包的狀態(tài),具體每一位含義見(jiàn)下表 | 16 * n | |
| recvDeltas[n | ]收到包的時(shí)間差值,具體每一位含義見(jiàn)下表 | 16 * n |
- packetStatus定義
共兩種, 其一:
struct PacketStatus_Repeat {
uint8_t type : 1;
uint8_t status : 2;
uint13_t count ;
};
| 字段名 | 含義 | 長(zhǎng)度(bit) | 值 |
|---|---|---|---|
| type | 兩種packetStatus中哪一種 | 1 | 0 |
| status | 包的狀態(tài) | 2 | 0x00 -- 未收到 ; 0x01 -- 收到,且recv delta較小; 0x02 --收到,且recv delta 較大; 0x03保留 |
| count | 有多個(gè)連續(xù)的包處于這種狀態(tài) | 13 | 1 - 8095 |
其二:
struct PacketStatus_Continue {
uint8_t type : 1;
uint8_t symbol : 1;
uint14_t symbolVector;
};
| 字段名 | 含義 | 長(zhǎng)度(bit) | 值 |
|---|---|---|---|
| type | 兩種packetStatus中哪一種 | 1 | 1 |
| symbol | 包的狀態(tài)的分類 | 1 | 0 -- 只有“收到”, “未收到”兩種狀態(tài); 1 -- 有以上三種狀態(tài) |
| symbolVector | 如果symbol = 0, 則可包含14個(gè)包的狀態(tài); 如果symbol = 1, 則包含7個(gè)包的狀態(tài)。 | 14 |
- recvDeltas定義
Recv delta 較小 : [-128, 127] ms
Recv delta 較大 : [-2048, 2047] ms, 并去掉較小部分
注:這個(gè)定義同參考draft不同。
struct RecvDeltas_Small {
uint8_t delta1;
uint8_t delta2;
};
| 字段名 | 含義 | 長(zhǎng)度(bit) | 值 |
|---|---|---|---|
| delta1 | 接收到的包的時(shí)間差 | 8 | 如果recvDeltas的第一個(gè)包,則是recvtime - baseTime (ms),否則是,recvtime - lastRecvTime, 即跟前一個(gè)包的時(shí)間差; |
| delta2 | 接收到的包的時(shí)間差 | 8 | 如果recvDeltas的第一個(gè)包,則是recvtime - baseTime (ms);否則是,recvtime - lastRecvTime, 即跟前一個(gè)包的時(shí)間差; |
struct RecvDeltas_Large {
uint8_t delta;
};
| 字段名 | 含義 | 長(zhǎng)度(bit) | 值 |
|---|---|---|---|
| delta | 接收到的包的時(shí)間差 | 16 | 如果recvDeltas的第一個(gè)包,則是recvtime - baseTime (ms);否則是,recvtime - lastRecvTime, 即跟前一個(gè)包的時(shí)間差; |
- 反饋報(bào)文頻率
draft建議: 一個(gè)rtt或是30 - 50ms。
實(shí)踐: 先定為400ms, 基于多次實(shí)驗(yàn)測(cè)試數(shù)據(jù)調(diào)節(jié)。
基于傳輸反饋的擁塞控制
- TCC算法
- trendline計(jì)算:
根據(jù)反饋的recv delta計(jì)算delay(同rtcp jitter):

然將delay做累加和平滑:

smoothingCoef是個(gè)經(jīng)驗(yàn)值, 在webrtc trendline_estimator.cc中取0.9。
另外還有一個(gè)recvTime = recvTime(i) - firstRecvTime;
接著將recvTime, accumulatedDelay和smoothedDelay保存到一個(gè)固定窗口大小的隊(duì)列HistoryQueue中,
然后按以下公式計(jì)算線性斜率:

得到的slope即是我們需要的帶寬變化趨勢(shì)。
為了限制slope不讓它跑偏了,
在HistoryQueue中取前80%的包中最小的accumlatedDelay(k), 以及這個(gè)包對(duì)應(yīng)的recvTime(k),
在HistoryQueue中取后80%的包中最大的accumlatedDelay(m), 以及這個(gè)包對(duì)應(yīng)的recvTime(k)

slope不能大于slope(max)。
基于slope判斷出網(wǎng)絡(luò)帶寬的使用狀態(tài): overuse, underuse, normal。
最后,基于新的網(wǎng)絡(luò)帶寬狀態(tài), 通過(guò)AIMD調(diào)整帶寬。
- trendline計(jì)算帶來(lái)的優(yōu)勢(shì):
- 算法簡(jiǎn)潔,易于實(shí)現(xiàn)和改進(jìn)
- 平滑jitter