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 11 matching lines...) Expand all Loading... |
22 #include "webrtc/modules/pacing/interval_budget.h" | 22 #include "webrtc/modules/pacing/interval_budget.h" |
23 #include "webrtc/modules/utility/include/process_thread.h" | 23 #include "webrtc/modules/utility/include/process_thread.h" |
24 #include "webrtc/rtc_base/checks.h" | 24 #include "webrtc/rtc_base/checks.h" |
25 #include "webrtc/rtc_base/logging.h" | 25 #include "webrtc/rtc_base/logging.h" |
26 #include "webrtc/system_wrappers/include/clock.h" | 26 #include "webrtc/system_wrappers/include/clock.h" |
27 #include "webrtc/system_wrappers/include/field_trial.h" | 27 #include "webrtc/system_wrappers/include/field_trial.h" |
28 | 28 |
29 namespace { | 29 namespace { |
30 // Time limit in milliseconds between packet bursts. | 30 // Time limit in milliseconds between packet bursts. |
31 const int64_t kMinPacketLimitMs = 5; | 31 const int64_t kMinPacketLimitMs = 5; |
32 const int64_t kPausedPacketIntervalMs = 500; | |
33 | 32 |
34 // Upper cap on process interval, in case process has not been called in a long | 33 // Upper cap on process interval, in case process has not been called in a long |
35 // time. | 34 // time. |
36 const int64_t kMaxIntervalTimeMs = 30; | 35 const int64_t kMaxIntervalTimeMs = 30; |
37 | 36 |
38 } // namespace | 37 } // namespace |
39 | 38 |
40 // TODO(sprang): Move at least PacketQueue out to separate | 39 // TODO(sprang): Move at least PacketQueue out to separate |
41 // files, so that we can more easily test them. | 40 // files, so that we can more easily test them. |
42 | 41 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 } | 232 } |
234 | 233 |
235 PacedSender::~PacedSender() {} | 234 PacedSender::~PacedSender() {} |
236 | 235 |
237 void PacedSender::CreateProbeCluster(int bitrate_bps) { | 236 void PacedSender::CreateProbeCluster(int bitrate_bps) { |
238 rtc::CritScope cs(&critsect_); | 237 rtc::CritScope cs(&critsect_); |
239 prober_->CreateProbeCluster(bitrate_bps, clock_->TimeInMilliseconds()); | 238 prober_->CreateProbeCluster(bitrate_bps, clock_->TimeInMilliseconds()); |
240 } | 239 } |
241 | 240 |
242 void PacedSender::Pause() { | 241 void PacedSender::Pause() { |
| 242 LOG(LS_INFO) << "PacedSender paused."; |
243 { | 243 { |
244 rtc::CritScope cs(&critsect_); | 244 rtc::CritScope cs(&critsect_); |
245 if (!paused_) | |
246 LOG(LS_INFO) << "PacedSender paused."; | |
247 paused_ = true; | 245 paused_ = true; |
248 } | 246 } |
249 // Tell the process thread to call our TimeUntilNextProcess() method to get | 247 // Tell the process thread to call our TimeUntilNextProcess() method to get |
250 // a new (longer) estimate for when to call Process(). | 248 // a new (longer) estimate for when to call Process(). |
251 if (process_thread_) | 249 if (process_thread_) |
252 process_thread_->WakeUp(this); | 250 process_thread_->WakeUp(this); |
253 } | 251 } |
254 | 252 |
255 void PacedSender::Resume() { | 253 void PacedSender::Resume() { |
| 254 LOG(LS_INFO) << "PacedSender resumed."; |
256 { | 255 { |
257 rtc::CritScope cs(&critsect_); | 256 rtc::CritScope cs(&critsect_); |
258 if (paused_) | |
259 LOG(LS_INFO) << "PacedSender resumed."; | |
260 paused_ = false; | 257 paused_ = false; |
261 } | 258 } |
262 // Tell the process thread to call our TimeUntilNextProcess() method to | 259 // Tell the process thread to call our TimeUntilNextProcess() method to |
263 // refresh the estimate for when to call Process(). | 260 // refresh the estimate for when to call Process(). |
264 if (process_thread_) | 261 if (process_thread_) |
265 process_thread_->WakeUp(this); | 262 process_thread_->WakeUp(this); |
266 } | 263 } |
267 | 264 |
268 void PacedSender::SetProbingEnabled(bool enabled) { | 265 void PacedSender::SetProbingEnabled(bool enabled) { |
269 RTC_CHECK_EQ(0, packet_counter_); | 266 RTC_CHECK_EQ(0, packet_counter_); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 } | 348 } |
352 | 349 |
353 int64_t PacedSender::AverageQueueTimeMs() { | 350 int64_t PacedSender::AverageQueueTimeMs() { |
354 rtc::CritScope cs(&critsect_); | 351 rtc::CritScope cs(&critsect_); |
355 packets_->UpdateQueueTime(clock_->TimeInMilliseconds()); | 352 packets_->UpdateQueueTime(clock_->TimeInMilliseconds()); |
356 return packets_->AverageQueueTimeMs(); | 353 return packets_->AverageQueueTimeMs(); |
357 } | 354 } |
358 | 355 |
359 int64_t PacedSender::TimeUntilNextProcess() { | 356 int64_t PacedSender::TimeUntilNextProcess() { |
360 rtc::CritScope cs(&critsect_); | 357 rtc::CritScope cs(&critsect_); |
361 int64_t elapsed_time_us = clock_->TimeInMicroseconds() - time_last_update_us_; | |
362 int64_t elapsed_time_ms = (elapsed_time_us + 500) / 1000; | |
363 // When paused we wake up every 500 ms to send a padding packet to ensure | |
364 // we won't get stuck in the paused state due to no feedback being received. | |
365 if (paused_) | 358 if (paused_) |
366 return std::max<int64_t>(kPausedPacketIntervalMs - elapsed_time_ms, 0); | 359 return 1000 * 60 * 60; |
367 | 360 |
368 if (prober_->IsProbing()) { | 361 if (prober_->IsProbing()) { |
369 int64_t ret = prober_->TimeUntilNextProbe(clock_->TimeInMilliseconds()); | 362 int64_t ret = prober_->TimeUntilNextProbe(clock_->TimeInMilliseconds()); |
370 if (ret > 0 || (ret == 0 && !probing_send_failure_)) | 363 if (ret > 0 || (ret == 0 && !probing_send_failure_)) |
371 return ret; | 364 return ret; |
372 } | 365 } |
| 366 int64_t elapsed_time_us = clock_->TimeInMicroseconds() - time_last_update_us_; |
| 367 int64_t elapsed_time_ms = (elapsed_time_us + 500) / 1000; |
373 return std::max<int64_t>(kMinPacketLimitMs - elapsed_time_ms, 0); | 368 return std::max<int64_t>(kMinPacketLimitMs - elapsed_time_ms, 0); |
374 } | 369 } |
375 | 370 |
376 void PacedSender::Process() { | 371 void PacedSender::Process() { |
377 int64_t now_us = clock_->TimeInMicroseconds(); | 372 int64_t now_us = clock_->TimeInMicroseconds(); |
378 rtc::CritScope cs(&critsect_); | 373 rtc::CritScope cs(&critsect_); |
379 int64_t elapsed_time_ms = (now_us - time_last_update_us_ + 500) / 1000; | 374 int64_t elapsed_time_ms = (now_us - time_last_update_us_ + 500) / 1000; |
| 375 time_last_update_us_ = now_us; |
380 int target_bitrate_kbps = pacing_bitrate_kbps_; | 376 int target_bitrate_kbps = pacing_bitrate_kbps_; |
381 | 377 if (!paused_ && elapsed_time_ms > 0) { |
382 if (paused_) { | |
383 PacedPacketInfo pacing_info; | |
384 time_last_update_us_ = now_us; | |
385 // We can not send padding unless a normal packet has first been sent. If we | |
386 // do, timestamps get messed up. | |
387 if (packet_counter_ == 0) | |
388 return; | |
389 size_t bytes_sent = SendPadding(1, pacing_info); | |
390 alr_detector_->OnBytesSent(bytes_sent, now_us / 1000); | |
391 return; | |
392 } | |
393 | |
394 if (elapsed_time_ms > 0) { | |
395 size_t queue_size_bytes = packets_->SizeInBytes(); | 378 size_t queue_size_bytes = packets_->SizeInBytes(); |
396 if (queue_size_bytes > 0) { | 379 if (queue_size_bytes > 0) { |
397 // Assuming equal size packets and input/output rate, the average packet | 380 // Assuming equal size packets and input/output rate, the average packet |
398 // has avg_time_left_ms left to get queue_size_bytes out of the queue, if | 381 // has avg_time_left_ms left to get queue_size_bytes out of the queue, if |
399 // time constraint shall be met. Determine bitrate needed for that. | 382 // time constraint shall be met. Determine bitrate needed for that. |
400 packets_->UpdateQueueTime(clock_->TimeInMilliseconds()); | 383 packets_->UpdateQueueTime(clock_->TimeInMilliseconds()); |
401 int64_t avg_time_left_ms = std::max<int64_t>( | 384 int64_t avg_time_left_ms = std::max<int64_t>( |
402 1, queue_time_limit - packets_->AverageQueueTimeMs()); | 385 1, queue_time_limit - packets_->AverageQueueTimeMs()); |
403 int min_bitrate_needed_kbps = | 386 int min_bitrate_needed_kbps = |
404 static_cast<int>(queue_size_bytes * 8 / avg_time_left_ms); | 387 static_cast<int>(queue_size_bytes * 8 / avg_time_left_ms); |
405 if (min_bitrate_needed_kbps > target_bitrate_kbps) | 388 if (min_bitrate_needed_kbps > target_bitrate_kbps) |
406 target_bitrate_kbps = min_bitrate_needed_kbps; | 389 target_bitrate_kbps = min_bitrate_needed_kbps; |
407 } | 390 } |
408 | 391 |
409 media_budget_->set_target_rate_kbps(target_bitrate_kbps); | 392 media_budget_->set_target_rate_kbps(target_bitrate_kbps); |
410 | 393 |
411 elapsed_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms); | 394 elapsed_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms); |
412 UpdateBudgetWithElapsedTime(elapsed_time_ms); | 395 UpdateBudgetWithElapsedTime(elapsed_time_ms); |
413 } | 396 } |
414 | 397 |
415 time_last_update_us_ = now_us; | |
416 | |
417 bool is_probing = prober_->IsProbing(); | 398 bool is_probing = prober_->IsProbing(); |
418 PacedPacketInfo pacing_info; | 399 PacedPacketInfo pacing_info; |
419 size_t bytes_sent = 0; | 400 size_t bytes_sent = 0; |
420 size_t recommended_probe_size = 0; | 401 size_t recommended_probe_size = 0; |
421 if (is_probing) { | 402 if (is_probing) { |
422 pacing_info = prober_->CurrentCluster(); | 403 pacing_info = prober_->CurrentCluster(); |
423 recommended_probe_size = prober_->RecommendedMinProbeSize(); | 404 recommended_probe_size = prober_->RecommendedMinProbeSize(); |
424 } | 405 } |
425 while (!packets_->Empty()) { | 406 while (!packets_->Empty()) { |
426 // Since we need to release the lock in order to send, we first pop the | 407 // Since we need to release the lock in order to send, we first pop the |
427 // element from the priority queue but keep it in storage, so that we can | 408 // element from the priority queue but keep it in storage, so that we can |
428 // reinsert it if send fails. | 409 // reinsert it if send fails. |
429 const paced_sender::Packet& packet = packets_->BeginPop(); | 410 const paced_sender::Packet& packet = packets_->BeginPop(); |
430 | 411 |
431 if (SendPacket(packet, pacing_info)) { | 412 if (SendPacket(packet, pacing_info)) { |
432 // Send succeeded, remove it from the queue. | 413 // Send succeeded, remove it from the queue. |
433 if (first_sent_packet_ms_ == -1) | 414 if (first_sent_packet_ms_ == -1) |
434 first_sent_packet_ms_ = clock_->TimeInMilliseconds(); | 415 first_sent_packet_ms_ = clock_->TimeInMilliseconds(); |
435 bytes_sent += packet.bytes; | 416 bytes_sent += packet.bytes; |
436 packets_->FinalizePop(packet); | 417 packets_->FinalizePop(packet); |
437 if (is_probing && bytes_sent > recommended_probe_size) | 418 if (is_probing && bytes_sent > recommended_probe_size) |
438 break; | 419 break; |
439 } else { | 420 } else { |
440 // Send failed, put it back into the queue. | 421 // Send failed, put it back into the queue. |
441 packets_->CancelPop(packet); | 422 packets_->CancelPop(packet); |
442 break; | 423 break; |
443 } | 424 } |
444 } | 425 } |
445 | 426 |
446 if (packets_->Empty()) { | 427 if (packets_->Empty() && !paused_) { |
447 // We can not send padding unless a normal packet has first been sent. If we | 428 // We can not send padding unless a normal packet has first been sent. If we |
448 // do, timestamps get messed up. | 429 // do, timestamps get messed up. |
449 if (packet_counter_ > 0) { | 430 if (packet_counter_ > 0) { |
450 int padding_needed = | 431 int padding_needed = |
451 static_cast<int>(is_probing ? (recommended_probe_size - bytes_sent) | 432 static_cast<int>(is_probing ? (recommended_probe_size - bytes_sent) |
452 : padding_budget_->bytes_remaining()); | 433 : padding_budget_->bytes_remaining()); |
| 434 |
453 if (padding_needed > 0) | 435 if (padding_needed > 0) |
454 bytes_sent += SendPadding(padding_needed, pacing_info); | 436 bytes_sent += SendPadding(padding_needed, pacing_info); |
455 } | 437 } |
456 } | 438 } |
457 if (is_probing) { | 439 if (is_probing) { |
458 probing_send_failure_ = bytes_sent == 0; | 440 probing_send_failure_ = bytes_sent == 0; |
459 if (!probing_send_failure_) | 441 if (!probing_send_failure_) |
460 prober_->ProbeSent(clock_->TimeInMilliseconds(), bytes_sent); | 442 prober_->ProbeSent(clock_->TimeInMilliseconds(), bytes_sent); |
461 } | 443 } |
462 alr_detector_->OnBytesSent(bytes_sent, elapsed_time_ms); | 444 alr_detector_->OnBytesSent(bytes_sent, elapsed_time_ms); |
463 } | 445 } |
464 | 446 |
465 void PacedSender::ProcessThreadAttached(ProcessThread* process_thread) { | 447 void PacedSender::ProcessThreadAttached(ProcessThread* process_thread) { |
466 LOG(LS_INFO) << "ProcessThreadAttached 0x" << std::hex << process_thread; | 448 LOG(LS_INFO) << "ProcessThreadAttached 0x" << std::hex << process_thread; |
467 process_thread_ = process_thread; | 449 process_thread_ = process_thread; |
468 } | 450 } |
469 | 451 |
470 bool PacedSender::SendPacket(const paced_sender::Packet& packet, | 452 bool PacedSender::SendPacket(const paced_sender::Packet& packet, |
471 const PacedPacketInfo& pacing_info) { | 453 const PacedPacketInfo& pacing_info) { |
472 RTC_DCHECK(!paused_); | 454 if (paused_) |
| 455 return false; |
473 if (media_budget_->bytes_remaining() == 0 && | 456 if (media_budget_->bytes_remaining() == 0 && |
474 pacing_info.probe_cluster_id == PacedPacketInfo::kNotAProbe) { | 457 pacing_info.probe_cluster_id == PacedPacketInfo::kNotAProbe) { |
475 return false; | 458 return false; |
476 } | 459 } |
477 | 460 |
478 critsect_.Leave(); | 461 critsect_.Leave(); |
479 const bool success = packet_sender_->TimeToSendPacket( | 462 const bool success = packet_sender_->TimeToSendPacket( |
480 packet.ssrc, packet.sequence_number, packet.capture_time_ms, | 463 packet.ssrc, packet.sequence_number, packet.capture_time_ms, |
481 packet.retransmission, pacing_info); | 464 packet.retransmission, pacing_info); |
482 critsect_.Enter(); | 465 critsect_.Enter(); |
483 | 466 |
484 if (success) { | 467 if (success) { |
485 // TODO(holmer): High priority packets should only be accounted for if we | 468 // TODO(holmer): High priority packets should only be accounted for if we |
486 // are allocating bandwidth for audio. | 469 // are allocating bandwidth for audio. |
487 if (packet.priority != kHighPriority) { | 470 if (packet.priority != kHighPriority) { |
488 // Update media bytes sent. | 471 // Update media bytes sent. |
489 // TODO(eladalon): TimeToSendPacket() can also return |true| in some | 472 // TODO(eladalon): TimeToSendPacket() can also return |true| in some |
490 // situations where nothing actually ended up being sent to the network, | 473 // situations where nothing actually ended up being sent to the network, |
491 // and we probably don't want to update the budget in such cases. | 474 // and we probably don't want to update the budget in such cases. |
492 // https://bugs.chromium.org/p/webrtc/issues/detail?id=8052 | 475 // https://bugs.chromium.org/p/webrtc/issues/detail?id=8052 |
493 UpdateBudgetWithBytesSent(packet.bytes); | 476 UpdateBudgetWithBytesSent(packet.bytes); |
494 } | 477 } |
495 } | 478 } |
496 | 479 |
497 return success; | 480 return success; |
498 } | 481 } |
499 | 482 |
500 size_t PacedSender::SendPadding(size_t padding_needed, | 483 size_t PacedSender::SendPadding(size_t padding_needed, |
501 const PacedPacketInfo& pacing_info) { | 484 const PacedPacketInfo& pacing_info) { |
502 RTC_DCHECK_GT(packet_counter_, 0); | |
503 critsect_.Leave(); | 485 critsect_.Leave(); |
504 size_t bytes_sent = | 486 size_t bytes_sent = |
505 packet_sender_->TimeToSendPadding(padding_needed, pacing_info); | 487 packet_sender_->TimeToSendPadding(padding_needed, pacing_info); |
506 critsect_.Enter(); | 488 critsect_.Enter(); |
507 | 489 |
508 if (bytes_sent > 0) { | 490 if (bytes_sent > 0) { |
509 UpdateBudgetWithBytesSent(bytes_sent); | 491 UpdateBudgetWithBytesSent(bytes_sent); |
510 } | 492 } |
511 return bytes_sent; | 493 return bytes_sent; |
512 } | 494 } |
(...skipping 12 matching lines...) Expand all Loading... |
525 rtc::CritScope cs(&critsect_); | 507 rtc::CritScope cs(&critsect_); |
526 pacing_factor_ = pacing_factor; | 508 pacing_factor_ = pacing_factor; |
527 } | 509 } |
528 | 510 |
529 void PacedSender::SetQueueTimeLimit(int limit_ms) { | 511 void PacedSender::SetQueueTimeLimit(int limit_ms) { |
530 rtc::CritScope cs(&critsect_); | 512 rtc::CritScope cs(&critsect_); |
531 queue_time_limit = limit_ms; | 513 queue_time_limit = limit_ms; |
532 } | 514 } |
533 | 515 |
534 } // namespace webrtc | 516 } // namespace webrtc |
OLD | NEW |