WebRTC中的前向纠错编码 - Red Packet

WebRTC 的FEC(前向纠错编码) 是其QoS的重要组成部分, 用于网络丢包的时候恢复原始数据包, 减少重传次数, 减少延时, 改善视频质量. 它是RFC 5109标准的实现. 下文, 我们将深入剖析其原理.

Redundant Coding

要理解WebRTC中的FEC, 首先需要先了解Red Packet. 所谓Red Packet, 就是Redundant Coding 产生的包. 其定义非常简单, 下面来看Block Header的格式:

0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F| block PT | timestamp offset | block length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

其定义如下:
F: 1 bit, 1 表示后面跟着其他的Block Header, 0 表示这个Block Header就是最后一个.
Block PT: 7 bits, 是这个block payload的 payload type
Timestamp Offset: 14 bits, 无符号数, 是RTP 的Timestamp 到这个Data block的时间偏移
Block Lenth: 10 bits, 是Data Block 长度.

另一种Primary Data Header, 之需要1byte

|F| Block PT|

用来描述最后的一个Data Block, 其TimeStamp 就是RTP Header的Timestap.
WebRTC的Red Packet, 编码时, 用一个rtp packet 产生 1个red packet, 所以使用了 Primary Data Header来描述的

如何协商 数据和Rad Channel 的绑定关系呢?

m=audio 12345 RTP/AVP 121 0 5
a=rtpmap:121 red/8000/1

这段SDP 表示, RTP 音频 Session, 它的Payload Type 是121, 0, 5, Codec Red payload type 是121.

下面来看一个例子:

0 12 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC=0 |M| PT | sequence number of primary |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp of primary encoding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1| block PT=7 | timestamp offset | block length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0| block PT=5 | |
+-+-+-+-+-+-+-+-+ +
|                                     |
+ LPC encoded redundant data (PT=7) +
| (14 bytes) |
+ +---------------+
| | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
+ +
| |
+ +
| |
+ +
| DVI4 encoded primary data (PT=5) |
+ (84 bytes, not to scale) +
/ /
+ +
| |
+ +
| |
+ +---------------+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

WebRTC中的实现:

//  生成Rad Packet 
RedPacket* ProducerFec::BuildRedPacket(const uint8_t* data_buffer,
                                       size_t payload_length,
                                       size_t rtp_header_length,
                                       int red_pl_type) {
  RedPacket* red_packet = new RedPacket(
      payload_length + kREDForFECHeaderLength + rtp_header_length);
  int pl_type = data_buffer[1] & 0x7f;
  red_packet->CreateHeader(data_buffer, rtp_header_length,
                           red_pl_type, pl_type);
  red_packet->AssignPayload(data_buffer + rtp_header_length, payload_length);
  return red_packet;
}
// 生成RedPacket Header
void RedPacket::CreateHeader(const uint8_t* rtp_header, size_t header_length,int red_pl_type, int pl_type) {
   memcpy(data_, rtp_header, header_length);
  // Replace payload type.
  data_[1] &= 0x80;
  data_[1] += red_pl_type;
  // Add RED header
  // f-bit always 0
  data_[header_length] = static_cast(pl_type);
  header_length_ = header_length + kREDForFECHeaderLength;
}
// 填上Payload
void RedPacket::AssignPayload(const uint8_t* payload, size_t length) {
   memcpy(data_ + header_length_, payload, length);
}

Reference:
1. rfc2198 - RTP Payload for Redundant Audio Data
2. rfc5109 - RTP Payload Format for Generic Forward Error Correction

你可能感兴趣的:(多媒体)