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 <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