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}
This commit is contained in:
Stefan Holmer
2015-12-08 09:10:43 +01:00
parent 03ef053202
commit 4654d204e4
4 changed files with 141 additions and 102 deletions

View File

@ -129,9 +129,7 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list,
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 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list,
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 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list,
// -- 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;
}

View File

@ -42,13 +42,13 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender)
_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 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer,
// 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 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer,
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 @@ void RTPSenderVideo::SetGenericFECStatus(const bool enable,
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 @@ void RTPSenderVideo::GenericFECStatus(bool& enable,
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 @@ int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType,
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

View File

@ -110,10 +110,10 @@ private:
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_);

View File

@ -127,12 +127,11 @@ TEST_F(VideoSendStreamTest, SupportsCName) {
}
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 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
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,15 +309,14 @@ class FakeReceiveStatistics : public NullReceiveStatistics {
StatisticianMap stats_map_;
};
TEST_F(VideoSendStreamTest, SupportsFec) {
class FecObserver : public test::SendTest {
public:
FecObserver()
: SendTest(kDefaultTimeoutMs),
explicit FecObserver(bool header_extensions_enabled)
: SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
send_count_(0),
received_media_(false),
received_fec_(false) {
}
received_fec_(false),
header_extensions_enabled_(header_extensions_enabled) {}
private:
Action OnSendRtp(const uint8_t* packet, size_t length) override {
@ -329,13 +327,14 @@ TEST_F(VideoSendStreamTest, SupportsFec) {
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);
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(kSendSsrcs[0]);
rtcp_sender.SetRemoteSSRC(VideoSendStreamTest::kSendSsrcs[0]);
RTCPSender::FeedbackState feedback_state;
@ -343,26 +342,48 @@ TEST_F(VideoSendStreamTest, SupportsFec) {
}
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.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(kFakeSendPayloadType, header.payloadType);
EXPECT_EQ(VideoSendStreamTest::kFakeSendPayloadType, header.payloadType);
}
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_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) {
if (encapsulated_payload_type ==
VideoSendStreamTest::kUlpfecPayloadType) {
received_fec_ = true;
} else {
received_media_ = true;
}
}
if (received_media_ && received_fec_)
if (received_media_ && received_fec_ && send_count_ > 100)
observation_complete_->Set();
prev_header_ = header;
return SEND_PACKET;
}
@ -372,8 +393,17 @@ TEST_F(VideoSendStreamTest, SupportsFec) {
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;
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 {
@ -384,7 +414,18 @@ TEST_F(VideoSendStreamTest, SupportsFec) {
int send_count_;
bool received_media_;
bool received_fec_;
} test;
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());
}