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
This commit is contained in:
parent
614000d638
commit
88e0dda475
@ -16,12 +16,13 @@
|
||||
#include <vector>
|
||||
|
||||
#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,
|
||||
|
@ -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<paced_sender::IntervalBudget> 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_;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -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<PacedSender> 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());
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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<int64_t>(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<uint32_t>(next_frame_ms_ * 90.0);
|
||||
prototype_header_.extension.absoluteSendTime = (kTimestampBase +
|
||||
((static_cast<int64_t>(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
|
||||
|
@ -22,7 +22,9 @@
|
||||
#include <vector>
|
||||
|
||||
#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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user