基于IP网络的多媒体通信系统(比如WebRTC)中,网络丢包对多媒体通信质量有非常严重的影响:例如造成视频的马赛克、图像模糊、帧率下降等问题,造成音频的声音失真、噪声干扰、音频中断等问题。这都会严重影响系统的通信质量,造成非常差的用户体验。
WebRTC主要采取两种手段对抗网络丢包:丢包重传(NACK)和前向纠错(FEC)。FEC是一种前向纠错技术,发送端将负载数据加上一定的冗余纠错码一起发送,接收端根据接收到的纠错码对数据进行差错检测,如果发现差错,则利用纠错码进行纠错。而ULPFEC(Uneven Level Protection FEC,直译为非均等保护前向纠错基于IP网络的多媒体通信系统(比如WebRTC)中,网络丢包对多媒体通信质量有非常严重的影响:例如造成视频的马赛克、图像模糊、帧率下降等问题,造成音频的声音失真、噪声干扰、音频中断等问题。这都会严重影响系统的通信质量,造成非常差的用户体验。
webrtc fec
相关源码在/src/webrtc/modules/rtp_rtcp/source目录下
解fec包
源码实现在 ulpfec_receiver_impl.cc
demo
void init() {
std::unique_ptr<webrtc::UlpfecReceiver> fec_receiver_;
fec_receiver_.reset(webrtc::UlpfecReceiver::Create(this));
}
void addAndParse(packet) {
webrtc::RTPHeader hacky_header;
hacky_header.headerLength = rtp_header->getHeaderLength();
hacky_header.sequenceNumber = rtp_header->getSeqNumber();
if (fec_receiver_->AddReceivedRedPacket(hacky_header,(const uint8_t*) packet->data, packet->length, external_ulp_pt_) == 0 {
fec_receiver_->ProcessReceivedFec();
}
}
OnRecoveredPacket(const uint8_t* rtp_packet, size_t rtp_packet_length) {
}
封fec包
支持fec功能时,一般都使用red封装格式。
demo
void init() {
webrtc::FecProtectionParams key_fec_params_{1, 60, webrtc::kFecMaskRandom}
fec_generator_.reset(new webrtc::UlpfecGenerator());
fec_generator_->SetFecParameters(key_fec_params_);
}
void buildFec(rtp) {
red_packet = buildRedPacket(rtp);
fec_generator_->AddRtpPacketAndGenerateFec((const uint8_t *)rtp->data, payload_length, header_length);
uint16_t num_fec_packets = fec_generator_->NumAvailableFecPackets();
if (num_fec_packets > 0) {
uint16_t first_fec_sequence_number = AllocateSequenceNumber(num_fec_packets);
fec_packets = fec_generator_->GetUlpfecPacketsAsRed(external_red_pt_, external_ulp_pt_, first_fec_sequence_number,header_length);
}
for (const auto& fec_packet : fec_packets) {
}
}
理解
- Fec采用的是冗余发送机制, 在带宽允许的情况下fec可以起到预期的效果,但对于带宽严重限制的情况下,有可能带来副作用。
- Fec的原理是通过几个原始包算出fec包,所有包的任意几个包,都可以算出其他包。类似 1+2=3, 3-1=2, 3-2=1
- Fec基于以上算法原理,在启用Fec时,可以发送原始包+Fec包,也可以全部发送Fec包,只要通过逆向算法求出原始包即可
- Fec包的时间戳与原始包一致,序列号紧随原始包之后。