Distinguish between missing packet and send failure.

This CL introduces three-value enum, in order to be able to distinguish
between send success, send failure, and invalid states such as missing
packet or invalid ssrc.

The behavior is unchanged in this CL, a follow-up will change the pacer
to not consume media budget on invalid states.

Bug: webrtc:8052,webrtc:8975
Change-Id: I1c9e2226f995356daa538d3d3cf44945f35e0133
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135165
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27923}
This commit is contained in:
Erik Språng
2019-05-10 08:29:01 -07:00
committed by Commit Bot
parent d7c7d0ed88
commit d28796209b
17 changed files with 215 additions and 171 deletions

View File

@ -371,11 +371,14 @@ void PacedSender::Process() {
break; break;
critsect_.Leave(); critsect_.Leave();
bool success = packet_sender_->TimeToSendPacket( RtpPacketSendResult success = packet_sender_->TimeToSendPacket(
packet->ssrc, packet->sequence_number, packet->capture_time_ms, packet->ssrc, packet->sequence_number, packet->capture_time_ms,
packet->retransmission, pacing_info); packet->retransmission, pacing_info);
critsect_.Enter(); critsect_.Enter();
if (success) { if (success == RtpPacketSendResult::kSuccess ||
success == RtpPacketSendResult::kPacketNotFound) {
// Packet sent or invalid packet, remove it from queue.
// TODO(webrtc:8052): Don't consume media budget on kInvalid.
bytes_sent += packet->bytes; bytes_sent += packet->bytes;
// Send succeeded, remove it from the queue. // Send succeeded, remove it from the queue.
OnPacketSent(packet); OnPacketSent(packet);
@ -443,10 +446,6 @@ void PacedSender::OnPacketSent(const RoundRobinPacketQueue::Packet* packet) {
bool audio_packet = packet->priority == kHighPriority; bool audio_packet = packet->priority == kHighPriority;
if (!audio_packet || account_for_audio_) { if (!audio_packet || account_for_audio_) {
// Update media bytes sent. // Update media bytes sent.
// TODO(eladalon): TimeToSendPacket() can also return |true| in some
// situations where nothing actually ended up being sent to the network,
// and we probably don't want to update the budget in such cases.
// https://bugs.chromium.org/p/webrtc/issues/detail?id=8052
UpdateBudgetWithBytesSent(packet->bytes); UpdateBudgetWithBytesSent(packet->bytes);
last_send_time_us_ = clock_->TimeInMicroseconds(); last_send_time_us_ = clock_->TimeInMicroseconds();
} }

View File

@ -44,11 +44,12 @@ class PacedSender : public Pacer {
// module again. // module again.
// Called when it's time to send a queued packet. // Called when it's time to send a queued packet.
// Returns false if packet cannot be sent. // Returns false if packet cannot be sent.
virtual bool TimeToSendPacket(uint32_t ssrc, virtual RtpPacketSendResult TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& cluster_info) = 0; bool retransmission,
const PacedPacketInfo& cluster_info) = 0;
// Called when it's a good time to send a padding data. // Called when it's a good time to send a padding data.
// Returns the number of bytes sent. // Returns the number of bytes sent.
virtual size_t TimeToSendPadding(size_t bytes, virtual size_t TimeToSendPadding(size_t bytes,

View File

@ -43,11 +43,11 @@ static const int kTargetBitrateBps = 800000;
class MockPacedSenderCallback : public PacedSender::PacketSender { class MockPacedSenderCallback : public PacedSender::PacketSender {
public: public:
MOCK_METHOD5(TimeToSendPacket, MOCK_METHOD5(TimeToSendPacket,
bool(uint32_t ssrc, RtpPacketSendResult(uint32_t ssrc,
uint16_t sequence_number, uint16_t sequence_number,
int64_t capture_time_ms, int64_t capture_time_ms,
bool retransmission, bool retransmission,
const PacedPacketInfo& pacing_info)); const PacedPacketInfo& pacing_info));
MOCK_METHOD2(TimeToSendPadding, MOCK_METHOD2(TimeToSendPadding,
size_t(size_t bytes, const PacedPacketInfo& pacing_info)); size_t(size_t bytes, const PacedPacketInfo& pacing_info));
}; };
@ -56,12 +56,13 @@ class PacedSenderPadding : public PacedSender::PacketSender {
public: public:
PacedSenderPadding() : padding_sent_(0) {} PacedSenderPadding() : padding_sent_(0) {}
bool TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) override { bool retransmission,
return true; const PacedPacketInfo& pacing_info) override {
return RtpPacketSendResult::kSuccess;
} }
size_t TimeToSendPadding(size_t bytes, size_t TimeToSendPadding(size_t bytes,
@ -82,13 +83,14 @@ class PacedSenderProbing : public PacedSender::PacketSender {
public: public:
PacedSenderProbing() : packets_sent_(0), padding_sent_(0) {} PacedSenderProbing() : packets_sent_(0), padding_sent_(0) {}
bool TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) override { bool retransmission,
const PacedPacketInfo& pacing_info) override {
packets_sent_++; packets_sent_++;
return true; return RtpPacketSendResult::kSuccess;
} }
size_t TimeToSendPadding(size_t bytes, size_t TimeToSendPadding(size_t bytes,
@ -134,7 +136,7 @@ class PacedSenderTest : public ::testing::TestWithParam<std::string> {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
capture_time_ms, retransmission, _)) capture_time_ms, retransmission, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
} }
SimulatedClock clock_; SimulatedClock clock_;
MockPacedSenderCallback callback_; MockPacedSenderCallback callback_;
@ -175,7 +177,8 @@ TEST_F(PacedSenderFieldTrialTest, DefaultNoPaddingInSilence) {
pacer.SetPacingRates(kTargetBitrateBps, 0); pacer.SetPacingRates(kTargetBitrateBps, 0);
// Video packet to reset last send time and provide padding data. // Video packet to reset last send time and provide padding data.
InsertPacket(&pacer, &video); InsertPacket(&pacer, &video);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
pacer.Process(); pacer.Process();
EXPECT_CALL(callback_, TimeToSendPadding).Times(0); EXPECT_CALL(callback_, TimeToSendPadding).Times(0);
@ -190,7 +193,8 @@ TEST_F(PacedSenderFieldTrialTest, PaddingInSilenceWithTrial) {
pacer.SetPacingRates(kTargetBitrateBps, 0); pacer.SetPacingRates(kTargetBitrateBps, 0);
// Video packet to reset last send time and provide padding data. // Video packet to reset last send time and provide padding data.
InsertPacket(&pacer, &video); InsertPacket(&pacer, &video);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
pacer.Process(); pacer.Process();
EXPECT_CALL(callback_, TimeToSendPadding).WillOnce(Return(1000)); EXPECT_CALL(callback_, TimeToSendPadding).WillOnce(Return(1000));
@ -207,7 +211,8 @@ TEST_F(PacedSenderFieldTrialTest, DefaultCongestionWindowAffectsAudio) {
pacer.UpdateOutstandingData(0); pacer.UpdateOutstandingData(0);
// Video packet fills congestion window. // Video packet fills congestion window.
InsertPacket(&pacer, &video); InsertPacket(&pacer, &video);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
ProcessNext(&pacer); ProcessNext(&pacer);
// Audio packet blocked due to congestion. // Audio packet blocked due to congestion.
InsertPacket(&pacer, &audio); InsertPacket(&pacer, &audio);
@ -217,7 +222,8 @@ TEST_F(PacedSenderFieldTrialTest, DefaultCongestionWindowAffectsAudio) {
// Audio packet unblocked when congestion window clear. // Audio packet unblocked when congestion window clear.
::testing::Mock::VerifyAndClearExpectations(&callback_); ::testing::Mock::VerifyAndClearExpectations(&callback_);
pacer.UpdateOutstandingData(0); pacer.UpdateOutstandingData(0);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
ProcessNext(&pacer); ProcessNext(&pacer);
} }
@ -230,11 +236,13 @@ TEST_F(PacedSenderFieldTrialTest, CongestionWindowDoesNotAffectAudioInTrial) {
pacer.UpdateOutstandingData(0); pacer.UpdateOutstandingData(0);
// Video packet fills congestion window. // Video packet fills congestion window.
InsertPacket(&pacer, &video); InsertPacket(&pacer, &video);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
ProcessNext(&pacer); ProcessNext(&pacer);
// Audio not blocked due to congestion. // Audio not blocked due to congestion.
InsertPacket(&pacer, &audio); InsertPacket(&pacer, &audio);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
ProcessNext(&pacer); ProcessNext(&pacer);
} }
@ -244,7 +252,8 @@ TEST_F(PacedSenderFieldTrialTest, DefaultBudgetAffectsAudio) {
0); 0);
// Video fills budget for following process periods. // Video fills budget for following process periods.
InsertPacket(&pacer, &video); InsertPacket(&pacer, &video);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
ProcessNext(&pacer); ProcessNext(&pacer);
// Audio packet blocked due to budget limit. // Audio packet blocked due to budget limit.
EXPECT_CALL(callback_, TimeToSendPacket).Times(0); EXPECT_CALL(callback_, TimeToSendPacket).Times(0);
@ -253,7 +262,8 @@ TEST_F(PacedSenderFieldTrialTest, DefaultBudgetAffectsAudio) {
ProcessNext(&pacer); ProcessNext(&pacer);
::testing::Mock::VerifyAndClearExpectations(&callback_); ::testing::Mock::VerifyAndClearExpectations(&callback_);
// Audio packet unblocked when the budget has recovered. // Audio packet unblocked when the budget has recovered.
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
ProcessNext(&pacer); ProcessNext(&pacer);
ProcessNext(&pacer); ProcessNext(&pacer);
} }
@ -266,10 +276,12 @@ TEST_F(PacedSenderFieldTrialTest, BudgetDoesNotAffectAudioInTrial) {
0); 0);
// Video fills budget for following process periods. // Video fills budget for following process periods.
InsertPacket(&pacer, &video); InsertPacket(&pacer, &video);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
ProcessNext(&pacer); ProcessNext(&pacer);
// Audio packet not blocked due to budget limit. // Audio packet not blocked due to budget limit.
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
InsertPacket(&pacer, &audio); InsertPacket(&pacer, &audio);
ProcessNext(&pacer); ProcessNext(&pacer);
} }
@ -322,7 +334,7 @@ TEST_F(PacedSenderTest, QueuePacket) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number++, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number++,
queued_packet_timestamp, false, _)) queued_packet_timestamp, false, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
send_bucket_->Process(); send_bucket_->Process();
sequence_number++; sequence_number++;
EXPECT_EQ(0u, send_bucket_->QueueSizePackets()); EXPECT_EQ(0u, send_bucket_->QueueSizePackets());
@ -371,7 +383,7 @@ TEST_F(PacedSenderTest, PaceQueuedPackets) {
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false, _)) EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false, _))
.Times(packets_to_send_per_interval) .Times(packets_to_send_per_interval)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
send_bucket_->Process(); send_bucket_->Process();
} }
@ -571,7 +583,7 @@ TEST_F(PacedSenderTest, Priority) {
EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0); EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, false, _)) EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, false, _))
.Times(packets_to_send_per_interval + 1) .Times(packets_to_send_per_interval + 1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
@ -583,7 +595,7 @@ TEST_F(PacedSenderTest, Priority) {
TimeToSendPacket(ssrc_low_priority, _, TimeToSendPacket(ssrc_low_priority, _,
capture_time_ms_low_priority, false, _)) capture_time_ms_low_priority, false, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
@ -622,7 +634,7 @@ TEST_F(PacedSenderTest, RetransmissionPriority) {
EXPECT_CALL(callback_, TimeToSendPacket( EXPECT_CALL(callback_, TimeToSendPacket(
ssrc, _, capture_time_ms_retransmission, true, _)) ssrc, _, capture_time_ms_retransmission, true, _))
.Times(packets_to_send_per_interval) .Times(packets_to_send_per_interval)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
@ -635,7 +647,7 @@ TEST_F(PacedSenderTest, RetransmissionPriority) {
EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, true, _)).Times(0); EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, true, _)).Times(0);
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, false, _)) EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, false, _))
.Times(packets_to_send_per_interval) .Times(packets_to_send_per_interval)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
@ -676,7 +688,7 @@ TEST_F(PacedSenderTest, HighPrioDoesntAffectBudget) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number++, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number++,
capture_time_ms, false, _)) capture_time_ms, false, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
send_bucket_->Process(); send_bucket_->Process();
@ -736,7 +748,8 @@ TEST_F(PacedSenderTest, DoesNotAllowOveruseAfterCongestion) {
send_bucket_->UpdateOutstandingData(0); send_bucket_->UpdateOutstandingData(0);
// Not yet budget limited or congested, packet is sent. // Not yet budget limited or congested, packet is sent.
send_bucket_->InsertPacket(prio, ssrc, seq_num++, now_ms(), size, false); send_bucket_->InsertPacket(prio, ssrc, seq_num++, now_ms(), size, false);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
send_bucket_->Process(); send_bucket_->Process();
// Packet blocked due to congestion. // Packet blocked due to congestion.
@ -752,7 +765,8 @@ TEST_F(PacedSenderTest, DoesNotAllowOveruseAfterCongestion) {
send_bucket_->UpdateOutstandingData(0); send_bucket_->UpdateOutstandingData(0);
// Congestion removed and budget has recovered, packet is sent. // Congestion removed and budget has recovered, packet is sent.
send_bucket_->InsertPacket(prio, ssrc, seq_num++, now_ms(), size, false); send_bucket_->InsertPacket(prio, ssrc, seq_num++, now_ms(), size, false);
EXPECT_CALL(callback_, TimeToSendPacket).WillOnce(Return(true)); EXPECT_CALL(callback_, TimeToSendPacket)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
send_bucket_->Process(); send_bucket_->Process();
send_bucket_->UpdateOutstandingData(0); send_bucket_->UpdateOutstandingData(0);
@ -799,7 +813,7 @@ TEST_F(PacedSenderTest, ResumesSendingWhenCongestionEnds) {
int ack_count = kCongestionCount / 2; int ack_count = kCongestionCount / 2;
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false, _)) EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false, _))
.Times(ack_count) .Times(ack_count)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
send_bucket_->UpdateOutstandingData(kCongestionWindow - send_bucket_->UpdateOutstandingData(kCongestionWindow -
kPacketSize * ack_count); kPacketSize * ack_count);
@ -814,7 +828,7 @@ TEST_F(PacedSenderTest, ResumesSendingWhenCongestionEnds) {
// marked as acked. // marked as acked.
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false, _)) EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false, _))
.Times(unacked_packets) .Times(unacked_packets)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
for (int duration = 0; duration < kCongestionTimeMs; duration += 5) { for (int duration = 0; duration < kCongestionTimeMs; duration += 5) {
send_bucket_->UpdateOutstandingData(0); send_bucket_->UpdateOutstandingData(0);
clock_.AdvanceTimeMilliseconds(5); clock_.AdvanceTimeMilliseconds(5);
@ -895,34 +909,34 @@ TEST_F(PacedSenderTest, Pause) {
EXPECT_CALL(callback_, EXPECT_CALL(callback_,
TimeToSendPacket(ssrc_high_priority, _, capture_time_ms, _, _)) TimeToSendPacket(ssrc_high_priority, _, capture_time_ms, _, _))
.Times(packets_to_send_per_interval) .Times(packets_to_send_per_interval)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
EXPECT_CALL(callback_, TimeToSendPacket(ssrc_high_priority, _, EXPECT_CALL(callback_, TimeToSendPacket(ssrc_high_priority, _,
second_capture_time_ms, _, _)) second_capture_time_ms, _, _))
.Times(packets_to_send_per_interval) .Times(packets_to_send_per_interval)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
for (size_t i = 0; i < packets_to_send_per_interval; ++i) { for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, _, _)) EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, _, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
} }
for (size_t i = 0; i < packets_to_send_per_interval; ++i) { for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
EXPECT_CALL(callback_, EXPECT_CALL(callback_,
TimeToSendPacket(ssrc, _, second_capture_time_ms, _, _)) TimeToSendPacket(ssrc, _, second_capture_time_ms, _, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
} }
for (size_t i = 0; i < packets_to_send_per_interval; ++i) { for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
EXPECT_CALL(callback_, EXPECT_CALL(callback_,
TimeToSendPacket(ssrc_low_priority, _, capture_time_ms, _, _)) TimeToSendPacket(ssrc_low_priority, _, capture_time_ms, _, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
} }
for (size_t i = 0; i < packets_to_send_per_interval; ++i) { for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc_low_priority, _, EXPECT_CALL(callback_, TimeToSendPacket(ssrc_low_priority, _,
second_capture_time_ms, _, _)) second_capture_time_ms, _, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
} }
} }
send_bucket_->Resume(); send_bucket_->Resume();
@ -961,7 +975,7 @@ TEST_F(PacedSenderTest, ResendPacket) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
capture_time_ms, false, _)) capture_time_ms, false, _))
.Times(1) .Times(1)
.WillOnce(Return(false)); .WillOnce(Return(RtpPacketSendResult::kTransportUnavailable));
clock_.AdvanceTimeMilliseconds(10000); clock_.AdvanceTimeMilliseconds(10000);
send_bucket_->Process(); send_bucket_->Process();
@ -973,11 +987,11 @@ TEST_F(PacedSenderTest, ResendPacket) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
capture_time_ms, false, _)) capture_time_ms, false, _))
.Times(1) .Times(1)
.WillOnce(Return(true)); .WillOnce(Return(RtpPacketSendResult::kSuccess));
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1,
capture_time_ms + 1, false, _)) capture_time_ms + 1, false, _))
.Times(1) .Times(1)
.WillOnce(Return(false)); .WillOnce(Return(RtpPacketSendResult::kTransportUnavailable));
clock_.AdvanceTimeMilliseconds(10000); clock_.AdvanceTimeMilliseconds(10000);
send_bucket_->Process(); send_bucket_->Process();
@ -989,7 +1003,7 @@ TEST_F(PacedSenderTest, ResendPacket) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1,
capture_time_ms + 1, false, _)) capture_time_ms + 1, false, _))
.Times(1) .Times(1)
.WillOnce(Return(true)); .WillOnce(Return(RtpPacketSendResult::kSuccess));
clock_.AdvanceTimeMilliseconds(10000); clock_.AdvanceTimeMilliseconds(10000);
send_bucket_->Process(); send_bucket_->Process();
EXPECT_EQ(0, send_bucket_->QueueInMs()); EXPECT_EQ(0, send_bucket_->QueueInMs());
@ -1183,7 +1197,7 @@ TEST_F(PacedSenderTest, AverageQueueTime) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
first_capture_time, false, _)) first_capture_time, false, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
send_bucket_->Process(); send_bucket_->Process();
EXPECT_EQ(10, send_bucket_->AverageQueueTimeMs()); EXPECT_EQ(10, send_bucket_->AverageQueueTimeMs());
@ -1192,7 +1206,7 @@ TEST_F(PacedSenderTest, AverageQueueTime) {
EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1, EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1,
first_capture_time + 10, false, _)) first_capture_time + 10, false, _))
.Times(1) .Times(1)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
clock_.AdvanceTimeMilliseconds(30); // Max delta. clock_.AdvanceTimeMilliseconds(30); // Max delta.
send_bucket_->Process(); send_bucket_->Process();
@ -1221,7 +1235,7 @@ TEST_F(PacedSenderTest, ProbeClusterId) {
TimeToSendPacket(_, _, _, _, TimeToSendPacket(_, _, _, _,
Field(&PacedPacketInfo::probe_cluster_id, 0))) Field(&PacedPacketInfo::probe_cluster_id, 0)))
.Times(5) .Times(5)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
clock_.AdvanceTimeMilliseconds(20); clock_.AdvanceTimeMilliseconds(20);
send_bucket_->Process(); send_bucket_->Process();
@ -1232,7 +1246,7 @@ TEST_F(PacedSenderTest, ProbeClusterId) {
TimeToSendPacket(_, _, _, _, TimeToSendPacket(_, _, _, _,
Field(&PacedPacketInfo::probe_cluster_id, 1))) Field(&PacedPacketInfo::probe_cluster_id, 1)))
.Times(5) .Times(5)
.WillRepeatedly(Return(true)); .WillRepeatedly(Return(RtpPacketSendResult::kSuccess));
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
clock_.AdvanceTimeMilliseconds(20); clock_.AdvanceTimeMilliseconds(20);
send_bucket_->Process(); send_bucket_->Process();
@ -1262,7 +1276,7 @@ TEST_F(PacedSenderTest, AvoidBusyLoopOnSendFailure) {
kPacketSize, false); kPacketSize, false);
EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, _, _)) EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, _, _))
.WillOnce(Return(true)); .WillOnce(Return(RtpPacketSendResult::kSuccess));
send_bucket_->Process(); send_bucket_->Process();
EXPECT_EQ(10, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(10, send_bucket_->TimeUntilNextProcess());
clock_.AdvanceTimeMilliseconds(9); clock_.AdvanceTimeMilliseconds(9);

View File

@ -99,11 +99,12 @@ void PacketRouter::RemoveReceiveRtpModule(
rtcp_feedback_senders_.erase(it); rtcp_feedback_senders_.erase(it);
} }
bool PacketRouter::TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult PacketRouter::TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_timestamp, uint16_t sequence_number,
bool retransmission, int64_t capture_timestamp,
const PacedPacketInfo& pacing_info) { bool retransmission,
const PacedPacketInfo& pacing_info) {
rtc::CritScope cs(&modules_crit_); rtc::CritScope cs(&modules_crit_);
for (auto* rtp_module : rtp_send_modules_) { for (auto* rtp_module : rtp_send_modules_) {
if (!rtp_module->SendingMedia()) { if (!rtp_module->SendingMedia()) {
@ -121,7 +122,7 @@ bool PacketRouter::TimeToSendPacket(uint32_t ssrc,
pacing_info); pacing_info);
} }
} }
return true; return RtpPacketSendResult::kPacketNotFound;
} }
size_t PacketRouter::TimeToSendPadding(size_t bytes_to_send, size_t PacketRouter::TimeToSendPadding(size_t bytes_to_send,

View File

@ -52,11 +52,12 @@ class PacketRouter : public PacedSender::PacketSender,
void RemoveReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender); void RemoveReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender);
// Implements PacedSender::Callback. // Implements PacedSender::Callback.
bool TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_timestamp, uint16_t sequence_number,
bool retransmission, int64_t capture_timestamp,
const PacedPacketInfo& packet_info) override; bool retransmission,
const PacedPacketInfo& packet_info) override;
size_t TimeToSendPadding(size_t bytes, size_t TimeToSendPadding(size_t bytes,
const PacedPacketInfo& packet_info) override; const PacedPacketInfo& packet_info) override;

View File

@ -54,11 +54,9 @@ TEST(PacketRouterTest, Sanity_NoModuleRegistered_TimeToSendPacket) {
constexpr bool retransmission = false; constexpr bool retransmission = false;
const PacedPacketInfo paced_info(1, kProbeMinProbes, kProbeMinBytes); const PacedPacketInfo paced_info(1, kProbeMinProbes, kProbeMinBytes);
// TODO(eladalon): TimeToSendPacket() returning true when nothing was EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
// sent, because no modules were registered, is sub-optimal. packet_router.TimeToSendPacket(ssrc, sequence_number, timestamp,
// https://bugs.chromium.org/p/webrtc/issues/detail?id=8052 retransmission, paced_info));
EXPECT_TRUE(packet_router.TimeToSendPacket(ssrc, sequence_number, timestamp,
retransmission, paced_info));
} }
TEST(PacketRouterTest, Sanity_NoModuleRegistered_TimeToSendPadding) { TEST(PacketRouterTest, Sanity_NoModuleRegistered_TimeToSendPadding) {
@ -116,11 +114,12 @@ TEST(PacketRouterTest, TimeToSendPacket) {
kSsrc1, sequence_number, timestamp, retransmission, kSsrc1, sequence_number, timestamp, retransmission,
Field(&PacedPacketInfo::probe_cluster_id, 1))) Field(&PacedPacketInfo::probe_cluster_id, 1)))
.Times(1) .Times(1)
.WillOnce(Return(true)); .WillOnce(Return(RtpPacketSendResult::kSuccess));
EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
EXPECT_TRUE(packet_router.TimeToSendPacket( EXPECT_EQ(RtpPacketSendResult::kSuccess,
kSsrc1, sequence_number, timestamp, retransmission, packet_router.TimeToSendPacket(
PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes))); kSsrc1, sequence_number, timestamp, retransmission,
PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes)));
// Send on the second module by letting rtp_2 be sending, but not rtp_1. // Send on the second module by letting rtp_2 be sending, but not rtp_1.
++sequence_number; ++sequence_number;
@ -135,19 +134,21 @@ TEST(PacketRouterTest, TimeToSendPacket) {
kSsrc2, sequence_number, timestamp, retransmission, kSsrc2, sequence_number, timestamp, retransmission,
Field(&PacedPacketInfo::probe_cluster_id, 2))) Field(&PacedPacketInfo::probe_cluster_id, 2)))
.Times(1) .Times(1)
.WillOnce(Return(true)); .WillOnce(Return(RtpPacketSendResult::kSuccess));
EXPECT_TRUE(packet_router.TimeToSendPacket( EXPECT_EQ(RtpPacketSendResult::kSuccess,
kSsrc2, sequence_number, timestamp, retransmission, packet_router.TimeToSendPacket(
PacedPacketInfo(2, kProbeMinProbes, kProbeMinBytes))); kSsrc2, sequence_number, timestamp, retransmission,
PacedPacketInfo(2, kProbeMinProbes, kProbeMinBytes)));
// No module is sending, hence no packet should be sent. // No module is sending, hence no packet should be sent.
EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(false)); EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(false));
EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(false)); EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(false));
EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
EXPECT_TRUE(packet_router.TimeToSendPacket( EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
kSsrc1, sequence_number, timestamp, retransmission, packet_router.TimeToSendPacket(
PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes))); kSsrc1, sequence_number, timestamp, retransmission,
PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes)));
// Add a packet with incorrect ssrc and test it's dropped in the router. // Add a packet with incorrect ssrc and test it's dropped in the router.
EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true)); EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
@ -156,9 +157,10 @@ TEST(PacketRouterTest, TimeToSendPacket) {
EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2)); EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
EXPECT_TRUE(packet_router.TimeToSendPacket( EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
kSsrc1 + kSsrc2, sequence_number, timestamp, retransmission, packet_router.TimeToSendPacket(
PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes))); kSsrc1 + kSsrc2, sequence_number, timestamp, retransmission,
PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes)));
packet_router.RemoveSendRtpModule(&rtp_1); packet_router.RemoveSendRtpModule(&rtp_1);
@ -167,10 +169,11 @@ TEST(PacketRouterTest, TimeToSendPacket) {
EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true)); EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2)); EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
EXPECT_TRUE(packet_router.TimeToSendPacket( EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
kSsrc1, sequence_number, timestamp, retransmission, packet_router.TimeToSendPacket(
PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes, kSsrc1, sequence_number, timestamp, retransmission,
kProbeMinBytes))); PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes,
kProbeMinBytes)));
packet_router.RemoveSendRtpModule(&rtp_2); packet_router.RemoveSendRtpModule(&rtp_2);
} }
@ -357,10 +360,11 @@ TEST(PacketRouterTest, SenderOnlyFunctionsRespectSendingMedia) {
// Verify that TimeToSendPacket does not end up in a receiver. // Verify that TimeToSendPacket does not end up in a receiver.
EXPECT_CALL(rtp, TimeToSendPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(rtp, TimeToSendPacket(_, _, _, _, _)).Times(0);
EXPECT_TRUE(packet_router.TimeToSendPacket( EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
kSsrc, 1, 1, false, packet_router.TimeToSendPacket(
PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes, kSsrc, 1, 1, false,
kProbeMinBytes))); PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes,
kProbeMinBytes)));
// Verify that TimeToSendPadding does not end up in a receiver. // Verify that TimeToSendPadding does not end up in a receiver.
EXPECT_CALL(rtp, TimeToSendPadding(_, _)).Times(0); EXPECT_CALL(rtp, TimeToSendPadding(_, _)).Times(0);
EXPECT_EQ(0u, packet_router.TimeToSendPadding( EXPECT_EQ(0u, packet_router.TimeToSendPadding(

View File

@ -130,9 +130,10 @@ void BbrPacedSender::Process() {
bool BbrPacedSender::TryToSendPacket(Packet* packet) { bool BbrPacedSender::TryToSendPacket(Packet* packet) {
PacedPacketInfo pacing_info; PacedPacketInfo pacing_info;
return packet_sender_->TimeToSendPacket(packet->ssrc, packet->sequence_number, return packet_sender_->TimeToSendPacket(
packet->capture_time_ms, packet->ssrc, packet->sequence_number, packet->capture_time_ms,
packet->retransmission, pacing_info); packet->retransmission,
pacing_info) != RtpPacketSendResult::kTransportUnavailable;
} }
} // namespace webrtc } // namespace webrtc

View File

@ -293,11 +293,12 @@ void PacedVideoSender::QueuePackets(Packets* batch,
batch->merge(to_transfer, DereferencingComparator<Packet>); batch->merge(to_transfer, DereferencingComparator<Packet>);
} }
bool PacedVideoSender::TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult PacedVideoSender::TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) { bool retransmission,
const PacedPacketInfo& pacing_info) {
for (Packets::iterator it = pacer_queue_.begin(); it != pacer_queue_.end(); for (Packets::iterator it = pacer_queue_.begin(); it != pacer_queue_.end();
++it) { ++it) {
MediaPacket* media_packet = static_cast<MediaPacket*>(*it); MediaPacket* media_packet = static_cast<MediaPacket*>(*it);
@ -306,17 +307,17 @@ bool PacedVideoSender::TimeToSendPacket(uint32_t ssrc,
// Make sure a packet is never paced out earlier than when it was put into // Make sure a packet is never paced out earlier than when it was put into
// the pacer. // the pacer.
assert(pace_out_time_ms >= media_packet->send_time_ms()); RTC_CHECK_GE(pace_out_time_ms, media_packet->send_time_ms());
media_packet->SetAbsSendTimeMs(pace_out_time_ms); media_packet->SetAbsSendTimeMs(pace_out_time_ms);
media_packet->set_send_time_us(1000 * pace_out_time_ms); media_packet->set_send_time_us(1000 * pace_out_time_ms);
media_packet->set_sender_timestamp_us(1000 * pace_out_time_ms); media_packet->set_sender_timestamp_us(1000 * pace_out_time_ms);
queue_.push_back(media_packet); queue_.push_back(media_packet);
pacer_queue_size_in_bytes_ -= media_packet->payload_size(); pacer_queue_size_in_bytes_ -= media_packet->payload_size();
pacer_queue_.erase(it); pacer_queue_.erase(it);
return true; return RtpPacketSendResult::kSuccess;
} }
} }
return false; return RtpPacketSendResult::kTransportUnavailable;
} }
size_t PacedVideoSender::TimeToSendPadding(size_t bytes, size_t PacedVideoSender::TimeToSendPadding(size_t bytes,

View File

@ -109,11 +109,12 @@ class PacedVideoSender : public VideoSender, public PacedSender::PacketSender {
void RunFor(int64_t time_ms, Packets* in_out) override; void RunFor(int64_t time_ms, Packets* in_out) override;
// Implements PacedSender::Callback. // Implements PacedSender::Callback.
bool TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) override; bool retransmission,
const PacedPacketInfo& pacing_info) override;
size_t TimeToSendPadding(size_t bytes, size_t TimeToSendPadding(size_t bytes,
const PacedPacketInfo& pacing_info) override; const PacedPacketInfo& pacing_info) override;

View File

@ -260,11 +260,12 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface {
int payload_type, int payload_type,
bool force_sender_report) = 0; bool force_sender_report) = 0;
virtual bool TimeToSendPacket(uint32_t ssrc, virtual RtpPacketSendResult TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) = 0; bool retransmission,
const PacedPacketInfo& pacing_info) = 0;
virtual size_t TimeToSendPadding(size_t bytes, virtual size_t TimeToSendPadding(size_t bytes,
const PacedPacketInfo& pacing_info) = 0; const PacedPacketInfo& pacing_info) = 0;

View File

@ -547,5 +547,12 @@ class SendPacketObserver {
uint32_t ssrc) = 0; uint32_t ssrc) = 0;
}; };
// Status returned from TimeToSendPacket() family of callbacks.
enum class RtpPacketSendResult {
kSuccess, // Packet sent OK.
kTransportUnavailable, // Network unavailable, try again later.
kPacketNotFound // SSRC/sequence number does not map to an available packet.
};
} // namespace webrtc } // namespace webrtc
#endif // MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_ #endif // MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_

View File

@ -83,11 +83,11 @@ class MockRtpRtcp : public RtpRtcp {
int(uint32_t* available_bandwidth)); int(uint32_t* available_bandwidth));
MOCK_METHOD4(OnSendingRtpFrame, bool(uint32_t, int64_t, int, bool)); MOCK_METHOD4(OnSendingRtpFrame, bool(uint32_t, int64_t, int, bool));
MOCK_METHOD5(TimeToSendPacket, MOCK_METHOD5(TimeToSendPacket,
bool(uint32_t ssrc, RtpPacketSendResult(uint32_t ssrc,
uint16_t sequence_number, uint16_t sequence_number,
int64_t capture_time_ms, int64_t capture_time_ms,
bool retransmission, bool retransmission,
const PacedPacketInfo& pacing_info)); const PacedPacketInfo& pacing_info));
MOCK_METHOD2(TimeToSendPadding, MOCK_METHOD2(TimeToSendPadding,
size_t(size_t bytes, const PacedPacketInfo& pacing_info)); size_t(size_t bytes, const PacedPacketInfo& pacing_info));
MOCK_METHOD2(RegisterRtcpObservers, MOCK_METHOD2(RegisterRtcpObservers,

View File

@ -407,11 +407,12 @@ bool ModuleRtpRtcpImpl::OnSendingRtpFrame(uint32_t timestamp,
return true; return true;
} }
bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult ModuleRtpRtcpImpl::TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) { bool retransmission,
const PacedPacketInfo& pacing_info) {
return rtp_sender_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms, return rtp_sender_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms,
retransmission, pacing_info); retransmission, pacing_info);
} }

View File

@ -133,11 +133,12 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp {
int payload_type, int payload_type,
bool force_sender_report) override; bool force_sender_report) override;
bool TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) override; bool retransmission,
const PacedPacketInfo& pacing_info) override;
// Returns the number of padding bytes actually sent, which can be more or // Returns the number of padding bytes actually sent, which can be more or
// less than |bytes|. // less than |bytes|.

View File

@ -538,13 +538,15 @@ void RTPSender::OnReceivedNack(
} }
// Called from pacer when we can send the packet. // Called from pacer when we can send the packet.
bool RTPSender::TimeToSendPacket(uint32_t ssrc, RtpPacketSendResult RTPSender::TimeToSendPacket(
uint16_t sequence_number, uint32_t ssrc,
int64_t capture_time_ms, uint16_t sequence_number,
bool retransmission, int64_t capture_time_ms,
const PacedPacketInfo& pacing_info) { bool retransmission,
if (!SendingMedia()) const PacedPacketInfo& pacing_info) {
return true; if (!SendingMedia()) {
return RtpPacketSendResult::kPacketNotFound;
}
std::unique_ptr<RtpPacketToSend> packet; std::unique_ptr<RtpPacketToSend> packet;
if (ssrc == SSRC()) { if (ssrc == SSRC()) {
@ -554,14 +556,16 @@ bool RTPSender::TimeToSendPacket(uint32_t ssrc,
} }
if (!packet) { if (!packet) {
// Packet cannot be found or was resend too recently. // Packet cannot be found or was resent too recently.
return true; return RtpPacketSendResult::kPacketNotFound;
} }
return PrepareAndSendPacket( return PrepareAndSendPacket(
std::move(packet), std::move(packet),
retransmission && (RtxStatus() & kRtxRetransmitted) > 0, retransmission, retransmission && (RtxStatus() & kRtxRetransmitted) > 0,
pacing_info); retransmission, pacing_info)
? RtpPacketSendResult::kSuccess
: RtpPacketSendResult::kTransportUnavailable;
} }
bool RTPSender::PrepareAndSendPacket(std::unique_ptr<RtpPacketToSend> packet, bool RTPSender::PrepareAndSendPacket(std::unique_ptr<RtpPacketToSend> packet,

View File

@ -103,11 +103,13 @@ class RTPSender : public AcknowledgedPacketsObserver {
bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) const; bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) const;
int32_t DeregisterRtpHeaderExtension(RTPExtensionType type); int32_t DeregisterRtpHeaderExtension(RTPExtensionType type);
bool TimeToSendPacket(uint32_t ssrc, // Returns an RtpPacketSendResult indicating succes, failure or invalid
uint16_t sequence_number, // status such as on incorrect sequence number.
int64_t capture_time_ms, RtpPacketSendResult TimeToSendPacket(uint32_t ssrc,
bool retransmission, uint16_t sequence_number,
const PacedPacketInfo& pacing_info); int64_t capture_time_ms,
bool retransmission,
const PacedPacketInfo& pacing_info);
size_t TimeToSendPadding(size_t bytes, const PacedPacketInfo& pacing_info); size_t TimeToSendPadding(size_t bytes, const PacedPacketInfo& pacing_info);
// NACK. // NACK.

View File

@ -1180,12 +1180,14 @@ TEST_P(RtpSenderTest, SendFlexfecPackets) {
EXPECT_CALL(mock_rtc_event_log_, EXPECT_CALL(mock_rtc_event_log_,
LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing))) LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing)))
.Times(2); .Times(2);
EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum, EXPECT_EQ(RtpPacketSendResult::kSuccess,
fake_clock_.TimeInMilliseconds(), rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum,
false, PacedPacketInfo())); fake_clock_.TimeInMilliseconds(),
EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kFlexfecSsrc, flexfec_seq_num, false, PacedPacketInfo()));
fake_clock_.TimeInMilliseconds(), EXPECT_EQ(RtpPacketSendResult::kSuccess,
false, PacedPacketInfo())); rtp_sender_->TimeToSendPacket(kFlexfecSsrc, flexfec_seq_num,
fake_clock_.TimeInMilliseconds(),
false, PacedPacketInfo()));
ASSERT_EQ(2, transport_.packets_sent()); ASSERT_EQ(2, transport_.packets_sent());
const RtpPacketReceived& media_packet = transport_.sent_packets_[0]; const RtpPacketReceived& media_packet = transport_.sent_packets_[0];
EXPECT_EQ(kMediaPayloadType, media_packet.PayloadType()); EXPECT_EQ(kMediaPayloadType, media_packet.PayloadType());
@ -1258,9 +1260,10 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) {
EXPECT_CALL(mock_rtc_event_log_, EXPECT_CALL(mock_rtc_event_log_,
LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing))) LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing)))
.Times(1); .Times(1);
EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum, EXPECT_EQ(RtpPacketSendResult::kSuccess,
fake_clock_.TimeInMilliseconds(), rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum,
false, PacedPacketInfo())); fake_clock_.TimeInMilliseconds(),
false, PacedPacketInfo()));
ASSERT_EQ(1, transport_.packets_sent()); ASSERT_EQ(1, transport_.packets_sent());
const RtpPacketReceived& media_packet = transport_.sent_packets_[0]; const RtpPacketReceived& media_packet = transport_.sent_packets_[0];
EXPECT_EQ(kMediaPayloadType, media_packet.PayloadType()); EXPECT_EQ(kMediaPayloadType, media_packet.PayloadType());
@ -1284,12 +1287,14 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) {
EXPECT_CALL(mock_rtc_event_log_, EXPECT_CALL(mock_rtc_event_log_,
LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing))) LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing)))
.Times(2); .Times(2);
EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum + 1, EXPECT_EQ(RtpPacketSendResult::kSuccess,
fake_clock_.TimeInMilliseconds(), rtp_sender_->TimeToSendPacket(kMediaSsrc, kSeqNum + 1,
false, PacedPacketInfo())); fake_clock_.TimeInMilliseconds(),
EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kFlexfecSsrc, flexfec_seq_num, false, PacedPacketInfo()));
fake_clock_.TimeInMilliseconds(), EXPECT_EQ(RtpPacketSendResult::kSuccess,
false, PacedPacketInfo())); rtp_sender_->TimeToSendPacket(kFlexfecSsrc, flexfec_seq_num,
fake_clock_.TimeInMilliseconds(),
false, PacedPacketInfo()));
ASSERT_EQ(3, transport_.packets_sent()); ASSERT_EQ(3, transport_.packets_sent());
const RtpPacketReceived& media_packet2 = transport_.sent_packets_[1]; const RtpPacketReceived& media_packet2 = transport_.sent_packets_[1];
EXPECT_EQ(kMediaPayloadType, media_packet2.PayloadType()); EXPECT_EQ(kMediaPayloadType, media_packet2.PayloadType());