blob: 8ab783f1327c0ccea381efcee9bbda27116a5f08 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
14#include <math.h> // ceil
15#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
niklase@google.com470e71d2011-07-07 08:21:25 +000017namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000018
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000019namespace RTCPUtility {
20uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) {
21 return (ntp_sec << 16) + (ntp_frac >> 16);
22} // end RTCPUtility
23}
24
25// RTCPParserV2 : currently read only
pbos@webrtc.org2f446732013-04-08 11:08:41 +000026RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
niklase@google.com470e71d2011-07-07 08:21:25 +000027 size_t rtcpDataLength,
28 bool rtcpReducedSizeEnable)
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000029 : _ptrRTCPDataBegin(rtcpData),
30 _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
31 _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
32 _validPacket(false),
33 _ptrRTCPData(rtcpData),
34 _ptrRTCPBlockEnd(NULL),
35 _state(State_TopLevel),
36 _numberOfBlocks(0),
37 _packetType(kRtcpNotValidCode) {
38 Validate();
niklase@google.com470e71d2011-07-07 08:21:25 +000039}
40
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000041RTCPUtility::RTCPParserV2::~RTCPParserV2() {
niklase@google.com470e71d2011-07-07 08:21:25 +000042}
43
44ptrdiff_t
45RTCPUtility::RTCPParserV2::LengthLeft() const
46{
47 return (_ptrRTCPDataEnd- _ptrRTCPData);
48}
49
50RTCPUtility::RTCPPacketTypes
51RTCPUtility::RTCPParserV2::PacketType() const
52{
53 return _packetType;
54}
55
56const RTCPUtility::RTCPPacket&
57RTCPUtility::RTCPParserV2::Packet() const
58{
59 return _packet;
60}
61
62RTCPUtility::RTCPPacketTypes
63RTCPUtility::RTCPParserV2::Begin()
64{
65 _ptrRTCPData = _ptrRTCPDataBegin;
66
67 return Iterate();
68}
69
70RTCPUtility::RTCPPacketTypes
71RTCPUtility::RTCPParserV2::Iterate()
72{
73 // Reset packet type
74 _packetType = kRtcpNotValidCode;
75
76 if (IsValid())
77 {
78 switch (_state)
79 {
80 case State_TopLevel:
81 IterateTopLevel();
82 break;
83 case State_ReportBlockItem:
84 IterateReportBlockItem();
85 break;
86 case State_SDESChunk:
87 IterateSDESChunk();
88 break;
89 case State_BYEItem:
90 IterateBYEItem();
91 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000092 case State_ExtendedJitterItem:
93 IterateExtendedJitterItem();
94 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000095 case State_RTPFB_NACKItem:
96 IterateNACKItem();
97 break;
98 case State_RTPFB_TMMBRItem:
99 IterateTMMBRItem();
100 break;
101 case State_RTPFB_TMMBNItem:
102 IterateTMMBNItem();
103 break;
104 case State_PSFB_SLIItem:
105 IterateSLIItem();
106 break;
107 case State_PSFB_RPSIItem:
108 IterateRPSIItem();
109 break;
110 case State_PSFB_FIRItem:
111 IterateFIRItem();
112 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000113 case State_PSFB_AppItem:
114 IteratePsfbAppItem();
115 break;
116 case State_PSFB_REMBItem:
117 IteratePsfbREMBItem();
118 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000119 case State_XRItem:
120 IterateXrItem();
121 break;
122 case State_XR_DLLRItem:
123 IterateXrDlrrItem();
124 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 case State_AppItem:
126 IterateAppItem();
127 break;
128 default:
129 assert(false); // Invalid state!
130 break;
131 }
132 }
133 return _packetType;
134}
135
136void
137RTCPUtility::RTCPParserV2::IterateTopLevel()
138{
139 for (;;)
140 {
141 RTCPCommonHeader header;
142
143 const bool success = RTCPParseCommonHeader(_ptrRTCPData,
144 _ptrRTCPDataEnd,
145 header);
146
147 if (!success)
148 {
149 return;
150 }
151 _ptrRTCPBlockEnd = _ptrRTCPData + header.LengthInOctets;
152 if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
153 {
154 // Bad block!
155 return;
156 }
157
158 switch (header.PT)
159 {
160 case PT_SR:
161 {
162 // number of Report blocks
163 _numberOfBlocks = header.IC;
164 ParseSR();
165 return;
166 }
167 case PT_RR:
168 {
169 // number of Report blocks
170 _numberOfBlocks = header.IC;
171 ParseRR();
172 return;
173 }
174 case PT_SDES:
175 {
176 // number of SDES blocks
177 _numberOfBlocks = header.IC;
178 const bool ok = ParseSDES();
179 if (!ok)
180 {
181 // Nothing supported found, continue to next block!
182 break;
183 }
184 return;
185 }
186 case PT_BYE:
187 {
188 _numberOfBlocks = header.IC;
189 const bool ok = ParseBYE();
190 if (!ok)
191 {
192 // Nothing supported found, continue to next block!
193 break;
194 }
195 return;
196 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000197 case PT_IJ:
198 {
199 // number of Report blocks
200 _numberOfBlocks = header.IC;
201 ParseIJ();
202 return;
203 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000204 case PT_RTPFB: // Fall through!
205 case PT_PSFB:
206 {
207 const bool ok = ParseFBCommon(header);
208 if (!ok)
209 {
210 // Nothing supported found, continue to next block!
211 break;
212 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 return;
214 }
215 case PT_APP:
216 {
217 const bool ok = ParseAPP(header);
218 if (!ok)
219 {
220 // Nothing supported found, continue to next block!
221 break;
222 }
223 return;
224 }
225 case PT_XR:
226 {
227 const bool ok = ParseXR();
228 if (!ok)
229 {
230 // Nothing supported found, continue to next block!
231 break;
232 }
233 return;
234 }
235 default:
236 // Not supported! Skip!
237 EndCurrentBlock();
238 break;
239 }
240 }
241}
242
243void
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000244RTCPUtility::RTCPParserV2::IterateXrItem()
245{
246 const bool success = ParseXRItem();
247 if (!success)
248 {
249 Iterate();
250 }
251}
252
253void
254RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
255{
256 const bool success = ParseXRDLRRReportBlockItem();
257 if (!success)
258 {
259 Iterate();
260 }
261}
262
263void
niklase@google.com470e71d2011-07-07 08:21:25 +0000264RTCPUtility::RTCPParserV2::IterateReportBlockItem()
265{
266 const bool success = ParseReportBlockItem();
267 if (!success)
268 {
269 Iterate();
270 }
271}
272
273void
274RTCPUtility::RTCPParserV2::IterateSDESChunk()
275{
276 const bool success = ParseSDESChunk();
277 if (!success)
278 {
279 Iterate();
280 }
281}
282
283void
284RTCPUtility::RTCPParserV2::IterateBYEItem()
285{
286 const bool success = ParseBYEItem();
287 if (!success)
288 {
289 Iterate();
290 }
291}
292
293void
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000294RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
295{
296 const bool success = ParseIJItem();
297 if (!success)
298 {
299 Iterate();
300 }
301}
302
303void
niklase@google.com470e71d2011-07-07 08:21:25 +0000304RTCPUtility::RTCPParserV2::IterateNACKItem()
305{
306 const bool success = ParseNACKItem();
307 if (!success)
308 {
309 Iterate();
310 }
311}
312
313void
314RTCPUtility::RTCPParserV2::IterateTMMBRItem()
315{
316 const bool success = ParseTMMBRItem();
317 if (!success)
318 {
319 Iterate();
320 }
321}
322
323void
324RTCPUtility::RTCPParserV2::IterateTMMBNItem()
325{
326 const bool success = ParseTMMBNItem();
327 if (!success)
328 {
329 Iterate();
330 }
331}
332
333void
334RTCPUtility::RTCPParserV2::IterateSLIItem()
335{
336 const bool success = ParseSLIItem();
337 if (!success)
338 {
339 Iterate();
340 }
341}
342
343void
344RTCPUtility::RTCPParserV2::IterateRPSIItem()
345{
346 const bool success = ParseRPSIItem();
347 if (!success)
348 {
349 Iterate();
350 }
351}
352
353void
354RTCPUtility::RTCPParserV2::IterateFIRItem()
355{
356 const bool success = ParseFIRItem();
357 if (!success)
358 {
359 Iterate();
360 }
361}
362
363void
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000364RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
365{
366 const bool success = ParsePsfbAppItem();
367 if (!success)
368 {
369 Iterate();
370 }
371}
372
373void
374RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
375{
376 const bool success = ParsePsfbREMBItem();
377 if (!success)
378 {
379 Iterate();
380 }
381}
382
383void
niklase@google.com470e71d2011-07-07 08:21:25 +0000384RTCPUtility::RTCPParserV2::IterateAppItem()
385{
386 const bool success = ParseAPPItem();
387 if (!success)
388 {
389 Iterate();
390 }
391}
392
393void
394RTCPUtility::RTCPParserV2::Validate()
395{
396 if (_ptrRTCPData == NULL)
397 {
398 return; // NOT VALID
399 }
400
401 RTCPCommonHeader header;
402 const bool success = RTCPParseCommonHeader(_ptrRTCPDataBegin,
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000403 _ptrRTCPDataEnd,
404 header);
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
406 if (!success)
407 {
408 return; // NOT VALID!
409 }
410
411 // * if (!reducedSize) : first packet must be RR or SR.
412 //
413 // * The padding bit (P) should be zero for the first packet of a
414 // compound RTCP packet because padding should only be applied,
415 // if it is needed, to the last packet. (NOT CHECKED!)
416 //
417 // * The length fields of the individual RTCP packets must add up
418 // to the overall length of the compound RTCP packet as
419 // received. This is a fairly strong check. (NOT CHECKED!)
420
421 if (!_RTCPReducedSizeEnable)
422 {
423 if ((header.PT != PT_SR) && (header.PT != PT_RR))
424 {
425 return; // NOT VALID
426 }
427 }
428
429 _validPacket = true;
430}
431
432bool
433RTCPUtility::RTCPParserV2::IsValid() const
434{
435 return _validPacket;
436}
437
438void
439RTCPUtility::RTCPParserV2::EndCurrentBlock()
440{
441 _ptrRTCPData = _ptrRTCPBlockEnd;
442}
443
444bool
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000445RTCPUtility::RTCPParseCommonHeader( const uint8_t* ptrDataBegin,
446 const uint8_t* ptrDataEnd,
niklase@google.com470e71d2011-07-07 08:21:25 +0000447 RTCPCommonHeader& parsedHeader)
448{
449 if (!ptrDataBegin || !ptrDataEnd)
450 {
451 return false;
452 }
453
454 // 0 1 2 3
455 // 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
456 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
457 // |V=2|P| IC | PT | length |
458 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
459 //
460 // Common header for all RTCP packets, 4 octets.
461
462 if ((ptrDataEnd - ptrDataBegin) < 4)
463 {
464 return false;
465 }
466
467 parsedHeader.V = ptrDataBegin[0] >> 6;
468 parsedHeader.P = ((ptrDataBegin[0] & 0x20) == 0) ? false : true;
469 parsedHeader.IC = ptrDataBegin[0] & 0x1f;
470 parsedHeader.PT = ptrDataBegin[1];
471
472 parsedHeader.LengthInOctets = (ptrDataBegin[2] << 8) + ptrDataBegin[3] + 1;
473 parsedHeader.LengthInOctets *= 4;
474
475 if(parsedHeader.LengthInOctets == 0)
476 {
477 return false;
478 }
479 // Check if RTP version field == 2
480 if (parsedHeader.V != 2)
481 {
482 return false;
483 }
484
485 return true;
486}
487
488bool
489RTCPUtility::RTCPParserV2::ParseRR()
490{
491 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
492
493 if (length < 8)
494 {
495 return false;
496 }
497
498
499 _ptrRTCPData += 4; // Skip header
500
501 _packetType = kRtcpRrCode;
502
503 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
504 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
505 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
506 _packet.RR.SenderSSRC += *_ptrRTCPData++;
507
508 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
509
510 // State transition
511 _state = State_ReportBlockItem;
512
513 return true;
514}
515
516bool
517RTCPUtility::RTCPParserV2::ParseSR()
518{
519 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
520
521 if (length < 28)
522 {
523 EndCurrentBlock();
524 return false;
525 }
526
527 _ptrRTCPData += 4; // Skip header
528
529 _packetType = kRtcpSrCode;
530
531 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
532 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
533 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
534 _packet.SR.SenderSSRC += *_ptrRTCPData++;
535
536 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
537 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
538 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
539 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
540
541 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
542 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
543 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
544 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
545
546 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
547 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
548 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
549 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
550
551 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
552 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
553 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
554 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
555
556 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
557 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
558 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
559 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
560
561 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
562
563 // State transition
564 if(_numberOfBlocks != 0)
565 {
566 _state = State_ReportBlockItem;
567 }else
568 {
569 // don't go to state report block item if 0 report blocks
570 _state = State_TopLevel;
571 EndCurrentBlock();
572 }
573 return true;
574}
575
576bool
577RTCPUtility::RTCPParserV2::ParseReportBlockItem()
578{
579 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
580
581 if (length < 24 || _numberOfBlocks <= 0)
582 {
583 _state = State_TopLevel;
584
585 EndCurrentBlock();
586 return false;
587 }
588 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
589 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
590 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
591 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
592
593 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
594
595 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
596 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
597 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
598
599 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
600 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
601 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
602 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
603
604 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
605 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
606 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
607 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
608
609 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
610 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
611 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
612 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
613
614 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
615 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
616 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
617 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
618
619 _numberOfBlocks--;
620 _packetType = kRtcpReportBlockItemCode;
621 return true;
622}
623
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000624/* From RFC 5450: Transmission Time Offsets in RTP Streams.
625 0 1 2 3
626 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
627 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
628 hdr |V=2|P| RC | PT=IJ=195 | length |
629 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
630 | inter-arrival jitter |
631 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
632 . .
633 . .
634 . .
635 | inter-arrival jitter |
636 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
637*/
638
639bool
640RTCPUtility::RTCPParserV2::ParseIJ()
641{
642 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
643
644 if (length < 4)
645 {
646 return false;
647 }
648
649 _ptrRTCPData += 4; // Skip header
650
651 _packetType = kRtcpExtendedIjCode;
652
653 // State transition
654 _state = State_ExtendedJitterItem;
655 return true;
656}
657
658bool
659RTCPUtility::RTCPParserV2::ParseIJItem()
660{
661 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
662
663 if (length < 4 || _numberOfBlocks <= 0)
664 {
665 _state = State_TopLevel;
666 EndCurrentBlock();
667 return false;
668 }
669
670 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
671 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
672 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
673 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
674
675 _numberOfBlocks--;
676 _packetType = kRtcpExtendedIjItemCode;
677 return true;
678}
679
niklase@google.com470e71d2011-07-07 08:21:25 +0000680bool
681RTCPUtility::RTCPParserV2::ParseSDES()
682{
683 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
684
685 if (length < 8)
686 {
687 _state = State_TopLevel;
688
689 EndCurrentBlock();
690 return false;
691 }
692 _ptrRTCPData += 4; // Skip header
693
694 _state = State_SDESChunk;
695 _packetType = kRtcpSdesCode;
696 return true;
697}
698
699bool
700RTCPUtility::RTCPParserV2::ParseSDESChunk()
701{
702 if(_numberOfBlocks <= 0)
703 {
704 _state = State_TopLevel;
705
706 EndCurrentBlock();
707 return false;
708 }
709 _numberOfBlocks--;
710
711 // Find CName item in a SDES chunk.
712 while (_ptrRTCPData < _ptrRTCPBlockEnd)
713 {
714 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
715 if (dataLen < 4)
716 {
717 _state = State_TopLevel;
718
719 EndCurrentBlock();
720 return false;
721 }
722
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000723 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000724 SSRC += *_ptrRTCPData++ << 16;
725 SSRC += *_ptrRTCPData++ << 8;
726 SSRC += *_ptrRTCPData++;
727
728 const bool foundCname = ParseSDESItem();
729 if (foundCname)
730 {
731 _packet.CName.SenderSSRC = SSRC; // Add SSRC
732 return true;
733 }
734 }
735 _state = State_TopLevel;
736
737 EndCurrentBlock();
738 return false;
739}
740
741bool
742RTCPUtility::RTCPParserV2::ParseSDESItem()
743{
744 // Find CName
745 // Only the CNAME item is mandatory. RFC 3550 page 46
746 bool foundCName = false;
747
748 size_t itemOctetsRead = 0;
749 while (_ptrRTCPData < _ptrRTCPBlockEnd)
750 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000751 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000752 ++itemOctetsRead;
753
754 if (tag == 0)
755 {
756 // End tag! 4 oct aligned
757 while ((itemOctetsRead++ % 4) != 0)
758 {
759 ++_ptrRTCPData;
760 }
761 return foundCName;
762 }
763
764 if (_ptrRTCPData < _ptrRTCPBlockEnd)
765 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000766 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000767 ++itemOctetsRead;
768
769 if (tag == 1)
770 {
771 // CNAME
772
773 // Sanity
774 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
775 {
776 _state = State_TopLevel;
777
778 EndCurrentBlock();
779 return false;
780 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000781 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000782 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000783 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000784 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000785 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
786 {
787 // Illegal char
788 _state = State_TopLevel;
789
790 EndCurrentBlock();
791 return false;
792 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000793 _packet.CName.CName[i] = c;
794 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000795 // Make sure we are null terminated.
796 _packet.CName.CName[i] = 0;
797 _packetType = kRtcpSdesChunkCode;
niklase@google.com470e71d2011-07-07 08:21:25 +0000798
799 foundCName = true;
800 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000801 _ptrRTCPData += len;
802 itemOctetsRead += len;
803 }
804 }
805
806 // No end tag found!
807 _state = State_TopLevel;
808
809 EndCurrentBlock();
810 return false;
811}
812
813bool
814RTCPUtility::RTCPParserV2::ParseBYE()
815{
816 _ptrRTCPData += 4; // Skip header
817
818 _state = State_BYEItem;
819
820 return ParseBYEItem();
821}
822
823bool
824RTCPUtility::RTCPParserV2::ParseBYEItem()
825{
826 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
827 if (length < 4 || _numberOfBlocks == 0)
828 {
829 _state = State_TopLevel;
830
831 EndCurrentBlock();
832 return false;
833 }
834
835 _packetType = kRtcpByeCode;
836
837 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
838 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
839 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
840 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
841
842 // we can have several CSRCs attached
843
844 // sanity
845 if(length >= 4*_numberOfBlocks)
846 {
847 _ptrRTCPData += (_numberOfBlocks -1)*4;
848 }
849 _numberOfBlocks = 0;
850
851 return true;
852}
853/*
854 0 1 2 3
855 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
856 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
857 |V=2|P|reserved | PT=XR=207 | length |
858 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
859 | SSRC |
860 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
861 : report blocks :
862 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
863*/
864bool RTCPUtility::RTCPParserV2::ParseXR()
865{
866 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000867 if (length < 8)
868 {
869 EndCurrentBlock();
870 return false;
871 }
872
873 _ptrRTCPData += 4; // Skip header
874
875 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
876 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
877 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
878 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
879
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000880 _packetType = kRtcpXrHeaderCode;
881 _state = State_XRItem;
882 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000883}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000884
niklase@google.com470e71d2011-07-07 08:21:25 +0000885/*
886 0 1 2 3
887 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
888 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
889 | BT | type-specific | block length |
890 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
891 : type-specific block contents :
892 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
893*/
niklase@google.com470e71d2011-07-07 08:21:25 +0000894bool
895RTCPUtility::RTCPParserV2::ParseXRItem()
896{
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000897 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000898
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000899 if (length < 4) {
900 _state = State_TopLevel;
901 EndCurrentBlock();
902 return false;
903 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000904
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000905 uint8_t blockType = *_ptrRTCPData++;
906 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000907
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000908 uint16_t blockLength = *_ptrRTCPData++ << 8;
909 blockLength = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000910
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000911 if (blockType == 4 && blockLength == 2)
912 {
913 return ParseXRReceiverReferenceTimeItem();
914 }
915 else if (blockType == 5 && (blockLength % 3) == 0)
916 {
917 _packetType = kRtcpXrDlrrReportBlockCode;
918 _state = State_XR_DLLRItem;
919 _numberOfBlocks = blockLength / 3;
920 return true;
921 }
922 else if (blockType == 7 && blockLength == 8)
923 {
924 return ParseXRVOIPMetricItem();
925 }
926
927 // Not supported.
928 _state = State_TopLevel;
929 EndCurrentBlock();
930 return false;
931}
932
933/* 0 1 2 3
934 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
935 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
936 | BT=4 | reserved | block length = 2 |
937 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
938 | NTP timestamp, most significant word |
939 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
940 | NTP timestamp, least significant word |
941 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942*/
943
944bool RTCPUtility::RTCPParserV2::ParseXRReceiverReferenceTimeItem() {
945 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
946 if (length < 8) {
947 _state = State_TopLevel;
948 EndCurrentBlock();
949 return false;
950 }
951
952 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant =
953 *_ptrRTCPData++ << 24;
954 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant +=
955 *_ptrRTCPData++ << 16;
956 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant +=
957 *_ptrRTCPData++ << 8;
958 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant += *_ptrRTCPData++;
959
960 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant =
961 *_ptrRTCPData++ << 24;
962 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant +=
963 *_ptrRTCPData++ << 16;
964 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant +=
965 *_ptrRTCPData++ << 8;
966 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant += *_ptrRTCPData++;
967
968 _packetType = kRtcpXrReceiverReferenceTimeCode;
969 _state = State_XRItem;
970 return true;
971}
972
973/* 0 1 2 3
974 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
975 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
976 | BT=5 | reserved | block length |
977 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
978 | SSRC_1 (SSRC of first receiver) | sub-
979 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
980 | last RR (LRR) | 1
981 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
982 | delay since last RR (DLRR) |
983 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
984 | SSRC_2 (SSRC of second receiver) | sub-
985 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
986 : ... : 2
987 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
988*/
989
990bool RTCPUtility::RTCPParserV2::ParseXRDLRRReportBlockItem() {
991 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
992 if (_numberOfBlocks == 0) {
993 _state = State_XRItem;
994 return false;
995 }
996 if (length < 12) {
997 _state = State_TopLevel;
998 EndCurrentBlock();
999 return false;
1000 }
1001
1002 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1003 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1004 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1005 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1006
1007 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1008 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1009 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1010 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1011
1012 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1013 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1014 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1015 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1016
1017 _packetType = kRtcpXrDlrrReportBlockItemCode;
1018 --_numberOfBlocks;
1019 _state = State_XR_DLLRItem;
1020 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001021}
1022/*
1023 0 1 2 3
1024 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
1025 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1026 | BT=7 | reserved | block length = 8 |
1027 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1028 | SSRC of source |
1029 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1030 | loss rate | discard rate | burst density | gap density |
1031 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1032 | burst duration | gap duration |
1033 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1034 | round trip delay | end system delay |
1035 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1036 | signal level | noise level | RERL | Gmin |
1037 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1038 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1039 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1040 | RX config | reserved | JB nominal |
1041 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1042 | JB maximum | JB abs max |
1043 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1044*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001045
niklase@google.com470e71d2011-07-07 08:21:25 +00001046bool
1047RTCPUtility::RTCPParserV2::ParseXRVOIPMetricItem()
1048{
1049 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1050
1051 if (length < 28)
1052 {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001053 _state = State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001054 EndCurrentBlock();
1055 return false;
1056 }
1057 _packetType = kRtcpXrVoipMetricCode;
1058
1059 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1060 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1061 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1062 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
1063
1064 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1065 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1066 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1067 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
1068
1069 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1070 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
1071
1072 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1073 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
1074
1075 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1076 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
1077
1078 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1079 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
1080
1081 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1082 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1083 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1084 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1085 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1086 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1087 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1088 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1089 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1090 _ptrRTCPData++; // skip reserved
1091
1092 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1093 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
1094
1095 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1096 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
1097
1098 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1099 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
1100
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001101 _state = State_XRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001102 return true;
1103}
1104
1105bool
1106RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
1107{
1108 assert((header.PT == PT_RTPFB) || (header.PT == PT_PSFB)); // Parser logic check
1109
1110 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1111
1112 if (length < 12) // 4 * 3, RFC4585 section 6.1
1113 {
1114 EndCurrentBlock();
1115 return false;
1116 }
1117
1118 _ptrRTCPData += 4; // Skip RTCP header
1119
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001120 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121 senderSSRC += *_ptrRTCPData++ << 16;
1122 senderSSRC += *_ptrRTCPData++ << 8;
1123 senderSSRC += *_ptrRTCPData++;
1124
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001125 uint32_t mediaSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001126 mediaSSRC += *_ptrRTCPData++ << 16;
1127 mediaSSRC += *_ptrRTCPData++ << 8;
1128 mediaSSRC += *_ptrRTCPData++;
1129
1130 if (header.PT == PT_RTPFB)
1131 {
1132 // Transport layer feedback
1133
1134 switch (header.IC)
1135 {
1136 case 1:
1137 {
1138 // NACK
1139 _packetType = kRtcpRtpfbNackCode;
1140 _packet.NACK.SenderSSRC = senderSSRC;
1141 _packet.NACK.MediaSSRC = mediaSSRC;
1142
1143 _state = State_RTPFB_NACKItem;
1144
1145 return true;
1146 }
1147 case 2:
1148 {
1149 // used to be ACK is this code point, which is removed
1150 // conficts with http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
1151 break;
1152 }
1153 case 3:
1154 {
1155 // TMMBR
1156 _packetType = kRtcpRtpfbTmmbrCode;
1157 _packet.TMMBR.SenderSSRC = senderSSRC;
1158 _packet.TMMBR.MediaSSRC = mediaSSRC;
1159
1160 _state = State_RTPFB_TMMBRItem;
1161
1162 return true;
1163 }
1164 case 4:
1165 {
1166 // TMMBN
1167 _packetType = kRtcpRtpfbTmmbnCode;
1168 _packet.TMMBN.SenderSSRC = senderSSRC;
1169 _packet.TMMBN.MediaSSRC = mediaSSRC;
1170
1171 _state = State_RTPFB_TMMBNItem;
1172
1173 return true;
1174 }
1175 case 5:
1176 {
1177 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1178 // draft-perkins-avt-rapid-rtp-sync-03.txt
1179 // trigger a new RTCP SR
1180 _packetType = kRtcpRtpfbSrReqCode;
1181
1182 // Note: No state transition, SR REQ is empty!
1183 return true;
1184 }
1185 default:
1186 break;
1187 }
1188 EndCurrentBlock();
1189 return false;
1190 }
1191 else if (header.PT == PT_PSFB)
1192 {
1193 // Payload specific feedback
1194 switch (header.IC)
1195 {
1196 case 1:
1197 // PLI
1198 _packetType = kRtcpPsfbPliCode;
1199 _packet.PLI.SenderSSRC = senderSSRC;
1200 _packet.PLI.MediaSSRC = mediaSSRC;
1201
1202 // Note: No state transition, PLI FCI is empty!
1203 return true;
1204 case 2:
1205 // SLI
1206 _packetType = kRtcpPsfbSliCode;
1207 _packet.SLI.SenderSSRC = senderSSRC;
1208 _packet.SLI.MediaSSRC = mediaSSRC;
1209
1210 _state = State_PSFB_SLIItem;
1211
1212 return true;
1213 case 3:
1214 _packetType = kRtcpPsfbRpsiCode;
1215 _packet.RPSI.SenderSSRC = senderSSRC;
1216 _packet.RPSI.MediaSSRC = mediaSSRC;
1217
1218 _state = State_PSFB_RPSIItem;
1219 return true;
1220 case 4:
1221 // FIR
1222 _packetType = kRtcpPsfbFirCode;
1223 _packet.FIR.SenderSSRC = senderSSRC;
1224 _packet.FIR.MediaSSRC = mediaSSRC;
1225
1226 _state = State_PSFB_FIRItem;
1227 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001228 case 15:
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001229 _packetType = kRtcpPsfbAppCode;
1230 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1231 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001232
1233 _state = State_PSFB_AppItem;
1234 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001235 default:
1236 break;
1237 }
1238
1239 EndCurrentBlock();
1240 return false;
1241 }
1242 else
1243 {
1244 assert(false);
1245
1246 EndCurrentBlock();
1247 return false;
1248 }
1249}
1250
1251bool
1252RTCPUtility::RTCPParserV2::ParseRPSIItem()
1253{
1254 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI)
1255 /*
1256 0 1 2 3
1257 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
1258 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1259 | PB |0| Payload Type| Native RPSI bit string |
1260 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1261 | defined per codec ... | Padding (0) |
1262 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1263 */
1264
1265 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1266
1267 if (length < 4)
1268 {
1269 _state = State_TopLevel;
1270
1271 EndCurrentBlock();
1272 return false;
1273 }
1274 if(length > 2+RTCP_RPSI_DATA_SIZE)
1275 {
1276 _state = State_TopLevel;
1277
1278 EndCurrentBlock();
1279 return false;
1280 }
1281
1282 _packetType = kRtcpPsfbRpsiCode;
1283
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001284 uint8_t paddingBits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001285 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1286
1287 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length-2);
1288
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001289 _packet.RPSI.NumberOfValidBits = uint16_t(length-2)*8 - paddingBits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001290 return true;
1291}
1292
1293bool
1294RTCPUtility::RTCPParserV2::ParseNACKItem()
1295{
1296 // RFC 4585 6.2.1. Generic NACK
1297
1298 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1299
1300 if (length < 4)
1301 {
1302 _state = State_TopLevel;
1303
1304 EndCurrentBlock();
1305 return false;
1306 }
1307
1308 _packetType = kRtcpRtpfbNackItemCode;
1309
1310 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1311 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1312
1313 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1314 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1315
1316 return true;
1317}
1318
1319bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001320RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1321{
1322 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1323
1324 if (length < 4)
1325 {
1326 _state = State_TopLevel;
1327
1328 EndCurrentBlock();
1329 return false;
1330 }
1331 if(*_ptrRTCPData++ != 'R')
1332 {
1333 _state = State_TopLevel;
1334
1335 EndCurrentBlock();
1336 return false;
1337 }
1338 if(*_ptrRTCPData++ != 'E')
1339 {
1340 _state = State_TopLevel;
1341
1342 EndCurrentBlock();
1343 return false;
1344 }
1345 if(*_ptrRTCPData++ != 'M')
1346 {
1347 _state = State_TopLevel;
1348
1349 EndCurrentBlock();
1350 return false;
1351 }
1352 if(*_ptrRTCPData++ != 'B')
1353 {
1354 _state = State_TopLevel;
1355
1356 EndCurrentBlock();
1357 return false;
1358 }
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001359 _packetType = kRtcpPsfbRembCode;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001360 _state = State_PSFB_REMBItem;
1361 return true;
1362}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001363
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001364bool
1365RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1366{
1367 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1368
1369 if (length < 4)
1370 {
1371 _state = State_TopLevel;
1372
1373 EndCurrentBlock();
1374 return false;
1375 }
1376
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001377 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001378 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001379
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001380 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001381 brMantissa += (_ptrRTCPData[1] << 8);
1382 brMantissa += (_ptrRTCPData[2]);
1383
1384 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001385 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001386
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001387 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1388 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1389 {
1390 _state = State_TopLevel;
1391
1392 EndCurrentBlock();
1393 return false;
1394 }
1395
1396 _packetType = kRtcpPsfbRembItemCode;
1397
1398 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1399 {
1400 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1401 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1402 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1403 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1404 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001405 return true;
1406}
1407
1408bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001409RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1410{
1411 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1412
1413 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1414
1415 if (length < 8)
1416 {
1417 _state = State_TopLevel;
1418
1419 EndCurrentBlock();
1420 return false;
1421 }
1422
1423 _packetType = kRtcpRtpfbTmmbrItemCode;
1424
1425 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1426 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1427 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1428 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1429
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001430 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001431
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001432 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001433 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1434 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1435
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001436 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001437 measuredOH += _ptrRTCPData[3];
1438
1439 _ptrRTCPData += 4; // Fwd read data
1440
1441 _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1442 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1443
1444 return true;
1445}
1446
1447bool
1448RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1449{
1450 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1451
1452 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1453
1454 if (length < 8)
1455 {
1456 _state = State_TopLevel;
1457
1458 EndCurrentBlock();
1459 return false;
1460 }
1461
1462 _packetType = kRtcpRtpfbTmmbnItemCode;
1463
1464 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1465 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1466 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1467 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1468
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001469 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001470
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001471 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001472 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1473 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1474
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001475 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001476 measuredOH += _ptrRTCPData[3];
1477
1478 _ptrRTCPData += 4; // Fwd read data
1479
1480 _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1481 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1482
1483 return true;
1484}
1485
1486bool
1487RTCPUtility::RTCPParserV2::ParseSLIItem()
1488{
1489 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1490 /*
1491 0 1 2 3
1492 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
1493 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1494 | First | Number | PictureID |
1495 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1496 */
1497
1498 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1499
1500 if (length < 4)
1501 {
1502 _state = State_TopLevel;
1503
1504 EndCurrentBlock();
1505 return false;
1506 }
1507 _packetType = kRtcpPsfbSliItemCode;
1508
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001509 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001510 buffer = *_ptrRTCPData++ << 24;
1511 buffer += *_ptrRTCPData++ << 16;
1512 buffer += *_ptrRTCPData++ << 8;
1513 buffer += *_ptrRTCPData++;
1514
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001515 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1516 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1517 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001518
1519 return true;
1520}
1521
1522bool
1523RTCPUtility::RTCPParserV2::ParseFIRItem()
1524{
1525 // RFC 5104 4.3.1. Full Intra Request (FIR)
1526
1527 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1528
1529 if (length < 8)
1530 {
1531 _state = State_TopLevel;
1532
1533 EndCurrentBlock();
1534 return false;
1535 }
1536
1537 _packetType = kRtcpPsfbFirItemCode;
1538
1539 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1540 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1541 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1542 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1543
1544 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1545 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1546 return true;
1547}
1548
1549bool
1550RTCPUtility::RTCPParserV2::ParseAPP( const RTCPCommonHeader& header)
1551{
1552 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1553
1554 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1555 {
1556 EndCurrentBlock();
1557 return false;
1558 }
1559
1560 _ptrRTCPData += 4; // Skip RTCP header
1561
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001562 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001563 senderSSRC += *_ptrRTCPData++ << 16;
1564 senderSSRC += *_ptrRTCPData++ << 8;
1565 senderSSRC += *_ptrRTCPData++;
1566
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001567 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001568 name += *_ptrRTCPData++ << 16;
1569 name += *_ptrRTCPData++ << 8;
1570 name += *_ptrRTCPData++;
1571
1572 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1573
1574 _packetType = kRtcpAppCode;
1575
1576 _packet.APP.SubType = header.IC;
1577 _packet.APP.Name = name;
1578
1579 _state = State_AppItem;
1580 return true;
1581}
1582
1583bool
1584RTCPUtility::RTCPParserV2::ParseAPPItem()
1585{
1586 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1587 if (length < 4)
1588 {
1589 _state = State_TopLevel;
1590
1591 EndCurrentBlock();
1592 return false;
1593 }
1594 _packetType = kRtcpAppItemCode;
1595
1596 if(length > kRtcpAppCode_DATA_SIZE)
1597 {
1598 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1599 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1600 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1601 }else
1602 {
1603 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001604 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001605 _ptrRTCPData += length;
1606 }
1607 return true;
1608}
1609
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001610RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001611 size_t rtcpDataLength)
1612 : _ptrBegin(rtcpData),
1613 _ptrEnd(rtcpData + rtcpDataLength),
1614 _ptrBlock(NULL) {
1615 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001616}
1617
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001618RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001619}
1620
1621const RTCPUtility::RTCPCommonHeader*
1622RTCPUtility::RTCPPacketIterator::Begin()
1623{
1624 _ptrBlock = _ptrBegin;
1625
1626 return Iterate();
1627}
1628
1629const RTCPUtility::RTCPCommonHeader*
1630RTCPUtility::RTCPPacketIterator::Iterate()
1631{
1632 const bool success = RTCPParseCommonHeader(_ptrBlock, _ptrEnd, _header);
1633 if (!success)
1634 {
1635 _ptrBlock = NULL;
1636 return NULL;
1637 }
1638 _ptrBlock += _header.LengthInOctets;
1639
1640 if (_ptrBlock > _ptrEnd)
1641 {
1642 _ptrBlock = NULL;
1643 return NULL;
1644 }
1645
1646 return &_header;
1647}
1648
1649const RTCPUtility::RTCPCommonHeader*
1650RTCPUtility::RTCPPacketIterator::Current()
1651{
1652 if (!_ptrBlock)
1653 {
1654 return NULL;
1655 }
1656
1657 return &_header;
1658}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001659} // namespace webrtc