Fix for RTX in combination with pacing.

Retransmissions didn't get sent over RTX when pacing was enabled since
the pacer didn't keep track of whether a packet was a retransmit or not.

BUG=1811
TEST=trybots
R=pbos@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5117 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org
2013-11-13 15:29:21 +00:00
parent 03f33709f8
commit 9b82f5a6ed
13 changed files with 154 additions and 113 deletions

View File

@ -660,7 +660,8 @@ int32_t ModuleRtpRtcpImpl::SendOutgoingData(
bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc,
uint16_t sequence_number,
int64_t capture_time_ms) {
int64_t capture_time_ms,
bool retransmission) {
WEBRTC_TRACE(
kTraceStream,
kTraceRtpRtcp,
@ -676,7 +677,8 @@ bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc,
if (no_child_modules) {
// Don't send from default module.
if (SendingMedia() && ssrc == rtp_sender_.SSRC()) {
return rtp_sender_.TimeToSendPacket(sequence_number, capture_time_ms);
return rtp_sender_.TimeToSendPacket(sequence_number, capture_time_ms,
retransmission);
}
} else {
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
@ -684,7 +686,8 @@ bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc,
while (it != child_modules_.end()) {
if ((*it)->SendingMedia() && ssrc == (*it)->rtp_sender_.SSRC()) {
return (*it)->rtp_sender_.TimeToSendPacket(sequence_number,
capture_time_ms);
capture_time_ms,
retransmission);
}
++it;
}

View File

@ -126,8 +126,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
const RTPFragmentationHeader* fragmentation = NULL,
const RTPVideoHeader* rtp_video_hdr = NULL) OVERRIDE;
virtual bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number,
int64_t capture_time_ms) OVERRIDE;
virtual bool TimeToSendPacket(uint32_t ssrc,
uint16_t sequence_number,
int64_t capture_time_ms,
bool retransmission) OVERRIDE;
// Returns the number of padding bytes actually sent, which can be more or
// less than |bytes|.
virtual int TimeToSendPadding(int bytes) OVERRIDE;

View File

@ -532,16 +532,6 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
return 0;
}
uint8_t data_buffer_rtx[IP_PACKET_SIZE];
if (rtx_ != kRtxOff) {
BuildRtxPacket(data_buffer, &length, data_buffer_rtx);
buffer_to_send_ptr = data_buffer_rtx;
}
ModuleRTPUtility::RTPHeaderParser rtp_parser(data_buffer, length);
RTPHeader header;
rtp_parser.Parse(header);
// Store the time when the packet was last sent or added to pacer.
packet_history_->UpdateResendTime(packet_id);
@ -554,6 +544,10 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
// re-transmit and not new payload data.
}
ModuleRTPUtility::RTPHeaderParser rtp_parser(data_buffer, length);
RTPHeader header;
rtp_parser.Parse(header);
TRACE_EVENT_INSTANT2("webrtc_rtp", "RTPSender::ReSendPacket",
"timestamp", header.timestamp,
"seqnum", header.sequenceNumber);
@ -563,13 +557,20 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
header.ssrc,
header.sequenceNumber,
capture_time_ms,
length - header.headerLength)) {
length - header.headerLength,
true)) {
// We can't send the packet right now.
// We will be called when it is time.
return length;
}
}
uint8_t data_buffer_rtx[IP_PACKET_SIZE];
if (rtx_ != kRtxOff) {
BuildRtxPacket(data_buffer, &length, data_buffer_rtx);
buffer_to_send_ptr = data_buffer_rtx;
}
if (SendPacketToNetwork(buffer_to_send_ptr, length)) {
return length;
}
@ -710,11 +711,13 @@ void RTPSender::UpdateNACKBitRate(const uint32_t bytes,
// Called from pacer when we can send the packet.
bool RTPSender::TimeToSendPacket(uint16_t sequence_number,
int64_t capture_time_ms) {
int64_t capture_time_ms,
bool retransmission) {
StorageType type;
uint16_t length = IP_PACKET_SIZE;
uint8_t data_buffer[IP_PACKET_SIZE];
int64_t stored_time_ms;
uint8_t *buffer_to_send_ptr = data_buffer;
if (packet_history_ == NULL) {
// Packet cannot be found. Allow sending to continue.
@ -734,19 +737,26 @@ bool RTPSender::TimeToSendPacket(uint16_t sequence_number,
"timestamp", rtp_header.timestamp,
"seqnum", sequence_number);
uint8_t data_buffer_rtx[IP_PACKET_SIZE];
if (retransmission && rtx_ != kRtxOff) {
BuildRtxPacket(data_buffer, &length, data_buffer_rtx);
buffer_to_send_ptr = data_buffer_rtx;
}
int64_t now_ms = clock_->TimeInMilliseconds();
int64_t diff_ms = now_ms - capture_time_ms;
bool updated_transmission_time_offset =
UpdateTransmissionTimeOffset(data_buffer, length, rtp_header, diff_ms);
UpdateTransmissionTimeOffset(buffer_to_send_ptr, length, rtp_header,
diff_ms);
bool updated_abs_send_time =
UpdateAbsoluteSendTime(data_buffer, length, rtp_header, now_ms);
UpdateAbsoluteSendTime(buffer_to_send_ptr, length, rtp_header, now_ms);
if (updated_transmission_time_offset || updated_abs_send_time) {
// Update stored packet in case of receiving a re-transmission request.
packet_history_->ReplaceRTPHeader(data_buffer,
packet_history_->ReplaceRTPHeader(buffer_to_send_ptr,
rtp_header.sequenceNumber,
rtp_header.headerLength);
}
return SendPacketToNetwork(data_buffer, length);
return SendPacketToNetwork(buffer_to_send_ptr, length);
}
int RTPSender::TimeToSendPadding(int bytes) {
@ -822,7 +832,7 @@ int32_t RTPSender::SendToNetwork(
if (paced_sender_ && storage != kDontStore) {
if (!paced_sender_->SendPacket(priority, rtp_header.ssrc,
rtp_header.sequenceNumber, capture_time_ms,
payload_length)) {
payload_length, false)) {
// We can't send the packet right now.
// We will be called when it is time.
return 0;

View File

@ -167,7 +167,8 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
const RTPHeader &rtp_header,
const int64_t now_ms) const;
bool TimeToSendPacket(uint16_t sequence_number, int64_t capture_time_ms);
bool TimeToSendPacket(uint16_t sequence_number, int64_t capture_time_ms,
bool retransmission);
int TimeToSendPadding(int bytes);
// NACK.

View File

@ -82,7 +82,7 @@ class RtpSenderTest : public ::testing::Test {
transport_(),
kMarkerBit(true) {
EXPECT_CALL(mock_paced_sender_,
SendPacket(_, _, _, _, _)).WillRepeatedly(testing::Return(true));
SendPacket(_, _, _, _, _, _)).WillRepeatedly(testing::Return(true));
}
virtual void SetUp() {
@ -344,7 +344,7 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
EXPECT_CALL(mock_paced_sender_,
SendPacket(PacedSender::kNormalPriority, _, kSeqNum, _, _)).
SendPacket(PacedSender::kNormalPriority, _, kSeqNum, _, _, _)).
WillOnce(testing::Return(false));
rtp_sender_->SetStorePacketsStatus(true, 10);
@ -373,7 +373,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
const int kStoredTimeInMs = 100;
fake_clock_.AdvanceTimeMilliseconds(kStoredTimeInMs);
rtp_sender_->TimeToSendPacket(kSeqNum, capture_time_ms);
rtp_sender_->TimeToSendPacket(kSeqNum, capture_time_ms, false);
// Process send bucket. Packet should now be sent.
EXPECT_EQ(1, transport_.packets_sent_);
@ -398,7 +398,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
EXPECT_CALL(mock_paced_sender_,
SendPacket(PacedSender::kNormalPriority, _, kSeqNum, _, _)).
SendPacket(PacedSender::kNormalPriority, _, kSeqNum, _, _, _)).
WillOnce(testing::Return(false));
rtp_sender_->SetStorePacketsStatus(true, 10);
@ -425,7 +425,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
EXPECT_EQ(0, transport_.packets_sent_);
EXPECT_CALL(mock_paced_sender_,
SendPacket(PacedSender::kHighPriority, _, kSeqNum, _, _)).
SendPacket(PacedSender::kHighPriority, _, kSeqNum, _, _, _)).
WillOnce(testing::Return(false));
const int kStoredTimeInMs = 100;
@ -434,7 +434,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
EXPECT_EQ(rtp_length, rtp_sender_->ReSendPacket(kSeqNum));
EXPECT_EQ(0, transport_.packets_sent_);
rtp_sender_->TimeToSendPacket(kSeqNum, capture_time_ms);
rtp_sender_->TimeToSendPacket(kSeqNum, capture_time_ms, false);
// Process send bucket. Packet should now be sent.
EXPECT_EQ(1, transport_.packets_sent_);