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:
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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_);
|
||||
|
||||
Reference in New Issue
Block a user