Home | History | Annotate | Download | only in source
      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 <assert.h>
     14 #include <math.h>  // ceil
     15 #include <string.h>  // memcpy
     16 
     17 #if defined(_WIN32)
     18 // Order for these headers are important
     19 #include <Windows.h>  // FILETIME
     20 
     21 #include <WinSock.h>  // timeval
     22 
     23 #include <MMSystem.h>  // timeGetTime
     24 #elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
     25 #include <sys/time.h>  // gettimeofday
     26 #include <time.h>
     27 #endif
     28 #if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
     29 #include <stdio.h>
     30 #endif
     31 
     32 #include "webrtc/system_wrappers/interface/tick_util.h"
     33 #include "webrtc/system_wrappers/interface/logging.h"
     34 
     35 #if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
     36 #define DEBUG_PRINT(...)           \
     37   {                                \
     38     char msg[256];                 \
     39     sprintf(msg, __VA_ARGS__);     \
     40     OutputDebugString(msg);        \
     41   }
     42 #else
     43 // special fix for visual 2003
     44 #define DEBUG_PRINT(exp)        ((void)0)
     45 #endif  // defined(_DEBUG) && defined(_WIN32)
     46 
     47 namespace webrtc {
     48 
     49 RtpData* NullObjectRtpData() {
     50   static NullRtpData null_rtp_data;
     51   return &null_rtp_data;
     52 }
     53 
     54 RtpFeedback* NullObjectRtpFeedback() {
     55   static NullRtpFeedback null_rtp_feedback;
     56   return &null_rtp_feedback;
     57 }
     58 
     59 RtpAudioFeedback* NullObjectRtpAudioFeedback() {
     60   static NullRtpAudioFeedback null_rtp_audio_feedback;
     61   return &null_rtp_audio_feedback;
     62 }
     63 
     64 ReceiveStatistics* NullObjectReceiveStatistics() {
     65   static NullReceiveStatistics null_receive_statistics;
     66   return &null_receive_statistics;
     67 }
     68 
     69 namespace RtpUtility {
     70 
     71 enum {
     72   kRtcpExpectedVersion = 2,
     73   kRtcpMinHeaderLength = 4,
     74   kRtcpMinParseLength = 8,
     75 
     76   kRtpExpectedVersion = 2,
     77   kRtpMinParseLength = 12
     78 };
     79 
     80 /*
     81  * Time routines.
     82  */
     83 
     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();
     89   }
     90   uint32_t secs = 0, frac = 0;
     91   local_clock->CurrentNtp(secs, frac);
     92   if (use_global_clock) {
     93     delete local_clock;
     94   }
     95   return ConvertNTPTimeToRTP(secs, frac, freq);
     96 }
     97 
     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;
    102 }
    103 
    104 uint32_t ConvertNTPTimeToMS(uint32_t NTPsec, uint32_t NTPfrac) {
    105   int freq = 1000;
    106   float ftemp = (float)NTPfrac / (float)NTP_FRAC;
    107   uint32_t tmp = (uint32_t)(ftemp * freq);
    108   uint32_t MStime = NTPsec * freq + tmp;
    109   return MStime;
    110 }
    111 
    112 /*
    113  * Misc utility routines
    114  */
    115 
    116 #if defined(_WIN32)
    117 bool StringCompare(const char* str1, const char* str2,
    118                    const uint32_t length) {
    119   return (_strnicmp(str1, str2, length) == 0) ? true : false;
    120 }
    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;
    125 }
    126 #endif
    127 
    128 /* for RTP/RTCP
    129     All integer fields are carried in network byte order, that is, most
    130     significant byte (octet) first.  AKA big-endian.
    131 */
    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);
    138 #else
    139   uint32_t* ptr = reinterpret_cast<uint32_t*>(dataBuffer);
    140   ptr[0] = value;
    141 #endif
    142 }
    143 
    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);
    149 #else
    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);
    153 #endif
    154 }
    155 
    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);
    160 #else
    161   uint16_t* ptr = reinterpret_cast<uint16_t*>(dataBuffer);
    162   ptr[0] = value;
    163 #endif
    164 }
    165 
    166 uint16_t BufferToUWord16(const uint8_t* dataBuffer) {
    167 #if defined(WEBRTC_ARCH_LITTLE_ENDIAN)
    168   return (dataBuffer[0] << 8) + dataBuffer[1];
    169 #else
    170   return *reinterpret_cast<const uint16_t*>(dataBuffer);
    171 #endif
    172 }
    173 
    174 uint32_t BufferToUWord24(const uint8_t* dataBuffer) {
    175   return (dataBuffer[0] << 16) + (dataBuffer[1] << 8) + dataBuffer[2];
    176 }
    177 
    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) +
    181       dataBuffer[3];
    182 #else
    183   return *reinterpret_cast<const uint32_t*>(dataBuffer);
    184 #endif
    185 }
    186 
    187 uint32_t pow2(uint8_t exp) {
    188   return 1 << exp;
    189 }
    190 
    191 RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
    192                                  const size_t rtpDataLength)
    193     : _ptrRTPDataBegin(rtpData),
    194       _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
    195 }
    196 
    197 RtpHeaderParser::~RtpHeaderParser() {
    198 }
    199 
    200 bool RtpHeaderParser::RTCP() const {
    201   // 72 to 76 is reserved for RTP
    202   // 77 to 79 is not reserver but  they are not assigned we will block them
    203   // for RTCP 200 SR  == marker bit + 72
    204   // for RTCP 204 APP == marker bit + 76
    205   /*
    206   *       RTCP
    207   *
    208   * FIR      full INTRA-frame request             192     [RFC2032]   supported
    209   * NACK     negative acknowledgement             193     [RFC2032]
    210   * IJ       Extended inter-arrival jitter report 195     [RFC-ietf-avt-rtp-toff
    211   * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
    212   * SR       sender report                        200     [RFC3551]   supported
    213   * RR       receiver report                      201     [RFC3551]   supported
    214   * SDES     source description                   202     [RFC3551]   supported
    215   * BYE      goodbye                              203     [RFC3551]   supported
    216   * APP      application-defined                  204     [RFC3551]   ignored
    217   * RTPFB    Transport layer FB message           205     [RFC4585]   supported
    218   * PSFB     Payload-specific FB message          206     [RFC4585]   supported
    219   * XR       extended report                      207     [RFC3611]   supported
    220   */
    221 
    222   /* 205       RFC 5104
    223    * FMT 1      NACK       supported
    224    * FMT 2      reserved
    225    * FMT 3      TMMBR      supported
    226    * FMT 4      TMMBN      supported
    227    */
    228 
    229   /* 206      RFC 5104
    230   * FMT 1:     Picture Loss Indication (PLI)                      supported
    231   * FMT 2:     Slice Lost Indication (SLI)
    232   * FMT 3:     Reference Picture Selection Indication (RPSI)
    233   * FMT 4:     Full Intra Request (FIR) Command                   supported
    234   * FMT 5:     Temporal-Spatial Trade-off Request (TSTR)
    235   * FMT 6:     Temporal-Spatial Trade-off Notification (TSTN)
    236   * FMT 7:     Video Back Channel Message (VBCM)
    237   * FMT 15:    Application layer FB message
    238   */
    239 
    240   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
    241   if (length < kRtcpMinHeaderLength) {
    242     return false;
    243   }
    244 
    245   const uint8_t V  = _ptrRTPDataBegin[0] >> 6;
    246   if (V != kRtcpExpectedVersion) {
    247     return false;
    248   }
    249 
    250   const uint8_t  payloadType = _ptrRTPDataBegin[1];
    251   bool RTCP = false;
    252   switch (payloadType) {
    253     case 192:
    254       RTCP = true;
    255       break;
    256     case 193:
    257       // not supported
    258       // pass through and check for a potential RTP packet
    259       break;
    260     case 195:
    261     case 200:
    262     case 201:
    263     case 202:
    264     case 203:
    265     case 204:
    266     case 205:
    267     case 206:
    268     case 207:
    269       RTCP = true;
    270       break;
    271   }
    272   return RTCP;
    273 }
    274 
    275 bool RtpHeaderParser::ParseRtcp(RTPHeader* header) const {
    276   assert(header != NULL);
    277 
    278   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
    279   if (length < kRtcpMinParseLength) {
    280     return false;
    281   }
    282 
    283   const uint8_t V = _ptrRTPDataBegin[0] >> 6;
    284   if (V != kRtcpExpectedVersion) {
    285     return false;
    286   }
    287 
    288   const uint8_t PT = _ptrRTPDataBegin[1];
    289   const uint16_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
    290   const uint8_t* ptr = &_ptrRTPDataBegin[4];
    291 
    292   uint32_t SSRC = *ptr++ << 24;
    293   SSRC += *ptr++ << 16;
    294   SSRC += *ptr++ << 8;
    295   SSRC += *ptr++;
    296 
    297   header->payloadType  = PT;
    298   header->ssrc         = SSRC;
    299   header->headerLength = 4 + (len << 2);
    300 
    301   return true;
    302 }
    303 
    304 bool RtpHeaderParser::Parse(RTPHeader& header,
    305                             RtpHeaderExtensionMap* ptrExtensionMap) const {
    306   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
    307   if (length < kRtpMinParseLength) {
    308     return false;
    309   }
    310 
    311   // Version
    312   const uint8_t V  = _ptrRTPDataBegin[0] >> 6;
    313   // Padding
    314   const bool          P  = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true;
    315   // eXtension
    316   const bool          X  = ((_ptrRTPDataBegin[0] & 0x10) == 0) ? false : true;
    317   const uint8_t CC = _ptrRTPDataBegin[0] & 0x0f;
    318   const bool          M  = ((_ptrRTPDataBegin[1] & 0x80) == 0) ? false : true;
    319 
    320   const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f;
    321 
    322   const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) +
    323       _ptrRTPDataBegin[3];
    324 
    325   const uint8_t* ptr = &_ptrRTPDataBegin[4];
    326 
    327   uint32_t RTPTimestamp = *ptr++ << 24;
    328   RTPTimestamp += *ptr++ << 16;
    329   RTPTimestamp += *ptr++ << 8;
    330   RTPTimestamp += *ptr++;
    331 
    332   uint32_t SSRC = *ptr++ << 24;
    333   SSRC += *ptr++ << 16;
    334   SSRC += *ptr++ << 8;
    335   SSRC += *ptr++;
    336 
    337   if (V != kRtpExpectedVersion) {
    338     return false;
    339   }
    340 
    341   const uint8_t CSRCocts = CC * 4;
    342 
    343   if ((ptr + CSRCocts) > _ptrRTPDataEnd) {
    344     return false;
    345   }
    346 
    347   header.markerBit      = M;
    348   header.payloadType    = PT;
    349   header.sequenceNumber = sequenceNumber;
    350   header.timestamp      = RTPTimestamp;
    351   header.ssrc           = SSRC;
    352   header.numCSRCs       = CC;
    353   header.paddingLength  = P ? *(_ptrRTPDataEnd - 1) : 0;
    354 
    355   for (unsigned int i = 0; i < CC; ++i) {
    356     uint32_t CSRC = *ptr++ << 24;
    357     CSRC += *ptr++ << 16;
    358     CSRC += *ptr++ << 8;
    359     CSRC += *ptr++;
    360     header.arrOfCSRCs[i] = CSRC;
    361   }
    362 
    363   header.headerLength   = 12 + CSRCocts;
    364 
    365   // If in effect, MAY be omitted for those packets for which the offset
    366   // is zero.
    367   header.extension.hasTransmissionTimeOffset = false;
    368   header.extension.transmissionTimeOffset = 0;
    369 
    370   // May not be present in packet.
    371   header.extension.hasAbsoluteSendTime = false;
    372   header.extension.absoluteSendTime = 0;
    373 
    374   // May not be present in packet.
    375   header.extension.hasAudioLevel = false;
    376   header.extension.audioLevel = 0;
    377 
    378   if (X) {
    379     /* RTP header extension, RFC 3550.
    380      0                   1                   2                   3
    381      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
    382     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    383     |      defined by profile       |           length              |
    384     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    385     |                        header extension                       |
    386     |                             ....                              |
    387     */
    388     const ptrdiff_t remain = _ptrRTPDataEnd - ptr;
    389     if (remain < 4) {
    390       return false;
    391     }
    392 
    393     header.headerLength += 4;
    394 
    395     uint16_t definedByProfile = *ptr++ << 8;
    396     definedByProfile += *ptr++;
    397 
    398     uint16_t XLen = *ptr++ << 8;
    399     XLen += *ptr++; // in 32 bit words
    400     XLen *= 4; // in octs
    401 
    402     if (remain < (4 + XLen)) {
    403       return false;
    404     }
    405     if (definedByProfile == kRtpOneByteHeaderExtensionId) {
    406       const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
    407       ParseOneByteExtensionHeader(header,
    408                                   ptrExtensionMap,
    409                                   ptrRTPDataExtensionEnd,
    410                                   ptr);
    411     }
    412     header.headerLength += XLen;
    413   }
    414   return true;
    415 }
    416 
    417 void RtpHeaderParser::ParseOneByteExtensionHeader(
    418     RTPHeader& header,
    419     const RtpHeaderExtensionMap* ptrExtensionMap,
    420     const uint8_t* ptrRTPDataExtensionEnd,
    421     const uint8_t* ptr) const {
    422   if (!ptrExtensionMap) {
    423     return;
    424   }
    425 
    426   while (ptrRTPDataExtensionEnd - ptr > 0) {
    427     //  0
    428     //  0 1 2 3 4 5 6 7
    429     // +-+-+-+-+-+-+-+-+
    430     // |  ID   |  len  |
    431     // +-+-+-+-+-+-+-+-+
    432 
    433     // Note that 'len' is the header extension element length, which is the
    434     // number of bytes - 1.
    435     const uint8_t id = (*ptr & 0xf0) >> 4;
    436     const uint8_t len = (*ptr & 0x0f);
    437     ptr++;
    438 
    439     if (id == 15) {
    440       LOG(LS_WARNING)
    441           << "RTP extension header 15 encountered. Terminate parsing.";
    442       return;
    443     }
    444 
    445     RTPExtensionType type;
    446     if (ptrExtensionMap->GetType(id, &type) != 0) {
    447       // If we encounter an unknown extension, just skip over it.
    448       LOG(LS_WARNING) << "Failed to find extension id: "
    449                       << static_cast<int>(id);
    450     } else {
    451       switch (type) {
    452         case kRtpExtensionTransmissionTimeOffset: {
    453           if (len != 2) {
    454             LOG(LS_WARNING) << "Incorrect transmission time offset len: "
    455                             << len;
    456             return;
    457           }
    458           //  0                   1                   2                   3
    459           //  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
    460           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    461           // |  ID   | len=2 |              transmission offset              |
    462           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    463 
    464           int32_t transmissionTimeOffset = ptr[0] << 16;
    465           transmissionTimeOffset += ptr[1] << 8;
    466           transmissionTimeOffset += ptr[2];
    467           header.extension.transmissionTimeOffset =
    468               transmissionTimeOffset;
    469           if (transmissionTimeOffset & 0x800000) {
    470             // Negative offset, correct sign for Word24 to Word32.
    471             header.extension.transmissionTimeOffset |= 0xFF000000;
    472           }
    473           header.extension.hasTransmissionTimeOffset = true;
    474           break;
    475         }
    476         case kRtpExtensionAudioLevel: {
    477           if (len != 0) {
    478             LOG(LS_WARNING) << "Incorrect audio level len: " << len;
    479             return;
    480           }
    481           //  0                   1                   2                   3
    482           //  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
    483           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    484           // |  ID   | len=0 |V|   level     |      0x00     |      0x00     |
    485           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    486           //
    487 
    488           // Parse out the fields but only use it for debugging for now.
    489           // const uint8_t V = (*ptr & 0x80) >> 7;
    490           // const uint8_t level = (*ptr & 0x7f);
    491           // DEBUG_PRINT("RTP_AUDIO_LEVEL_UNIQUE_ID: ID=%u, len=%u, V=%u,
    492           // level=%u", ID, len, V, level);
    493 
    494           header.extension.audioLevel = ptr[0];
    495           header.extension.hasAudioLevel = true;
    496           break;
    497         }
    498         case kRtpExtensionAbsoluteSendTime: {
    499           if (len != 2) {
    500             LOG(LS_WARNING) << "Incorrect absolute send time len: " << len;
    501             return;
    502           }
    503           //  0                   1                   2                   3
    504           //  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
    505           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    506           // |  ID   | len=2 |              absolute send time               |
    507           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    508 
    509           uint32_t absoluteSendTime = ptr[0] << 16;
    510           absoluteSendTime += ptr[1] << 8;
    511           absoluteSendTime += ptr[2];
    512           header.extension.absoluteSendTime = absoluteSendTime;
    513           header.extension.hasAbsoluteSendTime = true;
    514           break;
    515         }
    516         default: {
    517           LOG(LS_WARNING) << "Extension type not implemented: " << type;
    518           return;
    519         }
    520       }
    521     }
    522     ptr += (len + 1);
    523     uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr);
    524     ptr += num_bytes;
    525   }
    526 }
    527 
    528 uint8_t RtpHeaderParser::ParsePaddingBytes(
    529     const uint8_t* ptrRTPDataExtensionEnd,
    530     const uint8_t* ptr) const {
    531   uint8_t num_zero_bytes = 0;
    532   while (ptrRTPDataExtensionEnd - ptr > 0) {
    533     if (*ptr != 0) {
    534       return num_zero_bytes;
    535     }
    536     ptr++;
    537     num_zero_bytes++;
    538   }
    539   return num_zero_bytes;
    540 }
    541 }  // namespace RtpUtility
    542 
    543 }  // namespace webrtc
    544