Add test which verifies that the RTP header extensions are set correctly for FEC packets.
Also taking the opportunity to do a little bit of clean up.
BUG=webrtc:705
R=pbos@webrtc.org
Review URL: https://codereview.webrtc.org/1506863002 .
Cr-Commit-Position: refs/heads/master@{#10927}
diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
index 7a9a8be..e28dc27 100644
--- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
+++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
@@ -129,9 +129,7 @@
int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear;
// Do some error checking on the media packets.
- PacketList::const_iterator media_list_it = media_packet_list.begin();
- while (media_list_it != media_packet_list.end()) {
- Packet* media_packet = *media_list_it;
+ for (Packet* media_packet : media_packet_list) {
assert(media_packet);
if (media_packet->length < kRtpHeaderSize) {
@@ -146,7 +144,6 @@
LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes "
<< "with overhead is larger than " << IP_PACKET_SIZE;
}
- media_list_it++;
}
int num_fec_packets =
@@ -167,29 +164,30 @@
// -- Generate packet masks --
// Always allocate space for a large mask.
- uint8_t* packet_mask = new uint8_t[num_fec_packets * kMaskSizeLBitSet];
- memset(packet_mask, 0, num_fec_packets * num_maskBytes);
+ rtc::scoped_ptr<uint8_t[]> packet_mask(
+ new uint8_t[num_fec_packets * kMaskSizeLBitSet]);
+ memset(packet_mask.get(), 0, num_fec_packets * num_maskBytes);
internal::GeneratePacketMasks(num_media_packets, num_fec_packets,
num_important_packets, use_unequal_protection,
- mask_table, packet_mask);
+ mask_table, packet_mask.get());
- int num_maskBits = InsertZerosInBitMasks(media_packet_list, packet_mask,
- num_maskBytes, num_fec_packets);
+ int num_mask_bits = InsertZerosInBitMasks(
+ media_packet_list, packet_mask.get(), num_maskBytes, num_fec_packets);
- l_bit = (num_maskBits > 8 * kMaskSizeLBitClear);
+ l_bit = (num_mask_bits > 8 * kMaskSizeLBitClear);
- if (num_maskBits < 0) {
- delete[] packet_mask;
+ if (num_mask_bits < 0) {
return -1;
}
if (l_bit) {
num_maskBytes = kMaskSizeLBitSet;
}
- GenerateFecBitStrings(media_packet_list, packet_mask, num_fec_packets, l_bit);
- GenerateFecUlpHeaders(media_packet_list, packet_mask, l_bit, num_fec_packets);
+ GenerateFecBitStrings(media_packet_list, packet_mask.get(), num_fec_packets,
+ l_bit);
+ GenerateFecUlpHeaders(media_packet_list, packet_mask.get(), l_bit,
+ num_fec_packets);
- delete[] packet_mask;
return 0;
}
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
index 3e2a2b8..bec3623 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -42,13 +42,13 @@
_retransmissionSettings(kRetransmitBaseLayer),
// Generic FEC
- _fec(),
- _fecEnabled(false),
- _payloadTypeRED(-1),
- _payloadTypeFEC(-1),
+ fec_(),
+ fec_enabled_(false),
+ red_payload_type_(-1),
+ fec_payload_type_(-1),
delta_fec_params_(),
key_fec_params_(),
- producer_fec_(&_fec),
+ producer_fec_(&fec_),
_fecOverheadRate(clock, NULL),
_videoBitrate(clock, NULL) {
memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
@@ -130,7 +130,7 @@
// Only protect while creating RED and FEC packets, not when sending.
CriticalSectionScoped cs(crit_.get());
red_packet.reset(producer_fec_.BuildRedPacket(
- data_buffer, payload_length, rtp_header_length, _payloadTypeRED));
+ data_buffer, payload_length, rtp_header_length, red_payload_type_));
if (protect) {
producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, payload_length,
rtp_header_length);
@@ -140,7 +140,7 @@
next_fec_sequence_number =
_rtpSender.AllocateSequenceNumber(num_fec_packets);
fec_packets = producer_fec_.GetFecPackets(
- _payloadTypeRED, _payloadTypeFEC, next_fec_sequence_number,
+ red_payload_type_, fec_payload_type_, next_fec_sequence_number,
rtp_header_length);
RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
if (_retransmissionSettings & kRetransmitFECPackets)
@@ -180,9 +180,9 @@
const uint8_t payloadTypeRED,
const uint8_t payloadTypeFEC) {
CriticalSectionScoped cs(crit_.get());
- _fecEnabled = enable;
- _payloadTypeRED = payloadTypeRED;
- _payloadTypeFEC = payloadTypeFEC;
+ fec_enabled_ = enable;
+ red_payload_type_ = payloadTypeRED;
+ fec_payload_type_ = payloadTypeFEC;
memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
memset(&key_fec_params_, 0, sizeof(key_fec_params_));
delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
@@ -194,14 +194,14 @@
uint8_t& payloadTypeRED,
uint8_t& payloadTypeFEC) const {
CriticalSectionScoped cs(crit_.get());
- enable = _fecEnabled;
- payloadTypeRED = _payloadTypeRED;
- payloadTypeFEC = _payloadTypeFEC;
+ enable = fec_enabled_;
+ payloadTypeRED = red_payload_type_;
+ payloadTypeFEC = fec_payload_type_;
}
size_t RTPSenderVideo::FECPacketOverhead() const {
CriticalSectionScoped cs(crit_.get());
- if (_fecEnabled) {
+ if (fec_enabled_) {
// Overhead is FEC headers plus RED for FEC header plus anything in RTP
// header beyond the 12 bytes base header (CSRC list, extensions...)
// This reason for the header extensions to be included here is that
@@ -247,7 +247,7 @@
frameType == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_;
producer_fec_.SetFecParameters(fec_params, 0);
storage = packetizer->GetStorageType(_retransmissionSettings);
- fec_enabled = _fecEnabled;
+ fec_enabled = fec_enabled_;
}
// Register CVO rtp header extension at the first time when we receive a frame
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h
index 03ed600..a1e7976 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -110,10 +110,10 @@
int32_t _retransmissionSettings GUARDED_BY(crit_);
// FEC
- ForwardErrorCorrection _fec;
- bool _fecEnabled GUARDED_BY(crit_);
- int8_t _payloadTypeRED GUARDED_BY(crit_);
- int8_t _payloadTypeFEC GUARDED_BY(crit_);
+ ForwardErrorCorrection fec_;
+ bool fec_enabled_ GUARDED_BY(crit_);
+ int8_t red_payload_type_ GUARDED_BY(crit_);
+ int8_t fec_payload_type_ GUARDED_BY(crit_);
FecProtectionParams delta_fec_params_ GUARDED_BY(crit_);
FecProtectionParams key_fec_params_ GUARDED_BY(crit_);
ProducerFec producer_fec_ GUARDED_BY(crit_);
diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc
index 47a9613..0032230 100644
--- a/webrtc/video/video_send_stream_tests.cc
+++ b/webrtc/video/video_send_stream_tests.cc
@@ -127,12 +127,11 @@
}
TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
- static const uint8_t kAbsSendTimeExtensionId = 13;
class AbsoluteSendTimeObserver : public test::SendTest {
public:
AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
- kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
+ kRtpExtensionAbsoluteSendTime, test::kAbsSendTimeExtensionId));
}
Action OnSendRtp(const uint8_t* packet, size_t length) override {
@@ -152,8 +151,8 @@
std::vector<VideoReceiveStream::Config>* receive_configs,
VideoEncoderConfig* encoder_config) override {
send_config->rtp.extensions.clear();
- send_config->rtp.extensions.push_back(
- RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
+ send_config->rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
}
void PerformTest() override {
@@ -310,81 +309,123 @@
StatisticianMap stats_map_;
};
-TEST_F(VideoSendStreamTest, SupportsFec) {
- class FecObserver : public test::SendTest {
- public:
- FecObserver()
- : SendTest(kDefaultTimeoutMs),
- send_count_(0),
- received_media_(false),
- received_fec_(false) {
+class FecObserver : public test::SendTest {
+ public:
+ explicit FecObserver(bool header_extensions_enabled)
+ : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
+ send_count_(0),
+ received_media_(false),
+ received_fec_(false),
+ header_extensions_enabled_(header_extensions_enabled) {}
+
+ private:
+ Action OnSendRtp(const uint8_t* packet, size_t length) override {
+ RTPHeader header;
+ EXPECT_TRUE(parser_->Parse(packet, length, &header));
+
+ // Send lossy receive reports to trigger FEC enabling.
+ if (send_count_++ % 2 != 0) {
+ // Receive statistics reporting having lost 50% of the packets.
+ FakeReceiveStatistics lossy_receive_stats(
+ VideoSendStreamTest::kSendSsrcs[0], header.sequenceNumber,
+ send_count_ / 2, 127);
+ RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
+ &lossy_receive_stats, nullptr,
+ transport_adapter_.get());
+
+ rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
+ rtcp_sender.SetRemoteSSRC(VideoSendStreamTest::kSendSsrcs[0]);
+
+ RTCPSender::FeedbackState feedback_state;
+
+ EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
}
- private:
- Action OnSendRtp(const uint8_t* packet, size_t length) override {
- RTPHeader header;
- EXPECT_TRUE(parser_->Parse(packet, length, &header));
+ int encapsulated_payload_type = -1;
+ if (header.payloadType == VideoSendStreamTest::kRedPayloadType) {
+ encapsulated_payload_type = static_cast<int>(packet[header.headerLength]);
+ if (encapsulated_payload_type !=
+ VideoSendStreamTest::kFakeSendPayloadType)
+ EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
+ encapsulated_payload_type);
+ } else {
+ EXPECT_EQ(VideoSendStreamTest::kFakeSendPayloadType, header.payloadType);
+ }
- // Send lossy receive reports to trigger FEC enabling.
- if (send_count_++ % 2 != 0) {
- // Receive statistics reporting having lost 50% of the packets.
- FakeReceiveStatistics lossy_receive_stats(
- kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
- RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
- &lossy_receive_stats, nullptr,
- transport_adapter_.get());
-
- rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
- rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
-
- RTCPSender::FeedbackState feedback_state;
-
- EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
- }
-
- int encapsulated_payload_type = -1;
- if (header.payloadType == kRedPayloadType) {
- encapsulated_payload_type =
- static_cast<int>(packet[header.headerLength]);
- if (encapsulated_payload_type != kFakeSendPayloadType)
- EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
+ if (header_extensions_enabled_) {
+ EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
+ uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
+ if (header.extension.absoluteSendTime <= kHalf24BitsSpace &&
+ prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) {
+ // 24 bits wrap.
+ EXPECT_GT(prev_header_.extension.absoluteSendTime,
+ header.extension.absoluteSendTime);
} else {
- EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
+ EXPECT_GE(header.extension.absoluteSendTime,
+ prev_header_.extension.absoluteSendTime);
}
+ EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
+ uint16_t seq_num_diff = header.extension.transportSequenceNumber -
+ prev_header_.extension.transportSequenceNumber;
+ EXPECT_EQ(1, seq_num_diff);
+ }
- if (encapsulated_payload_type != -1) {
- if (encapsulated_payload_type == kUlpfecPayloadType) {
- received_fec_ = true;
- } else {
- received_media_ = true;
- }
+ if (encapsulated_payload_type != -1) {
+ if (encapsulated_payload_type ==
+ VideoSendStreamTest::kUlpfecPayloadType) {
+ received_fec_ = true;
+ } else {
+ received_media_ = true;
}
-
- if (received_media_ && received_fec_)
- observation_complete_->Set();
-
- return SEND_PACKET;
}
- void ModifyConfigs(VideoSendStream::Config* send_config,
- std::vector<VideoReceiveStream::Config>* receive_configs,
- VideoEncoderConfig* encoder_config) override {
- transport_adapter_.reset(
- new internal::TransportAdapter(send_config->send_transport));
- transport_adapter_->Enable();
- send_config->rtp.fec.red_payload_type = kRedPayloadType;
- send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
- }
+ if (received_media_ && received_fec_ && send_count_ > 100)
+ observation_complete_->Set();
- void PerformTest() override {
- EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
- }
+ prev_header_ = header;
- rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
- int send_count_;
- bool received_media_;
- bool received_fec_;
- } test;
+ return SEND_PACKET;
+ }
+
+ void ModifyConfigs(VideoSendStream::Config* send_config,
+ std::vector<VideoReceiveStream::Config>* receive_configs,
+ VideoEncoderConfig* encoder_config) override {
+ transport_adapter_.reset(
+ new internal::TransportAdapter(send_config->send_transport));
+ transport_adapter_->Enable();
+ send_config->rtp.fec.red_payload_type =
+ VideoSendStreamTest::kRedPayloadType;
+ send_config->rtp.fec.ulpfec_payload_type =
+ VideoSendStreamTest::kUlpfecPayloadType;
+ if (header_extensions_enabled_) {
+ send_config->rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
+ send_config->rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kTransportSequenceNumber,
+ test::kTransportSequenceNumberExtensionId));
+ }
+ }
+
+ void PerformTest() override {
+ EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
+ }
+
+ rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
+ int send_count_;
+ bool received_media_;
+ bool received_fec_;
+ bool header_extensions_enabled_;
+ RTPHeader prev_header_;
+};
+
+TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) {
+ FecObserver test(true);
+
+ RunBaseTest(&test, FakeNetworkPipe::Config());
+}
+
+TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) {
+ FecObserver test(false);
RunBaseTest(&test, FakeNetworkPipe::Config());
}