Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: media/cast/net/pacing/paced_sender.cc

Issue 539323002: [Cast] Sanity-check for unbounded queue growth in PacedSender. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: No packet dropping. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/cast/net/pacing/paced_sender.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « media/cast/net/pacing/paced_sender.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698