| Index: webrtc/modules/pacing/paced_sender.cc
|
| diff --git a/webrtc/modules/pacing/paced_sender.cc b/webrtc/modules/pacing/paced_sender.cc
|
| index 121f860c7daa344f0854530ee18a9cfc0fdb5a84..25ca2cf4c51c80f6cc3da1e025dd7d21939d0d95 100644
|
| --- a/webrtc/modules/pacing/paced_sender.cc
|
| +++ b/webrtc/modules/pacing/paced_sender.cc
|
| @@ -35,6 +35,15 @@ const int64_t kMaxIntervalTimeMs = 30;
|
| // TODO(sprang): Move at least PacketQueue and MediaBudget out to separate
|
| // 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 paced_sender {
|
| struct Packet {
|
| @@ -50,7 +59,8 @@ struct Packet {
|
| ssrc(ssrc),
|
| sequence_number(seq_number),
|
| 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),
|
| retransmission(retransmission),
|
| enqueue_order(enqueue_order) {}
|
| @@ -99,13 +109,16 @@ class PacketQueue {
|
| if (!AddToDupeSet(packet))
|
| return;
|
|
|
| - UpdateQueueTime(packet.enqueue_time_ms);
|
| + if (packet.enqueue_time_ms >= time_last_updated_)
|
| + UpdateQueueTime(packet.enqueue_time_ms);
|
|
|
| // Store packet in list, use pointers in priority queue for cheaper moves.
|
| // Packets have a handle to its own iterator in the list, for easy removal
|
| // when popping from queue.
|
| packet_list_.push_front(packet);
|
| 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.
|
| prio_queue_.push(&(*it)); // Pointer into list.
|
| bytes_ += packet.bytes;
|
| @@ -122,7 +135,8 @@ class PacketQueue {
|
| void FinalizePop(const Packet& packet) {
|
| RemoveFromDupeSet(packet);
|
| bytes_ -= packet.bytes;
|
| - queue_time_sum_ -= (time_last_updated_ - packet.enqueue_time_ms);
|
| + if (packet.enqueue_time_ms != -1)
|
| + queue_time_sum_ -= (time_last_updated_ - packet.enqueue_time_ms);
|
| packet_list_.erase(packet.this_it);
|
| RTC_DCHECK_EQ(packet_list_.size(), prio_queue_.size());
|
| if (packet_list_.empty())
|
| @@ -136,14 +150,18 @@ class PacketQueue {
|
| uint64_t SizeInBytes() const { return bytes_; }
|
|
|
| int64_t OldestEnqueueTimeMs() const {
|
| - auto it = packet_list_.rbegin();
|
| - if (it == packet_list_.rend())
|
| - return 0;
|
| - return it->enqueue_time_ms;
|
| + for (auto it = packet_list_.rbegin(); it != packet_list_.rend(); ++it) {
|
| + if (it->enqueue_time_ms != -1)
|
| + return it->enqueue_time_ms;
|
| + }
|
| + return 0;
|
| }
|
|
|
| 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_;
|
| // Use packet packet_list_.size() not prio_queue_.size() here, as there
|
| // might be an outstanding element popped from prio_queue_ currently in the
|
|
|