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

Side by Side Diff: webrtc/modules/pacing/paced_sender.cc

Issue 2235373004: Probing: Add support for exponential startup probing (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@fix_probing2
Patch Set: Updates Created 4 years, 4 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
OLDNEW
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 14 matching lines...) Expand all
25 #include "webrtc/system_wrappers/include/field_trial.h" 25 #include "webrtc/system_wrappers/include/field_trial.h"
26 26
27 namespace { 27 namespace {
28 // Time limit in milliseconds between packet bursts. 28 // Time limit in milliseconds between packet bursts.
29 const int64_t kMinPacketLimitMs = 5; 29 const int64_t kMinPacketLimitMs = 5;
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 // Maximum waiting time from the time of sending first probe to getting
36 // the measured results back.
37 const int64_t kMaxTimeWaitingForProbingResultMs = 1000;
38
35 } // namespace 39 } // namespace
36 40
37 // TODO(sprang): Move at least PacketQueue and MediaBudget out to separate 41 // TODO(sprang): Move at least PacketQueue and MediaBudget out to separate
38 // files, so that we can more easily test them. 42 // files, so that we can more easily test them.
39 43
40 namespace webrtc { 44 namespace webrtc {
41 namespace paced_sender { 45 namespace paced_sender {
42 struct Packet { 46 struct Packet {
43 Packet(RtpPacketSender::Priority priority, 47 Packet(RtpPacketSender::Priority priority,
44 uint32_t ssrc, 48 uint32_t ssrc,
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 paused_(false), 256 paused_(false),
253 media_budget_(new paced_sender::IntervalBudget(0)), 257 media_budget_(new paced_sender::IntervalBudget(0)),
254 padding_budget_(new paced_sender::IntervalBudget(0)), 258 padding_budget_(new paced_sender::IntervalBudget(0)),
255 prober_(new BitrateProber()), 259 prober_(new BitrateProber()),
256 estimated_bitrate_bps_(0), 260 estimated_bitrate_bps_(0),
257 min_send_bitrate_kbps_(0u), 261 min_send_bitrate_kbps_(0u),
258 max_padding_bitrate_kbps_(0u), 262 max_padding_bitrate_kbps_(0u),
259 pacing_bitrate_kbps_(0), 263 pacing_bitrate_kbps_(0),
260 time_last_update_us_(clock->TimeInMicroseconds()), 264 time_last_update_us_(clock->TimeInMicroseconds()),
261 packets_(new paced_sender::PacketQueue(clock)), 265 packets_(new paced_sender::PacketQueue(clock)),
262 packet_counter_(0) { 266 packet_counter_(0),
267 pacing_state_(State::kInit) {
263 UpdateBytesPerInterval(kMinPacketLimitMs); 268 UpdateBytesPerInterval(kMinPacketLimitMs);
264 } 269 }
265 270
266 PacedSender::~PacedSender() {} 271 PacedSender::~PacedSender() {}
267 272
268 void PacedSender::Pause() { 273 void PacedSender::Pause() {
269 LOG(LS_INFO) << "PacedSender paused."; 274 LOG(LS_INFO) << "PacedSender paused.";
270 CriticalSectionScoped cs(critsect_.get()); 275 CriticalSectionScoped cs(critsect_.get());
271 paused_ = true; 276 paused_ = true;
272 } 277 }
273 278
274 void PacedSender::Resume() { 279 void PacedSender::Resume() {
275 LOG(LS_INFO) << "PacedSender resumed."; 280 LOG(LS_INFO) << "PacedSender resumed.";
276 CriticalSectionScoped cs(critsect_.get()); 281 CriticalSectionScoped cs(critsect_.get());
277 paused_ = false; 282 paused_ = false;
278 } 283 }
279 284
280 void PacedSender::SetProbingEnabled(bool enabled) { 285 void PacedSender::SetProbingEnabled(bool enabled) {
281 RTC_CHECK_EQ(0u, packet_counter_); 286 RTC_CHECK_EQ(0u, packet_counter_);
282 CriticalSectionScoped cs(critsect_.get()); 287 CriticalSectionScoped cs(critsect_.get());
283 prober_->SetEnabled(enabled); 288 prober_->SetEnabled(enabled);
284 } 289 }
285 290
286 void PacedSender::SetEstimatedBitrate(uint32_t bitrate_bps) { 291 void PacedSender::SetEstimatedBitrate(int bitrate_bps) {
287 if (bitrate_bps == 0) 292 if (bitrate_bps == 0)
288 LOG(LS_ERROR) << "PacedSender is not designed to handle 0 bitrate."; 293 LOG(LS_ERROR) << "PacedSender is not designed to handle 0 bitrate.";
289 CriticalSectionScoped cs(critsect_.get()); 294 CriticalSectionScoped cs(critsect_.get());
290 estimated_bitrate_bps_ = bitrate_bps; 295 estimated_bitrate_bps_ = bitrate_bps;
291 padding_budget_->set_target_rate_kbps( 296 padding_budget_->set_target_rate_kbps(
292 std::min(estimated_bitrate_bps_ / 1000, max_padding_bitrate_kbps_)); 297 std::min(estimated_bitrate_bps_ / 1000, max_padding_bitrate_kbps_));
293 pacing_bitrate_kbps_ = 298 pacing_bitrate_kbps_ =
294 std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000) * 299 std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000) *
295 kDefaultPaceMultiplier; 300 kDefaultPaceMultiplier;
296 } 301 }
(...skipping 14 matching lines...) Expand all
311 uint32_t ssrc, 316 uint32_t ssrc,
312 uint16_t sequence_number, 317 uint16_t sequence_number,
313 int64_t capture_time_ms, 318 int64_t capture_time_ms,
314 size_t bytes, 319 size_t bytes,
315 bool retransmission) { 320 bool retransmission) {
316 CriticalSectionScoped cs(critsect_.get()); 321 CriticalSectionScoped cs(critsect_.get());
317 RTC_DCHECK(estimated_bitrate_bps_ > 0) 322 RTC_DCHECK(estimated_bitrate_bps_ > 0)
318 << "SetEstimatedBitrate must be called before InsertPacket."; 323 << "SetEstimatedBitrate must be called before InsertPacket.";
319 324
320 int64_t now_ms = clock_->TimeInMilliseconds(); 325 int64_t now_ms = clock_->TimeInMilliseconds();
321 prober_->OnIncomingPacket(estimated_bitrate_bps_, bytes, now_ms); 326
327 if (bytes >= PacedSender::kMinProbePacketSize) {
328 switch (pacing_state_) {
329 case State::kInit: {
330 int multipliers[] = {3, 6};
331 if (!prober_->InitiateProbing(estimated_bitrate_bps_, multipliers, 2)) {
332 LOG(LS_ERROR) << "kInit: Failed to initiate probing";
333 pacing_state_ = State::kNormal;
334 } else {
335 LOG(LS_INFO) << "kInit: entering kWaitForProbingResult";
336 pacing_state_ = State::kWaitForProbingResult;
337 start_time_wait_probe_result_ms_ = clock_->TimeInMilliseconds();
338 // When probing at 1.8 Mbps, this represents a threshold of
339 // 1.2 Mbps to continue probing.
340 min_bitrate_to_probe_further_ = 4 * estimated_bitrate_bps_;
stefan-webrtc 2016/08/16 11:27:04 What is different between being here and in kStart
Irfan 2016/08/16 18:12:47 The multiplers are 3 and 6 on the very first time
341 }
342 } break;
343 case State::kStartupProbing: {
344 int multipliers[] = {2};
345 if (!prober_->InitiateProbing(estimated_bitrate_bps_, multipliers, 1)) {
346 LOG(LS_ERROR) << "kStartupProbing: Failed to initiate probing";
347 pacing_state_ = State::kNormal;
348 } else {
349 LOG(LS_INFO) << "kStartupProbing: entering kWaitForProbingResult";
350 // A minimum of 25% gain to continue.
351 pacing_state_ = State::kWaitForProbingResult;
352 start_time_wait_probe_result_ms_ = clock_->TimeInMilliseconds();
353 min_bitrate_to_probe_further_ = 1.25 * estimated_bitrate_bps_;
354 }
355 } break;
356 case State::kWaitForProbingResult:
357 if ((clock_->TimeInMilliseconds() - start_time_wait_probe_result_ms_) >
358 kMaxTimeWaitingForProbingResultMs) {
359 pacing_state_ = State::kNormal;
360 LOG(LS_INFO) << "kWaitForProbingResult: timeout";
361 }
362 break;
363 case State::kNormal:
364 LOG(LS_INFO) << "Probing complete... kNormal";
365 break;
366 default:
367 RTC_NOTREACHED();
368 }
369 }
stefan-webrtc 2016/08/16 11:27:04 Isn't this adding a lot of complexity to paced_sen
Irfan 2016/08/16 18:12:47 I will evaluate a way to simplify paced_sender and
322 370
323 if (capture_time_ms < 0) 371 if (capture_time_ms < 0)
324 capture_time_ms = now_ms; 372 capture_time_ms = now_ms;
325 373
326 packets_->Push(paced_sender::Packet(priority, ssrc, sequence_number, 374 packets_->Push(paced_sender::Packet(priority, ssrc, sequence_number,
327 capture_time_ms, now_ms, bytes, 375 capture_time_ms, now_ms, bytes,
328 retransmission, packet_counter_++)); 376 retransmission, packet_counter_++));
329 } 377 }
330 378
331 int64_t PacedSender::ExpectedQueueTimeMs() const { 379 int64_t PacedSender::ExpectedQueueTimeMs() const {
332 CriticalSectionScoped cs(critsect_.get()); 380 CriticalSectionScoped cs(critsect_.get());
333 RTC_DCHECK_GT(pacing_bitrate_kbps_, 0u); 381 RTC_DCHECK_GT(pacing_bitrate_kbps_, 0);
334 return static_cast<int64_t>(packets_->SizeInBytes() * 8 / 382 return static_cast<int64_t>(packets_->SizeInBytes() * 8 /
335 pacing_bitrate_kbps_); 383 pacing_bitrate_kbps_);
336 } 384 }
337 385
338 size_t PacedSender::QueueSizePackets() const { 386 size_t PacedSender::QueueSizePackets() const {
339 CriticalSectionScoped cs(critsect_.get()); 387 CriticalSectionScoped cs(critsect_.get());
340 return packets_->SizeInPackets(); 388 return packets_->SizeInPackets();
341 } 389 }
342 390
343 int64_t PacedSender::QueueInMs() const { 391 int64_t PacedSender::QueueInMs() const {
(...skipping 17 matching lines...) Expand all
361 if (prober_->IsProbing()) { 409 if (prober_->IsProbing()) {
362 int64_t ret = prober_->TimeUntilNextProbe(clock_->TimeInMilliseconds()); 410 int64_t ret = prober_->TimeUntilNextProbe(clock_->TimeInMilliseconds());
363 if (ret >= 0) 411 if (ret >= 0)
364 return ret; 412 return ret;
365 } 413 }
366 int64_t elapsed_time_us = clock_->TimeInMicroseconds() - time_last_update_us_; 414 int64_t elapsed_time_us = clock_->TimeInMicroseconds() - time_last_update_us_;
367 int64_t elapsed_time_ms = (elapsed_time_us + 500) / 1000; 415 int64_t elapsed_time_ms = (elapsed_time_us + 500) / 1000;
368 return std::max<int64_t>(kMinPacketLimitMs - elapsed_time_ms, 0); 416 return std::max<int64_t>(kMinPacketLimitMs - elapsed_time_ms, 0);
369 } 417 }
370 418
419 PacedSender::State PacedSender::PacingState() {
420 CriticalSectionScoped(critsect_.get());
421 return pacing_state_;
422 }
423
424 void PacedSender::OnProbingBitrateMeasured(int bitrate_bps) {
425 CriticalSectionScoped cs(critsect_.get());
426 if (pacing_state_ == State::kWaitForProbingResult) {
427 LOG(LS_INFO) << "kWaitForProbingResult OnProbingBitrateMeasured "
428 << bitrate_bps << " min_bitrate_to_probe_further_ "
429 << min_bitrate_to_probe_further_
430 << " bitrate_below_expected_count_ "
431 << bitrate_below_expected_count_;
432 if (bitrate_bps > min_bitrate_to_probe_further_) {
433 pacing_state_ = State::kStartupProbing;
434 }
435 if (bitrate_bps > estimated_bitrate_bps_)
436 estimated_bitrate_bps_ = bitrate_bps;
stefan-webrtc 2016/08/16 11:27:04 I'm not sure this is the right way to set this. It
Irfan 2016/08/16 18:12:47 This is a good point. The reason its happening her
437 } else {
438 LOG(LS_WARNING) << "OnProbingBitrateMeasured while not waiting on results";
stefan-webrtc 2016/08/16 11:27:04 Should we simply DCHECK on this?
Irfan 2016/08/16 18:12:47 Done.
439 }
440 }
stefan-webrtc 2016/08/16 11:27:04 To keep the pacer simpler, I think it would be nic
Irfan 2016/08/16 18:12:47 Right, will evaluate simplifiying pacer
441
371 void PacedSender::Process() { 442 void PacedSender::Process() {
372 int64_t now_us = clock_->TimeInMicroseconds(); 443 int64_t now_us = clock_->TimeInMicroseconds();
373 CriticalSectionScoped cs(critsect_.get()); 444 CriticalSectionScoped cs(critsect_.get());
374 int64_t elapsed_time_ms = (now_us - time_last_update_us_ + 500) / 1000; 445 int64_t elapsed_time_ms = (now_us - time_last_update_us_ + 500) / 1000;
375 time_last_update_us_ = now_us; 446 time_last_update_us_ = now_us;
376 int target_bitrate_kbps = pacing_bitrate_kbps_; 447 int target_bitrate_kbps = pacing_bitrate_kbps_;
377 // TODO(holmer): Remove the !paused_ check when issue 5307 has been fixed. 448 // TODO(holmer): Remove the !paused_ check when issue 5307 has been fixed.
378 if (!paused_ && elapsed_time_ms > 0) { 449 if (!paused_ && elapsed_time_ms > 0) {
379 size_t queue_size_bytes = packets_->SizeInBytes(); 450 size_t queue_size_bytes = packets_->SizeInBytes();
380 if (queue_size_bytes > 0) { 451 if (queue_size_bytes > 0) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 return false; 517 return false;
447 } 518 }
448 } 519 }
449 critsect_->Leave(); 520 critsect_->Leave();
450 const bool success = packet_sender_->TimeToSendPacket( 521 const bool success = packet_sender_->TimeToSendPacket(
451 packet.ssrc, packet.sequence_number, packet.capture_time_ms, 522 packet.ssrc, packet.sequence_number, packet.capture_time_ms,
452 packet.retransmission, probe_cluster_id); 523 packet.retransmission, probe_cluster_id);
453 critsect_->Enter(); 524 critsect_->Enter();
454 525
455 if (success) { 526 if (success) {
456 prober_->PacketSent(clock_->TimeInMilliseconds(), packet.bytes); 527 // Is this a probe ?
528 if (probe_cluster_id != PacketInfo::kNotAProbe) {
stefan-webrtc 2016/08/16 11:27:04 Why only notify about sent probe packets?
Irfan 2016/08/16 18:12:47 I clarified this in an earlier reply. Let me know
529 if (prober_->PacketSent(clock_->TimeInMilliseconds(), packet.bytes) ==
530 BitrateProber::State::kComplete) {
531 LOG(LS_INFO) << "Probe complete";
532 }
533 }
457 // TODO(holmer): High priority packets should only be accounted for if we 534 // TODO(holmer): High priority packets should only be accounted for if we
458 // are allocating bandwidth for audio. 535 // are allocating bandwidth for audio.
459 if (packet.priority != kHighPriority) { 536 if (packet.priority != kHighPriority) {
460 // Update media bytes sent. 537 // Update media bytes sent.
461 media_budget_->UseBudget(packet.bytes); 538 media_budget_->UseBudget(packet.bytes);
462 padding_budget_->UseBudget(packet.bytes); 539 padding_budget_->UseBudget(packet.bytes);
463 } 540 }
464 } 541 }
465 542
466 return success; 543 return success;
467 } 544 }
468 545
469 void PacedSender::SendPadding(size_t padding_needed, int probe_cluster_id) { 546 void PacedSender::SendPadding(size_t padding_needed, int probe_cluster_id) {
470 critsect_->Leave(); 547 critsect_->Leave();
471 size_t bytes_sent = 548 size_t bytes_sent =
472 packet_sender_->TimeToSendPadding(padding_needed, probe_cluster_id); 549 packet_sender_->TimeToSendPadding(padding_needed, probe_cluster_id);
473 critsect_->Enter(); 550 critsect_->Enter();
474 551
475 if (bytes_sent > 0) { 552 if (bytes_sent > 0) {
476 prober_->PacketSent(clock_->TimeInMilliseconds(), bytes_sent); 553 // Is this a probe ?
554 if (probe_cluster_id != PacketInfo::kNotAProbe) {
555 if (prober_->PacketSent(clock_->TimeInMilliseconds(), bytes_sent) ==
556 BitrateProber::State::kComplete) {
557 LOG(LS_INFO) << "Probe complete";
558 }
559 }
477 media_budget_->UseBudget(bytes_sent); 560 media_budget_->UseBudget(bytes_sent);
478 padding_budget_->UseBudget(bytes_sent); 561 padding_budget_->UseBudget(bytes_sent);
479 } 562 }
480 } 563 }
481 564
482 void PacedSender::UpdateBytesPerInterval(int64_t delta_time_ms) { 565 void PacedSender::UpdateBytesPerInterval(int64_t delta_time_ms) {
483 media_budget_->IncreaseBudget(delta_time_ms); 566 media_budget_->IncreaseBudget(delta_time_ms);
484 padding_budget_->IncreaseBudget(delta_time_ms); 567 padding_budget_->IncreaseBudget(delta_time_ms);
485 } 568 }
486 } // namespace webrtc 569 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698