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