• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NullObjectRtpData()49 RtpData* NullObjectRtpData() {
50   static NullRtpData null_rtp_data;
51   return &null_rtp_data;
52 }
53 
NullObjectRtpFeedback()54 RtpFeedback* NullObjectRtpFeedback() {
55   static NullRtpFeedback null_rtp_feedback;
56   return &null_rtp_feedback;
57 }
58 
NullObjectRtpAudioFeedback()59 RtpAudioFeedback* NullObjectRtpAudioFeedback() {
60   static NullRtpAudioFeedback null_rtp_audio_feedback;
61   return &null_rtp_audio_feedback;
62 }
63 
NullObjectReceiveStatistics()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 
GetCurrentRTP(Clock * clock,uint32_t freq)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 
ConvertNTPTimeToRTP(uint32_t NTPsec,uint32_t NTPfrac,uint32_t 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;
102 }
103 
ConvertNTPTimeToMS(uint32_t NTPsec,uint32_t NTPfrac)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)
StringCompare(const char * str1,const char * str2,const uint32_t length)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)
StringCompare(const char * str1,const char * str2,const uint32_t length)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 */
AssignUWord32ToBuffer(uint8_t * dataBuffer,uint32_t value)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 
AssignUWord24ToBuffer(uint8_t * dataBuffer,uint32_t value)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 
AssignUWord16ToBuffer(uint8_t * dataBuffer,uint16_t value)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 
BufferToUWord16(const uint8_t * dataBuffer)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 
BufferToUWord24(const uint8_t * dataBuffer)174 uint32_t BufferToUWord24(const uint8_t* dataBuffer) {
175   return (dataBuffer[0] << 16) + (dataBuffer[1] << 8) + dataBuffer[2];
176 }
177 
BufferToUWord32(const uint8_t * dataBuffer)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 
pow2(uint8_t exp)187 uint32_t pow2(uint8_t exp) {
188   return 1 << exp;
189 }
190 
SetType(RtpVideoCodecTypes videoType)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 
RTPHeaderParser(const uint8_t * rtpData,const uint32_t rtpDataLength)218 RTPHeaderParser::RTPHeaderParser(const uint8_t* rtpData,
219                                  const uint32_t rtpDataLength)
220   : _ptrRTPDataBegin(rtpData),
221     _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
222 }
223 
~RTPHeaderParser()224 RTPHeaderParser::~RTPHeaderParser() {
225 }
226 
RTCP() const227 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 
ParseRtcp(RTPHeader * header) const302 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 
Parse(RTPHeader & header,RtpHeaderExtensionMap * ptrExtensionMap) const331 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 
ParseOneByteExtensionHeader(RTPHeader & header,const RtpHeaderExtensionMap * ptrExtensionMap,const uint8_t * ptrRTPDataExtensionEnd,const uint8_t * ptr) const444 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 
ParsePaddingBytes(const uint8_t * ptrRTPDataExtensionEnd,const uint8_t * ptr) const555 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 
RTPPayloadParser(const RtpVideoCodecTypes videoType,const uint8_t * payloadData,uint16_t payloadDataLength)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 
~RTPPayloadParser()577 RTPPayloadParser::~RTPPayloadParser() {
578 }
579 
Parse(RTPPayload & parsedPacket) const580 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 
ParseGeneric(RTPPayload &) const593 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 
ParseVP8(RTPPayload & parsedPacket) const622 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 
ParseVP8FrameSize(RTPPayload & parsedPacket,const uint8_t * dataPtr,int dataLength) const668 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 
ParseVP8Extension(RTPPayloadVP8 * vp8,const uint8_t * dataPtr,int dataLength) const686 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 
ParseVP8PictureID(RTPPayloadVP8 * vp8,const uint8_t ** dataPtr,int * dataLength,int * parsedBytes) const722 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 
ParseVP8Tl0PicIdx(RTPPayloadVP8 * vp8,const uint8_t ** dataPtr,int * dataLength,int * parsedBytes) const741 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 
ParseVP8TIDAndKeyIdx(RTPPayloadVP8 * vp8,const uint8_t ** dataPtr,int * dataLength,int * parsedBytes) const753 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