| 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 | 
|---|