1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/producer_fec.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" 14cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgenum { kREDForFECHeaderLength = 1 }; 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This controls the maximum amount of excess overhead (actual - target) 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// allowed in order to trigger GenerateFEC(), before |params_.max_fec_frames| 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// is reached. Overhead here is defined as relative to number of media packets. 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgenum { kMaxExcessOverhead = 50 }; // Q8. 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This is the minimum number of media packets required (above some protection 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// level) in order to trigger GenerateFEC(), before |params_.max_fec_frames| is 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// reached. 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgenum { kMinimumMediaPackets = 4 }; 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Threshold on the received FEC protection level, above which we enforce at 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// least |kMinimumMediaPackets| packets for the FEC code. Below this 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// threshold |kMinimumMediaPackets| is set to default value of 1. 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgenum { kHighProtectionThreshold = 80 }; // Corresponds to ~30 overhead, range 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// is 0 to 255, where 255 corresponds to 100% overhead (relative to number of 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// media packets). 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct RtpPacket { 35b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org uint16_t rtpHeaderLength; 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ForwardErrorCorrection::Packet* pkt; 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRedPacket::RedPacket(int length) 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : data_(new uint8_t[length]), 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org length_(length), 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org header_length_(0) { 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRedPacket::~RedPacket() { 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] data_; 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid RedPacket::CreateHeader(const uint8_t* rtp_header, int header_length, 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int red_pl_type, int pl_type) { 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(header_length + kREDForFECHeaderLength <= length_); 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(data_, rtp_header, header_length); 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Replace payload type. 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org data_[1] &= 0x80; 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org data_[1] += red_pl_type; 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Add RED header 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // f-bit always 0 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org data_[header_length] = pl_type; 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org header_length_ = header_length + kREDForFECHeaderLength; 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid RedPacket::SetSeqNum(int seq_num) { 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(seq_num >= 0 && seq_num < (1<<16)); 646aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org RtpUtility::AssignUWord16ToBuffer(&data_[2], seq_num); 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid RedPacket::AssignPayload(const uint8_t* payload, int length) { 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(header_length_ + length <= length_); 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(data_ + header_length_, payload, length); 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid RedPacket::ClearMarkerBit() { 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org data_[1] &= 0x7F; 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orguint8_t* RedPacket::data() const { 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return data_; 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint RedPacket::length() const { 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return length_; 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgProducerFec::ProducerFec(ForwardErrorCorrection* fec) 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : fec_(fec), 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org media_packets_fec_(), 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fec_packets_(), 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_frames_(0), 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org incomplete_frame_(false), 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_first_partition_(0), 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_media_packets_fec_(1), 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org params_(), 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org new_params_() { 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(¶ms_, 0, sizeof(params_)); 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&new_params_, 0, sizeof(new_params_)); 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgProducerFec::~ProducerFec() { 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DeletePackets(); 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ProducerFec::SetFecParameters(const FecProtectionParams* params, 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int num_first_partition) { 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Number of first partition packets cannot exceed kMaxMediaPackets 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(params->fec_rate >= 0 && params->fec_rate < 256); 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (num_first_partition > 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<int>(ForwardErrorCorrection::kMaxMediaPackets)) { 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_first_partition = 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ForwardErrorCorrection::kMaxMediaPackets; 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store the new params and apply them for the next set of FEC packets being 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // produced. 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org new_params_ = *params; 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_first_partition_ = num_first_partition; 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (params->fec_rate > kHighProtectionThreshold) { 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_media_packets_fec_ = kMinimumMediaPackets; 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_media_packets_fec_ = 1; 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRedPacket* ProducerFec::BuildRedPacket(const uint8_t* data_buffer, 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int payload_length, 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int rtp_header_length, 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int red_pl_type) { 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RedPacket* red_packet = new RedPacket(payload_length + 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kREDForFECHeaderLength + 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_header_length); 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int pl_type = data_buffer[1] & 0x7f; 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org red_packet->CreateHeader(data_buffer, rtp_header_length, 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org red_pl_type, pl_type); 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org red_packet->AssignPayload(data_buffer + rtp_header_length, payload_length); 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return red_packet; 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ProducerFec::AddRtpPacketAndGenerateFec(const uint8_t* data_buffer, 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int payload_length, 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int rtp_header_length) { 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(fec_packets_.empty()); 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (media_packets_fec_.empty()) { 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org params_ = new_params_; 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org incomplete_frame_ = true; 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const bool marker_bit = (data_buffer[1] & kRtpMarkerBitMask) ? true : false; 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (media_packets_fec_.size() < ForwardErrorCorrection::kMaxMediaPackets) { 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Generic FEC can only protect up to kMaxMediaPackets packets. 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ForwardErrorCorrection::Packet* packet = new ForwardErrorCorrection::Packet; 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->length = payload_length + rtp_header_length; 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(packet->data, data_buffer, packet->length); 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org media_packets_fec_.push_back(packet); 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (marker_bit) { 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ++num_frames_; 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org incomplete_frame_ = false; 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Produce FEC over at most |params_.max_fec_frames| frames, or as soon as: 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (1) the excess overhead (actual overhead - requested/target overhead) is 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // less than |kMaxExcessOverhead|, and 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (2) at least |minimum_media_packets_fec_| media packets is reached. 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!incomplete_frame_ && 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (num_frames_ == params_.max_fec_frames || 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (ExcessOverheadBelowMax() && MinimumMediaPacketsReached()))) { 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(num_first_partition_ <= 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<int>(ForwardErrorCorrection::kMaxMediaPackets)); 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int ret = fec_->GenerateFEC(media_packets_fec_, 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org params_.fec_rate, 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_first_partition_, 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org params_.use_uep_protection, 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org params_.fec_mask_type, 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &fec_packets_); 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (fec_packets_.empty()) { 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_frames_ = 0; 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DeletePackets(); 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Returns true if the excess overhead (actual - target) for the FEC is below 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// the amount |kMaxExcessOverhead|. This effects the lower protection level 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// cases and low number of media packets/frame. The target overhead is given by 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// |params_.fec_rate|, and is only achievable in the limit of large number of 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// media packets. 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ProducerFec::ExcessOverheadBelowMax() { 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ((Overhead() - params_.fec_rate) < kMaxExcessOverhead); 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Returns true if the media packet list for the FEC is at least 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// |minimum_media_packets_fec_|. This condition tries to capture the effect 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// that, for the same amount of protection/overhead, longer codes 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// (e.g. (2k,2m) vs (k,m)) are generally more effective at recovering losses. 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ProducerFec::MinimumMediaPacketsReached() { 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float avg_num_packets_frame = static_cast<float>(media_packets_fec_.size()) / 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_frames_; 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (avg_num_packets_frame < 2.0f) { 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (static_cast<int>(media_packets_fec_.size()) >= 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_media_packets_fec_); 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // For larger rates (more packets/frame), increase the threshold. 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (static_cast<int>(media_packets_fec_.size()) >= 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_media_packets_fec_ + 1); 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ProducerFec::FecAvailable() const { 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (fec_packets_.size() > 0); 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRedPacket* ProducerFec::GetFecPacket(int red_pl_type, 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fec_pl_type, 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uint16_t seq_num, 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int rtp_header_length) { 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (fec_packets_.empty()) 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return NULL; 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Build FEC packet. The FEC packets in |fec_packets_| doesn't 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // have RTP headers, so we're reusing the header from the last 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // media packet. 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ForwardErrorCorrection::Packet* packet_to_send = fec_packets_.front(); 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ForwardErrorCorrection::Packet* last_media_packet = media_packets_fec_.back(); 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RedPacket* return_packet = new RedPacket(packet_to_send->length + 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kREDForFECHeaderLength + 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_header_length); 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return_packet->CreateHeader(last_media_packet->data, 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_header_length, 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org red_pl_type, 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fec_pl_type); 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return_packet->SetSeqNum(seq_num); 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return_packet->ClearMarkerBit(); 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return_packet->AssignPayload(packet_to_send->data, packet_to_send->length); 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fec_packets_.pop_front(); 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (fec_packets_.empty()) { 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Done with all the FEC packets. Reset for next run. 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DeletePackets(); 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org num_frames_ = 0; 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return return_packet; 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ProducerFec::Overhead() const { 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Overhead is defined as relative to the number of media packets, and not 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // relative to total number of packets. This definition is inhereted from the 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // protection factor produced by video_coding module and how the FEC 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // generation is implemented. 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(!media_packets_fec_.empty()); 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int num_fec_packets = fec_->GetNumberOfFecPackets(media_packets_fec_.size(), 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org params_.fec_rate); 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Return the overhead in Q8. 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (num_fec_packets << 8) / media_packets_fec_.size(); 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ProducerFec::DeletePackets() { 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (!media_packets_fec_.empty()) { 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete media_packets_fec_.front(); 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org media_packets_fec_.pop_front(); 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(media_packets_fec_.empty()); 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace webrtc 261