| 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 audio_(audio ? new RTPSenderAudio(clock, this) : nullptr), | 82 audio_(audio ? new RTPSenderAudio(clock, this) : nullptr), |
| 83 video_(audio ? nullptr : new RTPSenderVideo(clock, this)), | 83 video_(audio ? nullptr : new RTPSenderVideo(clock, this)), |
| 84 paced_sender_(paced_sender), | 84 paced_sender_(paced_sender), |
| 85 transport_sequence_number_allocator_(sequence_number_allocator), | 85 transport_sequence_number_allocator_(sequence_number_allocator), |
| 86 transport_feedback_observer_(transport_feedback_observer), | 86 transport_feedback_observer_(transport_feedback_observer), |
| 87 last_capture_time_ms_sent_(0), | 87 last_capture_time_ms_sent_(0), |
| 88 transport_(transport), | 88 transport_(transport), |
| 89 sending_media_(true), // Default to sending media. | 89 sending_media_(true), // Default to sending media. |
| 90 max_payload_length_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP. | 90 max_payload_length_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP. |
| 91 payload_type_(-1), | 91 payload_type_(-1), |
| 92 payload_type_map_(), | |
| 93 rtp_header_extension_map_(), | |
| 94 transmission_time_offset_(0), | |
| 95 absolute_send_time_(0), | |
| 96 rotation_(kVideoRotation_0), | |
| 97 video_rotation_active_(false), | |
| 98 transport_sequence_number_(0), | |
| 99 playout_delay_active_(false), | 92 playout_delay_active_(false), |
| 100 packet_history_(clock), | 93 packet_history_(clock), |
| 101 // Statistics | 94 // Statistics |
| 102 rtp_stats_callback_(nullptr), | 95 rtp_stats_callback_(nullptr), |
| 103 total_bitrate_sent_(kBitrateStatisticsWindowMs, | 96 total_bitrate_sent_(kBitrateStatisticsWindowMs, |
| 104 RateStatistics::kBpsScale), | 97 RateStatistics::kBpsScale), |
| 105 nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale), | 98 nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale), |
| 106 frame_count_observer_(frame_count_observer), | 99 frame_count_observer_(frame_count_observer), |
| 107 send_side_delay_observer_(send_side_delay_observer), | 100 send_side_delay_observer_(send_side_delay_observer), |
| 108 event_log_(event_log), | 101 event_log_(event_log), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 return video_->FecOverheadRate(); | 169 return video_->FecOverheadRate(); |
| 177 } | 170 } |
| 178 return 0; | 171 return 0; |
| 179 } | 172 } |
| 180 | 173 |
| 181 uint32_t RTPSender::NackOverheadRate() const { | 174 uint32_t RTPSender::NackOverheadRate() const { |
| 182 rtc::CritScope cs(&statistics_crit_); | 175 rtc::CritScope cs(&statistics_crit_); |
| 183 return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0); | 176 return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0); |
| 184 } | 177 } |
| 185 | 178 |
| 186 int32_t RTPSender::SetTransmissionTimeOffset(int32_t transmission_time_offset) { | |
| 187 if (transmission_time_offset > (0x800000 - 1) || | |
| 188 transmission_time_offset < -(0x800000 - 1)) { // Word24. | |
| 189 return -1; | |
| 190 } | |
| 191 rtc::CritScope lock(&send_critsect_); | |
| 192 transmission_time_offset_ = transmission_time_offset; | |
| 193 return 0; | |
| 194 } | |
| 195 | |
| 196 int32_t RTPSender::SetAbsoluteSendTime(uint32_t absolute_send_time) { | |
| 197 if (absolute_send_time > 0xffffff) { // UWord24. | |
| 198 return -1; | |
| 199 } | |
| 200 rtc::CritScope lock(&send_critsect_); | |
| 201 absolute_send_time_ = absolute_send_time; | |
| 202 return 0; | |
| 203 } | |
| 204 | |
| 205 void RTPSender::SetVideoRotation(VideoRotation rotation) { | |
| 206 rtc::CritScope lock(&send_critsect_); | |
| 207 rotation_ = rotation; | |
| 208 } | |
| 209 | |
| 210 int32_t RTPSender::SetTransportSequenceNumber(uint16_t sequence_number) { | |
| 211 rtc::CritScope lock(&send_critsect_); | |
| 212 transport_sequence_number_ = sequence_number; | |
| 213 return 0; | |
| 214 } | |
| 215 | |
| 216 int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type, | 179 int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type, |
| 217 uint8_t id) { | 180 uint8_t id) { |
| 218 rtc::CritScope lock(&send_critsect_); | 181 rtc::CritScope lock(&send_critsect_); |
| 219 switch (type) { | 182 switch (type) { |
| 220 case kRtpExtensionVideoRotation: | |
| 221 video_rotation_active_ = false; | |
| 222 return rtp_header_extension_map_.RegisterInactive(type, id); | |
| 223 case kRtpExtensionPlayoutDelay: | 183 case kRtpExtensionPlayoutDelay: |
| 224 playout_delay_active_ = false; | 184 playout_delay_active_ = false; |
| 225 return rtp_header_extension_map_.RegisterInactive(type, id); | 185 return rtp_header_extension_map_.RegisterInactive(type, id); |
| 186 case kRtpExtensionVideoRotation: |
| 226 case kRtpExtensionTransmissionTimeOffset: | 187 case kRtpExtensionTransmissionTimeOffset: |
| 227 case kRtpExtensionAbsoluteSendTime: | 188 case kRtpExtensionAbsoluteSendTime: |
| 228 case kRtpExtensionAudioLevel: | 189 case kRtpExtensionAudioLevel: |
| 229 case kRtpExtensionTransportSequenceNumber: | 190 case kRtpExtensionTransportSequenceNumber: |
| 230 return rtp_header_extension_map_.Register(type, id); | 191 return rtp_header_extension_map_.Register(type, id); |
| 231 case kRtpExtensionNone: | 192 case kRtpExtensionNone: |
| 232 case kRtpExtensionNumberOfExtensions: | 193 case kRtpExtensionNumberOfExtensions: |
| 233 LOG(LS_ERROR) << "Invalid RTP extension type for registration"; | 194 LOG(LS_ERROR) << "Invalid RTP extension type for registration"; |
| 234 return -1; | 195 return -1; |
| 235 } | 196 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 SetSendPayloadType(payload_type); | 379 SetSendPayloadType(payload_type); |
| 419 RtpUtility::Payload* payload = it->second; | 380 RtpUtility::Payload* payload = it->second; |
| 420 assert(payload); | 381 assert(payload); |
| 421 if (!payload->audio && !audio_configured_) { | 382 if (!payload->audio && !audio_configured_) { |
| 422 video_->SetVideoCodecType(payload->typeSpecific.Video.videoCodecType); | 383 video_->SetVideoCodecType(payload->typeSpecific.Video.videoCodecType); |
| 423 *video_type = payload->typeSpecific.Video.videoCodecType; | 384 *video_type = payload->typeSpecific.Video.videoCodecType; |
| 424 } | 385 } |
| 425 return 0; | 386 return 0; |
| 426 } | 387 } |
| 427 | 388 |
| 428 bool RTPSender::ActivateCVORtpHeaderExtension() { | |
| 429 if (!video_rotation_active_) { | |
| 430 rtc::CritScope lock(&send_critsect_); | |
| 431 if (rtp_header_extension_map_.SetActive(kRtpExtensionVideoRotation, true)) { | |
| 432 video_rotation_active_ = true; | |
| 433 } | |
| 434 } | |
| 435 return video_rotation_active_; | |
| 436 } | |
| 437 | |
| 438 bool RTPSender::SendOutgoingData(FrameType frame_type, | 389 bool RTPSender::SendOutgoingData(FrameType frame_type, |
| 439 int8_t payload_type, | 390 int8_t payload_type, |
| 440 uint32_t capture_timestamp, | 391 uint32_t capture_timestamp, |
| 441 int64_t capture_time_ms, | 392 int64_t capture_time_ms, |
| 442 const uint8_t* payload_data, | 393 const uint8_t* payload_data, |
| 443 size_t payload_size, | 394 size_t payload_size, |
| 444 const RTPFragmentationHeader* fragmentation, | 395 const RTPFragmentationHeader* fragmentation, |
| 445 const RTPVideoHeader* rtp_header, | 396 const RTPVideoHeader* rtp_header, |
| 446 uint32_t* transport_frame_id_out) { | 397 uint32_t* transport_frame_id_out) { |
| 447 uint32_t ssrc; | 398 uint32_t ssrc; |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) { | 826 size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) { |
| 876 if (audio_configured_ || bytes == 0) | 827 if (audio_configured_ || bytes == 0) |
| 877 return 0; | 828 return 0; |
| 878 size_t bytes_sent = TrySendRedundantPayloads(bytes, probe_cluster_id); | 829 size_t bytes_sent = TrySendRedundantPayloads(bytes, probe_cluster_id); |
| 879 if (bytes_sent < bytes) | 830 if (bytes_sent < bytes) |
| 880 bytes_sent += | 831 bytes_sent += |
| 881 SendPadData(bytes - bytes_sent, false, 0, 0, probe_cluster_id); | 832 SendPadData(bytes - bytes_sent, false, 0, 0, probe_cluster_id); |
| 882 return bytes_sent; | 833 return bytes_sent; |
| 883 } | 834 } |
| 884 | 835 |
| 885 bool RTPSender::SendToNetwork(uint8_t* buffer, | |
| 886 size_t payload_length, | |
| 887 size_t rtp_header_length, | |
| 888 int64_t capture_time_ms, | |
| 889 StorageType storage, | |
| 890 RtpPacketSender::Priority priority) { | |
| 891 size_t length = payload_length + rtp_header_length; | |
| 892 std::unique_ptr<RtpPacketToSend> packet( | |
| 893 new RtpPacketToSend(&rtp_header_extension_map_, length)); | |
| 894 RTC_CHECK(packet->Parse(buffer, length)); | |
| 895 packet->set_capture_time_ms(capture_time_ms); | |
| 896 return SendToNetwork(std::move(packet), storage, priority); | |
| 897 } | |
| 898 | |
| 899 bool RTPSender::SendToNetwork(std::unique_ptr<RtpPacketToSend> packet, | 836 bool RTPSender::SendToNetwork(std::unique_ptr<RtpPacketToSend> packet, |
| 900 StorageType storage, | 837 StorageType storage, |
| 901 RtpPacketSender::Priority priority) { | 838 RtpPacketSender::Priority priority) { |
| 902 RTC_DCHECK(packet); | 839 RTC_DCHECK(packet); |
| 903 int64_t now_ms = clock_->TimeInMilliseconds(); | 840 int64_t now_ms = clock_->TimeInMilliseconds(); |
| 904 | 841 |
| 905 // |capture_time_ms| <= 0 is considered invalid. | 842 // |capture_time_ms| <= 0 is considered invalid. |
| 906 // TODO(holmer): This should be changed all over Video Engine so that negative | 843 // TODO(holmer): This should be changed all over Video Engine so that negative |
| 907 // time is consider invalid, while 0 is considered a valid time. | 844 // time is consider invalid, while 0 is considered a valid time. |
| 908 if (packet->capture_time_ms() > 0) { | 845 if (packet->capture_time_ms() > 0) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 return first_allocated_sequence_number; | 970 return first_allocated_sequence_number; |
| 1034 } | 971 } |
| 1035 | 972 |
| 1036 void RTPSender::GetDataCounters(StreamDataCounters* rtp_stats, | 973 void RTPSender::GetDataCounters(StreamDataCounters* rtp_stats, |
| 1037 StreamDataCounters* rtx_stats) const { | 974 StreamDataCounters* rtx_stats) const { |
| 1038 rtc::CritScope lock(&statistics_crit_); | 975 rtc::CritScope lock(&statistics_crit_); |
| 1039 *rtp_stats = rtp_stats_; | 976 *rtp_stats = rtp_stats_; |
| 1040 *rtx_stats = rtx_rtp_stats_; | 977 *rtx_stats = rtx_rtp_stats_; |
| 1041 } | 978 } |
| 1042 | 979 |
| 1043 size_t RTPSender::CreateRtpHeader(uint8_t* header, | 980 std::unique_ptr<RtpPacketToSend> RTPSender::AllocatePacket( |
| 1044 int8_t payload_type, | 981 bool minimalistic) const { |
| 1045 uint32_t ssrc, | 982 std::unique_ptr<RtpPacketToSend> packet( |
| 1046 bool marker_bit, | 983 new RtpPacketToSend(&rtp_header_extension_map_, max_payload_length_)); |
| 1047 uint32_t timestamp, | 984 rtc::CritScope lock(&send_critsect_); |
| 1048 uint16_t sequence_number, | 985 packet->SetSsrc(ssrc_); |
| 1049 const std::vector<uint32_t>& csrcs) const { | 986 if (!minimalistic) { |
| 1050 header[0] = 0x80; // version 2. | 987 packet->SetCsrcs(csrcs_); |
| 1051 header[1] = static_cast<uint8_t>(payload_type); | 988 // Reserve place for extensions, if registered. |
| 1052 if (marker_bit) { | 989 // It is important to reserve those extension before any other: they are set |
| 1053 header[1] |= kRtpMarkerBitMask; // Marker bit is set. | 990 // in RtpSender _after_ media packets proccessed for fec, meaning they can |
| 991 // damage any bytes in the packet that are at the same address. |
| 992 // Reserving these extensions first ensure it is just values of theese |
| 993 // extensions that are bogus in recovered packets. |
| 994 packet->ReserveExtension<AbsoluteSendTime>(); |
| 995 packet->ReserveExtension<TransmissionOffset>(); |
| 996 packet->ReserveExtension<TransportSequenceNumber>(); |
| 1054 } | 997 } |
| 1055 ByteWriter<uint16_t>::WriteBigEndian(header + 2, sequence_number); | 998 return packet; |
| 1056 ByteWriter<uint32_t>::WriteBigEndian(header + 4, timestamp); | |
| 1057 ByteWriter<uint32_t>::WriteBigEndian(header + 8, ssrc); | |
| 1058 int32_t rtp_header_length = kRtpHeaderLength; | |
| 1059 | |
| 1060 if (csrcs.size() > 0) { | |
| 1061 uint8_t* ptr = &header[rtp_header_length]; | |
| 1062 for (size_t i = 0; i < csrcs.size(); ++i) { | |
| 1063 ByteWriter<uint32_t>::WriteBigEndian(ptr, csrcs[i]); | |
| 1064 ptr += 4; | |
| 1065 } | |
| 1066 header[0] = (header[0] & 0xf0) | csrcs.size(); | |
| 1067 | |
| 1068 // Update length of header. | |
| 1069 rtp_header_length += sizeof(uint32_t) * csrcs.size(); | |
| 1070 } | |
| 1071 | |
| 1072 uint16_t len = | |
| 1073 BuildRtpHeaderExtension(header + rtp_header_length, marker_bit); | |
| 1074 if (len > 0) { | |
| 1075 header[0] |= 0x10; // Set extension bit. | |
| 1076 rtp_header_length += len; | |
| 1077 } | |
| 1078 return rtp_header_length; | |
| 1079 } | 999 } |
| 1080 | 1000 |
| 1081 int32_t RTPSender::BuildRTPheader(uint8_t* data_buffer, | 1001 bool RTPSender::PrepareToSend(RtpPacketToSend* packet) { |
| 1082 int8_t payload_type, | 1002 rtc::CritScope lock(&send_critsect_); |
| 1083 bool marker_bit, | 1003 if (!sending_media_) |
| 1084 uint32_t capture_timestamp, | 1004 return false; |
| 1085 int64_t capture_time_ms, | 1005 |
| 1086 bool timestamp_provided, | 1006 timestamp_ = start_timestamp_ + packet->Timestamp(); |
| 1087 bool inc_sequence_number) { | 1007 last_timestamp_time_ms_ = clock_->TimeInMilliseconds(); |
| 1088 return BuildRtpHeader(data_buffer, payload_type, marker_bit, | 1008 uint32_t sequence_number = sequence_number_++; |
| 1089 capture_timestamp, capture_time_ms); | 1009 capture_time_ms_ = packet->capture_time_ms(); |
| 1010 last_packet_marker_bit_ = packet->Marker(); |
| 1011 |
| 1012 packet->SetSequenceNumber(sequence_number); |
| 1013 packet->SetTimestamp(timestamp_); |
| 1014 return true; |
| 1090 } | 1015 } |
| 1091 | 1016 |
| 1092 int32_t RTPSender::BuildRtpHeader(uint8_t* data_buffer, | 1017 uint32_t RTPSender::TimestampOffset(uint32_t capture_timestamp) const { |
| 1093 int8_t payload_type, | |
| 1094 bool marker_bit, | |
| 1095 uint32_t capture_timestamp, | |
| 1096 int64_t capture_time_ms) { | |
| 1097 assert(payload_type >= 0); | |
| 1098 rtc::CritScope lock(&send_critsect_); | 1018 rtc::CritScope lock(&send_critsect_); |
| 1099 if (!sending_media_) | |
| 1100 return -1; | |
| 1101 | 1019 |
| 1102 timestamp_ = start_timestamp_ + capture_timestamp; | 1020 return start_timestamp_ + capture_timestamp - timestamp_; |
| 1103 last_timestamp_time_ms_ = clock_->TimeInMilliseconds(); | |
| 1104 uint32_t sequence_number = sequence_number_++; | |
| 1105 capture_time_ms_ = capture_time_ms; | |
| 1106 last_packet_marker_bit_ = marker_bit; | |
| 1107 return CreateRtpHeader(data_buffer, payload_type, ssrc_, marker_bit, | |
| 1108 timestamp_, sequence_number, csrcs_); | |
| 1109 } | 1021 } |
| 1110 | 1022 /* |
| 1111 uint16_t RTPSender::BuildRtpHeaderExtension(uint8_t* data_buffer, | |
| 1112 bool marker_bit) const { | |
| 1113 if (rtp_header_extension_map_.Size() <= 0) { | |
| 1114 return 0; | |
| 1115 } | |
| 1116 // RTP header extension, RFC 3550. | |
| 1117 // 0 1 2 3 | |
| 1118 // 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 | |
| 1119 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1120 // | defined by profile | length | | |
| 1121 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1122 // | header extension | | |
| 1123 // | .... | | |
| 1124 // | |
| 1125 const uint32_t kPosLength = 2; | |
| 1126 const uint32_t kHeaderLength = kRtpOneByteHeaderLength; | |
| 1127 | |
| 1128 // Add extension ID (0xBEDE). | |
| 1129 ByteWriter<uint16_t>::WriteBigEndian(data_buffer, | |
| 1130 kRtpOneByteHeaderExtensionId); | |
| 1131 | |
| 1132 // Add extensions. | |
| 1133 uint16_t total_block_length = 0; | |
| 1134 | |
| 1135 RTPExtensionType type = rtp_header_extension_map_.First(); | |
| 1136 while (type != kRtpExtensionNone) { | |
| 1137 uint8_t block_length = 0; | |
| 1138 uint8_t* extension_data = &data_buffer[kHeaderLength + total_block_length]; | |
| 1139 switch (type) { | |
| 1140 case kRtpExtensionTransmissionTimeOffset: | |
| 1141 block_length = BuildTransmissionTimeOffsetExtension(extension_data); | |
| 1142 break; | |
| 1143 case kRtpExtensionAudioLevel: | |
| 1144 block_length = BuildAudioLevelExtension(extension_data); | |
| 1145 break; | |
| 1146 case kRtpExtensionAbsoluteSendTime: | |
| 1147 block_length = BuildAbsoluteSendTimeExtension(extension_data); | |
| 1148 break; | |
| 1149 case kRtpExtensionVideoRotation: | |
| 1150 block_length = BuildVideoRotationExtension(extension_data); | |
| 1151 break; | |
| 1152 case kRtpExtensionTransportSequenceNumber: | |
| 1153 block_length = BuildTransportSequenceNumberExtension( | |
| 1154 extension_data, transport_sequence_number_); | |
| 1155 break; | |
| 1156 case kRtpExtensionPlayoutDelay: | |
| 1157 block_length = BuildPlayoutDelayExtension( | |
| 1158 extension_data, playout_delay_oracle_.min_playout_delay_ms(), | |
| 1159 playout_delay_oracle_.max_playout_delay_ms()); | |
| 1160 break; | |
| 1161 default: | |
| 1162 assert(false); | |
| 1163 } | |
| 1164 total_block_length += block_length; | |
| 1165 type = rtp_header_extension_map_.Next(type); | |
| 1166 } | |
| 1167 if (total_block_length == 0) { | |
| 1168 // No extension added. | |
| 1169 return 0; | |
| 1170 } | |
| 1171 // Add padding elements until we've filled a 32 bit block. | |
| 1172 size_t padding_bytes = | |
| 1173 RtpUtility::Word32Align(total_block_length) - total_block_length; | |
| 1174 if (padding_bytes > 0) { | |
| 1175 memset(&data_buffer[kHeaderLength + total_block_length], 0, padding_bytes); | |
| 1176 total_block_length += padding_bytes; | |
| 1177 } | |
| 1178 // Set header length (in number of Word32, header excluded). | |
| 1179 ByteWriter<uint16_t>::WriteBigEndian(data_buffer + kPosLength, | |
| 1180 total_block_length / 4); | |
| 1181 // Total added length. | |
| 1182 return kHeaderLength + total_block_length; | |
| 1183 } | |
| 1184 | |
| 1185 uint8_t RTPSender::BuildTransmissionTimeOffsetExtension( | |
| 1186 uint8_t* data_buffer) const { | |
| 1187 // From RFC 5450: Transmission Time Offsets in RTP Streams. | |
| 1188 // | |
| 1189 // The transmission time is signaled to the receiver in-band using the | |
| 1190 // general mechanism for RTP header extensions [RFC5285]. The payload | |
| 1191 // of this extension (the transmitted value) is a 24-bit signed integer. | |
| 1192 // When added to the RTP timestamp of the packet, it represents the | |
| 1193 // "effective" RTP transmission time of the packet, on the RTP | |
| 1194 // timescale. | |
| 1195 // | |
| 1196 // The form of the transmission offset extension block: | |
| 1197 // | |
| 1198 // 0 1 2 3 | |
| 1199 // 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 | |
| 1200 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1201 // | ID | len=2 | transmission offset | | |
| 1202 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1203 | |
| 1204 // Get id defined by user. | |
| 1205 uint8_t id; | |
| 1206 if (rtp_header_extension_map_.GetId(kRtpExtensionTransmissionTimeOffset, | |
| 1207 &id) != 0) { | |
| 1208 // Not registered. | |
| 1209 return 0; | |
| 1210 } | |
| 1211 size_t pos = 0; | |
| 1212 const uint8_t len = 2; | |
| 1213 data_buffer[pos++] = (id << 4) + len; | |
| 1214 ByteWriter<int32_t, 3>::WriteBigEndian(data_buffer + pos, | |
| 1215 transmission_time_offset_); | |
| 1216 pos += 3; | |
| 1217 assert(pos == kTransmissionTimeOffsetLength); | |
| 1218 return kTransmissionTimeOffsetLength; | |
| 1219 } | |
| 1220 | |
| 1221 uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const { | |
| 1222 // An RTP Header Extension for Client-to-Mixer Audio Level Indication | |
| 1223 // | |
| 1224 // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/ | |
| 1225 // | |
| 1226 // The form of the audio level extension block: | |
| 1227 // | |
| 1228 // 0 1 | |
| 1229 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 | |
| 1230 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1231 // | ID | len=0 |V| level | | |
| 1232 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1233 // | |
| 1234 | |
| 1235 // Get id defined by user. | |
| 1236 uint8_t id; | |
| 1237 if (rtp_header_extension_map_.GetId(kRtpExtensionAudioLevel, &id) != 0) { | |
| 1238 // Not registered. | |
| 1239 return 0; | |
| 1240 } | |
| 1241 size_t pos = 0; | |
| 1242 const uint8_t len = 0; | |
| 1243 data_buffer[pos++] = (id << 4) + len; | |
| 1244 data_buffer[pos++] = (1 << 7) + 0; // Voice, 0 dBov. | |
| 1245 assert(pos == kAudioLevelLength); | |
| 1246 return kAudioLevelLength; | |
| 1247 } | |
| 1248 | |
| 1249 uint8_t RTPSender::BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const { | |
| 1250 // Absolute send time in RTP streams. | |
| 1251 // | |
| 1252 // The absolute send time is signaled to the receiver in-band using the | |
| 1253 // general mechanism for RTP header extensions [RFC5285]. The payload | |
| 1254 // of this extension (the transmitted value) is a 24-bit unsigned integer | |
| 1255 // containing the sender's current time in seconds as a fixed point number | |
| 1256 // with 18 bits fractional part. | |
| 1257 // | |
| 1258 // The form of the absolute send time extension block: | |
| 1259 // | |
| 1260 // 0 1 2 3 | |
| 1261 // 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 | |
| 1262 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1263 // | ID | len=2 | absolute send time | | |
| 1264 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1265 | |
| 1266 // Get id defined by user. | |
| 1267 uint8_t id; | |
| 1268 if (rtp_header_extension_map_.GetId(kRtpExtensionAbsoluteSendTime, | |
| 1269 &id) != 0) { | |
| 1270 // Not registered. | |
| 1271 return 0; | |
| 1272 } | |
| 1273 size_t pos = 0; | |
| 1274 const uint8_t len = 2; | |
| 1275 data_buffer[pos++] = (id << 4) + len; | |
| 1276 ByteWriter<uint32_t, 3>::WriteBigEndian(data_buffer + pos, | |
| 1277 absolute_send_time_); | |
| 1278 pos += 3; | |
| 1279 assert(pos == kAbsoluteSendTimeLength); | |
| 1280 return kAbsoluteSendTimeLength; | |
| 1281 } | |
| 1282 | |
| 1283 uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const { | |
| 1284 // Coordination of Video Orientation in RTP streams. | |
| 1285 // | |
| 1286 // Coordination of Video Orientation consists in signaling of the current | |
| 1287 // orientation of the image captured on the sender side to the receiver for | |
| 1288 // appropriate rendering and displaying. | |
| 1289 // | |
| 1290 // 0 1 | |
| 1291 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 | |
| 1292 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1293 // | ID | len=0 |0 0 0 0 C F R R| | |
| 1294 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1295 // | |
| 1296 | |
| 1297 // Get id defined by user. | |
| 1298 uint8_t id; | |
| 1299 if (rtp_header_extension_map_.GetId(kRtpExtensionVideoRotation, &id) != 0) { | |
| 1300 // Not registered. | |
| 1301 return 0; | |
| 1302 } | |
| 1303 size_t pos = 0; | |
| 1304 const uint8_t len = 0; | |
| 1305 data_buffer[pos++] = (id << 4) + len; | |
| 1306 data_buffer[pos++] = ConvertVideoRotationToCVOByte(rotation_); | |
| 1307 assert(pos == kVideoRotationLength); | |
| 1308 return kVideoRotationLength; | |
| 1309 } | |
| 1310 | |
| 1311 uint8_t RTPSender::BuildTransportSequenceNumberExtension( | |
| 1312 uint8_t* data_buffer, | |
| 1313 uint16_t sequence_number) const { | |
| 1314 // 0 1 2 | |
| 1315 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 | |
| 1316 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1317 // | ID | L=1 |transport wide sequence number | | |
| 1318 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 1319 | |
| 1320 // Get id defined by user. | |
| 1321 uint8_t id; | |
| 1322 if (rtp_header_extension_map_.GetId(kRtpExtensionTransportSequenceNumber, | |
| 1323 &id) != 0) { | |
| 1324 // Not registered. | |
| 1325 return 0; | |
| 1326 } | |
| 1327 size_t pos = 0; | |
| 1328 const uint8_t len = 1; | |
| 1329 data_buffer[pos++] = (id << 4) + len; | |
| 1330 ByteWriter<uint16_t>::WriteBigEndian(data_buffer + pos, sequence_number); | |
| 1331 pos += 2; | |
| 1332 assert(pos == kTransportSequenceNumberLength); | |
| 1333 return kTransportSequenceNumberLength; | |
| 1334 } | |
| 1335 | |
| 1336 uint8_t RTPSender::BuildPlayoutDelayExtension( | 1023 uint8_t RTPSender::BuildPlayoutDelayExtension( |
| 1337 uint8_t* data_buffer, | 1024 uint8_t* data_buffer, |
| 1338 uint16_t min_playout_delay_ms, | 1025 uint16_t min_playout_delay_ms, |
| 1339 uint16_t max_playout_delay_ms) const { | 1026 uint16_t max_playout_delay_ms) const { |
| 1340 RTC_DCHECK_LE(min_playout_delay_ms, kPlayoutDelayMaxMs); | 1027 RTC_DCHECK_LE(min_playout_delay_ms, kPlayoutDelayMaxMs); |
| 1341 RTC_DCHECK_LE(max_playout_delay_ms, kPlayoutDelayMaxMs); | 1028 RTC_DCHECK_LE(max_playout_delay_ms, kPlayoutDelayMaxMs); |
| 1342 RTC_DCHECK_LE(min_playout_delay_ms, max_playout_delay_ms); | 1029 RTC_DCHECK_LE(min_playout_delay_ms, max_playout_delay_ms); |
| 1343 // 0 1 2 3 | 1030 // 0 1 2 3 |
| 1344 // 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 | 1031 // 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 |
| 1345 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 1032 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1356 uint16_t min_playout = min_playout_delay_ms / kPlayoutDelayGranularityMs; | 1043 uint16_t min_playout = min_playout_delay_ms / kPlayoutDelayGranularityMs; |
| 1357 uint16_t max_playout = max_playout_delay_ms / kPlayoutDelayGranularityMs; | 1044 uint16_t max_playout = max_playout_delay_ms / kPlayoutDelayGranularityMs; |
| 1358 | 1045 |
| 1359 data_buffer[pos++] = (id << 4) + len; | 1046 data_buffer[pos++] = (id << 4) + len; |
| 1360 data_buffer[pos++] = min_playout >> 4; | 1047 data_buffer[pos++] = min_playout >> 4; |
| 1361 data_buffer[pos++] = ((min_playout & 0xf) << 4) | (max_playout >> 8); | 1048 data_buffer[pos++] = ((min_playout & 0xf) << 4) | (max_playout >> 8); |
| 1362 data_buffer[pos++] = max_playout & 0xff; | 1049 data_buffer[pos++] = max_playout & 0xff; |
| 1363 assert(pos == kPlayoutDelayLength); | 1050 assert(pos == kPlayoutDelayLength); |
| 1364 return kPlayoutDelayLength; | 1051 return kPlayoutDelayLength; |
| 1365 } | 1052 } |
| 1366 | 1053 */ |
| 1367 bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type, | |
| 1368 const uint8_t* rtp_packet, | |
| 1369 size_t rtp_packet_length, | |
| 1370 const RTPHeader& rtp_header, | |
| 1371 size_t* position) const { | |
| 1372 // Get length until start of header extension block. | |
| 1373 int extension_block_pos = | |
| 1374 rtp_header_extension_map_.GetLengthUntilBlockStartInBytes(type); | |
| 1375 if (extension_block_pos < 0) { | |
| 1376 LOG(LS_WARNING) << "Failed to find extension position for " << type | |
| 1377 << " as it is not registered."; | |
| 1378 return false; | |
| 1379 } | |
| 1380 | |
| 1381 HeaderExtension header_extension(type); | |
| 1382 | |
| 1383 size_t extension_pos = | |
| 1384 kRtpHeaderLength + rtp_header.numCSRCs * sizeof(uint32_t); | |
| 1385 size_t block_pos = extension_pos + extension_block_pos; | |
| 1386 if (rtp_packet_length < block_pos + header_extension.length || | |
| 1387 rtp_header.headerLength < block_pos + header_extension.length) { | |
| 1388 LOG(LS_WARNING) << "Failed to find extension position for " << type | |
| 1389 << " as the length is invalid."; | |
| 1390 return false; | |
| 1391 } | |
| 1392 | |
| 1393 // Verify that header contains extension. | |
| 1394 if (!(rtp_packet[extension_pos] == 0xBE && | |
| 1395 rtp_packet[extension_pos + 1] == 0xDE)) { | |
| 1396 LOG(LS_WARNING) << "Failed to find extension position for " << type | |
| 1397 << "as hdr extension not found."; | |
| 1398 return false; | |
| 1399 } | |
| 1400 | |
| 1401 *position = block_pos; | |
| 1402 return true; | |
| 1403 } | |
| 1404 | |
| 1405 RTPSender::ExtensionStatus RTPSender::VerifyExtension( | |
| 1406 RTPExtensionType extension_type, | |
| 1407 uint8_t* rtp_packet, | |
| 1408 size_t rtp_packet_length, | |
| 1409 const RTPHeader& rtp_header, | |
| 1410 size_t extension_length_bytes, | |
| 1411 size_t* extension_offset) const { | |
| 1412 // Get id. | |
| 1413 uint8_t id = 0; | |
| 1414 if (rtp_header_extension_map_.GetId(extension_type, &id) != 0) | |
| 1415 return ExtensionStatus::kNotRegistered; | |
| 1416 | |
| 1417 size_t block_pos = 0; | |
| 1418 if (!FindHeaderExtensionPosition(extension_type, rtp_packet, | |
| 1419 rtp_packet_length, rtp_header, &block_pos)) | |
| 1420 return ExtensionStatus::kError; | |
| 1421 | |
| 1422 // Verify first byte in block. | |
| 1423 const uint8_t first_block_byte = (id << 4) + (extension_length_bytes - 2); | |
| 1424 if (rtp_packet[block_pos] != first_block_byte) | |
| 1425 return ExtensionStatus::kError; | |
| 1426 | |
| 1427 *extension_offset = block_pos; | |
| 1428 return ExtensionStatus::kOk; | |
| 1429 } | |
| 1430 | |
| 1431 bool RTPSender::UpdateAudioLevel(uint8_t* rtp_packet, | |
| 1432 size_t rtp_packet_length, | |
| 1433 const RTPHeader& rtp_header, | |
| 1434 bool is_voiced, | |
| 1435 uint8_t dBov) const { | |
| 1436 size_t offset; | |
| 1437 rtc::CritScope lock(&send_critsect_); | |
| 1438 | |
| 1439 switch (VerifyExtension(kRtpExtensionAudioLevel, rtp_packet, | |
| 1440 rtp_packet_length, rtp_header, kAudioLevelLength, | |
| 1441 &offset)) { | |
| 1442 case ExtensionStatus::kNotRegistered: | |
| 1443 return false; | |
| 1444 case ExtensionStatus::kError: | |
| 1445 LOG(LS_WARNING) << "Failed to update audio level."; | |
| 1446 return false; | |
| 1447 case ExtensionStatus::kOk: | |
| 1448 break; | |
| 1449 default: | |
| 1450 RTC_NOTREACHED(); | |
| 1451 } | |
| 1452 | |
| 1453 rtp_packet[offset + 1] = (is_voiced ? 0x80 : 0x00) + (dBov & 0x7f); | |
| 1454 return true; | |
| 1455 } | |
| 1456 | |
| 1457 bool RTPSender::UpdateVideoRotation(uint8_t* rtp_packet, | |
| 1458 size_t rtp_packet_length, | |
| 1459 const RTPHeader& rtp_header, | |
| 1460 VideoRotation rotation) const { | |
| 1461 size_t offset; | |
| 1462 rtc::CritScope lock(&send_critsect_); | |
| 1463 | |
| 1464 switch (VerifyExtension(kRtpExtensionVideoRotation, rtp_packet, | |
| 1465 rtp_packet_length, rtp_header, kVideoRotationLength, | |
| 1466 &offset)) { | |
| 1467 case ExtensionStatus::kNotRegistered: | |
| 1468 return false; | |
| 1469 case ExtensionStatus::kError: | |
| 1470 LOG(LS_WARNING) << "Failed to update CVO."; | |
| 1471 return false; | |
| 1472 case ExtensionStatus::kOk: | |
| 1473 break; | |
| 1474 default: | |
| 1475 RTC_NOTREACHED(); | |
| 1476 } | |
| 1477 | |
| 1478 rtp_packet[offset + 1] = ConvertVideoRotationToCVOByte(rotation); | |
| 1479 return true; | |
| 1480 } | |
| 1481 | 1054 |
| 1482 bool RTPSender::UpdateTransportSequenceNumber(RtpPacketToSend* packet, | 1055 bool RTPSender::UpdateTransportSequenceNumber(RtpPacketToSend* packet, |
| 1483 int* packet_id) const { | 1056 int* packet_id) const { |
| 1484 RTC_DCHECK(packet); | 1057 RTC_DCHECK(packet); |
| 1485 RTC_DCHECK(packet_id); | 1058 RTC_DCHECK(packet_id); |
| 1486 rtc::CritScope lock(&send_critsect_); | 1059 rtc::CritScope lock(&send_critsect_); |
| 1487 if (!rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId)) | 1060 if (!rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId)) |
| 1488 return false; | 1061 return false; |
| 1489 | 1062 |
| 1490 if (!transport_sequence_number_allocator_) | 1063 if (!transport_sequence_number_allocator_) |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1758 rtc::CritScope lock(&send_critsect_); | 1331 rtc::CritScope lock(&send_critsect_); |
| 1759 | 1332 |
| 1760 RtpState state; | 1333 RtpState state; |
| 1761 state.sequence_number = sequence_number_rtx_; | 1334 state.sequence_number = sequence_number_rtx_; |
| 1762 state.start_timestamp = start_timestamp_; | 1335 state.start_timestamp = start_timestamp_; |
| 1763 | 1336 |
| 1764 return state; | 1337 return state; |
| 1765 } | 1338 } |
| 1766 | 1339 |
| 1767 } // namespace webrtc | 1340 } // namespace webrtc |
| OLD | NEW |