OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/net/pacing/paced_sender.h" | 5 #include "media/cast/net/pacing/paced_sender.h" |
6 | 6 |
7 #include "base/big_endian.h" | 7 #include "base/big_endian.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/debug/dump_without_crashing.h" |
9 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
10 #include "media/cast/logging/logging_impl.h" | 11 #include "media/cast/logging/logging_impl.h" |
11 | 12 |
12 namespace media { | 13 namespace media { |
13 namespace cast { | 14 namespace cast { |
14 | 15 |
15 namespace { | 16 namespace { |
16 | 17 |
17 static const int64 kPacingIntervalMs = 10; | 18 static const int64 kPacingIntervalMs = 10; |
18 // Each frame will be split into no more than kPacingMaxBurstsPerFrame | 19 // Each frame will be split into no more than kPacingMaxBurstsPerFrame |
19 // bursts of packets. | 20 // bursts of packets. |
20 static const size_t kPacingMaxBurstsPerFrame = 3; | 21 static const size_t kPacingMaxBurstsPerFrame = 3; |
21 static const size_t kMaxDedupeWindowMs = 500; | 22 static const size_t kMaxDedupeWindowMs = 500; |
22 | 23 |
| 24 // "Impossible" upper-bound on the maximum number of packets that should ever be |
| 25 // enqueued in the pacer. This is used to detect bugs, reported as crash dumps. |
| 26 static const size_t kHugeQueueLengthSeconds = 10; |
| 27 static const size_t kRidiculousNumberOfPackets = |
| 28 kHugeQueueLengthSeconds * (kMaxBurstSize * 1000 / kPacingIntervalMs); |
| 29 |
23 } // namespace | 30 } // namespace |
24 | 31 |
25 DedupInfo::DedupInfo() : last_byte_acked_for_audio(0) {} | 32 DedupInfo::DedupInfo() : last_byte_acked_for_audio(0) {} |
26 | 33 |
27 // static | 34 // static |
28 PacketKey PacedPacketSender::MakePacketKey(const base::TimeTicks& ticks, | 35 PacketKey PacedPacketSender::MakePacketKey(const base::TimeTicks& ticks, |
29 uint32 ssrc, | 36 uint32 ssrc, |
30 uint16 packet_id) { | 37 uint16 packet_id) { |
31 return std::make_pair(ticks, std::make_pair(ssrc, packet_id)); | 38 return std::make_pair(ticks, std::make_pair(ssrc, packet_id)); |
32 } | 39 } |
(...skipping 14 matching lines...) Expand all Loading... |
47 transport_task_runner_(transport_task_runner), | 54 transport_task_runner_(transport_task_runner), |
48 audio_ssrc_(0), | 55 audio_ssrc_(0), |
49 video_ssrc_(0), | 56 video_ssrc_(0), |
50 target_burst_size_(target_burst_size), | 57 target_burst_size_(target_burst_size), |
51 max_burst_size_(max_burst_size), | 58 max_burst_size_(max_burst_size), |
52 current_max_burst_size_(target_burst_size_), | 59 current_max_burst_size_(target_burst_size_), |
53 next_max_burst_size_(target_burst_size_), | 60 next_max_burst_size_(target_burst_size_), |
54 next_next_max_burst_size_(target_burst_size_), | 61 next_next_max_burst_size_(target_burst_size_), |
55 current_burst_size_(0), | 62 current_burst_size_(0), |
56 state_(State_Unblocked), | 63 state_(State_Unblocked), |
| 64 has_reached_upper_bound_once_(false), |
57 weak_factory_(this) { | 65 weak_factory_(this) { |
58 } | 66 } |
59 | 67 |
60 PacedSender::~PacedSender() {} | 68 PacedSender::~PacedSender() {} |
61 | 69 |
62 void PacedSender::RegisterAudioSsrc(uint32 audio_ssrc) { | 70 void PacedSender::RegisterAudioSsrc(uint32 audio_ssrc) { |
63 audio_ssrc_ = audio_ssrc; | 71 audio_ssrc_ = audio_ssrc; |
64 } | 72 } |
65 | 73 |
66 void PacedSender::RegisterVideoSsrc(uint32 video_ssrc) { | 74 void PacedSender::RegisterVideoSsrc(uint32 video_ssrc) { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 // let us know that it's ok to send again. | 223 // let us know that it's ok to send again. |
216 // 3. state_ == State_BurstFull and there are still packets to send. In this | 224 // 3. state_ == State_BurstFull and there are still packets to send. In this |
217 // case we called PostDelayedTask on this function to start a new burst. | 225 // case we called PostDelayedTask on this function to start a new burst. |
218 void PacedSender::SendStoredPackets() { | 226 void PacedSender::SendStoredPackets() { |
219 State previous_state = state_; | 227 State previous_state = state_; |
220 state_ = State_Unblocked; | 228 state_ = State_Unblocked; |
221 if (empty()) { | 229 if (empty()) { |
222 return; | 230 return; |
223 } | 231 } |
224 | 232 |
| 233 // If the queue ever becomes impossibly long, send a crash dump without |
| 234 // actually crashing the process. |
| 235 if (size() > kRidiculousNumberOfPackets && !has_reached_upper_bound_once_) { |
| 236 NOTREACHED(); |
| 237 // Please use Cr=Internals-Cast label in bug reports: |
| 238 base::debug::DumpWithoutCrashing(); |
| 239 has_reached_upper_bound_once_ = true; |
| 240 } |
| 241 |
225 base::TimeTicks now = clock_->NowTicks(); | 242 base::TimeTicks now = clock_->NowTicks(); |
226 // I don't actually trust that PostDelayTask(x - now) will mean that | 243 // I don't actually trust that PostDelayTask(x - now) will mean that |
227 // now >= x when the call happens, so check if the previous state was | 244 // now >= x when the call happens, so check if the previous state was |
228 // State_BurstFull too. | 245 // State_BurstFull too. |
229 if (now >= burst_end_ || previous_state == State_BurstFull) { | 246 if (now >= burst_end_ || previous_state == State_BurstFull) { |
230 // Start a new burst. | 247 // Start a new burst. |
231 current_burst_size_ = 0; | 248 current_burst_size_ = 0; |
232 burst_end_ = now + base::TimeDelta::FromMilliseconds(kPacingIntervalMs); | 249 burst_end_ = now + base::TimeDelta::FromMilliseconds(kPacingIntervalMs); |
233 | 250 |
234 // The goal here is to try to send out the queued packets over the next | 251 // The goal here is to try to send out the queued packets over the next |
235 // three bursts, while trying to keep the burst size below 10 if possible. | 252 // three bursts, while trying to keep the burst size below 10 if possible. |
236 // We have some evidence that sending more than 12 packets in a row doesn't | 253 // We have some evidence that sending more than 12 packets in a row doesn't |
237 // work very well, but we don't actually know why yet. Sending out packets | 254 // work very well, but we don't actually know why yet. Sending out packets |
238 // sooner is better than sending out packets later as that gives us more | 255 // sooner is better than sending out packets later as that gives us more |
239 // time to re-send them if needed. So if we have less than 30 packets, just | 256 // time to re-send them if needed. So if we have less than 30 packets, just |
240 // send 10 at a time. If we have less than 60 packets, send n / 3 at a time. | 257 // send 10 at a time. If we have less than 60 packets, send n / 3 at a time. |
241 // if we have more than 60, we send 20 at a time. 20 packets is ~24Mbit/s | 258 // if we have more than 60, we send 20 at a time. 20 packets is ~24Mbit/s |
242 // which is more bandwidth than the cast library should need, and sending | 259 // which is more bandwidth than the cast library should need, and sending |
243 // out more data per second is unlikely to be helpful. | 260 // out more data per second is unlikely to be helpful. |
244 size_t max_burst_size = std::min( | 261 size_t max_burst_size = std::min( |
245 max_burst_size_, | 262 max_burst_size_, |
246 std::max(target_burst_size_, size() / kPacingMaxBurstsPerFrame)); | 263 std::max(target_burst_size_, size() / kPacingMaxBurstsPerFrame)); |
247 | |
248 // If the queue is long, issue a warning. Try to limit the number of | |
249 // warnings issued by only issuing the warning when the burst size | |
250 // grows. Otherwise we might get 100 warnings per second. | |
251 if (max_burst_size > next_next_max_burst_size_ && size() > 100) { | |
252 LOG(WARNING) << "Packet queue is very long:" << size(); | |
253 } | |
254 | |
255 current_max_burst_size_ = std::max(next_max_burst_size_, max_burst_size); | 264 current_max_burst_size_ = std::max(next_max_burst_size_, max_burst_size); |
256 next_max_burst_size_ = std::max(next_next_max_burst_size_, max_burst_size); | 265 next_max_burst_size_ = std::max(next_next_max_burst_size_, max_burst_size); |
257 next_next_max_burst_size_ = max_burst_size; | 266 next_next_max_burst_size_ = max_burst_size; |
258 } | 267 } |
259 | 268 |
260 base::Closure cb = base::Bind(&PacedSender::SendStoredPackets, | 269 base::Closure cb = base::Bind(&PacedSender::SendStoredPackets, |
261 weak_factory_.GetWeakPtr()); | 270 weak_factory_.GetWeakPtr()); |
262 while (!empty()) { | 271 while (!empty()) { |
263 if (current_burst_size_ >= current_max_burst_size_) { | 272 if (current_burst_size_ >= current_max_burst_size_) { |
264 transport_task_runner_->PostDelayedTask(FROM_HERE, | 273 transport_task_runner_->PostDelayedTask(FROM_HERE, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 return; | 338 return; |
330 } | 339 } |
331 | 340 |
332 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; | 341 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; |
333 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, | 342 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, |
334 packet); | 343 packet); |
335 } | 344 } |
336 | 345 |
337 } // namespace cast | 346 } // namespace cast |
338 } // namespace media | 347 } // namespace media |
OLD | NEW |