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