Chromium Code Reviews| 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 14 matching lines...) Expand all Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |