Add delay limit to ChokeFilter.
BUG= R=stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/3079005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5058 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -464,7 +464,7 @@ class ReorderFilter : public PacketProcessorInterface {
|
||||
// Apply a bitrate choke with an infinite queue on the packet stream.
|
||||
class ChokeFilter : public PacketProcessorInterface {
|
||||
public:
|
||||
ChokeFilter() : kbps_(1200), last_send_time_us_(0) {}
|
||||
ChokeFilter() : kbps_(1200), max_delay_us_(0), last_send_time_us_(0) {}
|
||||
virtual ~ChokeFilter() {}
|
||||
|
||||
void SetCapacity(uint32_t kbps) {
|
||||
@ -473,18 +473,34 @@ class ChokeFilter : public PacketProcessorInterface {
|
||||
kbps_ = kbps;
|
||||
}
|
||||
|
||||
void SetMaxDelay(int64_t max_delay_ms) {
|
||||
BWE_TEST_LOGGING_ENABLE(false);
|
||||
BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast<int>(max_delay_ms));
|
||||
assert(max_delay_ms >= 0);
|
||||
max_delay_us_ = max_delay_ms * 1000;
|
||||
}
|
||||
|
||||
virtual void RunFor(int64_t /*time_ms*/, Packets* in_out) {
|
||||
assert(in_out);
|
||||
for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
|
||||
for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
|
||||
int64_t earliest_send_time_us = last_send_time_us_ +
|
||||
(it->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_;
|
||||
last_send_time_us_ = std::max(it->send_time_us(), earliest_send_time_us);
|
||||
it->set_send_time_us(last_send_time_us_);
|
||||
int64_t new_send_time_us = std::max(it->send_time_us(),
|
||||
earliest_send_time_us);
|
||||
if (max_delay_us_ == 0 ||
|
||||
max_delay_us_ >= (new_send_time_us - it->send_time_us())) {
|
||||
it->set_send_time_us(new_send_time_us);
|
||||
last_send_time_us_ = new_send_time_us;
|
||||
++it;
|
||||
} else {
|
||||
it = in_out->erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t kbps_;
|
||||
int64_t max_delay_us_;
|
||||
int64_t last_send_time_us_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ChokeFilter);
|
||||
|
@ -727,13 +727,16 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test {
|
||||
: filter_(),
|
||||
now_ms_(0),
|
||||
sequence_number_(0),
|
||||
output_packets_() {
|
||||
output_packets_(),
|
||||
send_times_us_() {
|
||||
}
|
||||
virtual ~BweTestFramework_ChokeFilterTest() {}
|
||||
|
||||
protected:
|
||||
ChokeFilter filter_;
|
||||
|
||||
void TestChoke(int64_t run_for_ms, uint32_t packets_to_generate,
|
||||
uint32_t choke_kbps, uint32_t expected_kbit_transmitted) {
|
||||
uint32_t expected_kbit_transmitted) {
|
||||
// Generate a bunch of packets, apply choke, verify output is ordered.
|
||||
Packets packets;
|
||||
RTPHeader header = {0};
|
||||
@ -742,9 +745,9 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test {
|
||||
header.sequenceNumber = sequence_number_++;
|
||||
// Payload is 1000 bits.
|
||||
packets.push_back(BwePacket(send_time_ms * 1000, 125, header));
|
||||
send_times_us_.push_back(send_time_ms * 1000);
|
||||
}
|
||||
ASSERT_TRUE(IsTimeSorted(packets));
|
||||
filter_.SetCapacity(choke_kbps);
|
||||
filter_.RunFor(run_for_ms, &packets);
|
||||
now_ms_ += run_for_ms;
|
||||
output_packets_.splice(output_packets_.end(), packets);
|
||||
@ -764,11 +767,21 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test {
|
||||
EXPECT_EQ(expected_kbit_transmitted, (bytes_transmitted * 8) / 1000);
|
||||
}
|
||||
|
||||
void CheckMaxDelay(int64_t max_delay_ms) {
|
||||
for (PacketsIt it = output_packets_.begin(); it != output_packets_.end();
|
||||
++it) {
|
||||
const BwePacket& packet = *it;
|
||||
int64_t delay_us = packet.send_time_us() -
|
||||
send_times_us_[packet.header().sequenceNumber];
|
||||
EXPECT_GE(max_delay_ms * 1000, delay_us);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ChokeFilter filter_;
|
||||
int64_t now_ms_;
|
||||
uint32_t sequence_number_;
|
||||
Packets output_packets_;
|
||||
std::vector<int64_t> send_times_us_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BweTestFramework_ChokeFilterTest);
|
||||
};
|
||||
@ -777,38 +790,69 @@ TEST_F(BweTestFramework_ChokeFilterTest, Short) {
|
||||
// 100ms, 100 packets, 10 kbps choke -> 1 kbit of data should have propagated.
|
||||
// That is actually just a single packet, since each packet has 1000 bits of
|
||||
// payload.
|
||||
TestChoke(100, 100, 10, 1);
|
||||
filter_.SetCapacity(10);
|
||||
TestChoke(100, 100, 1);
|
||||
}
|
||||
|
||||
TEST_F(BweTestFramework_ChokeFilterTest, Medium) {
|
||||
// 100ms, 10 packets, 10 kbps choke -> 1 packet through, or 1 kbit.
|
||||
TestChoke(100, 10, 10, 1);
|
||||
// 200ms, no new packets, same choke -> another packet through.
|
||||
TestChoke(100, 0, 10, 1);
|
||||
// 1000ms, no new packets, same choke -> 8 more packets.
|
||||
TestChoke(800, 0, 10, 8);
|
||||
// 2000ms, no new packets, same choke -> queue is empty so no output.
|
||||
TestChoke(1000, 0, 10, 0);
|
||||
filter_.SetCapacity(10);
|
||||
TestChoke(100, 10, 1);
|
||||
// 200ms, no new packets -> another packet through.
|
||||
TestChoke(100, 0, 1);
|
||||
// 1000ms, no new packets -> 8 more packets.
|
||||
TestChoke(800, 0, 8);
|
||||
// 2000ms, no new packets -> queue is empty so no output.
|
||||
TestChoke(1000, 0, 0);
|
||||
}
|
||||
|
||||
TEST_F(BweTestFramework_ChokeFilterTest, Long) {
|
||||
// 100ms, 100 packets in queue, 10 kbps choke -> 1 packet through, or 1 kbit.
|
||||
TestChoke(100, 100, 10, 1);
|
||||
filter_.SetCapacity(10);
|
||||
TestChoke(100, 100, 1);
|
||||
// 200ms, no input, another packet through.
|
||||
TestChoke(100, 0, 10, 1);
|
||||
TestChoke(100, 0, 1);
|
||||
// 1000ms, no input, 8 packets through.
|
||||
TestChoke(800, 0, 10, 8);
|
||||
TestChoke(800, 0, 8);
|
||||
// 10000ms, no input, raise choke to 100 kbps. Remaining 90 packets in queue
|
||||
// should be propagated, for a total of 90 kbps.
|
||||
TestChoke(9000, 0, 100, 90);
|
||||
// 10100ms, 20 more packets, 100 kbps choke -> 10 packets or 10 kbit through.
|
||||
TestChoke(100, 20, 100, 10);
|
||||
// 10300ms, 10 more packets, same choke -> 20 packets out.
|
||||
TestChoke(200, 10, 100, 20);
|
||||
filter_.SetCapacity(100);
|
||||
TestChoke(9000, 0, 90);
|
||||
// 10100ms, 20 more packets -> 10 packets or 10 kbit through.
|
||||
TestChoke(100, 20, 10);
|
||||
// 10300ms, 10 more packets -> 20 packets out.
|
||||
TestChoke(200, 10, 20);
|
||||
// 11300ms, no input, queue should be empty.
|
||||
TestChoke(1000, 0, 10, 0);
|
||||
filter_.SetCapacity(10);
|
||||
TestChoke(1000, 0, 0);
|
||||
}
|
||||
|
||||
TEST_F(BweTestFramework_ChokeFilterTest, MaxDelay) {
|
||||
// 10 kbps choke, 500 ms delay cap
|
||||
filter_.SetCapacity(10);
|
||||
filter_.SetMaxDelay(500);
|
||||
// 100ms, 100 packets in queue, 10 kbps choke -> 1 packet through, or 1 kbit.
|
||||
TestChoke(100, 100, 1);
|
||||
CheckMaxDelay(500);
|
||||
// 500ms, no input, 4 more packets through.
|
||||
TestChoke(400, 0, 4);
|
||||
// 10000ms, no input, remaining packets should have been dropped.
|
||||
TestChoke(9500, 0, 0);
|
||||
|
||||
// 100 ms delay cap
|
||||
filter_.SetMaxDelay(100);
|
||||
// 10100ms, 50 more packets -> 2 packets or 2 kbit through.
|
||||
TestChoke(100, 50, 2);
|
||||
CheckMaxDelay(100);
|
||||
// 20000ms, no input, remaining packets in queue should have been dropped.
|
||||
TestChoke(9900, 0, 0);
|
||||
|
||||
// Reset delay cap (0 is no cap) and verify no packets are dropped.
|
||||
filter_.SetCapacity(10);
|
||||
filter_.SetMaxDelay(0);
|
||||
TestChoke(100, 100, 2);
|
||||
TestChoke(9900, 0, 98);
|
||||
}
|
||||
} // namespace bwe
|
||||
} // namespace testing
|
||||
} // namespace webrtc
|
||||
|
Reference in New Issue
Block a user