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:
solenberg@webrtc.org
2013-10-30 19:18:07 +00:00
parent f424cb8e13
commit dce70ccb0b
2 changed files with 85 additions and 25 deletions

View File

@ -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);

View File

@ -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