From 88e0dda475e1f6a5fa5855eec0be111bddbf00ac Mon Sep 17 00:00:00 2001 From: "stefan@webrtc.org" Date: Fri, 4 Jul 2014 09:20:42 +0000 Subject: [PATCH] Introduces PacedVideoSender to test framework and moves the Pacer to use Clock. R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/14729004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6600 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../pacing/include/mock/mock_paced_sender.h | 3 +- webrtc/modules/pacing/include/paced_sender.h | 20 ++- webrtc/modules/pacing/paced_sender.cc | 29 ++-- .../modules/pacing/paced_sender_unittest.cc | 136 +++++++++--------- .../bwe_simulations.cc | 30 ++++ .../remote_bitrate_estimator/test/bwe_test.cc | 6 +- .../test/bwe_test_framework.cc | 103 ++++++++++++- .../test/bwe_test_framework.h | 44 +++++- webrtc/modules/rtp_rtcp/source/rtp_sender.cc | 13 +- webrtc/video_engine/vie_encoder.cc | 24 ++-- 10 files changed, 295 insertions(+), 113 deletions(-) diff --git a/webrtc/modules/pacing/include/mock/mock_paced_sender.h b/webrtc/modules/pacing/include/mock/mock_paced_sender.h index 3841ef3753..6600a9292d 100644 --- a/webrtc/modules/pacing/include/mock/mock_paced_sender.h +++ b/webrtc/modules/pacing/include/mock/mock_paced_sender.h @@ -16,12 +16,13 @@ #include #include "webrtc/modules/pacing/include/paced_sender.h" +#include "webrtc/system_wrappers/interface/clock.h" namespace webrtc { class MockPacedSender : public PacedSender { public: - MockPacedSender() : PacedSender(NULL, 0, 0) {} + MockPacedSender() : PacedSender(Clock::GetRealTimeClock(), NULL, 0, 0) {} MOCK_METHOD6(SendPacket, bool(Priority priority, uint32_t ssrc, uint16_t sequence_number, diff --git a/webrtc/modules/pacing/include/paced_sender.h b/webrtc/modules/pacing/include/paced_sender.h index 95f1a86e8f..887ab44e94 100644 --- a/webrtc/modules/pacing/include/paced_sender.h +++ b/webrtc/modules/pacing/include/paced_sender.h @@ -16,11 +16,12 @@ #include "webrtc/modules/interface/module.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/typedefs.h" namespace webrtc { +class Clock; class CriticalSectionWrapper; + namespace paced_sender { class IntervalBudget; struct Packet; @@ -48,6 +49,7 @@ class PacedSender : public Module { int64_t capture_time_ms, bool retransmission) = 0; // Called when it's a good time to send a padding data. + // Returns the number of bytes sent. virtual int TimeToSendPadding(int bytes) = 0; protected: @@ -55,8 +57,17 @@ class PacedSender : public Module { }; static const int kDefaultMaxQueueLengthMs = 2000; + // Pace in kbits/s until we receive first estimate. + static const int kDefaultInitialPaceKbps = 2000; + // Pacing-rate relative to our target send rate. + // Multiplicative factor that is applied to the target bitrate to calculate + // the number of bytes that can be transmitted per interval. + // Increasing this factor will result in lower delays in cases of bitrate + // overshoots from the encoder. + static const float kDefaultPaceMultiplier; - PacedSender(Callback* callback, int max_bitrate_kbps, int min_bitrate_kbps); + PacedSender(Clock* clock, Callback* callback, int max_bitrate_kbps, + int min_bitrate_kbps); virtual ~PacedSender(); @@ -114,6 +125,7 @@ class PacedSender : public Module { // Updates the buffers with the number of bytes that we sent. void UpdateMediaBytesSent(int num_bytes); + Clock* clock_; Callback* callback_; bool enabled_; bool paused_; @@ -127,8 +139,8 @@ class PacedSender : public Module { // utilized when there's no media to send. scoped_ptr padding_budget_; - TickTime time_last_update_; - TickTime time_last_send_; + int64_t time_last_update_; + int64_t time_last_send_; int64_t capture_time_ms_last_queued_; int64_t capture_time_ms_last_sent_; diff --git a/webrtc/modules/pacing/paced_sender.cc b/webrtc/modules/pacing/paced_sender.cc index e9f9bddced..0069c6bfeb 100644 --- a/webrtc/modules/pacing/paced_sender.cc +++ b/webrtc/modules/pacing/paced_sender.cc @@ -13,6 +13,7 @@ #include #include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/system_wrappers/interface/clock.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/trace_event.h" @@ -120,17 +121,21 @@ class IntervalBudget { }; } // namespace paced_sender -PacedSender::PacedSender(Callback* callback, +const float PacedSender::kDefaultPaceMultiplier = 2.5f; + +PacedSender::PacedSender(Clock* clock, + Callback* callback, int max_bitrate_kbps, int min_bitrate_kbps) - : callback_(callback), + : clock_(clock), + callback_(callback), enabled_(true), paused_(false), max_queue_length_ms_(kDefaultMaxQueueLengthMs), critsect_(CriticalSectionWrapper::CreateCriticalSection()), media_budget_(new paced_sender::IntervalBudget(max_bitrate_kbps)), padding_budget_(new paced_sender::IntervalBudget(min_bitrate_kbps)), - time_last_update_(TickTime::Now()), + time_last_update_(clock_->TimeInMilliseconds()), capture_time_ms_last_queued_(0), capture_time_ms_last_sent_(0), high_priority_packets_(new paced_sender::PacketList), @@ -178,7 +183,7 @@ bool PacedSender::SendPacket(Priority priority, uint32_t ssrc, return true; // We can send now. } if (capture_time_ms < 0) { - capture_time_ms = TickTime::MillisecondTimestamp(); + capture_time_ms = clock_->TimeInMilliseconds(); } if (priority != kHighPriority && capture_time_ms > capture_time_ms_last_queued_) { @@ -201,7 +206,7 @@ bool PacedSender::SendPacket(Priority priority, uint32_t ssrc, packet_list->push_back(paced_sender::Packet(ssrc, sequence_number, capture_time_ms, - TickTime::MillisecondTimestamp(), + clock_->TimeInMilliseconds(), bytes, retransmission)); return false; @@ -214,7 +219,7 @@ void PacedSender::set_max_queue_length_ms(int max_queue_length_ms) { int PacedSender::QueueInMs() const { CriticalSectionScoped cs(critsect_.get()); - int64_t now_ms = TickTime::MillisecondTimestamp(); + int64_t now_ms = clock_->TimeInMilliseconds(); int64_t oldest_packet_enqueue_time = now_ms; if (!high_priority_packets_->empty()) { oldest_packet_enqueue_time = std::min( @@ -237,7 +242,7 @@ int PacedSender::QueueInMs() const { int32_t PacedSender::TimeUntilNextProcess() { CriticalSectionScoped cs(critsect_.get()); int64_t elapsed_time_ms = - (TickTime::Now() - time_last_update_).Milliseconds(); + clock_->TimeInMilliseconds() - time_last_update_; if (elapsed_time_ms <= 0) { return kMinPacketLimitMs; } @@ -248,10 +253,10 @@ int32_t PacedSender::TimeUntilNextProcess() { } int32_t PacedSender::Process() { - TickTime now = TickTime::Now(); + int64_t now_ms = clock_->TimeInMilliseconds(); CriticalSectionScoped cs(critsect_.get()); - int elapsed_time_ms = (now - time_last_update_).Milliseconds(); - time_last_update_ = now; + int elapsed_time_ms = now_ms - time_last_update_; + time_last_update_ = now_ms; if (!enabled_) { return 0; } @@ -323,7 +328,7 @@ bool PacedSender::ShouldSendNextPacket(paced_sender::PacketList** packet_list) { if (media_budget_->bytes_remaining() <= 0) { // All bytes consumed for this interval. // Check if we have not sent in a too long time. - if ((TickTime::Now() - time_last_send_).Milliseconds() > + if (clock_->TimeInMilliseconds() - time_last_send_ > kMaxQueueTimeWithoutSendingMs) { if (!high_priority_packets_->empty()) { *packet_list = high_priority_packets_.get(); @@ -376,7 +381,7 @@ paced_sender::Packet PacedSender::GetNextPacketFromList( // MUST have critsect_ when calling. void PacedSender::UpdateMediaBytesSent(int num_bytes) { - time_last_send_ = TickTime::Now(); + time_last_send_ = clock_->TimeInMilliseconds(); media_budget_->UseBudget(num_bytes); padding_budget_->UseBudget(num_bytes); } diff --git a/webrtc/modules/pacing/paced_sender_unittest.cc b/webrtc/modules/pacing/paced_sender_unittest.cc index 9763c80070..1387cc4b45 100644 --- a/webrtc/modules/pacing/paced_sender_unittest.cc +++ b/webrtc/modules/pacing/paced_sender_unittest.cc @@ -12,6 +12,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/pacing/include/paced_sender.h" +#include "webrtc/system_wrappers/interface/clock.h" using testing::_; using testing::Return; @@ -55,12 +56,12 @@ class PacedSenderPadding : public PacedSender::Callback { class PacedSenderTest : public ::testing::Test { protected: - PacedSenderTest() { + PacedSenderTest() : clock_(123456) { srand(0); - TickTime::UseFakeClock(123456); // Need to initialize PacedSender after we initialize clock. send_bucket_.reset( - new PacedSender(&callback_, kPaceMultiplier * kTargetBitrate, 0)); + new PacedSender( + &clock_, &callback_, kPaceMultiplier * kTargetBitrate, 0)); } void SendAndExpectPacket(PacedSender::Priority priority, @@ -75,6 +76,7 @@ class PacedSenderTest : public ::testing::Test { .WillRepeatedly(Return(true)); } + SimulatedClock clock_; MockPacedSenderCallback callback_; scoped_ptr send_bucket_; }; @@ -84,20 +86,20 @@ TEST_F(PacedSenderTest, QueuePacket) { uint16_t sequence_number = 1234; // Due to the multiplicative factor we can send 3 packets not 2 packets. SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); - int64_t queued_packet_timestamp = TickTime::MillisecondTimestamp(); + clock_.TimeInMilliseconds(), 250, false); + int64_t queued_packet_timestamp = clock_.TimeInMilliseconds(); EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, sequence_number, queued_packet_timestamp, 250, false)); send_bucket_->Process(); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0); - TickTime::AdvanceFakeClock(4); + clock_.AdvanceTimeMilliseconds(4); EXPECT_EQ(1, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(1); + clock_.AdvanceTimeMilliseconds(1); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_CALL(callback_, TimeToSendPacket( ssrc, sequence_number++, queued_packet_timestamp, false)) @@ -106,11 +108,11 @@ TEST_F(PacedSenderTest, QueuePacket) { send_bucket_->Process(); sequence_number++; SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, - sequence_number++, TickTime::MillisecondTimestamp(), 250, false)); + sequence_number++, clock_.TimeInMilliseconds(), 250, false)); send_bucket_->Process(); } @@ -121,17 +123,17 @@ TEST_F(PacedSenderTest, PaceQueuedPackets) { // Due to the multiplicative factor we can send 3 packets not 2 packets. for (int i = 0; i < 3; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); } for (int j = 0; j < 30; ++j) { EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, - sequence_number++, TickTime::MillisecondTimestamp(), 250, false)); + sequence_number++, clock_.TimeInMilliseconds(), 250, false)); } send_bucket_->Process(); EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0); for (int k = 0; k < 10; ++k) { EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false)) .Times(3) @@ -140,17 +142,17 @@ TEST_F(PacedSenderTest, PaceQueuedPackets) { EXPECT_EQ(0, send_bucket_->Process()); } EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, - sequence_number, TickTime::MillisecondTimestamp(), 250, false)); + sequence_number, clock_.TimeInMilliseconds(), 250, false)); send_bucket_->Process(); } @@ -162,22 +164,22 @@ TEST_F(PacedSenderTest, PaceQueuedPacketsWithDuplicates) { // Due to the multiplicative factor we can send 3 packets not 2 packets. for (int i = 0; i < 3; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); } queued_sequence_number = sequence_number; for (int j = 0; j < 30; ++j) { // Send in duplicate packets. EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, - sequence_number, TickTime::MillisecondTimestamp(), 250, false)); + sequence_number, clock_.TimeInMilliseconds(), 250, false)); EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, - sequence_number++, TickTime::MillisecondTimestamp(), 250, false)); + sequence_number++, clock_.TimeInMilliseconds(), 250, false)); } EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0); send_bucket_->Process(); for (int k = 0; k < 10; ++k) { EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); for (int i = 0; i < 3; ++i) { EXPECT_CALL(callback_, TimeToSendPacket(ssrc, queued_sequence_number++, @@ -190,17 +192,17 @@ TEST_F(PacedSenderTest, PaceQueuedPacketsWithDuplicates) { EXPECT_EQ(0, send_bucket_->Process()); } EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, - sequence_number++, TickTime::MillisecondTimestamp(), 250, false)); + sequence_number++, clock_.TimeInMilliseconds(), 250, false)); send_bucket_->Process(); } @@ -211,15 +213,15 @@ TEST_F(PacedSenderTest, Padding) { send_bucket_->UpdateBitrate(kPaceMultiplier * kTargetBitrate, kTargetBitrate); // Due to the multiplicative factor we can send 3 packets not 2 packets. SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), 250, false); + clock_.TimeInMilliseconds(), 250, false); // No padding is expected since we have sent too much already. EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); @@ -227,7 +229,7 @@ TEST_F(PacedSenderTest, Padding) { EXPECT_CALL(callback_, TimeToSendPadding(250)).Times(1). WillOnce(Return(250)); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); } @@ -238,12 +240,12 @@ TEST_F(PacedSenderTest, NoPaddingWhenDisabled) { // No padding is expected since the pacer is disabled. EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); } @@ -255,11 +257,11 @@ TEST_F(PacedSenderTest, VerifyPaddingUpToBitrate) { const int kTimeStep = 5; const int64_t kBitrateWindow = 100; send_bucket_->UpdateBitrate(kPaceMultiplier * kTargetBitrate, kTargetBitrate); - int64_t start_time = TickTime::MillisecondTimestamp(); - while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) { + int64_t start_time = clock_.TimeInMilliseconds(); + while (clock_.TimeInMilliseconds() - start_time < kBitrateWindow) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, capture_time_ms, 250, false); - TickTime::AdvanceFakeClock(kTimeStep); + clock_.AdvanceTimeMilliseconds(kTimeStep); EXPECT_CALL(callback_, TimeToSendPadding(250)).Times(1). WillOnce(Return(250)); send_bucket_->Process(); @@ -274,17 +276,17 @@ TEST_F(PacedSenderTest, VerifyAverageBitrateVaryingMediaPayload) { const int64_t kBitrateWindow = 10000; PacedSenderPadding callback; send_bucket_.reset( - new PacedSender(&callback, kPaceMultiplier * kTargetBitrate, 0)); + new PacedSender(&clock_, &callback, kPaceMultiplier * kTargetBitrate, 0)); send_bucket_->UpdateBitrate(kPaceMultiplier * kTargetBitrate, kTargetBitrate); - int64_t start_time = TickTime::MillisecondTimestamp(); + int64_t start_time = clock_.TimeInMilliseconds(); int media_bytes = 0; - while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) { + while (clock_.TimeInMilliseconds() - start_time < kBitrateWindow) { int media_payload = rand() % 100 + 200; // [200, 300] bytes. EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, capture_time_ms, media_payload, false)); media_bytes += media_payload; - TickTime::AdvanceFakeClock(kTimeStep); + clock_.AdvanceTimeMilliseconds(kTimeStep); send_bucket_->Process(); } EXPECT_NEAR(kTargetBitrate, 8 * (media_bytes + callback.padding_sent()) / @@ -325,7 +327,7 @@ TEST_F(PacedSenderTest, Priority) { .WillRepeatedly(Return(true)); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); @@ -335,7 +337,7 @@ TEST_F(PacedSenderTest, Priority) { .WillRepeatedly(Return(true)); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); } @@ -344,7 +346,7 @@ TEST_F(PacedSenderTest, Pause) { uint32_t ssrc_low_priority = 12345; uint32_t ssrc = 12346; uint16_t sequence_number = 1234; - int64_t capture_time_ms = TickTime::MillisecondTimestamp(); + int64_t capture_time_ms = clock_.TimeInMilliseconds(); EXPECT_EQ(0, send_bucket_->QueueInMs()); @@ -366,15 +368,15 @@ TEST_F(PacedSenderTest, Pause) { EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kHighPriority, ssrc, sequence_number++, capture_time_ms, 250, false)); - TickTime::AdvanceFakeClock(10000); - int64_t second_capture_time_ms = TickTime::MillisecondTimestamp(); + clock_.AdvanceTimeMilliseconds(10000); + int64_t second_capture_time_ms = clock_.TimeInMilliseconds(); // Expect everything to be queued. EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kLowPriority, ssrc_low_priority, sequence_number++, second_capture_time_ms, 250, false)); - EXPECT_EQ(TickTime::MillisecondTimestamp() - capture_time_ms, + EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms, send_bucket_->QueueInMs()); // Expect no packet to come out while paused. @@ -382,7 +384,7 @@ TEST_F(PacedSenderTest, Pause) { EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, _)).Times(0); for (int i = 0; i < 10; ++i) { - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); } @@ -394,7 +396,7 @@ TEST_F(PacedSenderTest, Pause) { send_bucket_->Resume(); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); @@ -403,7 +405,7 @@ TEST_F(PacedSenderTest, Pause) { .Times(1) .WillRepeatedly(Return(true)); EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess()); - TickTime::AdvanceFakeClock(5); + clock_.AdvanceTimeMilliseconds(5); EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess()); EXPECT_EQ(0, send_bucket_->Process()); EXPECT_EQ(0, send_bucket_->QueueInMs()); @@ -412,7 +414,7 @@ TEST_F(PacedSenderTest, Pause) { TEST_F(PacedSenderTest, ResendPacket) { uint32_t ssrc = 12346; uint16_t sequence_number = 1234; - int64_t capture_time_ms = TickTime::MillisecondTimestamp(); + int64_t capture_time_ms = clock_.TimeInMilliseconds(); EXPECT_EQ(0, send_bucket_->QueueInMs()); EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, @@ -421,26 +423,26 @@ TEST_F(PacedSenderTest, ResendPacket) { capture_time_ms, 250, false)); - TickTime::AdvanceFakeClock(1); + clock_.AdvanceTimeMilliseconds(1); EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc, sequence_number + 1, capture_time_ms + 1, 250, false)); - TickTime::AdvanceFakeClock(9999); - EXPECT_EQ(TickTime::MillisecondTimestamp() - capture_time_ms, + clock_.AdvanceTimeMilliseconds(9999); + EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms, send_bucket_->QueueInMs()); // Fails to send first packet so only one call. EXPECT_CALL(callback_, TimeToSendPacket( ssrc, sequence_number, capture_time_ms, false)) .Times(1) .WillOnce(Return(false)); - TickTime::AdvanceFakeClock(10000); + clock_.AdvanceTimeMilliseconds(10000); send_bucket_->Process(); // Queue remains unchanged. - EXPECT_EQ(TickTime::MillisecondTimestamp() - capture_time_ms, + EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms, send_bucket_->QueueInMs()); // Fails to send second packet. @@ -452,11 +454,11 @@ TEST_F(PacedSenderTest, ResendPacket) { ssrc, sequence_number + 1, capture_time_ms + 1, false)) .Times(1) .WillOnce(Return(false)); - TickTime::AdvanceFakeClock(10000); + clock_.AdvanceTimeMilliseconds(10000); send_bucket_->Process(); // Queue is reduced by 1 packet. - EXPECT_EQ(TickTime::MillisecondTimestamp() - capture_time_ms - 1, + EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms - 1, send_bucket_->QueueInMs()); // Send second packet and queue becomes empty. @@ -464,7 +466,7 @@ TEST_F(PacedSenderTest, ResendPacket) { ssrc, sequence_number + 1, capture_time_ms + 1, false)) .Times(1) .WillOnce(Return(true)); - TickTime::AdvanceFakeClock(10000); + clock_.AdvanceTimeMilliseconds(10000); send_bucket_->Process(); EXPECT_EQ(0, send_bucket_->QueueInMs()); } @@ -479,22 +481,22 @@ TEST_F(PacedSenderTest, MaxQueueLength) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), + clock_.TimeInMilliseconds(), 1200, false); } - TickTime::AdvanceFakeClock(2001); + clock_.AdvanceTimeMilliseconds(2001); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, - TickTime::MillisecondTimestamp(), + clock_.TimeInMilliseconds(), 1200, false); EXPECT_EQ(2001, send_bucket_->QueueInMs()); send_bucket_->Process(); EXPECT_EQ(0, send_bucket_->QueueInMs()); - TickTime::AdvanceFakeClock(31); + clock_.AdvanceTimeMilliseconds(31); send_bucket_->Process(); } @@ -507,11 +509,11 @@ TEST_F(PacedSenderTest, QueueTimeGrowsOverTime) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number, - TickTime::MillisecondTimestamp(), + clock_.TimeInMilliseconds(), 1200, false); - TickTime::AdvanceFakeClock(500); + clock_.AdvanceTimeMilliseconds(500); EXPECT_EQ(500, send_bucket_->QueueInMs()); send_bucket_->Process(); EXPECT_EQ(0, send_bucket_->QueueInMs()); diff --git a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc index 6b208e4999..47390f78f6 100644 --- a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc +++ b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc @@ -96,6 +96,36 @@ TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) { RunFor(60 * 1000); } +TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) { + VerboseLogging(true); + AdaptiveVideoSender source(0, NULL, 30, 300, 0, 0); + PacedVideoSender sender(this, 300, &source); + ChokeFilter filter(this); + RateCounterFilter counter(this, "receiver_input"); + filter.SetCapacity(1000); + filter.SetMaxDelay(500); + RunFor(60 * 1000); + filter.SetCapacity(500); + RunFor(60 * 1000); + filter.SetCapacity(1000); + RunFor(60 * 1000); +} + +TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) { + VerboseLogging(true); + AdaptiveVideoSender source(0, NULL, 30, 300, 0, 0); + PacedVideoSender sender(this, 300, &source); + ChokeFilter filter(this); + RateCounterFilter counter(this, "receiver_input"); + filter.SetCapacity(200); + filter.SetMaxDelay(500); + RunFor(60 * 1000); + filter.SetCapacity(30); + RunFor(60 * 1000); + filter.SetCapacity(200); + RunFor(60 * 1000); +} + TEST_P(BweSimulation, Choke200kbps30kbps200kbps) { VerboseLogging(true); AdaptiveVideoSender sender(0, this, 30, 300, 0, 0); diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc index 90ce6a3e85..d4919e7377 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc @@ -76,11 +76,11 @@ class TestedEstimator : public RemoteBitrateObserver { } } - int64_t step_ms = estimator_->TimeUntilNextProcess(); + int64_t step_ms = std::max(estimator_->TimeUntilNextProcess(), 0); while ((clock_.TimeInMilliseconds() + step_ms) < packet_time_ms) { clock_.AdvanceTimeMilliseconds(step_ms); estimator_->Process(); - step_ms = estimator_->TimeUntilNextProcess(); + step_ms = std::max(estimator_->TimeUntilNextProcess(), 0); } estimator_->IncomingPacket(packet_time_ms, packet.payload_size(), packet.header()); @@ -195,13 +195,13 @@ class PacketProcessorRunner { if (queue_.empty()) { return; } - Packets to_transfer; Packets::iterator it = queue_.begin(); for (; it != queue_.end(); ++it) { if (it->send_time_us() > end_of_batch_time_us) { break; } } + Packets to_transfer; to_transfer.splice(to_transfer.begin(), queue_, queue_.begin(), it); batch->merge(to_transfer); } diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc index b3cd7db972..194db4d3dc 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc @@ -154,6 +154,11 @@ void Packet::set_send_time_us(int64_t send_time_us) { send_time_us_ = send_time_us; } +void Packet::SetAbsSendTimeMs(int64_t abs_send_time_ms) { + header_.extension.absoluteSendTime = ((static_cast(abs_send_time_ms * + (1 << 18)) + 500) / 1000) & 0x00fffffful; +} + bool IsTimeSorted(const Packets& packets) { PacketsConstIt last_it = packets.begin(); for (PacketsConstIt it = last_it; it != packets.end(); ++it) { @@ -566,12 +571,8 @@ void VideoSender::RunFor(int64_t time_ms, Packets* in_out) { now_ms_ += time_ms; Packets new_packets; while (now_ms_ >= next_frame_ms_) { - prototype_header_.sequenceNumber++; prototype_header_.timestamp = kTimestampBase + static_cast(next_frame_ms_ * 90.0); - prototype_header_.extension.absoluteSendTime = (kTimestampBase + - ((static_cast(next_frame_ms_ * (1 << 18)) + 500) / 1000)) & - 0x00fffffful; prototype_header_.extension.transmissionTimeOffset = 0; // Generate new packets for this frame, all with the same timestamp, @@ -581,9 +582,11 @@ void VideoSender::RunFor(int64_t time_ms, Packets* in_out) { int64_t send_time_us = next_frame_ms_ * 1000.0; uint32_t payload_size = frame_size_bytes_; while (payload_size > 0) { + ++prototype_header_.sequenceNumber; uint32_t size = std::min(kMaxPayloadSizeBytes, payload_size); new_packets.push_back(Packet(flow_ids()[0], send_time_us, size, prototype_header_)); + new_packets.back().SetAbsSendTimeMs(next_frame_ms_); payload_size -= size; } @@ -604,6 +607,98 @@ void AdaptiveVideoSender::GiveFeedback(const PacketSender::Feedback& feedback) { bytes_per_second_ = feedback.estimated_bps / 8; frame_size_bytes_ = (bytes_per_second_ * frame_period_ms_ + 500) / 1000; } + +PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener, + uint32_t kbps, + AdaptiveVideoSender* source) + // It is important that the first_frame_offset and the initial time of + // clock_ are both zero, otherwise we can't have absolute time in this + // class. + : PacketSender(listener, source->flow_ids()), + clock_(0), + start_of_run_ms_(0), + pacer_(&clock_, this, PacedSender::kDefaultPaceMultiplier * kbps, 0), + source_(source) {} + +void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) { + start_of_run_ms_ = clock_.TimeInMilliseconds(); + Packets generated_packets; + source_->RunFor(time_ms, &generated_packets); + Packets::iterator it = generated_packets.begin(); + // Run process periodically to allow the packets to be paced out. + const int kProcessIntervalMs = 10; + for (int64_t current_time = 0; current_time < time_ms; + current_time += kProcessIntervalMs) { + int64_t end_of_interval_us = + 1000 * (clock_.TimeInMilliseconds() + kProcessIntervalMs); + while (it != generated_packets.end() && + end_of_interval_us >= it->send_time_us()) { + // Time to send next packet to pacer. + pacer_.SendPacket(PacedSender::kNormalPriority, + it->header().ssrc, + it->header().sequenceNumber, + (it->send_time_us() + 500) / 1000, + it->payload_size(), + false); + pacer_queue_.push_back(*it); + const size_t kMaxPacerQueueSize = 1000; + if (pacer_queue_.size() > kMaxPacerQueueSize) { + pacer_queue_.pop_front(); + } + ++it; + } + clock_.AdvanceTimeMilliseconds(kProcessIntervalMs); + pacer_.Process(); + } + QueuePackets(in_out, (start_of_run_ms_ + time_ms) * 1000); +} + +void PacedVideoSender::QueuePackets(Packets* batch, + int64_t end_of_batch_time_us) { + queue_.merge(*batch); + if (queue_.empty()) { + return; + } + Packets::iterator it = queue_.begin(); + for (; it != queue_.end(); ++it) { + if (it->send_time_us() > end_of_batch_time_us) { + break; + } + } + Packets to_transfer; + to_transfer.splice(to_transfer.begin(), queue_, queue_.begin(), it); + batch->merge(to_transfer); +} + +void PacedVideoSender::GiveFeedback(const PacketSender::Feedback& feedback) { + source_->GiveFeedback(feedback); + pacer_.UpdateBitrate( + PacedSender::kDefaultPaceMultiplier * feedback.estimated_bps / 1000, 0); +} + +bool PacedVideoSender::TimeToSendPacket(uint32_t ssrc, + uint16_t sequence_number, + int64_t capture_time_ms, + bool retransmission) { + for (Packets::iterator it = pacer_queue_.begin(); it != pacer_queue_.end(); + ++it) { + if (it->header().sequenceNumber == sequence_number) { + int64_t pace_out_time_ms = clock_.TimeInMilliseconds(); + // Make sure a packet is never paced out earlier than when it was put into + // the pacer. + assert(1000 * pace_out_time_ms >= it->send_time_us()); + it->SetAbsSendTimeMs(pace_out_time_ms); + it->set_send_time_us(1000 * pace_out_time_ms); + queue_.push_back(*it); + return true; + } + } + return false; +} + +int PacedVideoSender::TimeToSendPadding(int bytes) { + return 0; +} } // namespace bwe } // namespace testing } // namespace webrtc diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h index 8af07f9183..0ab3b5f9db 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h @@ -22,7 +22,9 @@ #include #include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/pacing/include/paced_sender.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" +#include "webrtc/system_wrappers/interface/clock.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { @@ -161,6 +163,7 @@ class Packet { int64_t creation_time_us() const { return creation_time_us_; } void set_send_time_us(int64_t send_time_us); int64_t send_time_us() const { return send_time_us_; } + void SetAbsSendTimeMs(int64_t abs_send_time_ms); uint32_t payload_size() const { return payload_size_; } const RTPHeader& header() const { return header_; } @@ -391,9 +394,9 @@ class VideoSender : public PacketSender { uint32_t max_payload_size_bytes() const { return kMaxPayloadSizeBytes; } uint32_t bytes_per_second() const { return bytes_per_second_; } - virtual uint32_t GetCapacityKbps() const; + virtual uint32_t GetCapacityKbps() const OVERRIDE; - virtual void RunFor(int64_t time_ms, Packets* in_out); + virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE; protected: const uint32_t kMaxPayloadSizeBytes; @@ -417,12 +420,43 @@ class AdaptiveVideoSender : public VideoSender { float first_frame_offset); virtual ~AdaptiveVideoSender() {} - virtual int GetFeedbackIntervalMs() const { return 100; } - virtual void GiveFeedback(const Feedback& feedback); + virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; } + virtual void GiveFeedback(const Feedback& feedback) OVERRIDE; -private: + private: DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveVideoSender); }; + +class PacedVideoSender : public PacketSender, public PacedSender::Callback { + public: + PacedVideoSender(PacketProcessorListener* listener, + uint32_t kbps, AdaptiveVideoSender* source); + virtual ~PacedVideoSender() {} + + virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; } + virtual void GiveFeedback(const Feedback& feedback) OVERRIDE; + virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE; + + // Implements PacedSender::Callback. + virtual bool TimeToSendPacket(uint32_t ssrc, + uint16_t sequence_number, + int64_t capture_time_ms, + bool retransmission) OVERRIDE; + virtual int TimeToSendPadding(int bytes) OVERRIDE; + + private: + void QueuePackets(Packets* batch, int64_t end_of_batch_time_us); + + static const int64_t kInitialTimeMs = 0; + SimulatedClock clock_; + int64_t start_of_run_ms_; + PacedSender pacer_; + Packets pacer_queue_; + Packets queue_; + AdaptiveVideoSender* source_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(PacedVideoSender); +}; } // namespace bwe } // namespace testing } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 74947693b8..c0383934f4 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -16,6 +16,7 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" +#include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/system_wrappers/interface/trace_event.h" namespace webrtc { @@ -610,10 +611,15 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) { assert(false); return -1; } + // Convert from TickTime to Clock since capture_time_ms is based on + // TickTime. + // TODO(holmer): Remove this conversion when we remove the use of TickTime. + int64_t clock_delta_ms = clock_->TimeInMilliseconds() - + TickTime::MillisecondTimestamp(); if (!paced_sender_->SendPacket(PacedSender::kHighPriority, header.ssrc, header.sequenceNumber, - capture_time_ms, + capture_time_ms + clock_delta_ms, length - header.headerLength, true)) { // We can't send the packet right now. @@ -930,8 +936,11 @@ int32_t RTPSender::SendToNetwork( } if (paced_sender_ && storage != kDontStore) { + int64_t clock_delta_ms = clock_->TimeInMilliseconds() - + TickTime::MillisecondTimestamp(); if (!paced_sender_->SendPacket(priority, rtp_header.ssrc, - rtp_header.sequenceNumber, capture_time_ms, + rtp_header.sequenceNumber, + capture_time_ms + clock_delta_ms, payload_length, false)) { // We can't send the packet right now. // We will be called when it is time. diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc index a009c06a67..fd3f0d7893 100644 --- a/webrtc/video_engine/vie_encoder.cc +++ b/webrtc/video_engine/vie_encoder.cc @@ -23,6 +23,7 @@ #include "webrtc/modules/video_coding/main/interface/video_coding.h" #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" #include "webrtc/modules/video_coding/main/source/encoded_frame.h" +#include "webrtc/system_wrappers/interface/clock.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/tick_util.h" @@ -34,16 +35,6 @@ namespace webrtc { -// Pace in kbits/s until we receive first estimate. -static const int kInitialPace = 2000; - -// Pacing-rate relative to our target send rate. -// Multiplicative factor that is applied to the target bitrate to calculate the -// number of bytes that can be transmitted per interval. -// Increasing this factor will result in lower delays in cases of bitrate -// overshoots from the encoder. -static const float kPaceMultiplier = 2.5f; - // Margin on when we pause the encoder when the pacing buffer overflows relative // to the configured buffer delay. static const float kEncoderPausePacerMargin = 2.0f; @@ -172,7 +163,8 @@ ViEEncoder::ViEEncoder(int32_t engine_id, bitrate_observer_.reset(new ViEBitrateObserver(this)); pacing_callback_.reset(new ViEPacedSenderCallback(this)); paced_sender_.reset( - new PacedSender(pacing_callback_.get(), kInitialPace, kPaceMultiplier)); + new PacedSender(Clock::GetRealTimeClock(), pacing_callback_.get(), + PacedSender::kDefaultInitialPaceKbps, 0)); } bool ViEEncoder::Init() { @@ -383,8 +375,9 @@ int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) { if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_) pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_; - paced_sender_->UpdateBitrate(kPaceMultiplier * video_codec.startBitrate, - pad_up_to_bitrate_kbps); + paced_sender_->UpdateBitrate( + PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate, + pad_up_to_bitrate_kbps); return 0; } @@ -894,8 +887,9 @@ void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps, if (pad_up_to_bitrate_kbps > bitrate_kbps) pad_up_to_bitrate_kbps = bitrate_kbps; - paced_sender_->UpdateBitrate(kPaceMultiplier * bitrate_kbps, - pad_up_to_bitrate_kbps); + paced_sender_->UpdateBitrate( + PacedSender::kDefaultPaceMultiplier * bitrate_kbps, + pad_up_to_bitrate_kbps); default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates); if (video_suspended_ == video_is_suspended) return;