Temporary hack to avoid assert errors when time moves backwards.

Once we have eliminated all non-monotonic clocks, revert this change.

BUG=webrtc:5452

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

Cr-Commit-Position: refs/heads/master@{#11361}
This commit is contained in:
sprang 2016-01-22 13:36:32 -08:00 committed by Commit bot
parent cc71c4107f
commit 38b39d59d1

View File

@ -35,6 +35,15 @@ const int64_t kMaxIntervalTimeMs = 30;
// TODO(sprang): Move at least PacketQueue and MediaBudget out to separate // TODO(sprang): Move at least PacketQueue and MediaBudget out to separate
// files, so that we can more easily test them. // files, so that we can more easily test them.
// Note about the -1 enqueue times below:
// This is a temporary hack to avoid crashes when the real-time clock is
// adjusted backwards, which can happen on Android when the phone syncs the
// clock to the network. See this bug:
// https://bugs.chromium.org/p/webrtc/issues/detail?id=5452
// We can't just comment out the DCHECK either, as that would lead to the sum
// being wrong. Instead we just ignore packets from the past when we calculate
// the average queue time.
namespace webrtc { namespace webrtc {
namespace paced_sender { namespace paced_sender {
struct Packet { struct Packet {
@ -50,7 +59,8 @@ struct Packet {
ssrc(ssrc), ssrc(ssrc),
sequence_number(seq_number), sequence_number(seq_number),
capture_time_ms(capture_time_ms), capture_time_ms(capture_time_ms),
enqueue_time_ms(enqueue_time_ms), // TODO(sprang): Remove -1 option once we can guarantee monotonic clock.
enqueue_time_ms(enqueue_time_ms), // -1 = not valid; don't count.
bytes(length_in_bytes), bytes(length_in_bytes),
retransmission(retransmission), retransmission(retransmission),
enqueue_order(enqueue_order) {} enqueue_order(enqueue_order) {}
@ -99,6 +109,7 @@ class PacketQueue {
if (!AddToDupeSet(packet)) if (!AddToDupeSet(packet))
return; return;
if (packet.enqueue_time_ms >= time_last_updated_)
UpdateQueueTime(packet.enqueue_time_ms); UpdateQueueTime(packet.enqueue_time_ms);
// Store packet in list, use pointers in priority queue for cheaper moves. // Store packet in list, use pointers in priority queue for cheaper moves.
@ -106,6 +117,8 @@ class PacketQueue {
// when popping from queue. // when popping from queue.
packet_list_.push_front(packet); packet_list_.push_front(packet);
std::list<Packet>::iterator it = packet_list_.begin(); std::list<Packet>::iterator it = packet_list_.begin();
if (packet.enqueue_time_ms < time_last_updated_)
it->enqueue_time_ms = -1;
it->this_it = it; // Handle for direct removal from list. it->this_it = it; // Handle for direct removal from list.
prio_queue_.push(&(*it)); // Pointer into list. prio_queue_.push(&(*it)); // Pointer into list.
bytes_ += packet.bytes; bytes_ += packet.bytes;
@ -122,6 +135,7 @@ class PacketQueue {
void FinalizePop(const Packet& packet) { void FinalizePop(const Packet& packet) {
RemoveFromDupeSet(packet); RemoveFromDupeSet(packet);
bytes_ -= packet.bytes; bytes_ -= packet.bytes;
if (packet.enqueue_time_ms != -1)
queue_time_sum_ -= (time_last_updated_ - packet.enqueue_time_ms); queue_time_sum_ -= (time_last_updated_ - packet.enqueue_time_ms);
packet_list_.erase(packet.this_it); packet_list_.erase(packet.this_it);
RTC_DCHECK_EQ(packet_list_.size(), prio_queue_.size()); RTC_DCHECK_EQ(packet_list_.size(), prio_queue_.size());
@ -136,14 +150,18 @@ class PacketQueue {
uint64_t SizeInBytes() const { return bytes_; } uint64_t SizeInBytes() const { return bytes_; }
int64_t OldestEnqueueTimeMs() const { int64_t OldestEnqueueTimeMs() const {
auto it = packet_list_.rbegin(); for (auto it = packet_list_.rbegin(); it != packet_list_.rend(); ++it) {
if (it == packet_list_.rend()) if (it->enqueue_time_ms != -1)
return 0;
return it->enqueue_time_ms; return it->enqueue_time_ms;
} }
return 0;
}
void UpdateQueueTime(int64_t timestamp_ms) { void UpdateQueueTime(int64_t timestamp_ms) {
RTC_DCHECK_GE(timestamp_ms, time_last_updated_); // TODO(sprang): Remove this condition and reinstate a DCHECK once we have
// made sure all clocks are monotonic.
if (timestamp_ms < time_last_updated_)
return;
int64_t delta = timestamp_ms - time_last_updated_; int64_t delta = timestamp_ms - time_last_updated_;
// Use packet packet_list_.size() not prio_queue_.size() here, as there // Use packet packet_list_.size() not prio_queue_.size() here, as there
// might be an outstanding element popped from prio_queue_ currently in the // might be an outstanding element popped from prio_queue_ currently in the