1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 12 13 #include <string.h> 14 15 #include "webrtc/base/logging.h" 16 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 17 18 namespace webrtc { 19 20 RtpData* NullObjectRtpData() { 21 static NullRtpData null_rtp_data; 22 return &null_rtp_data; 23 } 24 25 RtpFeedback* NullObjectRtpFeedback() { 26 static NullRtpFeedback null_rtp_feedback; 27 return &null_rtp_feedback; 28 } 29 30 RtpAudioFeedback* NullObjectRtpAudioFeedback() { 31 static NullRtpAudioFeedback null_rtp_audio_feedback; 32 return &null_rtp_audio_feedback; 33 } 34 35 ReceiveStatistics* NullObjectReceiveStatistics() { 36 static NullReceiveStatistics null_receive_statistics; 37 return &null_receive_statistics; 38 } 39 40 namespace RtpUtility { 41 42 enum { 43 kRtcpExpectedVersion = 2, 44 kRtcpMinHeaderLength = 4, 45 kRtcpMinParseLength = 8, 46 47 kRtpExpectedVersion = 2, 48 kRtpMinParseLength = 12 49 }; 50 51 /* 52 * Misc utility routines 53 */ 54 55 #if defined(_WIN32) 56 bool StringCompare(const char* str1, const char* str2, 57 const uint32_t length) { 58 return _strnicmp(str1, str2, length) == 0; 59 } 60 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 61 bool StringCompare(const char* str1, const char* str2, 62 const uint32_t length) { 63 return strncasecmp(str1, str2, length) == 0; 64 } 65 #endif 66 67 size_t Word32Align(size_t size) { 68 uint32_t remainder = size % 4; 69 if (remainder != 0) 70 return size + 4 - remainder; 71 return size; 72 } 73 74 RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData, 75 const size_t rtpDataLength) 76 : _ptrRTPDataBegin(rtpData), 77 _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) { 78 } 79 80 RtpHeaderParser::~RtpHeaderParser() { 81 } 82 83 bool RtpHeaderParser::RTCP() const { 84 // 72 to 76 is reserved for RTP 85 // 77 to 79 is not reserver but they are not assigned we will block them 86 // for RTCP 200 SR == marker bit + 72 87 // for RTCP 204 APP == marker bit + 76 88 /* 89 * RTCP 90 * 91 * FIR full INTRA-frame request 192 [RFC2032] supported 92 * NACK negative acknowledgement 193 [RFC2032] 93 * IJ Extended inter-arrival jitter report 195 [RFC-ietf-avt-rtp-toff 94 * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07 95 * SR sender report 200 [RFC3551] supported 96 * RR receiver report 201 [RFC3551] supported 97 * SDES source description 202 [RFC3551] supported 98 * BYE goodbye 203 [RFC3551] supported 99 * APP application-defined 204 [RFC3551] ignored 100 * RTPFB Transport layer FB message 205 [RFC4585] supported 101 * PSFB Payload-specific FB message 206 [RFC4585] supported 102 * XR extended report 207 [RFC3611] supported 103 */ 104 105 /* 205 RFC 5104 106 * FMT 1 NACK supported 107 * FMT 2 reserved 108 * FMT 3 TMMBR supported 109 * FMT 4 TMMBN supported 110 */ 111 112 /* 206 RFC 5104 113 * FMT 1: Picture Loss Indication (PLI) supported 114 * FMT 2: Slice Lost Indication (SLI) 115 * FMT 3: Reference Picture Selection Indication (RPSI) 116 * FMT 4: Full Intra Request (FIR) Command supported 117 * FMT 5: Temporal-Spatial Trade-off Request (TSTR) 118 * FMT 6: Temporal-Spatial Trade-off Notification (TSTN) 119 * FMT 7: Video Back Channel Message (VBCM) 120 * FMT 15: Application layer FB message 121 */ 122 123 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin; 124 if (length < kRtcpMinHeaderLength) { 125 return false; 126 } 127 128 const uint8_t V = _ptrRTPDataBegin[0] >> 6; 129 if (V != kRtcpExpectedVersion) { 130 return false; 131 } 132 133 const uint8_t payloadType = _ptrRTPDataBegin[1]; 134 switch (payloadType) { 135 case 192: 136 return true; 137 case 193: 138 // not supported 139 // pass through and check for a potential RTP packet 140 return false; 141 case 195: 142 case 200: 143 case 201: 144 case 202: 145 case 203: 146 case 204: 147 case 205: 148 case 206: 149 case 207: 150 return true; 151 default: 152 return false; 153 } 154 } 155 156 bool RtpHeaderParser::ParseRtcp(RTPHeader* header) const { 157 assert(header != NULL); 158 159 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin; 160 if (length < kRtcpMinParseLength) { 161 return false; 162 } 163 164 const uint8_t V = _ptrRTPDataBegin[0] >> 6; 165 if (V != kRtcpExpectedVersion) { 166 return false; 167 } 168 169 const uint8_t PT = _ptrRTPDataBegin[1]; 170 const size_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3]; 171 const uint8_t* ptr = &_ptrRTPDataBegin[4]; 172 173 uint32_t SSRC = ByteReader<uint32_t>::ReadBigEndian(ptr); 174 ptr += 4; 175 176 header->payloadType = PT; 177 header->ssrc = SSRC; 178 header->headerLength = 4 + (len << 2); 179 180 return true; 181 } 182 183 bool RtpHeaderParser::Parse(RTPHeader* header, 184 RtpHeaderExtensionMap* ptrExtensionMap) const { 185 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin; 186 if (length < kRtpMinParseLength) { 187 return false; 188 } 189 190 // Version 191 const uint8_t V = _ptrRTPDataBegin[0] >> 6; 192 // Padding 193 const bool P = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true; 194 // eXtension 195 const bool X = ((_ptrRTPDataBegin[0] & 0x10) == 0) ? false : true; 196 const uint8_t CC = _ptrRTPDataBegin[0] & 0x0f; 197 const bool M = ((_ptrRTPDataBegin[1] & 0x80) == 0) ? false : true; 198 199 const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f; 200 201 const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) + 202 _ptrRTPDataBegin[3]; 203 204 const uint8_t* ptr = &_ptrRTPDataBegin[4]; 205 206 uint32_t RTPTimestamp = ByteReader<uint32_t>::ReadBigEndian(ptr); 207 ptr += 4; 208 209 uint32_t SSRC = ByteReader<uint32_t>::ReadBigEndian(ptr); 210 ptr += 4; 211 212 if (V != kRtpExpectedVersion) { 213 return false; 214 } 215 216 const size_t CSRCocts = CC * 4; 217 218 if ((ptr + CSRCocts) > _ptrRTPDataEnd) { 219 return false; 220 } 221 222 header->markerBit = M; 223 header->payloadType = PT; 224 header->sequenceNumber = sequenceNumber; 225 header->timestamp = RTPTimestamp; 226 header->ssrc = SSRC; 227 header->numCSRCs = CC; 228 header->paddingLength = P ? *(_ptrRTPDataEnd - 1) : 0; 229 230 for (uint8_t i = 0; i < CC; ++i) { 231 uint32_t CSRC = ByteReader<uint32_t>::ReadBigEndian(ptr); 232 ptr += 4; 233 header->arrOfCSRCs[i] = CSRC; 234 } 235 236 header->headerLength = 12 + CSRCocts; 237 238 // If in effect, MAY be omitted for those packets for which the offset 239 // is zero. 240 header->extension.hasTransmissionTimeOffset = false; 241 header->extension.transmissionTimeOffset = 0; 242 243 // May not be present in packet. 244 header->extension.hasAbsoluteSendTime = false; 245 header->extension.absoluteSendTime = 0; 246 247 // May not be present in packet. 248 header->extension.hasAudioLevel = false; 249 header->extension.voiceActivity = false; 250 header->extension.audioLevel = 0; 251 252 // May not be present in packet. 253 header->extension.hasVideoRotation = false; 254 header->extension.videoRotation = 0; 255 256 if (X) { 257 /* RTP header extension, RFC 3550. 258 0 1 2 3 259 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 260 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 261 | defined by profile | length | 262 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 263 | header extension | 264 | .... | 265 */ 266 const ptrdiff_t remain = _ptrRTPDataEnd - ptr; 267 if (remain < 4) { 268 return false; 269 } 270 271 header->headerLength += 4; 272 273 uint16_t definedByProfile = ByteReader<uint16_t>::ReadBigEndian(ptr); 274 ptr += 2; 275 276 // in 32 bit words 277 size_t XLen = ByteReader<uint16_t>::ReadBigEndian(ptr); 278 ptr += 2; 279 XLen *= 4; // in bytes 280 281 if (static_cast<size_t>(remain) < (4 + XLen)) { 282 return false; 283 } 284 if (definedByProfile == kRtpOneByteHeaderExtensionId) { 285 const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen; 286 ParseOneByteExtensionHeader(header, 287 ptrExtensionMap, 288 ptrRTPDataExtensionEnd, 289 ptr); 290 } 291 header->headerLength += XLen; 292 } 293 if (header->headerLength + header->paddingLength > 294 static_cast<size_t>(length)) 295 return false; 296 return true; 297 } 298 299 void RtpHeaderParser::ParseOneByteExtensionHeader( 300 RTPHeader* header, 301 const RtpHeaderExtensionMap* ptrExtensionMap, 302 const uint8_t* ptrRTPDataExtensionEnd, 303 const uint8_t* ptr) const { 304 if (!ptrExtensionMap) { 305 return; 306 } 307 308 while (ptrRTPDataExtensionEnd - ptr > 0) { 309 // 0 310 // 0 1 2 3 4 5 6 7 311 // +-+-+-+-+-+-+-+-+ 312 // | ID | len | 313 // +-+-+-+-+-+-+-+-+ 314 315 // Note that 'len' is the header extension element length, which is the 316 // number of bytes - 1. 317 const int id = (*ptr & 0xf0) >> 4; 318 const int len = (*ptr & 0x0f); 319 ptr++; 320 321 if (id == 15) { 322 LOG(LS_WARNING) 323 << "RTP extension header 15 encountered. Terminate parsing."; 324 return; 325 } 326 327 RTPExtensionType type; 328 if (ptrExtensionMap->GetType(id, &type) != 0) { 329 // If we encounter an unknown extension, just skip over it. 330 LOG(LS_WARNING) << "Failed to find extension id: " << id; 331 } else { 332 switch (type) { 333 case kRtpExtensionTransmissionTimeOffset: { 334 if (len != 2) { 335 LOG(LS_WARNING) << "Incorrect transmission time offset len: " 336 << len; 337 return; 338 } 339 // 0 1 2 3 340 // 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 341 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 342 // | ID | len=2 | transmission offset | 343 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 344 345 header->extension.transmissionTimeOffset = 346 ByteReader<int32_t, 3>::ReadBigEndian(ptr); 347 header->extension.hasTransmissionTimeOffset = true; 348 break; 349 } 350 case kRtpExtensionAudioLevel: { 351 if (len != 0) { 352 LOG(LS_WARNING) << "Incorrect audio level len: " << len; 353 return; 354 } 355 // 0 1 356 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 357 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 358 // | ID | len=0 |V| level | 359 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 360 // 361 header->extension.audioLevel = ptr[0] & 0x7f; 362 header->extension.voiceActivity = (ptr[0] & 0x80) != 0; 363 header->extension.hasAudioLevel = true; 364 break; 365 } 366 case kRtpExtensionAbsoluteSendTime: { 367 if (len != 2) { 368 LOG(LS_WARNING) << "Incorrect absolute send time len: " << len; 369 return; 370 } 371 // 0 1 2 3 372 // 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 373 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 374 // | ID | len=2 | absolute send time | 375 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 376 377 header->extension.absoluteSendTime = 378 ByteReader<uint32_t, 3>::ReadBigEndian(ptr); 379 header->extension.hasAbsoluteSendTime = true; 380 break; 381 } 382 case kRtpExtensionVideoRotation: { 383 if (len != 0) { 384 LOG(LS_WARNING) 385 << "Incorrect coordination of video coordination len: " << len; 386 return; 387 } 388 // 0 1 389 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 390 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 391 // | ID | len=0 |0 0 0 0 C F R R| 392 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 393 header->extension.hasVideoRotation = true; 394 header->extension.videoRotation = ptr[0]; 395 break; 396 } 397 case kRtpExtensionTransportSequenceNumber: { 398 if (len != 1) { 399 LOG(LS_WARNING) << "Incorrect transport sequence number len: " 400 << len; 401 return; 402 } 403 // 0 1 2 404 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 406 // | ID | L=1 |transport wide sequence number | 407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 408 409 uint16_t sequence_number = ptr[0] << 8; 410 sequence_number += ptr[1]; 411 header->extension.transportSequenceNumber = sequence_number; 412 header->extension.hasTransportSequenceNumber = true; 413 break; 414 } 415 default: { 416 LOG(LS_WARNING) << "Extension type not implemented: " << type; 417 return; 418 } 419 } 420 } 421 ptr += (len + 1); 422 uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr); 423 ptr += num_bytes; 424 } 425 } 426 427 uint8_t RtpHeaderParser::ParsePaddingBytes( 428 const uint8_t* ptrRTPDataExtensionEnd, 429 const uint8_t* ptr) const { 430 uint8_t num_zero_bytes = 0; 431 while (ptrRTPDataExtensionEnd - ptr > 0) { 432 if (*ptr != 0) { 433 return num_zero_bytes; 434 } 435 ptr++; 436 num_zero_bytes++; 437 } 438 return num_zero_bytes; 439 } 440 } // namespace RtpUtility 441 } // namespace webrtc 442