一種基于rudp的實時互動視頻的高效可靠傳輸方案

注:本文已收錄專利,版權所有。另外,部分段落縮減了部分內容。

1. 背景

當下移動互聯網視頻直播正處于如火如荼的井噴式發展當中,不同的行業(比如教育、醫療、旅游等)都涉足參與進來,企圖在這個市場上占有一席之地,爭當獨角獸式的公司。傳統的直播,大多數是單向型,比如電視臺或者運營商直播,用戶只需要打開終端收看即可,對于實時性并沒有太大的要求。而移動直播往往在功能上需要主播端和播放端有交互,這種交互不限于文字的互動,視頻與語音的互動也日趨成為基本的交互場景需求,傳統的做法是主播端采集視頻數據并編碼成x264、采集音頻數據并編碼成aac,再合并打包后通過一定的Qos算法將音視頻流數據通過rtmp協議(基于TCP協議之上)推流到CDN服務器進行分發,用戶端從CDN服務器拉流解碼來播放,這種方式的延時表現在rtmp推流到CDN和播放器從CDN通過rtmp拉流緩存播放,整個網絡鏈路的延遲通常在1-3秒或者更差。在網絡不穩定的情況下,通常提高用戶觀看體驗的方式是通過在主播端和播放端設置Gop緩存,讓碼率均勻;另外可以在主播端通過Qos算法檢測變化的網絡來動態改變碼率和幀率;還可以接入多個視頻云服務CDN提供商,這樣可以做推拉流線路互備,對推流后視頻服務集群再優化并根據端點網絡狀況做實時線路切換。另外一種方式是通過http HLS的方式進行傳輸,這種切片式的直播方式延遲更大,不適合高互動式的場景直播。

所以本文提出了一種基于UDP方式的視頻傳輸方案(webrtc層外),旨在服務于低延遲高實時互動式的直播場景,這種方式能將延遲控制在800ms人眼可接收范圍內,在網絡帶寬比較差或者強丟包、亂序的情況下,通過緩存機制、帶寬自適應檢測機制實時匯報給編碼器降低碼率、分辨率、幀率,能可靠有效的將實時畫面完整的播放出來,提高了用戶體驗。

2 視頻傳輸流程

2.1 視頻傳輸時序圖

本方案采用基于udp協議的報文傳輸,設計了一套私有的報文格式,以使得整個報文在網絡鏈路中傳輸簡單可靠并可控,相對于TCP傳輸的方式,大大的降低了報文的大小與復雜度,保證了整個傳輸過程的實時性。如下圖1為視頻傳輸的時序圖。

圖1 視頻傳輸時序圖

2.2 關鍵技術

本方案視頻編碼采用h264的形式(也可以是h265,負載數據是不受傳輸模塊限制的,可以在兩端進行適配和協調),因為B幀是雙向預測幀,它需要根據后向視頻幀來預測編碼,一定程度上會增大編解碼延遲,所以為了保證傳輸和播放的實時性,本方案視頻壓縮丟棄B幀編碼。

2.2.1 發送端處理

2.2.1.1 視頻切片算法

當編碼器編碼出一幀完整的h264視頻幀數據時送入發送端,對于高分辨率的視頻編碼幀,幀大小往往高于UDP網絡MTU,所以此時需要發送端對其進行分片處理再發送,每次按照分片單位來發送幀塊數據。

視頻編碼幀的最大分片數SMAX為500,規定單個分片字節大小SEGS為800bytes (根據探測MTU可動態計算調整)。當幀字節大小FS小于SEGS+50時只分為一個分片;否則,整數倍的分片數S為FS/SEGS,超出的最后字節數FS1為FS%SEGS,如果FS1大于50,則再單獨分一個分片,此時總分片數為S+1,否則如果FS1小于50并且大于0時,將FS1字節累加放入最后一個分片中,此時總分片數為S。如下圖2為視頻分片結構與流程。

圖2 視頻分片結構

2.2.1.2 發送端滑動窗口

發送緩存區保存著所有正在發送且沒有收到接收方連續seq確認acked的報文。當收到peer端發來的分片的ack信息(攜帶一系列丟包的分片seq和已經ack并連續處理到的seq)時,發送端從發送緩存中獲取對應的那些丟包seq并重發分片(如下圖的seq 10/12分片),同時從緩存中刪除區間[s1+1, s2]中的分片,同時移動滑動窗口。如下圖3為發送端滑動窗口滑動過程圖。

圖3 發送端滑動窗口

2.2.1.3 發送端帶寬自適應調整算法

對于網絡的不可預測性,可能出現抖動、擁塞或者很多的丟包,如果按照固定的碼率和參數來發送視頻幀,這會導致發送端與接收端的線路間更擁塞,從而使觀看端出現更多的播放延遲或者馬賽克。所以在發送端需要做帶寬的實時估算來探測網絡情況,從而便于實時根據網絡帶寬來調整上層視頻編碼器的幀率或者碼率。

在發送端設置了一個定時器,每10秒鐘(可配置)做一次帶寬統計。rtt修正值(網絡抖動的時間差值)為rtt_var,期望目標帶寬為dst_bw,當前發送的幀分片時間為cur_ts,最后acked的幀分片時間為acked_ts,則

delay_ts_delta = cur_ts–acked_ts

當前單位時間內的acked帶寬為bw,則帶寬抖動修正值acked_bw為:

acked_bw = (acked_bw * 3 + bw) / 4

如果當前有包在重發,且 delay _ts_delta 大于 8 * MAX(rtt + rtt_var, 100),則dst_bw = acked_bw,向下降低調整視頻編碼器的分辨率、幀率或碼率來保證播放的實時性和流暢性;否則如果acked_bw 大于0,則dst_bw = acked_bw * 9 / 8,向上提高調整視頻編碼器的分辨率、幀率或碼率來恢復清晰度和提高播放體驗。

2.2.1.4 過期幀丟棄策略

在網絡擁塞時可能發送窗口緩沖區中有很多正在發送中的分片報文,為了緩解擁塞和減少延遲會對整個緩沖區做檢查,如果有超過一定閾值時間的GOP 幀存在,則會將這個 GOP 內的所有幀的分片從窗口緩沖區移除,并將它的下一個 GOP 的 I 幀 fid和分片seq 通過 syn 協議同步到各個接收端上,接收端接收到此協議,會將最新連續 seq 設置成同步過來的 seq。如果頻繁出現過期幀丟棄處理則會造成一定程度上的播放卡頓,此時說明當前網絡不適合傳輸高分辨率或高幀率的視頻,可以通知上層視頻編碼器設置為更小的分辨率或幀率。

2.2.2 接收端處理

2.2.2.1 接收端收包處理

接收端收到服務器中轉過來的syn消息(攜帶用戶uid、開始分片序列號start_seq、幀率)后,根據uid查找(或分配)對應的發送者并激活,同時根據start_seq更新已經連續接收到的分片序列號base_seq和當前接收到的分片最大序列號max_seq。

圖4 接收者存儲表

接收端第一幀必須是關鍵幀(即一個完整GOP的開始),如果是其他幀則丟棄,直到出現關鍵幀為止,因為如果第一幀是P幀將出現花屏現象。

每收到一個分片,如果此分片的seq小于base_seq或者幀fid小于已經接收到的最小幀min_fid(已經接收過了)或者分片的seq大于max_seq+2000(太大的跳變導致丟包緩存太大),則丟棄;否則,當收到第一個關鍵幀的第一個片段時,記下此時max_seq和base_seq,將此分片放入對應幀fid的分片緩存區,同時計算單位時間內的幀間隔時長,并更新丟包緩存表,如果此分片的seq和前一個已接收分片的seq連續,則更新base_seq為此分片的seq,再更新max_seq為MAX(max_seq, seq),最后發送ack給peer端。

如下圖5為接收端收到幀分片并存儲到緩存區的一個實例,對于一個完整的幀fid1的分片序列為區間seq [1, 8],幀fid2的分片序列為區間seq [9, 20]。幀的分片seq總是單調遞增的。

圖5 接收幀分片緩存區

2.2.2.2 更新丟包緩存區策略

如下圖所示,接收端已經連續收到了seq [1, 5] 的分片包,此時base_seq 和 max_seq 都是5,當接收到下一個分片包seq 10時,將seq 10從丟包緩存中刪除,此時認為 seq [6, 9] 是暫時丟失的(可能亂序不一定真丟失,需要后續的包來確認),如果丟包緩存中沒有此序號的丟包,則將它們放入丟包緩存中,同時更新它們的丟包時間戳(當前時間減去rtt值),等待下一次的接收確認。

圖6 接收端滑動窗口

2.2.2.3 接收端發送回應ack策略

當接收端每次收到peer端發來的分片,需要判斷是否發送回應ack給peer端,發送周期是10ms(毫秒),小于10ms則不發送ack,發送太頻繁會導致網絡擁塞;否則,獲取接收緩存中最老的一幀中最小的分片包序號min_seq,檢查接收端丟包緩存區,并刪除區間[base_seq+1, min_seq]中的丟包,表明這些丟包已經處理過了,同時設置滑動窗口的base_seq為min_seq,然后循環掃描丟包緩存區檢查當前時間是否超過一個發送分片的rtt時間,如果超過則累加此分片的丟包計數器,并更新丟包分片的時間為當前時間,最后將所有超過rtt時長的丟包發送ack回peer端,最后計算播放緩存延遲時長。

在幀緩存中會選擇性刪除一些播放過的幀分片,播放過的幀分片是不需要進行重發的。

在接收端設置了一個定時器,每隔5ms(毫秒)也會檢測一次是否發送回應ack給peer端,并掃描檢查和更新丟包緩存區。

2.2.3 獲取播放視頻幀處理

2.2.3.1 播放緩存區策略

在當前播放端設置了一個幀緩存區,如果緩存區過大時播放延遲就大,過小時又會出現播放卡頓情況。所以設置播放緩存區策略就至關重要,緩沖時間大小wait_ts應該大于rtt + 2 * rtt_val,根據重發報文的次數來決定,在接收端的計時器中定期檢查丟包數和rtt時長來動態的確定wait_ts的大小。

每次上層從播放緩存區獲取一幀時,內部都會檢查當前播放緩存區是處于可播放(max_fid>min_fid并且緩存區中最新幀(max_fid)的時間戳max_ts>wait_ts * 5 / 4,則更新可播放的絕對時間戳play_ts為當前系統時間且cached_ts = max_ts - wait_ts * 5 / 4)中還是緩沖(max_fid=min_fid)中,如果在緩沖中則返回空數據;否則同步更新播放緩沖幀時間戳,如果緩存中最久的一幀(min_fid)的所有分片已經接收完整并且此幀時間F_Oldest_ts在播放緩存時間cached_ts內,則合并當前幀分片返回給上層解碼播放,同時從緩存中刪除此幀,并且更新min_fid為此幀的fid和當前已經緩存到的幀的時間戳cached_ts。

此cached_ts的計算方式為:當 F_Oldest_ts + wait_ts * 5 / 4 >= max_ts(說明緩存區幀很少)或者 min_fid + 1 = max_fid (說明只剩一幀)時,cached_ts = F_Oldest_ts;否則cached_ts = max_ts - wait_ts * 5 / 4,說明緩存區的幀足夠。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379