Fixes RTX related bugs.

- An RTX packet with no payload should be dropped prior to parsing RTX header since it doesn't have an RTX header. This can for example happen when sending padding-only packets over the RTX stream.
- The retransmit code path when the pacer is disabled doesn't properly update the abs-send-time and ts-offset header extensions.

TEST=trybots
R=mflodman@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/9189004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5728 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2014-03-19 18:14:52 +00:00
parent 9af85c4ac2
commit 7c6ff2da26
3 changed files with 25 additions and 30 deletions

View File

@ -458,7 +458,7 @@ int RTPSender::SendRedundantPayloads(int payload_type, int bytes_to_send) {
&capture_time_ms)) {
break;
}
if (!PrepareAndSendPacket(buffer, length, capture_time_ms, true))
if (!PrepareAndSendPacket(buffer, length, capture_time_ms, true, false))
return -1;
ModuleRTPUtility::RTPHeaderParser rtp_parser(buffer, length);
RTPHeader rtp_header;
@ -598,7 +598,6 @@ bool RTPSender::StorePackets() const {
int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
uint16_t length = IP_PACKET_SIZE;
uint8_t data_buffer[IP_PACKET_SIZE];
uint8_t *buffer_to_send_ptr = data_buffer;
int64_t capture_time_ms;
if (!packet_history_.GetPacketAndSetSendTime(packet_id, min_resend_time, true,
data_buffer, &length,
@ -607,19 +606,15 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
return 0;
}
ModuleRTPUtility::RTPHeaderParser rtp_parser(data_buffer, length);
RTPHeader header;
if (!rtp_parser.Parse(header)) {
assert(false);
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id_,
"Failed to parse RTP header of packet to be retransmitted.");
return -1;
}
TRACE_EVENT_INSTANT2("webrtc_rtp", "RTPSender::ReSendPacket",
"timestamp", header.timestamp,
"seqnum", header.sequenceNumber);
if (paced_sender_) {
ModuleRTPUtility::RTPHeaderParser rtp_parser(data_buffer, length);
RTPHeader header;
if (!rtp_parser.Parse(header)) {
assert(false);
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id_,
"Failed to parse RTP header of packet to be retransmitted.");
return -1;
}
if (!paced_sender_->SendPacket(PacedSender::kHighPriority,
header.ssrc,
header.sequenceNumber,
@ -632,17 +627,8 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
}
}
uint8_t data_buffer_rtx[IP_PACKET_SIZE];
if ((rtx_ & kRtxRetransmitted) > 0) {
BuildRtxPacket(data_buffer, &length, data_buffer_rtx);
buffer_to_send_ptr = data_buffer_rtx;
}
if (SendPacketToNetwork(buffer_to_send_ptr, length)) {
UpdateRtpStats(buffer_to_send_ptr, length, header, rtx_ != kRtxOff, true);
return length;
}
return -1;
return PrepareAndSendPacket(data_buffer, length, capture_time_ms,
(rtx_ & kRtxRetransmitted) > 0, true) ? 0 : -1;
}
bool RTPSender::SendPacketToNetwork(const uint8_t *packet, uint32_t size) {
@ -798,19 +784,21 @@ bool RTPSender::TimeToSendPacket(uint16_t sequence_number,
UpdateDelayStatistics(capture_time_ms, clock_->TimeInMilliseconds());
}
return PrepareAndSendPacket(data_buffer, length, capture_time_ms,
retransmission && (rtx_ & kRtxRetransmitted) > 0);
retransmission && (rtx_ & kRtxRetransmitted) > 0,
retransmission);
}
bool RTPSender::PrepareAndSendPacket(uint8_t* buffer,
uint16_t length,
int64_t capture_time_ms,
bool send_over_rtx) {
bool send_over_rtx,
bool is_retransmit) {
uint8_t *buffer_to_send_ptr = buffer;
ModuleRTPUtility::RTPHeaderParser rtp_parser(buffer, length);
RTPHeader rtp_header;
rtp_parser.Parse(rtp_header);
TRACE_EVENT_INSTANT2("webrtc_rtp", "RTPSender::TimeToSendPacket",
TRACE_EVENT_INSTANT2("webrtc_rtp", "PrepareAndSendPacket",
"timestamp", rtp_header.timestamp,
"seqnum", rtp_header.sequenceNumber);
@ -835,7 +823,8 @@ bool RTPSender::PrepareAndSendPacket(uint8_t* buffer,
}
bool ret = SendPacketToNetwork(buffer_to_send_ptr, length);
UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, false, false);
UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, send_over_rtx,
is_retransmit);
return ret;
}

View File

@ -302,7 +302,8 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
bool PrepareAndSendPacket(uint8_t* buffer,
uint16_t length,
int64_t capture_time_ms,
bool send_over_rtx);
bool send_over_rtx,
bool is_retransmit);
int SendRedundantPayloads(int payload_type, int bytes);

View File

@ -258,6 +258,11 @@ bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
}
return fec_receiver_->ProcessReceivedFec() == 0;
} else if (rtp_payload_registry_->IsRtx(header)) {
if (header.headerLength + header.paddingLength == packet_length) {
// This is an empty packet and should be silently dropped before trying to
// parse the RTX header.
return true;
}
// Remove the RTX header and parse the original RTP header.
if (packet_length < header.headerLength)
return false;