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 |