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

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_sender.cc

Issue 2007743003: Add sender controlled playout delay limits (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@cleanup_rtp_hdr_extensions
Patch Set: Removed audio changes and added locking on playout delay oracle Created 4 years, 6 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
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" 11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
12 12
13 #include <stdlib.h> // srand 13 #include <stdlib.h> // srand
14 #include <algorithm> 14 #include <algorithm>
15 #include <utility> 15 #include <utility>
16 16
17 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
18 #include "webrtc/base/logging.h" 18 #include "webrtc/base/logging.h"
19 #include "webrtc/base/trace_event.h" 19 #include "webrtc/base/trace_event.h"
20 #include "webrtc/base/timeutils.h" 20 #include "webrtc/base/timeutils.h"
21 #include "webrtc/call.h" 21 #include "webrtc/call.h"
22 #include "webrtc/call/rtc_event_log.h" 22 #include "webrtc/call/rtc_event_log.h"
23 #include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" 23 #include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
24 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 24 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
25 #include "webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h"
25 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" 26 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h"
26 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" 27 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
27 #include "webrtc/modules/rtp_rtcp/source/time_util.h" 28 #include "webrtc/modules/rtp_rtcp/source/time_util.h"
28 29
29 namespace webrtc { 30 namespace webrtc {
30 31
31 // Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP. 32 // Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
32 static const size_t kMaxPaddingLength = 224; 33 static const size_t kMaxPaddingLength = 224;
33 static const int kSendSideDelayWindowMs = 1000; 34 static const int kSendSideDelayWindowMs = 1000;
34 static const uint32_t kAbsSendTimeFraction = 18; 35 static const uint32_t kAbsSendTimeFraction = 18;
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 485
485 int32_t RTPSender::SendOutgoingData(FrameType frame_type, 486 int32_t RTPSender::SendOutgoingData(FrameType frame_type,
486 int8_t payload_type, 487 int8_t payload_type,
487 uint32_t capture_timestamp, 488 uint32_t capture_timestamp,
488 int64_t capture_time_ms, 489 int64_t capture_time_ms,
489 const uint8_t* payload_data, 490 const uint8_t* payload_data,
490 size_t payload_size, 491 size_t payload_size,
491 const RTPFragmentationHeader* fragmentation, 492 const RTPFragmentationHeader* fragmentation,
492 const RTPVideoHeader* rtp_hdr) { 493 const RTPVideoHeader* rtp_hdr) {
493 uint32_t ssrc; 494 uint32_t ssrc;
495 uint16_t sequence_number;
494 { 496 {
495 // Drop this packet if we're not sending media packets. 497 // Drop this packet if we're not sending media packets.
496 rtc::CritScope lock(&send_critsect_); 498 rtc::CritScope lock(&send_critsect_);
497 ssrc = ssrc_; 499 ssrc = ssrc_;
500 sequence_number = sequence_number_;
498 if (!sending_media_) { 501 if (!sending_media_) {
499 return 0; 502 return 0;
500 } 503 }
501 } 504 }
502 RtpVideoCodecTypes video_type = kRtpVideoGeneric; 505 RtpVideoCodecTypes video_type = kRtpVideoGeneric;
503 if (CheckPayloadType(payload_type, &video_type) != 0) { 506 if (CheckPayloadType(payload_type, &video_type) != 0) {
504 LOG(LS_ERROR) << "Don't send data with unknown payload type: " 507 LOG(LS_ERROR) << "Don't send data with unknown payload type: "
505 << static_cast<int>(payload_type) << "."; 508 << static_cast<int>(payload_type) << ".";
506 return -1; 509 return -1;
507 } 510 }
508 511
509 int32_t ret_val; 512 int32_t ret_val;
510 if (audio_configured_) { 513 if (audio_configured_) {
511 TRACE_EVENT_ASYNC_STEP1("webrtc", "Audio", capture_timestamp, 514 TRACE_EVENT_ASYNC_STEP1("webrtc", "Audio", capture_timestamp,
512 "Send", "type", FrameTypeToString(frame_type)); 515 "Send", "type", FrameTypeToString(frame_type));
513 assert(frame_type == kAudioFrameSpeech || frame_type == kAudioFrameCN || 516 assert(frame_type == kAudioFrameSpeech || frame_type == kAudioFrameCN ||
514 frame_type == kEmptyFrame); 517 frame_type == kEmptyFrame);
515 518
516 ret_val = audio_->SendAudio(frame_type, payload_type, capture_timestamp, 519 ret_val = audio_->SendAudio(frame_type, payload_type, capture_timestamp,
517 payload_data, payload_size, fragmentation); 520 payload_data, payload_size, fragmentation);
518 } else { 521 } else {
519 TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", capture_time_ms, 522 TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", capture_time_ms,
520 "Send", "type", FrameTypeToString(frame_type)); 523 "Send", "type", FrameTypeToString(frame_type));
521 assert(frame_type != kAudioFrameSpeech && frame_type != kAudioFrameCN); 524 assert(frame_type != kAudioFrameSpeech && frame_type != kAudioFrameCN);
522 525
523 if (frame_type == kEmptyFrame) 526 if (frame_type == kEmptyFrame)
524 return 0; 527 return 0;
525 528
526 ret_val = 529 if (rtp_hdr)
stefan-webrtc 2016/05/28 05:01:44 Add {} since this is a multi-line if (>2 lines).
Irfan 2016/06/01 08:38:33 Done.
527 video_->SendVideo(video_type, frame_type, payload_type, 530 playout_delay_oracle_.UpdateRequest(ssrc, rtp_hdr->playout_delay,
528 capture_timestamp, capture_time_ms, payload_data, 531 sequence_number);
529 payload_size, fragmentation, rtp_hdr); 532
533 ret_val = video_->SendVideo(
534 video_type, frame_type, payload_type, capture_timestamp,
535 capture_time_ms, payload_data, payload_size, fragmentation, rtp_hdr);
530 } 536 }
531 537
532 rtc::CritScope cs(&statistics_crit_); 538 rtc::CritScope cs(&statistics_crit_);
533 // Note: This is currently only counting for video. 539 // Note: This is currently only counting for video.
534 if (frame_type == kVideoFrameKey) { 540 if (frame_type == kVideoFrameKey) {
535 ++frame_counts_.key_frames; 541 ++frame_counts_.key_frames;
536 } else if (frame_type == kVideoFrameDelta) { 542 } else if (frame_type == kVideoFrameDelta) {
537 ++frame_counts_.delta_frames; 543 ++frame_counts_.delta_frames;
538 } 544 }
539 if (frame_count_observer_) { 545 if (frame_count_observer_) {
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 if (bytes_re_sent > target_bytes) { 820 if (bytes_re_sent > target_bytes) {
815 break; // Ignore the rest of the packets in the list. 821 break; // Ignore the rest of the packets in the list.
816 } 822 }
817 } 823 }
818 } 824 }
819 if (bytes_re_sent > 0) { 825 if (bytes_re_sent > 0) {
820 UpdateNACKBitRate(bytes_re_sent, now); 826 UpdateNACKBitRate(bytes_re_sent, now);
821 } 827 }
822 } 828 }
823 829
830 void RTPSender::OnReceivedRtcpReceiverReport(
831 const ReportBlockList& report_blocks) {
832 rtc::CritScope lock(&send_critsect_);
stefan-webrtc 2016/05/28 05:01:44 Do you really have to lock this? Had you not alrea
Irfan 2016/06/01 08:38:33 Good catch. Fixed.
833 playout_delay_oracle_.OnReceivedRtcpReceiverReport(report_blocks);
834 }
835
824 bool RTPSender::ProcessNACKBitRate(uint32_t now) { 836 bool RTPSender::ProcessNACKBitRate(uint32_t now) {
825 uint32_t num = 0; 837 uint32_t num = 0;
826 size_t byte_count = 0; 838 size_t byte_count = 0;
827 const uint32_t kAvgIntervalMs = 1000; 839 const uint32_t kAvgIntervalMs = 1000;
828 uint32_t target_bitrate = GetTargetBitrate(); 840 uint32_t target_bitrate = GetTargetBitrate();
829 841
830 rtc::CritScope lock(&send_critsect_); 842 rtc::CritScope lock(&send_critsect_);
831 843
832 if (target_bitrate == 0) { 844 if (target_bitrate == 0) {
833 return true; 845 return true;
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 // |capture_time_ms| <= 0 is considered invalid. 1039 // |capture_time_ms| <= 0 is considered invalid.
1028 // TODO(holmer): This should be changed all over Video Engine so that negative 1040 // TODO(holmer): This should be changed all over Video Engine so that negative
1029 // time is consider invalid, while 0 is considered a valid time. 1041 // time is consider invalid, while 0 is considered a valid time.
1030 if (capture_time_ms > 0) { 1042 if (capture_time_ms > 0) {
1031 UpdateTransmissionTimeOffset(buffer, length, rtp_header, 1043 UpdateTransmissionTimeOffset(buffer, length, rtp_header,
1032 now_ms - capture_time_ms); 1044 now_ms - capture_time_ms);
1033 } 1045 }
1034 1046
1035 UpdateAbsoluteSendTime(buffer, length, rtp_header, now_ms); 1047 UpdateAbsoluteSendTime(buffer, length, rtp_header, now_ms);
1036 1048
1049 if (playout_delay_oracle_.send_playout_delay())
stefan-webrtc 2016/05/28 05:01:44 {}
Irfan 2016/06/01 08:38:33 Done.
1050 UpdatePlayoutDelayLimits(buffer, length, rtp_header,
1051 playout_delay_oracle_.min_playout_delay_ms(),
1052 playout_delay_oracle_.max_playout_delay_ms());
stefan-webrtc 2016/05/28 05:01:44 Are you sure you have to update here? Can the valu
Irfan 2016/06/01 08:38:33 This is indeed redundant. removed.
1053
1037 // Used for NACK and to spread out the transmission of packets. 1054 // Used for NACK and to spread out the transmission of packets.
1038 if (packet_history_.PutRTPPacket(buffer, length, capture_time_ms, storage) != 1055 if (packet_history_.PutRTPPacket(buffer, length, capture_time_ms, storage) !=
1039 0) { 1056 0) {
1040 return -1; 1057 return -1;
1041 } 1058 }
1042 1059
1043 if (paced_sender_) { 1060 if (paced_sender_) {
1044 // Correct offset between implementations of millisecond time stamps in 1061 // Correct offset between implementations of millisecond time stamps in
1045 // TickTime and Clock. 1062 // TickTime and Clock.
1046 int64_t corrected_time_ms = capture_time_ms + clock_delta_ms_; 1063 int64_t corrected_time_ms = capture_time_ms + clock_delta_ms_;
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 case kRtpExtensionAbsoluteSendTime: 1280 case kRtpExtensionAbsoluteSendTime:
1264 block_length = BuildAbsoluteSendTimeExtension(extension_data); 1281 block_length = BuildAbsoluteSendTimeExtension(extension_data);
1265 break; 1282 break;
1266 case kRtpExtensionVideoRotation: 1283 case kRtpExtensionVideoRotation:
1267 block_length = BuildVideoRotationExtension(extension_data); 1284 block_length = BuildVideoRotationExtension(extension_data);
1268 break; 1285 break;
1269 case kRtpExtensionTransportSequenceNumber: 1286 case kRtpExtensionTransportSequenceNumber:
1270 block_length = BuildTransportSequenceNumberExtension( 1287 block_length = BuildTransportSequenceNumberExtension(
1271 extension_data, transport_sequence_number_); 1288 extension_data, transport_sequence_number_);
1272 break; 1289 break;
1290 case kRtpExtensionPlayoutDelay:
1291 if (playout_delay_oracle_.send_playout_delay()) {
1292 block_length = BuildPlayoutDelayExtension(
1293 extension_data, playout_delay_oracle_.min_playout_delay_ms(),
1294 playout_delay_oracle_.max_playout_delay_ms());
1295 }
1296 break;
1273 default: 1297 default:
1274 assert(false); 1298 assert(false);
1275 } 1299 }
1276 total_block_length += block_length; 1300 total_block_length += block_length;
1277 type = rtp_header_extension_map_.Next(type); 1301 type = rtp_header_extension_map_.Next(type);
1278 } 1302 }
1279 if (total_block_length == 0) { 1303 if (total_block_length == 0) {
1280 // No extension added. 1304 // No extension added.
1281 return 0; 1305 return 0;
1282 } 1306 }
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 } 1462 }
1439 size_t pos = 0; 1463 size_t pos = 0;
1440 const uint8_t len = 1; 1464 const uint8_t len = 1;
1441 data_buffer[pos++] = (id << 4) + len; 1465 data_buffer[pos++] = (id << 4) + len;
1442 ByteWriter<uint16_t>::WriteBigEndian(data_buffer + pos, sequence_number); 1466 ByteWriter<uint16_t>::WriteBigEndian(data_buffer + pos, sequence_number);
1443 pos += 2; 1467 pos += 2;
1444 assert(pos == kTransportSequenceNumberLength); 1468 assert(pos == kTransportSequenceNumberLength);
1445 return kTransportSequenceNumberLength; 1469 return kTransportSequenceNumberLength;
1446 } 1470 }
1447 1471
1472 uint8_t RTPSender::BuildPlayoutDelayExtension(
1473 uint8_t* data_buffer,
1474 uint16_t min_playout_delay_ms,
1475 uint16_t max_playout_delay_ms) const {
1476 RTC_DCHECK_LE(min_playout_delay_ms, kPlayoutDelayMaxMs);
1477 RTC_DCHECK_LE(max_playout_delay_ms, kPlayoutDelayMaxMs);
stefan-webrtc 2016/05/28 05:01:44 Maybe also check that min <= max?
Irfan 2016/06/01 08:38:33 Done.
1478 // 0 1 2 3
1479 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1480 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1481 // | ID | len=2 | MIN delay | MAX delay |
1482 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1483 uint8_t id;
1484 if (rtp_header_extension_map_.GetId(kRtpExtensionPlayoutDelay, &id) != 0) {
1485 // Not registered.
1486 return 0;
1487 }
1488 size_t pos = 0;
1489 const uint8_t len = 2;
1490 // Convert MS to value to be sent on extension header.
1491 uint16_t min_playout = min_playout_delay_ms / kPlayoutDelayGranularityMs;
1492 uint16_t max_playout = max_playout_delay_ms / kPlayoutDelayGranularityMs;
1493
1494 data_buffer[pos++] = (id << 4) + len;
1495 data_buffer[pos++] = min_playout >> 4;
1496 data_buffer[pos++] = ((min_playout & 0xf) << 4) | (max_playout >> 8);
1497 data_buffer[pos++] = max_playout & 0xff;
stefan-webrtc 2016/05/28 05:01:44 I think you can use ByteWriter for this?
sprang 2016/05/30 12:13:15 That's mostly useful for integers with full byte s
Irfan 2016/06/01 08:38:33 The current code is explicit about how bytes are f
1498 assert(pos == kPlayoutDelayLength);
1499 return kPlayoutDelayLength;
1500 }
1501
1448 bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type, 1502 bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type,
1449 const uint8_t* rtp_packet, 1503 const uint8_t* rtp_packet,
1450 size_t rtp_packet_length, 1504 size_t rtp_packet_length,
1451 const RTPHeader& rtp_header, 1505 const RTPHeader& rtp_header,
1452 size_t* position) const { 1506 size_t* position) const {
1453 // Get length until start of header extension block. 1507 // Get length until start of header extension block.
1454 int extension_block_pos = 1508 int extension_block_pos =
1455 rtp_header_extension_map_.GetLengthUntilBlockStartInBytes(type); 1509 rtp_header_extension_map_.GetLengthUntilBlockStartInBytes(type);
1456 if (extension_block_pos < 0) { 1510 if (extension_block_pos < 0) {
1457 LOG(LS_WARNING) << "Failed to find extension position for " << type 1511 LOG(LS_WARNING) << "Failed to find extension position for " << type
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1631 case ExtensionStatus::kOk: 1685 case ExtensionStatus::kOk:
1632 break; 1686 break;
1633 default: 1687 default:
1634 RTC_NOTREACHED(); 1688 RTC_NOTREACHED();
1635 } 1689 }
1636 1690
1637 BuildTransportSequenceNumberExtension(rtp_packet + offset, sequence_number); 1691 BuildTransportSequenceNumberExtension(rtp_packet + offset, sequence_number);
1638 return true; 1692 return true;
1639 } 1693 }
1640 1694
1695 void RTPSender::UpdatePlayoutDelayLimits(uint8_t* rtp_packet,
1696 size_t rtp_packet_length,
1697 const RTPHeader& rtp_header,
1698 uint16_t min_playout_delay_ms,
1699 uint16_t max_playout_delay_ms) const {
1700 size_t offset;
1701 rtc::CritScope lock(&send_critsect_);
1702
1703 switch (VerifyExtension(kRtpExtensionPlayoutDelay, rtp_packet,
1704 rtp_packet_length, rtp_header, kPlayoutDelayLength,
1705 &offset)) {
1706 case ExtensionStatus::kNotRegistered:
1707 return;
1708 case ExtensionStatus::kError:
1709 LOG(LS_WARNING) << "Failed to update playout delay limits";
1710 return;
1711 case ExtensionStatus::kOk:
1712 break;
1713 default:
1714 RTC_NOTREACHED();
1715 }
1716
1717 BuildPlayoutDelayExtension(rtp_packet + offset, min_playout_delay_ms,
1718 max_playout_delay_ms);
1719 return;
1720 }
1721
1641 bool RTPSender::AllocateTransportSequenceNumber(int* packet_id) const { 1722 bool RTPSender::AllocateTransportSequenceNumber(int* packet_id) const {
1642 if (!transport_sequence_number_allocator_) 1723 if (!transport_sequence_number_allocator_)
1643 return false; 1724 return false;
1644 1725
1645 *packet_id = transport_sequence_number_allocator_->AllocateSequenceNumber(); 1726 *packet_id = transport_sequence_number_allocator_->AllocateSequenceNumber();
1646 return true; 1727 return true;
1647 } 1728 }
1648 1729
1649 void RTPSender::SetSendingStatus(bool enabled) { 1730 void RTPSender::SetSendingStatus(bool enabled) {
1650 if (enabled) { 1731 if (enabled) {
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1911 rtc::CritScope lock(&send_critsect_); 1992 rtc::CritScope lock(&send_critsect_);
1912 1993
1913 RtpState state; 1994 RtpState state;
1914 state.sequence_number = sequence_number_rtx_; 1995 state.sequence_number = sequence_number_rtx_;
1915 state.start_timestamp = start_timestamp_; 1996 state.start_timestamp = start_timestamp_;
1916 1997
1917 return state; 1998 return state;
1918 } 1999 }
1919 2000
1920 } // namespace webrtc 2001 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698