Only use paced packets for estimating bitrate probes.

BUG=4778
R=mflodman@webrtc.org, solenberg@webrtc.org

Review URL: https://codereview.webrtc.org/1188823007.

Cr-Commit-Position: refs/heads/master@{#9463}
This commit is contained in:
Stefan Holmer 2015-06-18 16:01:33 +02:00
parent 141725f50f
commit ff4ea9310e
13 changed files with 98 additions and 62 deletions

View File

@ -67,11 +67,13 @@ struct PacketInfo {
PacketInfo(int64_t arrival_time_ms,
int64_t send_time_ms,
uint16_t sequence_number,
size_t payload_size)
size_t payload_size,
bool was_paced)
: arrival_time_ms(arrival_time_ms),
send_time_ms(send_time_ms),
sequence_number(sequence_number),
payload_size(payload_size) {}
payload_size(payload_size),
was_paced(was_paced) {}
// Time corresponding to when the packet was received. Timestamped with the
// receiver's clock.
int64_t arrival_time_ms;
@ -83,6 +85,8 @@ struct PacketInfo {
uint16_t sequence_number;
// Size of the packet excluding RTP headers.
size_t payload_size;
// True if the packet was paced out by the pacer.
bool was_paced;
};
class RemoteBitrateEstimator : public CallStatsObserver, public Module {
@ -101,7 +105,8 @@ class RemoteBitrateEstimator : public CallStatsObserver, public Module {
// Note that |arrival_time_ms| can be of an arbitrary time base.
virtual void IncomingPacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) = 0;
const RTPHeader& header,
bool was_paced) = 0;
// Removes all data for |ssrc|.
virtual void RemoveStream(unsigned int ssrc) = 0;

View File

@ -116,7 +116,8 @@ class RemoteBitrateEstimatorAbsSendTimeImpl : public RemoteBitrateEstimator {
void IncomingPacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) override;
const RTPHeader& header,
bool was_paced) override;
// This class relies on Process() being called periodically (at least once
// every other second) for streams to be timed out properly. Therefore it
// shouldn't be detached from the ProcessThread except if it's about to be
@ -155,7 +156,8 @@ class RemoteBitrateEstimatorAbsSendTimeImpl : public RemoteBitrateEstimator {
void IncomingPacketInfo(int64_t arrival_time_ms,
uint32_t send_time_24bits,
size_t payload_size,
uint32_t ssrc);
uint32_t ssrc,
bool was_paced);
bool IsProbe(int64_t send_time_ms, int payload_size) const
EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get());
@ -338,27 +340,29 @@ void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketFeedbackVector(
uint32_t send_time_24bits =
send_time_32bits >> kAbsSendTimeInterArrivalUpshift;
IncomingPacketInfo(packet_info.arrival_time_ms, send_time_24bits,
packet_info.payload_size, 0);
packet_info.payload_size, 0, packet_info.was_paced);
}
}
void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacket(
int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) {
const RTPHeader& header,
bool was_paced) {
if (!header.extension.hasAbsoluteSendTime) {
LOG(LS_WARNING) << "RemoteBitrateEstimatorAbsSendTimeImpl: Incoming packet "
"is missing absolute send time extension!";
}
IncomingPacketInfo(arrival_time_ms, header.extension.absoluteSendTime,
payload_size, header.ssrc);
payload_size, header.ssrc, was_paced);
}
void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketInfo(
int64_t arrival_time_ms,
uint32_t send_time_24bits,
size_t payload_size,
uint32_t ssrc) {
uint32_t ssrc,
bool was_paced) {
assert(send_time_24bits < (1ul << 24));
// Shift up send time to use the full 32 bits that inter_arrival works with,
// so wrapping works properly.
@ -380,8 +384,9 @@ void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketInfo(
int64_t t_delta = 0;
int size_delta = 0;
// For now only try to detect probes while we don't have a valid estimate.
if (!remote_rate_->ValidEstimate() ||
now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs) {
if (was_paced &&
(!remote_rate_->ValidEstimate() ||
now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs)) {
// TODO(holmer): Use a map instead to get correct order?
if (total_probes_received_ < kMaxProbePackets) {
int send_delta_ms = -1;

View File

@ -99,7 +99,7 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest, TestProcessAfterTimeout) {
// RemoteBitrateEstimator.
const int64_t kStreamTimeOutMs = 2000;
const int64_t kProcessIntervalMs = 1000;
IncomingPacket(0, 1000, clock_.TimeInMilliseconds(), 0, 0);
IncomingPacket(0, 1000, clock_.TimeInMilliseconds(), 0, 0, true);
clock_.AdvanceTimeMilliseconds(kStreamTimeOutMs + 1);
// Trigger timeout.
EXPECT_EQ(0, bitrate_estimator_->Process());
@ -115,14 +115,16 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest, TestProbeDetection) {
for (int i = 0; i < kProbeLength; ++i) {
clock_.AdvanceTimeMilliseconds(10);
now_ms = clock_.TimeInMilliseconds();
IncomingPacket(0, 1000, now_ms, 90 * now_ms, AbsSendTime(now_ms, 1000));
IncomingPacket(0, 1000, now_ms, 90 * now_ms, AbsSendTime(now_ms, 1000),
true);
}
// Second burst sent at 8 * 1000 / 5 = 1600 kbps.
for (int i = 0; i < kProbeLength; ++i) {
clock_.AdvanceTimeMilliseconds(5);
now_ms = clock_.TimeInMilliseconds();
IncomingPacket(0, 1000, now_ms, 90 * now_ms, AbsSendTime(now_ms, 1000));
IncomingPacket(0, 1000, now_ms, 90 * now_ms, AbsSendTime(now_ms, 1000),
true);
}
EXPECT_EQ(0, bitrate_estimator_->Process());
@ -130,6 +132,28 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest, TestProbeDetection) {
EXPECT_GT(bitrate_observer_->latest_bitrate(), 1500000u);
}
TEST_F(RemoteBitrateEstimatorAbsSendTimeTest,
TestProbeDetectionNonPacedPackets) {
const int kProbeLength = 5;
int64_t now_ms = clock_.TimeInMilliseconds();
// First burst sent at 8 * 1000 / 10 = 800 kbps, but with every other packet
// not being paced which could mess things up.
for (int i = 0; i < kProbeLength; ++i) {
clock_.AdvanceTimeMilliseconds(5);
now_ms = clock_.TimeInMilliseconds();
IncomingPacket(0, 1000, now_ms, 90 * now_ms, AbsSendTime(now_ms, 1000),
true);
// Non-paced packet, arriving 5 ms after.
clock_.AdvanceTimeMilliseconds(5);
IncomingPacket(0, 100, now_ms, 90 * now_ms, AbsSendTime(now_ms, 1000),
false);
}
EXPECT_EQ(0, bitrate_estimator_->Process());
EXPECT_TRUE(bitrate_observer_->updated());
EXPECT_GT(bitrate_observer_->latest_bitrate(), 800000u);
}
// Packets will require 5 ms to be transmitted to the receiver, causing packets
// of the second probe to be dispersed.
TEST_F(RemoteBitrateEstimatorAbsSendTimeTest,
@ -143,7 +167,7 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest,
now_ms = clock_.TimeInMilliseconds();
send_time_ms += 10;
IncomingPacket(0, 1000, now_ms, 90 * send_time_ms,
AbsSendTime(send_time_ms, 1000));
AbsSendTime(send_time_ms, 1000), true);
}
// Second burst sent at 8 * 1000 / 5 = 1600 kbps, arriving at 8 * 1000 / 8 =
@ -153,7 +177,7 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest,
now_ms = clock_.TimeInMilliseconds();
send_time_ms += 5;
IncomingPacket(0, 1000, now_ms, send_time_ms,
AbsSendTime(send_time_ms, 1000));
AbsSendTime(send_time_ms, 1000), true);
}
EXPECT_EQ(0, bitrate_estimator_->Process());
@ -173,7 +197,7 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest,
send_time_ms += 10;
now_ms = clock_.TimeInMilliseconds();
IncomingPacket(0, 1000, now_ms, 90 * send_time_ms,
AbsSendTime(send_time_ms, 1000));
AbsSendTime(send_time_ms, 1000), true);
}
EXPECT_EQ(0, bitrate_estimator_->Process());
@ -192,7 +216,7 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest, TestProbeDetectionFasterArrival) {
send_time_ms += 10;
now_ms = clock_.TimeInMilliseconds();
IncomingPacket(0, 1000, now_ms, 90 * send_time_ms,
AbsSendTime(send_time_ms, 1000));
AbsSendTime(send_time_ms, 1000), true);
}
EXPECT_EQ(0, bitrate_estimator_->Process());
@ -210,7 +234,7 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest, TestProbeDetectionSlowerArrival) {
send_time_ms += 5;
now_ms = clock_.TimeInMilliseconds();
IncomingPacket(0, 1000, now_ms, 90 * send_time_ms,
AbsSendTime(send_time_ms, 1000));
AbsSendTime(send_time_ms, 1000), true);
}
EXPECT_EQ(0, bitrate_estimator_->Process());
@ -230,7 +254,7 @@ TEST_F(RemoteBitrateEstimatorAbsSendTimeTest,
send_time_ms += 1;
now_ms = clock_.TimeInMilliseconds();
IncomingPacket(0, 1000, now_ms, 90 * send_time_ms,
AbsSendTime(send_time_ms, 1000));
AbsSendTime(send_time_ms, 1000), true);
}
EXPECT_EQ(0, bitrate_estimator_->Process());

View File

@ -38,7 +38,8 @@ class RemoteBitrateEstimatorImpl : public RemoteBitrateEstimator {
void IncomingPacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) override;
const RTPHeader& header,
bool was_paced) override;
int32_t Process() override;
int64_t TimeUntilNextProcess() override;
void OnRttUpdate(int64_t rtt) override;
@ -107,10 +108,10 @@ RemoteBitrateEstimatorImpl::~RemoteBitrateEstimatorImpl() {
}
}
void RemoteBitrateEstimatorImpl::IncomingPacket(
int64_t arrival_time_ms,
void RemoteBitrateEstimatorImpl::IncomingPacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) {
const RTPHeader& header,
bool was_paced) {
uint32_t ssrc = header.ssrc;
uint32_t rtp_timestamp = header.timestamp +
header.extension.transmissionTimeOffset;

View File

@ -221,7 +221,8 @@ void RemoteBitrateEstimatorTest::IncomingPacket(uint32_t ssrc,
size_t payload_size,
int64_t arrival_time,
uint32_t rtp_timestamp,
uint32_t absolute_send_time) {
uint32_t absolute_send_time,
bool was_paced) {
RTPHeader header;
memset(&header, 0, sizeof(header));
header.ssrc = ssrc;
@ -229,7 +230,7 @@ void RemoteBitrateEstimatorTest::IncomingPacket(uint32_t ssrc,
header.extension.hasAbsoluteSendTime = true;
header.extension.absoluteSendTime = absolute_send_time;
bitrate_estimator_->IncomingPacket(arrival_time + kArrivalTimeClockOffsetMs,
payload_size, header);
payload_size, header, was_paced);
}
// Generates a frame of packets belonging to a stream at a given bitrate and
@ -252,11 +253,9 @@ bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc,
// since both are used in IncomingPacket().
clock_.AdvanceTimeMicroseconds(packet->arrival_time -
clock_.TimeInMicroseconds());
IncomingPacket(packet->ssrc,
packet->size,
(packet->arrival_time + 500) / 1000,
packet->rtp_timestamp,
AbsSendTime(packet->send_time, 1000000));
IncomingPacket(packet->ssrc, packet->size,
(packet->arrival_time + 500) / 1000, packet->rtp_timestamp,
AbsSendTime(packet->send_time, 1000000), true);
if (bitrate_observer_->updated()) {
// Verify that new estimates only are triggered by an overuse and a
// rate decrease.
@ -323,7 +322,7 @@ void RemoteBitrateEstimatorTest::InitialBehaviorTestHelper(
clock_.AdvanceTimeMilliseconds(1000);
// Inserting a packet. Still no valid estimate. We need to wait 1 second.
IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
bitrate_estimator_->Process();
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
EXPECT_EQ(0u, ssrcs.size());
@ -332,7 +331,7 @@ void RemoteBitrateEstimatorTest::InitialBehaviorTestHelper(
// Inserting packets for one second to get a valid estimate.
for (int i = 0; i < kFramerate; ++i) {
IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
clock_.AdvanceTimeMilliseconds(1000 / kFramerate);
timestamp += 90 * kFrameIntervalMs;
absolute_send_time = AddAbsSendTime(absolute_send_time,
@ -360,13 +359,13 @@ void RemoteBitrateEstimatorTest::RateIncreaseReorderingTestHelper(
uint32_t timestamp = 0;
uint32_t absolute_send_time = 0;
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
bitrate_estimator_->Process();
EXPECT_FALSE(bitrate_observer_->updated()); // No valid estimate.
// Inserting packets for one second to get a valid estimate.
for (int i = 0; i < kFramerate; ++i) {
IncomingPacket(kDefaultSsrc, kMtu, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
timestamp += 90 * kFrameIntervalMs;
absolute_send_time = AddAbsSendTime(absolute_send_time,
@ -383,11 +382,12 @@ void RemoteBitrateEstimatorTest::RateIncreaseReorderingTestHelper(
absolute_send_time = AddAbsSendTime(absolute_send_time,
2 * kFrameIntervalAbsSendTime);
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(),
absolute_send_time, true);
IncomingPacket(
kDefaultSsrc, 1000, clock_.TimeInMilliseconds(),
timestamp - 90 * kFrameIntervalMs,
AddAbsSendTime(absolute_send_time,
-int(kFrameIntervalAbsSendTime)));
AddAbsSendTime(absolute_send_time, -int(kFrameIntervalAbsSendTime)),
true);
}
bitrate_estimator_->Process();
EXPECT_TRUE(bitrate_observer_->updated());
@ -525,7 +525,7 @@ void RemoteBitrateEstimatorTest::TestTimestampGroupingTestHelper() {
// Initial set of frames to increase the bitrate.
for (int i = 0; i <= 100; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
bitrate_estimator_->Process();
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
timestamp += 90 * kFrameIntervalMs;
@ -546,7 +546,7 @@ void RemoteBitrateEstimatorTest::TestTimestampGroupingTestHelper() {
// Insert |kTimestampGroupLength| frames with just 1 timestamp ticks in
// between. Should be treated as part of the same group by the estimator.
IncomingPacket(kDefaultSsrc, 100, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs / kTimestampGroupLength);
timestamp += 1;
absolute_send_time = AddAbsSendTime(absolute_send_time,
@ -579,7 +579,7 @@ void RemoteBitrateEstimatorTest::TestGetStatsHelper() {
// Inject propagation_time_delta of kFrameIntervalMs.
for (size_t i = 0; i < 3; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
timestamp += kFrameIntervalMs;
// Insert a kFrameIntervalMs propagation_time_delta.
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs * 2);
@ -597,7 +597,7 @@ void RemoteBitrateEstimatorTest::TestGetStatsHelper() {
// should be adjusted to 0.
for (size_t i = 0; i < 3; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
timestamp += 10 * kFrameIntervalMs;
clock_.AdvanceTimeMilliseconds(kBurstThresholdMs + 1);
absolute_send_time = AddAbsSendTime(absolute_send_time,
@ -610,7 +610,7 @@ void RemoteBitrateEstimatorTest::TestGetStatsHelper() {
// limits.
for (size_t i = 0; i < 1001; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
timestamp += kFrameIntervalMs;
absolute_send_time = AddAbsSendTime(absolute_send_time,
kFrameIntervalAbsSendTime);
@ -635,7 +635,7 @@ void RemoteBitrateEstimatorTest::TestWrappingHelper(
for (size_t i = 0; i < 3000; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
timestamp += kFrameIntervalMs;
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
absolute_send_time = AddAbsSendTime(absolute_send_time,
@ -652,7 +652,7 @@ void RemoteBitrateEstimatorTest::TestWrappingHelper(
bitrate_estimator_->Process();
for (size_t i = 0; i < 100; ++i) {
IncomingPacket(kDefaultSsrc, 1000, clock_.TimeInMilliseconds(), timestamp,
absolute_send_time);
absolute_send_time, true);
timestamp += kFrameIntervalMs;
clock_.AdvanceTimeMilliseconds(2 * kFrameIntervalMs);
absolute_send_time = AddAbsSendTime(absolute_send_time,

View File

@ -168,7 +168,8 @@ class RemoteBitrateEstimatorTest : public ::testing::Test {
size_t payload_size,
int64_t arrival_time,
uint32_t rtp_timestamp,
uint32_t absolute_send_time);
uint32_t absolute_send_time,
bool was_paced);
// Generates a frame of packets belonging to a stream at a given bitrate and
// with a given ssrc. The stream is pushed through a very simple simulated

View File

@ -96,7 +96,7 @@ void RembReceiver::ReceivePacket(int64_t arrival_time_ms,
step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
}
estimator_->IncomingPacket(arrival_time_ms, media_packet.payload_size(),
media_packet.header());
media_packet.header(), true);
clock_.AdvanceTimeMilliseconds(arrival_time_ms - clock_.TimeInMilliseconds());
ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds());

View File

@ -126,7 +126,7 @@ void SendSideBweReceiver::ReceivePacket(int64_t arrival_time_ms,
const MediaPacket& media_packet) {
packet_feedback_vector_.push_back(PacketInfo(
arrival_time_ms, media_packet.sender_timestamp_us() / 1000,
media_packet.header().sequenceNumber, media_packet.payload_size()));
media_packet.header().sequenceNumber, media_packet.payload_size(), true));
received_packets_.Insert(media_packet.sequence_number(),
media_packet.send_time_ms(), arrival_time_ms,

View File

@ -90,8 +90,7 @@ int main(int argc, char** argv) {
packet_length = packet.original_length;
}
rbe->IncomingPacket(clock.TimeInMilliseconds(),
packet_length - header.headerLength,
header);
packet_length - header.headerLength, header, true);
++packet_counter;
if (!rtp_reader->NextPacket(&packet)) {
break;

View File

@ -83,7 +83,7 @@ bool AudioReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
int64_t arrival_time_ms = TickTime::MillisecondTimestamp();
size_t payload_size = length - header.headerLength;
remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
header);
header, false);
}
return true;
}

View File

@ -121,8 +121,8 @@ bool StreamObserver::SendRtp(const uint8_t* packet, size_t length) {
EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
receive_stats_->IncomingPacket(header, length, false);
payload_registry_->SetIncomingPayloadType(header);
remote_bitrate_estimator_->IncomingPacket(
clock_->TimeInMilliseconds(), length - 12, header);
remote_bitrate_estimator_->IncomingPacket(clock_->TimeInMilliseconds(),
length - 12, header, true);
if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
remote_bitrate_estimator_->Process();
}
@ -267,8 +267,8 @@ PacketReceiver::DeliveryStatus LowRateStreamObserver::DeliverPacket(
RTPHeader header;
EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
receive_stats_->IncomingPacket(header, length, false);
remote_bitrate_estimator_->IncomingPacket(
clock_->TimeInMilliseconds(), length - 12, header);
remote_bitrate_estimator_->IncomingPacket(clock_->TimeInMilliseconds(),
length - 12, header, true);
if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
remote_bitrate_estimator_->Process();
}

View File

@ -55,10 +55,11 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
void IncomingPacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) override {
const RTPHeader& header,
bool was_paced) override {
CriticalSectionScoped cs(crit_sect_.get());
PickEstimatorFromHeader(header);
rbe_->IncomingPacket(arrival_time_ms, payload_size, header);
rbe_->IncomingPacket(arrival_time_ms, payload_size, header, was_paced);
}
int32_t Process() override {

View File

@ -280,8 +280,8 @@ int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
}
}
remote_bitrate_estimator_->IncomingPacket(arrival_time_ms,
payload_length, header);
remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_length,
header, true);
header.payload_type_frequency = kVideoPayloadTypeFrequency;
bool in_order = IsPacketInOrder(header);