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 ModuleRTPUtility {
     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 void RTPPayload::SetType(RtpVideoCodecTypes videoType) {
    192   type = videoType;
    193 
    194   switch (type) {
    195     case kRtpVideoGeneric:
    196       break;
    197     case kRtpVideoVp8: {
    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;
    207       info.VP8.tID = -1;
    208       info.VP8.layerSync = false;
    209       info.VP8.frameWidth = 0;
    210       info.VP8.frameHeight = 0;
    211       break;
    212     }
    213     default:
    214       break;
    215   }
    216 }
    217 
    218 RTPHeaderParser::RTPHeaderParser(const uint8_t* rtpData,
    219                                  const uint32_t rtpDataLength)
    220   : _ptrRTPDataBegin(rtpData),
    221     _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
    222 }
    223 
    224 RTPHeaderParser::~RTPHeaderParser() {
    225 }
    226 
    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
    232   /*
    233   *       RTCP
    234   *
    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
    247   */
    248 
    249   /* 205       RFC 5104
    250    * FMT 1      NACK       supported
    251    * FMT 2      reserved
    252    * FMT 3      TMMBR      supported
    253    * FMT 4      TMMBN      supported
    254    */
    255 
    256   /* 206      RFC 5104
    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
    265   */
    266 
    267   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
    268   if (length < kRtcpMinHeaderLength) {
    269     return false;
    270   }
    271 
    272   const uint8_t V  = _ptrRTPDataBegin[0] >> 6;
    273   if (V != kRtcpExpectedVersion) {
    274     return false;
    275   }
    276 
    277   const uint8_t  payloadType = _ptrRTPDataBegin[1];
    278   bool RTCP = false;
    279   switch (payloadType) {
    280     case 192:
    281       RTCP = true;
    282       break;
    283     case 193:
    284       // not supported
    285       // pass through and check for a potential RTP packet
    286       break;
    287     case 195:
    288     case 200:
    289     case 201:
    290     case 202:
    291     case 203:
    292     case 204:
    293     case 205:
    294     case 206:
    295     case 207:
    296       RTCP = true;
    297       break;
    298   }
    299   return RTCP;
    300 }
    301 
    302 bool RTPHeaderParser::ParseRtcp(RTPHeader* header) const {
    303   assert(header != NULL);
    304 
    305   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
    306   if (length < kRtcpMinParseLength) {
    307     return false;
    308   }
    309 
    310   const uint8_t V = _ptrRTPDataBegin[0] >> 6;
    311   if (V != kRtcpExpectedVersion) {
    312     return false;
    313   }
    314 
    315   const uint8_t PT = _ptrRTPDataBegin[1];
    316   const uint16_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
    317   const uint8_t* ptr = &_ptrRTPDataBegin[4];
    318 
    319   uint32_t SSRC = *ptr++ << 24;
    320   SSRC += *ptr++ << 16;
    321   SSRC += *ptr++ << 8;
    322   SSRC += *ptr++;
    323 
    324   header->payloadType  = PT;
    325   header->ssrc         = SSRC;
    326   header->headerLength = 4 + (len << 2);
    327 
    328   return true;
    329 }
    330 
    331 bool RTPHeaderParser::Parse(RTPHeader& header,
    332                             RtpHeaderExtensionMap* ptrExtensionMap) const {
    333   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
    334   if (length < kRtpMinParseLength) {
    335     return false;
    336   }
    337 
    338   // Version
    339   const uint8_t V  = _ptrRTPDataBegin[0] >> 6;
    340   // Padding
    341   const bool          P  = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true;
    342   // eXtension
    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;
    346 
    347   const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f;
    348 
    349   const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) +
    350       _ptrRTPDataBegin[3];
    351 
    352   const uint8_t* ptr = &_ptrRTPDataBegin[4];
    353 
    354   uint32_t RTPTimestamp = *ptr++ << 24;
    355   RTPTimestamp += *ptr++ << 16;
    356   RTPTimestamp += *ptr++ << 8;
    357   RTPTimestamp += *ptr++;
    358 
    359   uint32_t SSRC = *ptr++ << 24;
    360   SSRC += *ptr++ << 16;
    361   SSRC += *ptr++ << 8;
    362   SSRC += *ptr++;
    363 
    364   if (V != kRtpExpectedVersion) {
    365     return false;
    366   }
    367 
    368   const uint8_t CSRCocts = CC * 4;
    369 
    370   if ((ptr + CSRCocts) > _ptrRTPDataEnd) {
    371     return false;
    372   }
    373 
    374   header.markerBit      = M;
    375   header.payloadType    = PT;
    376   header.sequenceNumber = sequenceNumber;
    377   header.timestamp      = RTPTimestamp;
    378   header.ssrc           = SSRC;
    379   header.numCSRCs       = CC;
    380   header.paddingLength  = P ? *(_ptrRTPDataEnd - 1) : 0;
    381 
    382   for (unsigned int i = 0; i < CC; ++i) {
    383     uint32_t CSRC = *ptr++ << 24;
    384     CSRC += *ptr++ << 16;
    385     CSRC += *ptr++ << 8;
    386     CSRC += *ptr++;
    387     header.arrOfCSRCs[i] = CSRC;
    388   }
    389 
    390   header.headerLength   = 12 + CSRCocts;
    391 
    392   // If in effect, MAY be omitted for those packets for which the offset
    393   // is zero.
    394   header.extension.hasTransmissionTimeOffset = false;
    395   header.extension.transmissionTimeOffset = 0;
    396 
    397   // May not be present in packet.
    398   header.extension.hasAbsoluteSendTime = false;
    399   header.extension.absoluteSendTime = 0;
    400 
    401   // May not be present in packet.
    402   header.extension.hasAudioLevel = false;
    403   header.extension.audioLevel = 0;
    404 
    405   if (X) {
    406     /* RTP header extension, RFC 3550.
    407      0                   1                   2                   3
    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     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    412     |                        header extension                       |
    413     |                             ....                              |
    414     */
    415     const ptrdiff_t remain = _ptrRTPDataEnd - ptr;
    416     if (remain < 4) {
    417       return false;
    418     }
    419 
    420     header.headerLength += 4;
    421 
    422     uint16_t definedByProfile = *ptr++ << 8;
    423     definedByProfile += *ptr++;
    424 
    425     uint16_t XLen = *ptr++ << 8;
    426     XLen += *ptr++; // in 32 bit words
    427     XLen *= 4; // in octs
    428 
    429     if (remain < (4 + XLen)) {
    430       return false;
    431     }
    432     if (definedByProfile == kRtpOneByteHeaderExtensionId) {
    433       const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
    434       ParseOneByteExtensionHeader(header,
    435                                   ptrExtensionMap,
    436                                   ptrRTPDataExtensionEnd,
    437                                   ptr);
    438     }
    439     header.headerLength += XLen;
    440   }
    441   return true;
    442 }
    443 
    444 void RTPHeaderParser::ParseOneByteExtensionHeader(
    445     RTPHeader& header,
    446     const RtpHeaderExtensionMap* ptrExtensionMap,
    447     const uint8_t* ptrRTPDataExtensionEnd,
    448     const uint8_t* ptr) const {
    449   if (!ptrExtensionMap) {
    450     return;
    451   }
    452 
    453   while (ptrRTPDataExtensionEnd - ptr > 0) {
    454     //  0
    455     //  0 1 2 3 4 5 6 7
    456     // +-+-+-+-+-+-+-+-+
    457     // |  ID   |  len  |
    458     // +-+-+-+-+-+-+-+-+
    459 
    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);
    464     ptr++;
    465 
    466     if (id == 15) {
    467       LOG(LS_WARNING)
    468           << "RTP extension header 15 encountered. Terminate parsing.";
    469       return;
    470     }
    471 
    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);
    477     } else {
    478       switch (type) {
    479         case kRtpExtensionTransmissionTimeOffset: {
    480           if (len != 2) {
    481             LOG(LS_WARNING) << "Incorrect transmission time offset len: "
    482                             << len;
    483             return;
    484           }
    485           //  0                   1                   2                   3
    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           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    490 
    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;
    499           }
    500           header.extension.hasTransmissionTimeOffset = true;
    501           break;
    502         }
    503         case kRtpExtensionAudioLevel: {
    504           if (len != 0) {
    505             LOG(LS_WARNING) << "Incorrect audio level len: " << len;
    506             return;
    507           }
    508           //  0                   1                   2                   3
    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           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    513           //
    514 
    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);
    520 
    521           header.extension.audioLevel = ptr[0];
    522           header.extension.hasAudioLevel = true;
    523           break;
    524         }
    525         case kRtpExtensionAbsoluteSendTime: {
    526           if (len != 2) {
    527             LOG(LS_WARNING) << "Incorrect absolute send time len: " << len;
    528             return;
    529           }
    530           //  0                   1                   2                   3
    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           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    535 
    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;
    541           break;
    542         }
    543         default: {
    544           LOG(LS_WARNING) << "Extension type not implemented: " << type;
    545           return;
    546         }
    547       }
    548     }
    549     ptr += (len + 1);
    550     uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr);
    551     ptr += num_bytes;
    552   }
    553 }
    554 
    555 uint8_t RTPHeaderParser::ParsePaddingBytes(
    556   const uint8_t* ptrRTPDataExtensionEnd,
    557   const uint8_t* ptr) const {
    558 
    559   uint8_t num_zero_bytes = 0;
    560   while (ptrRTPDataExtensionEnd - ptr > 0) {
    561     if (*ptr != 0) {
    562       return num_zero_bytes;
    563     }
    564     ptr++;
    565     num_zero_bytes++;
    566   }
    567   return num_zero_bytes;
    568 }
    569 
    570 RTPPayloadParser::RTPPayloadParser(const RtpVideoCodecTypes videoType,
    571                                    const uint8_t* payloadData,
    572                                    uint16_t payloadDataLength)
    573     : _dataPtr(payloadData),
    574       _dataLength(payloadDataLength),
    575       _videoType(videoType) {}
    576 
    577 RTPPayloadParser::~RTPPayloadParser() {
    578 }
    579 
    580 bool RTPPayloadParser::Parse(RTPPayload& parsedPacket) const {
    581   parsedPacket.SetType(_videoType);
    582 
    583   switch (_videoType) {
    584     case kRtpVideoGeneric:
    585       return ParseGeneric(parsedPacket);
    586     case kRtpVideoVp8:
    587       return ParseVP8(parsedPacket);
    588     default:
    589       return false;
    590   }
    591 }
    592 
    593 bool RTPPayloadParser::ParseGeneric(RTPPayload& /*parsedPacket*/) const {
    594   return false;
    595 }
    596 
    597 //
    598 // VP8 format:
    599 //
    600 // Payload descriptor
    601 //       0 1 2 3 4 5 6 7
    602 //      +-+-+-+-+-+-+-+-+
    603 //      |X|R|N|S|PartID | (REQUIRED)
    604 //      +-+-+-+-+-+-+-+-+
    605 // X:   |I|L|T|K|  RSV  | (OPTIONAL)
    606 //      +-+-+-+-+-+-+-+-+
    607 // I:   |   PictureID   | (OPTIONAL)
    608 //      +-+-+-+-+-+-+-+-+
    609 // L:   |   TL0PICIDX   | (OPTIONAL)
    610 //      +-+-+-+-+-+-+-+-+
    611 // T/K: |TID:Y| KEYIDX  | (OPTIONAL)
    612 //      +-+-+-+-+-+-+-+-+
    613 //
    614 // Payload header (considered part of the actual payload, sent to decoder)
    615 //       0 1 2 3 4 5 6 7
    616 //      +-+-+-+-+-+-+-+-+
    617 //      |Size0|H| VER |P|
    618 //      +-+-+-+-+-+-+-+-+
    619 //      |      ...      |
    620 //      +               +
    621 
    622 bool RTPPayloadParser::ParseVP8(RTPPayload& parsedPacket) const {
    623   RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
    624   const uint8_t* dataPtr = _dataPtr;
    625   int dataLength = _dataLength;
    626 
    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
    632 
    633   if (vp8->partitionID > 8) {
    634     // Weak check for corrupt data: PartID MUST NOT be larger than 8.
    635     return false;
    636   }
    637 
    638   // Advance dataPtr and decrease remaining payload size
    639   dataPtr++;
    640   dataLength--;
    641 
    642   if (extension) {
    643     const int parsedBytes = ParseVP8Extension(vp8, dataPtr, dataLength);
    644     if (parsedBytes < 0) return false;
    645     dataPtr += parsedBytes;
    646     dataLength -= parsedBytes;
    647   }
    648 
    649   if (dataLength <= 0) {
    650     LOG(LS_ERROR) << "Error parsing VP8 payload descriptor!";
    651     return false;
    652   }
    653 
    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;
    657   } else {
    658     parsedPacket.frameType = kPFrame;
    659   }
    660   if (0 != ParseVP8FrameSize(parsedPacket, dataPtr, dataLength)) {
    661     return false;
    662   }
    663   parsedPacket.info.VP8.data       = dataPtr;
    664   parsedPacket.info.VP8.dataLength = dataLength;
    665   return true;
    666 }
    667 
    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.
    673     return 0;
    674   }
    675   if (dataLength < 10) {
    676     // For an I-frame we should always have the uncompressed VP8 header
    677     // in the beginning of the partition.
    678     return -1;
    679   }
    680   RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
    681   vp8->frameWidth = ((dataPtr[7] << 8) + dataPtr[6]) & 0x3FFF;
    682   vp8->frameHeight = ((dataPtr[9] << 8) + dataPtr[8]) & 0x3FFF;
    683   return 0;
    684 }
    685 
    686 int RTPPayloadParser::ParseVP8Extension(RTPPayloadVP8* vp8,
    687                                         const uint8_t* dataPtr,
    688                                         int dataLength) const {
    689   int parsedBytes = 0;
    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
    696 
    697   // Advance dataPtr and decrease remaining payload size
    698   dataPtr++;
    699   parsedBytes++;
    700   dataLength--;
    701 
    702   if (vp8->hasPictureID) {
    703     if (ParseVP8PictureID(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
    704       return -1;
    705     }
    706   }
    707 
    708   if (vp8->hasTl0PicIdx) {
    709     if (ParseVP8Tl0PicIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
    710       return -1;
    711     }
    712   }
    713 
    714   if (vp8->hasTID || vp8->hasKeyIdx) {
    715     if (ParseVP8TIDAndKeyIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
    716       return -1;
    717     }
    718   }
    719   return parsedBytes;
    720 }
    721 
    722 int RTPPayloadParser::ParseVP8PictureID(RTPPayloadVP8* vp8,
    723                                         const uint8_t** dataPtr,
    724                                         int* dataLength,
    725                                         int* parsedBytes) const {
    726   if (*dataLength <= 0) return -1;
    727   vp8->pictureID = (**dataPtr & 0x7F);
    728   if (**dataPtr & 0x80) {
    729     (*dataPtr)++;
    730     (*parsedBytes)++;
    731     if (--(*dataLength) <= 0) return -1;
    732     // PictureID is 15 bits
    733     vp8->pictureID = (vp8->pictureID << 8) +** dataPtr;
    734   }
    735   (*dataPtr)++;
    736   (*parsedBytes)++;
    737   (*dataLength)--;
    738   return 0;
    739 }
    740 
    741 int RTPPayloadParser::ParseVP8Tl0PicIdx(RTPPayloadVP8* vp8,
    742                                         const uint8_t** dataPtr,
    743                                         int* dataLength,
    744                                         int* parsedBytes) const {
    745   if (*dataLength <= 0) return -1;
    746   vp8->tl0PicIdx = **dataPtr;
    747   (*dataPtr)++;
    748   (*parsedBytes)++;
    749   (*dataLength)--;
    750   return 0;
    751 }
    752 
    753 int RTPPayloadParser::ParseVP8TIDAndKeyIdx(RTPPayloadVP8* vp8,
    754                                            const uint8_t** dataPtr,
    755                                            int* dataLength,
    756                                            int* parsedBytes) const {
    757   if (*dataLength <= 0) return -1;
    758   if (vp8->hasTID) {
    759     vp8->tID = ((**dataPtr >> 6) & 0x03);
    760     vp8->layerSync = (**dataPtr & 0x20) ? true : false;  // Y bit
    761   }
    762   if (vp8->hasKeyIdx) {
    763     vp8->keyIdx = (**dataPtr & 0x1F);
    764   }
    765   (*dataPtr)++;
    766   (*parsedBytes)++;
    767   (*dataLength)--;
    768   return 0;
    769 }
    770 
    771 }  // namespace ModuleRTPUtility
    772 
    773 }  // namespace webrtc
    774