OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 | 28 |
29 // Upper cap on process interval, in case process has not been called in a long | 29 // Upper cap on process interval, in case process has not been called in a long |
30 // time. | 30 // time. |
31 const int64_t kMaxIntervalTimeMs = 30; | 31 const int64_t kMaxIntervalTimeMs = 30; |
32 | 32 |
33 } // namespace | 33 } // namespace |
34 | 34 |
35 // TODO(sprang): Move at least PacketQueue and MediaBudget out to separate | 35 // TODO(sprang): Move at least PacketQueue and MediaBudget out to separate |
36 // files, so that we can more easily test them. | 36 // files, so that we can more easily test them. |
37 | 37 |
| 38 // Note about the -1 enqueue times below: |
| 39 // This is a temporary hack to avoid crashes when the real-time clock is |
| 40 // adjusted backwards, which can happen on Android when the phone syncs the |
| 41 // clock to the network. See this bug: |
| 42 // https://bugs.chromium.org/p/webrtc/issues/detail?id=5452 |
| 43 // We can't just comment out the DCHECK either, as that would lead to the sum |
| 44 // being wrong. Instead we just ignore packets from the past when we calculate |
| 45 // the average queue time. |
| 46 |
38 namespace webrtc { | 47 namespace webrtc { |
39 namespace paced_sender { | 48 namespace paced_sender { |
40 struct Packet { | 49 struct Packet { |
41 Packet(RtpPacketSender::Priority priority, | 50 Packet(RtpPacketSender::Priority priority, |
42 uint32_t ssrc, | 51 uint32_t ssrc, |
43 uint16_t seq_number, | 52 uint16_t seq_number, |
44 int64_t capture_time_ms, | 53 int64_t capture_time_ms, |
45 int64_t enqueue_time_ms, | 54 int64_t enqueue_time_ms, |
46 size_t length_in_bytes, | 55 size_t length_in_bytes, |
47 bool retransmission, | 56 bool retransmission, |
48 uint64_t enqueue_order) | 57 uint64_t enqueue_order) |
49 : priority(priority), | 58 : priority(priority), |
50 ssrc(ssrc), | 59 ssrc(ssrc), |
51 sequence_number(seq_number), | 60 sequence_number(seq_number), |
52 capture_time_ms(capture_time_ms), | 61 capture_time_ms(capture_time_ms), |
53 enqueue_time_ms(enqueue_time_ms), | 62 // TODO(sprang): Remove -1 option once we can guarantee monotonic clock. |
| 63 enqueue_time_ms(enqueue_time_ms), // -1 = not valid; don't count. |
54 bytes(length_in_bytes), | 64 bytes(length_in_bytes), |
55 retransmission(retransmission), | 65 retransmission(retransmission), |
56 enqueue_order(enqueue_order) {} | 66 enqueue_order(enqueue_order) {} |
57 | 67 |
58 RtpPacketSender::Priority priority; | 68 RtpPacketSender::Priority priority; |
59 uint32_t ssrc; | 69 uint32_t ssrc; |
60 uint16_t sequence_number; | 70 uint16_t sequence_number; |
61 int64_t capture_time_ms; | 71 int64_t capture_time_ms; |
62 int64_t enqueue_time_ms; | 72 int64_t enqueue_time_ms; |
63 size_t bytes; | 73 size_t bytes; |
(...skipping 28 matching lines...) Expand all Loading... |
92 : bytes_(0), | 102 : bytes_(0), |
93 clock_(clock), | 103 clock_(clock), |
94 queue_time_sum_(0), | 104 queue_time_sum_(0), |
95 time_last_updated_(clock_->TimeInMilliseconds()) {} | 105 time_last_updated_(clock_->TimeInMilliseconds()) {} |
96 virtual ~PacketQueue() {} | 106 virtual ~PacketQueue() {} |
97 | 107 |
98 void Push(const Packet& packet) { | 108 void Push(const Packet& packet) { |
99 if (!AddToDupeSet(packet)) | 109 if (!AddToDupeSet(packet)) |
100 return; | 110 return; |
101 | 111 |
102 UpdateQueueTime(packet.enqueue_time_ms); | 112 if (packet.enqueue_time_ms >= time_last_updated_) |
| 113 UpdateQueueTime(packet.enqueue_time_ms); |
103 | 114 |
104 // Store packet in list, use pointers in priority queue for cheaper moves. | 115 // Store packet in list, use pointers in priority queue for cheaper moves. |
105 // Packets have a handle to its own iterator in the list, for easy removal | 116 // Packets have a handle to its own iterator in the list, for easy removal |
106 // when popping from queue. | 117 // when popping from queue. |
107 packet_list_.push_front(packet); | 118 packet_list_.push_front(packet); |
108 std::list<Packet>::iterator it = packet_list_.begin(); | 119 std::list<Packet>::iterator it = packet_list_.begin(); |
| 120 if (packet.enqueue_time_ms < time_last_updated_) |
| 121 it->enqueue_time_ms = -1; |
109 it->this_it = it; // Handle for direct removal from list. | 122 it->this_it = it; // Handle for direct removal from list. |
110 prio_queue_.push(&(*it)); // Pointer into list. | 123 prio_queue_.push(&(*it)); // Pointer into list. |
111 bytes_ += packet.bytes; | 124 bytes_ += packet.bytes; |
112 } | 125 } |
113 | 126 |
114 const Packet& BeginPop() { | 127 const Packet& BeginPop() { |
115 const Packet& packet = *prio_queue_.top(); | 128 const Packet& packet = *prio_queue_.top(); |
116 prio_queue_.pop(); | 129 prio_queue_.pop(); |
117 return packet; | 130 return packet; |
118 } | 131 } |
119 | 132 |
120 void CancelPop(const Packet& packet) { prio_queue_.push(&(*packet.this_it)); } | 133 void CancelPop(const Packet& packet) { prio_queue_.push(&(*packet.this_it)); } |
121 | 134 |
122 void FinalizePop(const Packet& packet) { | 135 void FinalizePop(const Packet& packet) { |
123 RemoveFromDupeSet(packet); | 136 RemoveFromDupeSet(packet); |
124 bytes_ -= packet.bytes; | 137 bytes_ -= packet.bytes; |
125 queue_time_sum_ -= (time_last_updated_ - packet.enqueue_time_ms); | 138 if (packet.enqueue_time_ms != -1) |
| 139 queue_time_sum_ -= (time_last_updated_ - packet.enqueue_time_ms); |
126 packet_list_.erase(packet.this_it); | 140 packet_list_.erase(packet.this_it); |
127 RTC_DCHECK_EQ(packet_list_.size(), prio_queue_.size()); | 141 RTC_DCHECK_EQ(packet_list_.size(), prio_queue_.size()); |
128 if (packet_list_.empty()) | 142 if (packet_list_.empty()) |
129 RTC_DCHECK_EQ(0u, queue_time_sum_); | 143 RTC_DCHECK_EQ(0u, queue_time_sum_); |
130 } | 144 } |
131 | 145 |
132 bool Empty() const { return prio_queue_.empty(); } | 146 bool Empty() const { return prio_queue_.empty(); } |
133 | 147 |
134 size_t SizeInPackets() const { return prio_queue_.size(); } | 148 size_t SizeInPackets() const { return prio_queue_.size(); } |
135 | 149 |
136 uint64_t SizeInBytes() const { return bytes_; } | 150 uint64_t SizeInBytes() const { return bytes_; } |
137 | 151 |
138 int64_t OldestEnqueueTimeMs() const { | 152 int64_t OldestEnqueueTimeMs() const { |
139 auto it = packet_list_.rbegin(); | 153 for (auto it = packet_list_.rbegin(); it != packet_list_.rend(); ++it) { |
140 if (it == packet_list_.rend()) | 154 if (it->enqueue_time_ms != -1) |
141 return 0; | 155 return it->enqueue_time_ms; |
142 return it->enqueue_time_ms; | 156 } |
| 157 return 0; |
143 } | 158 } |
144 | 159 |
145 void UpdateQueueTime(int64_t timestamp_ms) { | 160 void UpdateQueueTime(int64_t timestamp_ms) { |
146 RTC_DCHECK_GE(timestamp_ms, time_last_updated_); | 161 // TODO(sprang): Remove this condition and reinstate a DCHECK once we have |
| 162 // made sure all clocks are monotonic. |
| 163 if (timestamp_ms < time_last_updated_) |
| 164 return; |
147 int64_t delta = timestamp_ms - time_last_updated_; | 165 int64_t delta = timestamp_ms - time_last_updated_; |
148 // Use packet packet_list_.size() not prio_queue_.size() here, as there | 166 // Use packet packet_list_.size() not prio_queue_.size() here, as there |
149 // might be an outstanding element popped from prio_queue_ currently in the | 167 // might be an outstanding element popped from prio_queue_ currently in the |
150 // SendPacket() call, while packet_list_ will always be correct. | 168 // SendPacket() call, while packet_list_ will always be correct. |
151 queue_time_sum_ += delta * packet_list_.size(); | 169 queue_time_sum_ += delta * packet_list_.size(); |
152 time_last_updated_ = timestamp_ms; | 170 time_last_updated_ = timestamp_ms; |
153 } | 171 } |
154 | 172 |
155 int64_t AverageQueueTimeMs() const { | 173 int64_t AverageQueueTimeMs() const { |
156 if (prio_queue_.empty()) | 174 if (prio_queue_.empty()) |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 media_budget_->UseBudget(bytes_sent); | 470 media_budget_->UseBudget(bytes_sent); |
453 padding_budget_->UseBudget(bytes_sent); | 471 padding_budget_->UseBudget(bytes_sent); |
454 } | 472 } |
455 } | 473 } |
456 | 474 |
457 void PacedSender::UpdateBytesPerInterval(int64_t delta_time_ms) { | 475 void PacedSender::UpdateBytesPerInterval(int64_t delta_time_ms) { |
458 media_budget_->IncreaseBudget(delta_time_ms); | 476 media_budget_->IncreaseBudget(delta_time_ms); |
459 padding_budget_->IncreaseBudget(delta_time_ms); | 477 padding_budget_->IncreaseBudget(delta_time_ms); |
460 } | 478 } |
461 } // namespace webrtc | 479 } // namespace webrtc |
OLD | NEW |