织梦CMS - 轻松建站从此开始!

罗索

WebRTC中丢包重传机制的实现

jackyhwei 发布于 2018-05-14 15:34 点击:次 
当网络质量突然变的很差并开始丢包时,声音听起来音质会变差,画面帧速会下降,甚至会完全卡住。我们可能需要某种机制来应对这种情况。在WebRTC中,主要有两种机制来应该网络变差的情况
TAG: WebRTC  丢包重传  NACK  FEC  

当网络质量突然变的很差并开始丢包时,声音听起来音质会变差,画面帧速会下降,甚至会完全卡住。我们可能需要某种机制来应对这种情况。在WebRTC中,主要有两种机制来应该网络变差的情况:
  1. 前向纠错:在每个数据包中,您将添加一些关于前一个信息的信息,以防丢失,您需要重新构建它们(flexfec是WebRTC [1]中的新格式)。
  2. 重传:当接收方检测到有丢包时,它会发送NACK类型的RTCP包给发送方,发送方会重发这些数据。
 
这些机制可以根据网络条件进行组合,也可以针对特定情况进行调整,如[2]中所述的可扩展视频。在Chrome中,理论上音频,视频丢包都可以重传,但默认情况下只会启用视频丢包重传。下面会详细介绍丢包重传的具体实现。
 
RTP接收方
丢包重传的请求是由RTP接收方发起的。当RTP接收方检测RTP包头中的seq属性发现有丢包时,丢包重传机制就会启用。但是,是否检测到下一个RTP包不是自己预期想要的哪个就会要求重传呢?比如当前RTP序号是99,下一个来的包序号是101,哪就是否意味着序号为100的包就丢了呢?由于RTP协议是基于UDP的,而UDP又是无序传输的。再下一个包又可能就是序号为100的包。WebRTC会以500毫秒周期性的检测有没有丢包,然后不断请求重传特定数据包,除非序列号为“超过10000 old”,列表中丢失的数据包数量大于1000,您已经询问了相同的数据包10次,或者您有一个新的可解码的完整数据帧(任何依赖于其他帧的数据包都不丢失)。 
# code from nack_module.cc
on_packet(rtp):
#检测丢包
if rtp.seq_num < newest_seq_num: # out of order or retransmnission
return

add_missing(newest_seq_num + 1, rtp.seq_num)
if rtp.is_first_packet_of_keyframe:
keyframes.insert(rtp.seq_num)

newest_seq_num = packet.seq_num
if nack = generate_nack(SEQ):
send_nack(nack)

#删除过时的包
add_missing(from_seq_num, to_seq_num):
packets_lost.remove_older_than(10000) # MAX_PACKET_AGE (sequence numbers)
if packets_lost.size() > 1000: # MAX_SIZE
packets_lost.remove_until_keyframe()

if packets_lost.size() > 1000: # Still too big
packets_lost.clear()

sender.request_keyframe()

return

for seq_num in range(from_seq_num, to_seq_num):
packets_lost.insert(seq_num)


# 有一个最新的可解码完整帧,清空重传队列
cleanup_to(to_seq_num):
packets_lost.remove(seq_num < to_seq_num);

generate_nack(mode):
seq_nums = []
for packet in packets_lost:

if packet.retries > 10: # MAX_RETRIES
packets_lost.remove(packet)

if (mode == SEQ and packet.seq_num < newest_seq_num) or (mode == TIME and packet.sent_at + rtt > now()):
seq_nums.insert(packet.seq_num)

packet.sent_at = now()

return seq_nums

every_20_msec():

if nack = generate_nack(TIME):

send_nack(nack)
#rtp_rtcp_impl.cc 发送nack重传rtcp包
send_nack(seq_nums):
if now - time_last_full_nack_sent < 1.5 * RTT:
seq_nums.filter(seq_num > seq_num_last_nack_sent)
else:
time_last_full_nack_sent = now

if seq_nums.length > 253:
seq_nums = seq_nums[:-253]

send(new RtcpNack(seq_nums))
 
RTP发送方实现
RTP发送方接收到NACK重传请求后会重传所有的数据包吗?WebRTC是这样实现的:
  1. 保留在最近1000毫秒(“历史”)中发送的数据包的副本。
  2. 当接收到NACK时,如果历史记录中仍然有这个数据包,尝试发送数据包。
  3. 但...(rtp_sender.cc)
  • 如果这个数据包刚在前面一个RTT时间范围内传输过了,就忽略。
  • 如果要求重传数据太多,请忽略该请求。
  • 如果启用了WebRTC的pacing模块,则将该重传数据包插入到队列中,并且具有正常的优先级,由pacing模块发送。
(tanningzhong)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201805/17535.html]
本文出处:CSDN博客 作者:tanningzhong 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容