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