2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
14 #include <math.h> // ceil
15 #include <string.h> // memcpy
18 // Order for these headers are important
19 #include <Windows.h> // FILETIME
21 #include <WinSock.h> // timeval
23 #include <MMSystem.h> // timeGetTime
24 #elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
25 #include <sys/time.h> // gettimeofday
28 #if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
32 #include "webrtc/system_wrappers/interface/tick_util.h"
33 #include "webrtc/system_wrappers/interface/logging.h"
35 #if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
36 #define DEBUG_PRINT(...) \
39 sprintf(msg, __VA_ARGS__); \
40 OutputDebugString(msg); \
43 // special fix for visual 2003
44 #define DEBUG_PRINT(exp) ((void)0)
45 #endif // defined(_DEBUG) && defined(_WIN32)
49 RtpData* NullObjectRtpData() {
50 static NullRtpData null_rtp_data;
51 return &null_rtp_data;
54 RtpFeedback* NullObjectRtpFeedback() {
55 static NullRtpFeedback null_rtp_feedback;
56 return &null_rtp_feedback;
59 RtpAudioFeedback* NullObjectRtpAudioFeedback() {
60 static NullRtpAudioFeedback null_rtp_audio_feedback;
61 return &null_rtp_audio_feedback;
64 ReceiveStatistics* NullObjectReceiveStatistics() {
65 static NullReceiveStatistics null_receive_statistics;
66 return &null_receive_statistics;
69 namespace ModuleRTPUtility {
72 kRtcpExpectedVersion = 2,
73 kRtcpMinHeaderLength = 4,
74 kRtcpMinParseLength = 8,
76 kRtpExpectedVersion = 2,
77 kRtpMinParseLength = 12
84 uint32_t GetCurrentRTP(Clock* clock, uint32_t freq) {
85 const bool use_global_clock = (clock == NULL);
86 Clock* local_clock = clock;
87 if (use_global_clock) {
88 local_clock = Clock::GetRealTimeClock();
90 uint32_t secs = 0, frac = 0;
91 local_clock->CurrentNtp(secs, frac);
92 if (use_global_clock) {
95 return ConvertNTPTimeToRTP(secs, frac, freq);
98 uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, uint32_t NTPfrac, uint32_t freq) {
99 float ftemp = (float)NTPfrac / (float)NTP_FRAC;
100 uint32_t tmp = (uint32_t)(ftemp * freq);
101 return NTPsec * freq + tmp;
104 uint32_t ConvertNTPTimeToMS(uint32_t NTPsec, uint32_t NTPfrac) {
106 float ftemp = (float)NTPfrac / (float)NTP_FRAC;
107 uint32_t tmp = (uint32_t)(ftemp * freq);
108 uint32_t MStime = NTPsec * freq + tmp;
113 * Misc utility routines
117 bool StringCompare(const char* str1, const char* str2,
118 const uint32_t length) {
119 return (_strnicmp(str1, str2, length) == 0) ? true : false;
121 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
122 bool StringCompare(const char* str1, const char* str2,
123 const uint32_t length) {
124 return (strncasecmp(str1, str2, length) == 0) ? true : false;
129 All integer fields are carried in network byte order, that is, most
130 significant byte (octet) first. AKA big-endian.
132 void AssignUWord32ToBuffer(uint8_t* dataBuffer, uint32_t value) {
133 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
134 dataBuffer[0] = static_cast<uint8_t>(value >> 24);
135 dataBuffer[1] = static_cast<uint8_t>(value >> 16);
136 dataBuffer[2] = static_cast<uint8_t>(value >> 8);
137 dataBuffer[3] = static_cast<uint8_t>(value);
139 uint32_t* ptr = reinterpret_cast<uint32_t*>(dataBuffer);
144 void AssignUWord24ToBuffer(uint8_t* dataBuffer, uint32_t value) {
145 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
146 dataBuffer[0] = static_cast<uint8_t>(value >> 16);
147 dataBuffer[1] = static_cast<uint8_t>(value >> 8);
148 dataBuffer[2] = static_cast<uint8_t>(value);
150 dataBuffer[0] = static_cast<uint8_t>(value);
151 dataBuffer[1] = static_cast<uint8_t>(value >> 8);
152 dataBuffer[2] = static_cast<uint8_t>(value >> 16);
156 void AssignUWord16ToBuffer(uint8_t* dataBuffer, uint16_t value) {
157 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
158 dataBuffer[0] = static_cast<uint8_t>(value >> 8);
159 dataBuffer[1] = static_cast<uint8_t>(value);
161 uint16_t* ptr = reinterpret_cast<uint16_t*>(dataBuffer);
166 uint16_t BufferToUWord16(const uint8_t* dataBuffer) {
167 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
168 return (dataBuffer[0] << 8) + dataBuffer[1];
170 return *reinterpret_cast<const uint16_t*>(dataBuffer);
174 uint32_t BufferToUWord24(const uint8_t* dataBuffer) {
175 return (dataBuffer[0] << 16) + (dataBuffer[1] << 8) + dataBuffer[2];
178 uint32_t BufferToUWord32(const uint8_t* dataBuffer) {
179 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
180 return (dataBuffer[0] << 24) + (dataBuffer[1] << 16) + (dataBuffer[2] << 8) +
183 return *reinterpret_cast<const uint32_t*>(dataBuffer);
187 uint32_t pow2(uint8_t exp) {
191 void RTPPayload::SetType(RtpVideoCodecTypes videoType) {
195 case kRtpVideoGeneric:
198 info.VP8.nonReferenceFrame = false;
199 info.VP8.beginningOfPartition = false;
200 info.VP8.partitionID = 0;
201 info.VP8.hasPictureID = false;
202 info.VP8.hasTl0PicIdx = false;
203 info.VP8.hasTID = false;
204 info.VP8.hasKeyIdx = false;
205 info.VP8.pictureID = -1;
206 info.VP8.tl0PicIdx = -1;
208 info.VP8.layerSync = false;
209 info.VP8.frameWidth = 0;
210 info.VP8.frameHeight = 0;
218 RTPHeaderParser::RTPHeaderParser(const uint8_t* rtpData,
219 const uint32_t rtpDataLength)
220 : _ptrRTPDataBegin(rtpData),
221 _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
224 RTPHeaderParser::~RTPHeaderParser() {
227 bool RTPHeaderParser::RTCP() const {
228 // 72 to 76 is reserved for RTP
229 // 77 to 79 is not reserver but they are not assigned we will block them
230 // for RTCP 200 SR == marker bit + 72
231 // for RTCP 204 APP == marker bit + 76
235 * FIR full INTRA-frame request 192 [RFC2032] supported
236 * NACK negative acknowledgement 193 [RFC2032]
237 * IJ Extended inter-arrival jitter report 195 [RFC-ietf-avt-rtp-toff
238 * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
239 * SR sender report 200 [RFC3551] supported
240 * RR receiver report 201 [RFC3551] supported
241 * SDES source description 202 [RFC3551] supported
242 * BYE goodbye 203 [RFC3551] supported
243 * APP application-defined 204 [RFC3551] ignored
244 * RTPFB Transport layer FB message 205 [RFC4585] supported
245 * PSFB Payload-specific FB message 206 [RFC4585] supported
246 * XR extended report 207 [RFC3611] supported
250 * FMT 1 NACK supported
252 * FMT 3 TMMBR supported
253 * FMT 4 TMMBN supported
257 * FMT 1: Picture Loss Indication (PLI) supported
258 * FMT 2: Slice Lost Indication (SLI)
259 * FMT 3: Reference Picture Selection Indication (RPSI)
260 * FMT 4: Full Intra Request (FIR) Command supported
261 * FMT 5: Temporal-Spatial Trade-off Request (TSTR)
262 * FMT 6: Temporal-Spatial Trade-off Notification (TSTN)
263 * FMT 7: Video Back Channel Message (VBCM)
264 * FMT 15: Application layer FB message
267 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
268 if (length < kRtcpMinHeaderLength) {
272 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
273 if (V != kRtcpExpectedVersion) {
277 const uint8_t payloadType = _ptrRTPDataBegin[1];
279 switch (payloadType) {
285 // pass through and check for a potential RTP packet
302 bool RTPHeaderParser::ParseRtcp(RTPHeader* header) const {
303 assert(header != NULL);
305 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
306 if (length < kRtcpMinParseLength) {
310 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
311 if (V != kRtcpExpectedVersion) {
315 const uint8_t PT = _ptrRTPDataBegin[1];
316 const uint16_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
317 const uint8_t* ptr = &_ptrRTPDataBegin[4];
319 uint32_t SSRC = *ptr++ << 24;
320 SSRC += *ptr++ << 16;
324 header->payloadType = PT;
326 header->headerLength = 4 + (len << 2);
331 bool RTPHeaderParser::Parse(RTPHeader& header,
332 RtpHeaderExtensionMap* ptrExtensionMap) const {
333 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
334 if (length < kRtpMinParseLength) {
339 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
341 const bool P = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true;
343 const bool X = ((_ptrRTPDataBegin[0] & 0x10) == 0) ? false : true;
344 const uint8_t CC = _ptrRTPDataBegin[0] & 0x0f;
345 const bool M = ((_ptrRTPDataBegin[1] & 0x80) == 0) ? false : true;
347 const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f;
349 const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) +
352 const uint8_t* ptr = &_ptrRTPDataBegin[4];
354 uint32_t RTPTimestamp = *ptr++ << 24;
355 RTPTimestamp += *ptr++ << 16;
356 RTPTimestamp += *ptr++ << 8;
357 RTPTimestamp += *ptr++;
359 uint32_t SSRC = *ptr++ << 24;
360 SSRC += *ptr++ << 16;
364 if (V != kRtpExpectedVersion) {
368 const uint8_t CSRCocts = CC * 4;
370 if ((ptr + CSRCocts) > _ptrRTPDataEnd) {
374 header.markerBit = M;
375 header.payloadType = PT;
376 header.sequenceNumber = sequenceNumber;
377 header.timestamp = RTPTimestamp;
379 header.numCSRCs = CC;
380 header.paddingLength = P ? *(_ptrRTPDataEnd - 1) : 0;
382 for (unsigned int i = 0; i < CC; ++i) {
383 uint32_t CSRC = *ptr++ << 24;
384 CSRC += *ptr++ << 16;
387 header.arrOfCSRCs[i] = CSRC;
390 header.headerLength = 12 + CSRCocts;
392 // If in effect, MAY be omitted for those packets for which the offset
394 header.extension.hasTransmissionTimeOffset = false;
395 header.extension.transmissionTimeOffset = 0;
397 // May not be present in packet.
398 header.extension.hasAbsoluteSendTime = false;
399 header.extension.absoluteSendTime = 0;
401 // May not be present in packet.
402 header.extension.hasAudioLevel = false;
403 header.extension.audioLevel = 0;
406 /* RTP header extension, RFC 3550.
408 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
409 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
410 | defined by profile | length |
411 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
415 const ptrdiff_t remain = _ptrRTPDataEnd - ptr;
420 header.headerLength += 4;
422 uint16_t definedByProfile = *ptr++ << 8;
423 definedByProfile += *ptr++;
425 uint16_t XLen = *ptr++ << 8;
426 XLen += *ptr++; // in 32 bit words
427 XLen *= 4; // in octs
429 if (remain < (4 + XLen)) {
432 if (definedByProfile == kRtpOneByteHeaderExtensionId) {
433 const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
434 ParseOneByteExtensionHeader(header,
436 ptrRTPDataExtensionEnd,
439 header.headerLength += XLen;
444 void RTPHeaderParser::ParseOneByteExtensionHeader(
446 const RtpHeaderExtensionMap* ptrExtensionMap,
447 const uint8_t* ptrRTPDataExtensionEnd,
448 const uint8_t* ptr) const {
449 if (!ptrExtensionMap) {
453 while (ptrRTPDataExtensionEnd - ptr > 0) {
460 // Note that 'len' is the header extension element length, which is the
461 // number of bytes - 1.
462 const uint8_t id = (*ptr & 0xf0) >> 4;
463 const uint8_t len = (*ptr & 0x0f);
468 << "RTP extension header 15 encountered. Terminate parsing.";
472 RTPExtensionType type;
473 if (ptrExtensionMap->GetType(id, &type) != 0) {
474 // If we encounter an unknown extension, just skip over it.
475 LOG(LS_WARNING) << "Failed to find extension id: "
476 << static_cast<int>(id);
479 case kRtpExtensionTransmissionTimeOffset: {
481 LOG(LS_WARNING) << "Incorrect transmission time offset len: "
486 // 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
487 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
488 // | ID | len=2 | transmission offset |
489 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
491 int32_t transmissionTimeOffset = ptr[0] << 16;
492 transmissionTimeOffset += ptr[1] << 8;
493 transmissionTimeOffset += ptr[2];
494 header.extension.transmissionTimeOffset =
495 transmissionTimeOffset;
496 if (transmissionTimeOffset & 0x800000) {
497 // Negative offset, correct sign for Word24 to Word32.
498 header.extension.transmissionTimeOffset |= 0xFF000000;
500 header.extension.hasTransmissionTimeOffset = true;
503 case kRtpExtensionAudioLevel: {
505 LOG(LS_WARNING) << "Incorrect audio level len: " << len;
509 // 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
510 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511 // | ID | len=0 |V| level | 0x00 | 0x00 |
512 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
515 // Parse out the fields but only use it for debugging for now.
516 // const uint8_t V = (*ptr & 0x80) >> 7;
517 // const uint8_t level = (*ptr & 0x7f);
518 // DEBUG_PRINT("RTP_AUDIO_LEVEL_UNIQUE_ID: ID=%u, len=%u, V=%u,
519 // level=%u", ID, len, V, level);
521 header.extension.audioLevel = ptr[0];
522 header.extension.hasAudioLevel = true;
525 case kRtpExtensionAbsoluteSendTime: {
527 LOG(LS_WARNING) << "Incorrect absolute send time len: " << len;
531 // 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
532 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
533 // | ID | len=2 | absolute send time |
534 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
536 uint32_t absoluteSendTime = ptr[0] << 16;
537 absoluteSendTime += ptr[1] << 8;
538 absoluteSendTime += ptr[2];
539 header.extension.absoluteSendTime = absoluteSendTime;
540 header.extension.hasAbsoluteSendTime = true;
544 LOG(LS_WARNING) << "Extension type not implemented: " << type;
550 uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr);
555 uint8_t RTPHeaderParser::ParsePaddingBytes(
556 const uint8_t* ptrRTPDataExtensionEnd,
557 const uint8_t* ptr) const {
559 uint8_t num_zero_bytes = 0;
560 while (ptrRTPDataExtensionEnd - ptr > 0) {
562 return num_zero_bytes;
567 return num_zero_bytes;
570 RTPPayloadParser::RTPPayloadParser(const RtpVideoCodecTypes videoType,
571 const uint8_t* payloadData,
572 uint16_t payloadDataLength)
573 : _dataPtr(payloadData),
574 _dataLength(payloadDataLength),
575 _videoType(videoType) {}
577 RTPPayloadParser::~RTPPayloadParser() {
580 bool RTPPayloadParser::Parse(RTPPayload& parsedPacket) const {
581 parsedPacket.SetType(_videoType);
583 switch (_videoType) {
584 case kRtpVideoGeneric:
585 return ParseGeneric(parsedPacket);
587 return ParseVP8(parsedPacket);
593 bool RTPPayloadParser::ParseGeneric(RTPPayload& /*parsedPacket*/) const {
600 // Payload descriptor
603 // |X|R|N|S|PartID | (REQUIRED)
605 // X: |I|L|T|K| RSV | (OPTIONAL)
607 // I: | PictureID | (OPTIONAL)
609 // L: | TL0PICIDX | (OPTIONAL)
611 // T/K: |TID:Y| KEYIDX | (OPTIONAL)
614 // Payload header (considered part of the actual payload, sent to decoder)
622 bool RTPPayloadParser::ParseVP8(RTPPayload& parsedPacket) const {
623 RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
624 const uint8_t* dataPtr = _dataPtr;
625 int dataLength = _dataLength;
627 // Parse mandatory first byte of payload descriptor
628 bool extension = (*dataPtr & 0x80) ? true : false; // X bit
629 vp8->nonReferenceFrame = (*dataPtr & 0x20) ? true : false; // N bit
630 vp8->beginningOfPartition = (*dataPtr & 0x10) ? true : false; // S bit
631 vp8->partitionID = (*dataPtr & 0x0F); // PartID field
633 if (vp8->partitionID > 8) {
634 // Weak check for corrupt data: PartID MUST NOT be larger than 8.
638 // Advance dataPtr and decrease remaining payload size
643 const int parsedBytes = ParseVP8Extension(vp8, dataPtr, dataLength);
644 if (parsedBytes < 0) return false;
645 dataPtr += parsedBytes;
646 dataLength -= parsedBytes;
649 if (dataLength <= 0) {
650 LOG(LS_ERROR) << "Error parsing VP8 payload descriptor!";
654 // Read P bit from payload header (only at beginning of first partition)
655 if (dataLength > 0 && vp8->beginningOfPartition && vp8->partitionID == 0) {
656 parsedPacket.frameType = (*dataPtr & 0x01) ? kPFrame : kIFrame;
658 parsedPacket.frameType = kPFrame;
660 if (0 != ParseVP8FrameSize(parsedPacket, dataPtr, dataLength)) {
663 parsedPacket.info.VP8.data = dataPtr;
664 parsedPacket.info.VP8.dataLength = dataLength;
668 int RTPPayloadParser::ParseVP8FrameSize(RTPPayload& parsedPacket,
669 const uint8_t* dataPtr,
670 int dataLength) const {
671 if (parsedPacket.frameType != kIFrame) {
672 // Included in payload header for I-frames.
675 if (dataLength < 10) {
676 // For an I-frame we should always have the uncompressed VP8 header
677 // in the beginning of the partition.
680 RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
681 vp8->frameWidth = ((dataPtr[7] << 8) + dataPtr[6]) & 0x3FFF;
682 vp8->frameHeight = ((dataPtr[9] << 8) + dataPtr[8]) & 0x3FFF;
686 int RTPPayloadParser::ParseVP8Extension(RTPPayloadVP8* vp8,
687 const uint8_t* dataPtr,
688 int dataLength) const {
690 if (dataLength <= 0) return -1;
691 // Optional X field is present
692 vp8->hasPictureID = (*dataPtr & 0x80) ? true : false; // I bit
693 vp8->hasTl0PicIdx = (*dataPtr & 0x40) ? true : false; // L bit
694 vp8->hasTID = (*dataPtr & 0x20) ? true : false; // T bit
695 vp8->hasKeyIdx = (*dataPtr & 0x10) ? true : false; // K bit
697 // Advance dataPtr and decrease remaining payload size
702 if (vp8->hasPictureID) {
703 if (ParseVP8PictureID(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
708 if (vp8->hasTl0PicIdx) {
709 if (ParseVP8Tl0PicIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
714 if (vp8->hasTID || vp8->hasKeyIdx) {
715 if (ParseVP8TIDAndKeyIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
722 int RTPPayloadParser::ParseVP8PictureID(RTPPayloadVP8* vp8,
723 const uint8_t** dataPtr,
725 int* parsedBytes) const {
726 if (*dataLength <= 0) return -1;
727 vp8->pictureID = (**dataPtr & 0x7F);
728 if (**dataPtr & 0x80) {
731 if (--(*dataLength) <= 0) return -1;
732 // PictureID is 15 bits
733 vp8->pictureID = (vp8->pictureID << 8) +** dataPtr;
741 int RTPPayloadParser::ParseVP8Tl0PicIdx(RTPPayloadVP8* vp8,
742 const uint8_t** dataPtr,
744 int* parsedBytes) const {
745 if (*dataLength <= 0) return -1;
746 vp8->tl0PicIdx = **dataPtr;
753 int RTPPayloadParser::ParseVP8TIDAndKeyIdx(RTPPayloadVP8* vp8,
754 const uint8_t** dataPtr,
756 int* parsedBytes) const {
757 if (*dataLength <= 0) return -1;
759 vp8->tID = ((**dataPtr >> 6) & 0x03);
760 vp8->layerSync = (**dataPtr & 0x20) ? true : false; // Y bit
762 if (vp8->hasKeyIdx) {
763 vp8->keyIdx = (**dataPtr & 0x1F);
771 } // namespace ModuleRTPUtility
773 } // namespace webrtc