blob: b330e18e581bfcbb1e0e1ec5fbb7e24180bdede6 [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
11#include "rtcp_utility.h"
12
13#include <cstring> // memcpy
14#include <cmath> // ceil
15#include <cassert>
16
niklase@google.com470e71d2011-07-07 08:21:25 +000017namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000018// RTCPParserV2 : currently read only
19
pbos@webrtc.org2f446732013-04-08 11:08:41 +000020RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
niklase@google.com470e71d2011-07-07 08:21:25 +000021 size_t rtcpDataLength,
22 bool rtcpReducedSizeEnable)
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000023 : _ptrRTCPDataBegin(rtcpData),
24 _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
25 _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
26 _validPacket(false),
27 _ptrRTCPData(rtcpData),
28 _ptrRTCPBlockEnd(NULL),
29 _state(State_TopLevel),
30 _numberOfBlocks(0),
31 _packetType(kRtcpNotValidCode) {
32 Validate();
niklase@google.com470e71d2011-07-07 08:21:25 +000033}
34
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000035RTCPUtility::RTCPParserV2::~RTCPParserV2() {
niklase@google.com470e71d2011-07-07 08:21:25 +000036}
37
38ptrdiff_t
39RTCPUtility::RTCPParserV2::LengthLeft() const
40{
41 return (_ptrRTCPDataEnd- _ptrRTCPData);
42}
43
44RTCPUtility::RTCPPacketTypes
45RTCPUtility::RTCPParserV2::PacketType() const
46{
47 return _packetType;
48}
49
50const RTCPUtility::RTCPPacket&
51RTCPUtility::RTCPParserV2::Packet() const
52{
53 return _packet;
54}
55
56RTCPUtility::RTCPPacketTypes
57RTCPUtility::RTCPParserV2::Begin()
58{
59 _ptrRTCPData = _ptrRTCPDataBegin;
60
61 return Iterate();
62}
63
64RTCPUtility::RTCPPacketTypes
65RTCPUtility::RTCPParserV2::Iterate()
66{
67 // Reset packet type
68 _packetType = kRtcpNotValidCode;
69
70 if (IsValid())
71 {
72 switch (_state)
73 {
74 case State_TopLevel:
75 IterateTopLevel();
76 break;
77 case State_ReportBlockItem:
78 IterateReportBlockItem();
79 break;
80 case State_SDESChunk:
81 IterateSDESChunk();
82 break;
83 case State_BYEItem:
84 IterateBYEItem();
85 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000086 case State_ExtendedJitterItem:
87 IterateExtendedJitterItem();
88 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000089 case State_RTPFB_NACKItem:
90 IterateNACKItem();
91 break;
92 case State_RTPFB_TMMBRItem:
93 IterateTMMBRItem();
94 break;
95 case State_RTPFB_TMMBNItem:
96 IterateTMMBNItem();
97 break;
98 case State_PSFB_SLIItem:
99 IterateSLIItem();
100 break;
101 case State_PSFB_RPSIItem:
102 IterateRPSIItem();
103 break;
104 case State_PSFB_FIRItem:
105 IterateFIRItem();
106 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000107 case State_PSFB_AppItem:
108 IteratePsfbAppItem();
109 break;
110 case State_PSFB_REMBItem:
111 IteratePsfbREMBItem();
112 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000113 case State_AppItem:
114 IterateAppItem();
115 break;
116 default:
117 assert(false); // Invalid state!
118 break;
119 }
120 }
121 return _packetType;
122}
123
124void
125RTCPUtility::RTCPParserV2::IterateTopLevel()
126{
127 for (;;)
128 {
129 RTCPCommonHeader header;
130
131 const bool success = RTCPParseCommonHeader(_ptrRTCPData,
132 _ptrRTCPDataEnd,
133 header);
134
135 if (!success)
136 {
137 return;
138 }
139 _ptrRTCPBlockEnd = _ptrRTCPData + header.LengthInOctets;
140 if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
141 {
142 // Bad block!
143 return;
144 }
145
146 switch (header.PT)
147 {
148 case PT_SR:
149 {
150 // number of Report blocks
151 _numberOfBlocks = header.IC;
152 ParseSR();
153 return;
154 }
155 case PT_RR:
156 {
157 // number of Report blocks
158 _numberOfBlocks = header.IC;
159 ParseRR();
160 return;
161 }
162 case PT_SDES:
163 {
164 // number of SDES blocks
165 _numberOfBlocks = header.IC;
166 const bool ok = ParseSDES();
167 if (!ok)
168 {
169 // Nothing supported found, continue to next block!
170 break;
171 }
172 return;
173 }
174 case PT_BYE:
175 {
176 _numberOfBlocks = header.IC;
177 const bool ok = ParseBYE();
178 if (!ok)
179 {
180 // Nothing supported found, continue to next block!
181 break;
182 }
183 return;
184 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000185 case PT_IJ:
186 {
187 // number of Report blocks
188 _numberOfBlocks = header.IC;
189 ParseIJ();
190 return;
191 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000192 case PT_RTPFB: // Fall through!
193 case PT_PSFB:
194 {
195 const bool ok = ParseFBCommon(header);
196 if (!ok)
197 {
198 // Nothing supported found, continue to next block!
199 break;
200 }
201
202 return;
203 }
204 case PT_APP:
205 {
206 const bool ok = ParseAPP(header);
207 if (!ok)
208 {
209 // Nothing supported found, continue to next block!
210 break;
211 }
212 return;
213 }
214 case PT_XR:
215 {
216 const bool ok = ParseXR();
217 if (!ok)
218 {
219 // Nothing supported found, continue to next block!
220 break;
221 }
222 return;
223 }
224 default:
225 // Not supported! Skip!
226 EndCurrentBlock();
227 break;
228 }
229 }
230}
231
232void
233RTCPUtility::RTCPParserV2::IterateReportBlockItem()
234{
235 const bool success = ParseReportBlockItem();
236 if (!success)
237 {
238 Iterate();
239 }
240}
241
242void
243RTCPUtility::RTCPParserV2::IterateSDESChunk()
244{
245 const bool success = ParseSDESChunk();
246 if (!success)
247 {
248 Iterate();
249 }
250}
251
252void
253RTCPUtility::RTCPParserV2::IterateBYEItem()
254{
255 const bool success = ParseBYEItem();
256 if (!success)
257 {
258 Iterate();
259 }
260}
261
262void
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000263RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
264{
265 const bool success = ParseIJItem();
266 if (!success)
267 {
268 Iterate();
269 }
270}
271
272void
niklase@google.com470e71d2011-07-07 08:21:25 +0000273RTCPUtility::RTCPParserV2::IterateNACKItem()
274{
275 const bool success = ParseNACKItem();
276 if (!success)
277 {
278 Iterate();
279 }
280}
281
282void
283RTCPUtility::RTCPParserV2::IterateTMMBRItem()
284{
285 const bool success = ParseTMMBRItem();
286 if (!success)
287 {
288 Iterate();
289 }
290}
291
292void
293RTCPUtility::RTCPParserV2::IterateTMMBNItem()
294{
295 const bool success = ParseTMMBNItem();
296 if (!success)
297 {
298 Iterate();
299 }
300}
301
302void
303RTCPUtility::RTCPParserV2::IterateSLIItem()
304{
305 const bool success = ParseSLIItem();
306 if (!success)
307 {
308 Iterate();
309 }
310}
311
312void
313RTCPUtility::RTCPParserV2::IterateRPSIItem()
314{
315 const bool success = ParseRPSIItem();
316 if (!success)
317 {
318 Iterate();
319 }
320}
321
322void
323RTCPUtility::RTCPParserV2::IterateFIRItem()
324{
325 const bool success = ParseFIRItem();
326 if (!success)
327 {
328 Iterate();
329 }
330}
331
332void
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000333RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
334{
335 const bool success = ParsePsfbAppItem();
336 if (!success)
337 {
338 Iterate();
339 }
340}
341
342void
343RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
344{
345 const bool success = ParsePsfbREMBItem();
346 if (!success)
347 {
348 Iterate();
349 }
350}
351
352void
niklase@google.com470e71d2011-07-07 08:21:25 +0000353RTCPUtility::RTCPParserV2::IterateAppItem()
354{
355 const bool success = ParseAPPItem();
356 if (!success)
357 {
358 Iterate();
359 }
360}
361
362void
363RTCPUtility::RTCPParserV2::Validate()
364{
365 if (_ptrRTCPData == NULL)
366 {
367 return; // NOT VALID
368 }
369
370 RTCPCommonHeader header;
371 const bool success = RTCPParseCommonHeader(_ptrRTCPDataBegin,
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000372 _ptrRTCPDataEnd,
373 header);
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
375 if (!success)
376 {
377 return; // NOT VALID!
378 }
379
380 // * if (!reducedSize) : first packet must be RR or SR.
381 //
382 // * The padding bit (P) should be zero for the first packet of a
383 // compound RTCP packet because padding should only be applied,
384 // if it is needed, to the last packet. (NOT CHECKED!)
385 //
386 // * The length fields of the individual RTCP packets must add up
387 // to the overall length of the compound RTCP packet as
388 // received. This is a fairly strong check. (NOT CHECKED!)
389
390 if (!_RTCPReducedSizeEnable)
391 {
392 if ((header.PT != PT_SR) && (header.PT != PT_RR))
393 {
394 return; // NOT VALID
395 }
396 }
397
398 _validPacket = true;
399}
400
401bool
402RTCPUtility::RTCPParserV2::IsValid() const
403{
404 return _validPacket;
405}
406
407void
408RTCPUtility::RTCPParserV2::EndCurrentBlock()
409{
410 _ptrRTCPData = _ptrRTCPBlockEnd;
411}
412
413bool
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000414RTCPUtility::RTCPParseCommonHeader( const uint8_t* ptrDataBegin,
415 const uint8_t* ptrDataEnd,
niklase@google.com470e71d2011-07-07 08:21:25 +0000416 RTCPCommonHeader& parsedHeader)
417{
418 if (!ptrDataBegin || !ptrDataEnd)
419 {
420 return false;
421 }
422
423 // 0 1 2 3
424 // 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
425 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
426 // |V=2|P| IC | PT | length |
427 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
428 //
429 // Common header for all RTCP packets, 4 octets.
430
431 if ((ptrDataEnd - ptrDataBegin) < 4)
432 {
433 return false;
434 }
435
436 parsedHeader.V = ptrDataBegin[0] >> 6;
437 parsedHeader.P = ((ptrDataBegin[0] & 0x20) == 0) ? false : true;
438 parsedHeader.IC = ptrDataBegin[0] & 0x1f;
439 parsedHeader.PT = ptrDataBegin[1];
440
441 parsedHeader.LengthInOctets = (ptrDataBegin[2] << 8) + ptrDataBegin[3] + 1;
442 parsedHeader.LengthInOctets *= 4;
443
444 if(parsedHeader.LengthInOctets == 0)
445 {
446 return false;
447 }
448 // Check if RTP version field == 2
449 if (parsedHeader.V != 2)
450 {
451 return false;
452 }
453
454 return true;
455}
456
457bool
458RTCPUtility::RTCPParserV2::ParseRR()
459{
460 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
461
462 if (length < 8)
463 {
464 return false;
465 }
466
467
468 _ptrRTCPData += 4; // Skip header
469
470 _packetType = kRtcpRrCode;
471
472 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
473 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
474 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
475 _packet.RR.SenderSSRC += *_ptrRTCPData++;
476
477 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
478
479 // State transition
480 _state = State_ReportBlockItem;
481
482 return true;
483}
484
485bool
486RTCPUtility::RTCPParserV2::ParseSR()
487{
488 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
489
490 if (length < 28)
491 {
492 EndCurrentBlock();
493 return false;
494 }
495
496 _ptrRTCPData += 4; // Skip header
497
498 _packetType = kRtcpSrCode;
499
500 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
501 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
502 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
503 _packet.SR.SenderSSRC += *_ptrRTCPData++;
504
505 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
506 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
507 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
508 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
509
510 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
511 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
512 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
513 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
514
515 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
516 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
517 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
518 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
519
520 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
521 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
522 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
523 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
524
525 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
526 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
527 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
528 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
529
530 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
531
532 // State transition
533 if(_numberOfBlocks != 0)
534 {
535 _state = State_ReportBlockItem;
536 }else
537 {
538 // don't go to state report block item if 0 report blocks
539 _state = State_TopLevel;
540 EndCurrentBlock();
541 }
542 return true;
543}
544
545bool
546RTCPUtility::RTCPParserV2::ParseReportBlockItem()
547{
548 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
549
550 if (length < 24 || _numberOfBlocks <= 0)
551 {
552 _state = State_TopLevel;
553
554 EndCurrentBlock();
555 return false;
556 }
557 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
558 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
559 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
560 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
561
562 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
563
564 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
565 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
566 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
567
568 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
569 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
570 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
571 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
572
573 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
574 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
575 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
576 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
577
578 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
579 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
580 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
581 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
582
583 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
584 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
585 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
586 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
587
588 _numberOfBlocks--;
589 _packetType = kRtcpReportBlockItemCode;
590 return true;
591}
592
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000593/* From RFC 5450: Transmission Time Offsets in RTP Streams.
594 0 1 2 3
595 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
596 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
597 hdr |V=2|P| RC | PT=IJ=195 | length |
598 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
599 | inter-arrival jitter |
600 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
601 . .
602 . .
603 . .
604 | inter-arrival jitter |
605 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
606*/
607
608bool
609RTCPUtility::RTCPParserV2::ParseIJ()
610{
611 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
612
613 if (length < 4)
614 {
615 return false;
616 }
617
618 _ptrRTCPData += 4; // Skip header
619
620 _packetType = kRtcpExtendedIjCode;
621
622 // State transition
623 _state = State_ExtendedJitterItem;
624 return true;
625}
626
627bool
628RTCPUtility::RTCPParserV2::ParseIJItem()
629{
630 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
631
632 if (length < 4 || _numberOfBlocks <= 0)
633 {
634 _state = State_TopLevel;
635 EndCurrentBlock();
636 return false;
637 }
638
639 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
640 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
641 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
642 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
643
644 _numberOfBlocks--;
645 _packetType = kRtcpExtendedIjItemCode;
646 return true;
647}
648
niklase@google.com470e71d2011-07-07 08:21:25 +0000649bool
650RTCPUtility::RTCPParserV2::ParseSDES()
651{
652 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
653
654 if (length < 8)
655 {
656 _state = State_TopLevel;
657
658 EndCurrentBlock();
659 return false;
660 }
661 _ptrRTCPData += 4; // Skip header
662
663 _state = State_SDESChunk;
664 _packetType = kRtcpSdesCode;
665 return true;
666}
667
668bool
669RTCPUtility::RTCPParserV2::ParseSDESChunk()
670{
671 if(_numberOfBlocks <= 0)
672 {
673 _state = State_TopLevel;
674
675 EndCurrentBlock();
676 return false;
677 }
678 _numberOfBlocks--;
679
680 // Find CName item in a SDES chunk.
681 while (_ptrRTCPData < _ptrRTCPBlockEnd)
682 {
683 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
684 if (dataLen < 4)
685 {
686 _state = State_TopLevel;
687
688 EndCurrentBlock();
689 return false;
690 }
691
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000692 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000693 SSRC += *_ptrRTCPData++ << 16;
694 SSRC += *_ptrRTCPData++ << 8;
695 SSRC += *_ptrRTCPData++;
696
697 const bool foundCname = ParseSDESItem();
698 if (foundCname)
699 {
700 _packet.CName.SenderSSRC = SSRC; // Add SSRC
701 return true;
702 }
703 }
704 _state = State_TopLevel;
705
706 EndCurrentBlock();
707 return false;
708}
709
710bool
711RTCPUtility::RTCPParserV2::ParseSDESItem()
712{
713 // Find CName
714 // Only the CNAME item is mandatory. RFC 3550 page 46
715 bool foundCName = false;
716
717 size_t itemOctetsRead = 0;
718 while (_ptrRTCPData < _ptrRTCPBlockEnd)
719 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000720 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000721 ++itemOctetsRead;
722
723 if (tag == 0)
724 {
725 // End tag! 4 oct aligned
726 while ((itemOctetsRead++ % 4) != 0)
727 {
728 ++_ptrRTCPData;
729 }
730 return foundCName;
731 }
732
733 if (_ptrRTCPData < _ptrRTCPBlockEnd)
734 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000735 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000736 ++itemOctetsRead;
737
738 if (tag == 1)
739 {
740 // CNAME
741
742 // Sanity
743 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
744 {
745 _state = State_TopLevel;
746
747 EndCurrentBlock();
748 return false;
749 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000750 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000751 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000752 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000754 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
755 {
756 // Illegal char
757 _state = State_TopLevel;
758
759 EndCurrentBlock();
760 return false;
761 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000762 _packet.CName.CName[i] = c;
763 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000764 // Make sure we are null terminated.
765 _packet.CName.CName[i] = 0;
766 _packetType = kRtcpSdesChunkCode;
niklase@google.com470e71d2011-07-07 08:21:25 +0000767
768 foundCName = true;
769 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000770 _ptrRTCPData += len;
771 itemOctetsRead += len;
772 }
773 }
774
775 // No end tag found!
776 _state = State_TopLevel;
777
778 EndCurrentBlock();
779 return false;
780}
781
782bool
783RTCPUtility::RTCPParserV2::ParseBYE()
784{
785 _ptrRTCPData += 4; // Skip header
786
787 _state = State_BYEItem;
788
789 return ParseBYEItem();
790}
791
792bool
793RTCPUtility::RTCPParserV2::ParseBYEItem()
794{
795 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
796 if (length < 4 || _numberOfBlocks == 0)
797 {
798 _state = State_TopLevel;
799
800 EndCurrentBlock();
801 return false;
802 }
803
804 _packetType = kRtcpByeCode;
805
806 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
807 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
808 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
809 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
810
811 // we can have several CSRCs attached
812
813 // sanity
814 if(length >= 4*_numberOfBlocks)
815 {
816 _ptrRTCPData += (_numberOfBlocks -1)*4;
817 }
818 _numberOfBlocks = 0;
819
820 return true;
821}
822/*
823 0 1 2 3
824 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
825 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826 |V=2|P|reserved | PT=XR=207 | length |
827 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
828 | SSRC |
829 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
830 : report blocks :
831 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
832*/
833bool RTCPUtility::RTCPParserV2::ParseXR()
834{
835 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
836
837 if (length < 8)
838 {
839 EndCurrentBlock();
840 return false;
841 }
842
843 _ptrRTCPData += 4; // Skip header
844
845 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
846 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
847 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
848 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
849
850 return ParseXRItem();
851}
852/*
853 0 1 2 3
854 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
855 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
856 | BT | type-specific | block length |
857 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
858 : type-specific block contents :
859 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
860*/
861
862bool
863RTCPUtility::RTCPParserV2::ParseXRItem()
864{
865 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
866
867 if (length < 4) //
868 {
869 EndCurrentBlock();
870 return false;
871 }
872
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000873 uint8_t blockType = *_ptrRTCPData++;
874 uint8_t typeSpecific = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000875
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000876 uint16_t blockLength = *_ptrRTCPData++ << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +0000877 blockLength = *_ptrRTCPData++;
878
879 if(blockType == 7 && typeSpecific == 0)
880 {
881 if(blockLength != 8)
882 {
883 EndCurrentBlock();
884 return false;
885 }
886 return ParseXRVOIPMetricItem();
887 }else
888 {
889 EndCurrentBlock();
890 return false;
891 }
892}
893/*
894 0 1 2 3
895 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
896 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
897 | BT=7 | reserved | block length = 8 |
898 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
899 | SSRC of source |
900 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
901 | loss rate | discard rate | burst density | gap density |
902 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
903 | burst duration | gap duration |
904 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
905 | round trip delay | end system delay |
906 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
907 | signal level | noise level | RERL | Gmin |
908 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
910 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911 | RX config | reserved | JB nominal |
912 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913 | JB maximum | JB abs max |
914 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
915*/
916bool
917RTCPUtility::RTCPParserV2::ParseXRVOIPMetricItem()
918{
919 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
920
921 if (length < 28)
922 {
923 EndCurrentBlock();
924 return false;
925 }
926 _packetType = kRtcpXrVoipMetricCode;
927
928 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
929 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
930 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
931 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
932
933 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
934 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
935 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
936 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
937
938 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
939 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
940
941 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
942 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
943
944 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
945 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
946
947 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
948 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
949
950 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
951 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
952 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
953 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
954 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
955 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
956 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
957 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
958 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
959 _ptrRTCPData++; // skip reserved
960
961 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
962 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
963
964 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
965 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
966
967 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
968 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
969
970 return true;
971}
972
973bool
974RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
975{
976 assert((header.PT == PT_RTPFB) || (header.PT == PT_PSFB)); // Parser logic check
977
978 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
979
980 if (length < 12) // 4 * 3, RFC4585 section 6.1
981 {
982 EndCurrentBlock();
983 return false;
984 }
985
986 _ptrRTCPData += 4; // Skip RTCP header
987
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000988 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000989 senderSSRC += *_ptrRTCPData++ << 16;
990 senderSSRC += *_ptrRTCPData++ << 8;
991 senderSSRC += *_ptrRTCPData++;
992
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000993 uint32_t mediaSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000994 mediaSSRC += *_ptrRTCPData++ << 16;
995 mediaSSRC += *_ptrRTCPData++ << 8;
996 mediaSSRC += *_ptrRTCPData++;
997
998 if (header.PT == PT_RTPFB)
999 {
1000 // Transport layer feedback
1001
1002 switch (header.IC)
1003 {
1004 case 1:
1005 {
1006 // NACK
1007 _packetType = kRtcpRtpfbNackCode;
1008 _packet.NACK.SenderSSRC = senderSSRC;
1009 _packet.NACK.MediaSSRC = mediaSSRC;
1010
1011 _state = State_RTPFB_NACKItem;
1012
1013 return true;
1014 }
1015 case 2:
1016 {
1017 // used to be ACK is this code point, which is removed
1018 // conficts with http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
1019 break;
1020 }
1021 case 3:
1022 {
1023 // TMMBR
1024 _packetType = kRtcpRtpfbTmmbrCode;
1025 _packet.TMMBR.SenderSSRC = senderSSRC;
1026 _packet.TMMBR.MediaSSRC = mediaSSRC;
1027
1028 _state = State_RTPFB_TMMBRItem;
1029
1030 return true;
1031 }
1032 case 4:
1033 {
1034 // TMMBN
1035 _packetType = kRtcpRtpfbTmmbnCode;
1036 _packet.TMMBN.SenderSSRC = senderSSRC;
1037 _packet.TMMBN.MediaSSRC = mediaSSRC;
1038
1039 _state = State_RTPFB_TMMBNItem;
1040
1041 return true;
1042 }
1043 case 5:
1044 {
1045 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1046 // draft-perkins-avt-rapid-rtp-sync-03.txt
1047 // trigger a new RTCP SR
1048 _packetType = kRtcpRtpfbSrReqCode;
1049
1050 // Note: No state transition, SR REQ is empty!
1051 return true;
1052 }
1053 default:
1054 break;
1055 }
1056 EndCurrentBlock();
1057 return false;
1058 }
1059 else if (header.PT == PT_PSFB)
1060 {
1061 // Payload specific feedback
1062 switch (header.IC)
1063 {
1064 case 1:
1065 // PLI
1066 _packetType = kRtcpPsfbPliCode;
1067 _packet.PLI.SenderSSRC = senderSSRC;
1068 _packet.PLI.MediaSSRC = mediaSSRC;
1069
1070 // Note: No state transition, PLI FCI is empty!
1071 return true;
1072 case 2:
1073 // SLI
1074 _packetType = kRtcpPsfbSliCode;
1075 _packet.SLI.SenderSSRC = senderSSRC;
1076 _packet.SLI.MediaSSRC = mediaSSRC;
1077
1078 _state = State_PSFB_SLIItem;
1079
1080 return true;
1081 case 3:
1082 _packetType = kRtcpPsfbRpsiCode;
1083 _packet.RPSI.SenderSSRC = senderSSRC;
1084 _packet.RPSI.MediaSSRC = mediaSSRC;
1085
1086 _state = State_PSFB_RPSIItem;
1087 return true;
1088 case 4:
1089 // FIR
1090 _packetType = kRtcpPsfbFirCode;
1091 _packet.FIR.SenderSSRC = senderSSRC;
1092 _packet.FIR.MediaSSRC = mediaSSRC;
1093
1094 _state = State_PSFB_FIRItem;
1095 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001096 case 15:
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001097 _packetType = kRtcpPsfbAppCode;
1098 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1099 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001100
1101 _state = State_PSFB_AppItem;
1102 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001103 default:
1104 break;
1105 }
1106
1107 EndCurrentBlock();
1108 return false;
1109 }
1110 else
1111 {
1112 assert(false);
1113
1114 EndCurrentBlock();
1115 return false;
1116 }
1117}
1118
1119bool
1120RTCPUtility::RTCPParserV2::ParseRPSIItem()
1121{
1122 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI)
1123 /*
1124 0 1 2 3
1125 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
1126 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1127 | PB |0| Payload Type| Native RPSI bit string |
1128 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1129 | defined per codec ... | Padding (0) |
1130 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1131 */
1132
1133 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1134
1135 if (length < 4)
1136 {
1137 _state = State_TopLevel;
1138
1139 EndCurrentBlock();
1140 return false;
1141 }
1142 if(length > 2+RTCP_RPSI_DATA_SIZE)
1143 {
1144 _state = State_TopLevel;
1145
1146 EndCurrentBlock();
1147 return false;
1148 }
1149
1150 _packetType = kRtcpPsfbRpsiCode;
1151
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001152 uint8_t paddingBits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001153 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1154
1155 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length-2);
1156
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001157 _packet.RPSI.NumberOfValidBits = uint16_t(length-2)*8 - paddingBits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001158 return true;
1159}
1160
1161bool
1162RTCPUtility::RTCPParserV2::ParseNACKItem()
1163{
1164 // RFC 4585 6.2.1. Generic NACK
1165
1166 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1167
1168 if (length < 4)
1169 {
1170 _state = State_TopLevel;
1171
1172 EndCurrentBlock();
1173 return false;
1174 }
1175
1176 _packetType = kRtcpRtpfbNackItemCode;
1177
1178 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1179 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1180
1181 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1182 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1183
1184 return true;
1185}
1186
1187bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001188RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1189{
1190 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1191
1192 if (length < 4)
1193 {
1194 _state = State_TopLevel;
1195
1196 EndCurrentBlock();
1197 return false;
1198 }
1199 if(*_ptrRTCPData++ != 'R')
1200 {
1201 _state = State_TopLevel;
1202
1203 EndCurrentBlock();
1204 return false;
1205 }
1206 if(*_ptrRTCPData++ != 'E')
1207 {
1208 _state = State_TopLevel;
1209
1210 EndCurrentBlock();
1211 return false;
1212 }
1213 if(*_ptrRTCPData++ != 'M')
1214 {
1215 _state = State_TopLevel;
1216
1217 EndCurrentBlock();
1218 return false;
1219 }
1220 if(*_ptrRTCPData++ != 'B')
1221 {
1222 _state = State_TopLevel;
1223
1224 EndCurrentBlock();
1225 return false;
1226 }
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001227 _packetType = kRtcpPsfbRembCode;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001228 _state = State_PSFB_REMBItem;
1229 return true;
1230}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001231
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001232bool
1233RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1234{
1235 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1236
1237 if (length < 4)
1238 {
1239 _state = State_TopLevel;
1240
1241 EndCurrentBlock();
1242 return false;
1243 }
1244
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001245 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001246 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001247
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001248 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001249 brMantissa += (_ptrRTCPData[1] << 8);
1250 brMantissa += (_ptrRTCPData[2]);
1251
1252 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001253 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001254
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001255 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1256 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1257 {
1258 _state = State_TopLevel;
1259
1260 EndCurrentBlock();
1261 return false;
1262 }
1263
1264 _packetType = kRtcpPsfbRembItemCode;
1265
1266 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1267 {
1268 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1269 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1270 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1271 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1272 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001273 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
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001298 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001299
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001300 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001301 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1302 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1303
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001304 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001305 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
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001337 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001338
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001339 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001340 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1341 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1342
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001343 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001344 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
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001377 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001378 buffer = *_ptrRTCPData++ << 24;
1379 buffer += *_ptrRTCPData++ << 16;
1380 buffer += *_ptrRTCPData++ << 8;
1381 buffer += *_ptrRTCPData++;
1382
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001383 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1384 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1385 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001386
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
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001430 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001431 senderSSRC += *_ptrRTCPData++ << 16;
1432 senderSSRC += *_ptrRTCPData++ << 8;
1433 senderSSRC += *_ptrRTCPData++;
1434
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001435 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001436 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);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001472 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001473 _ptrRTCPData += length;
1474 }
1475 return true;
1476}
1477
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001478RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001479 size_t rtcpDataLength)
1480 : _ptrBegin(rtcpData),
1481 _ptrEnd(rtcpData + rtcpDataLength),
1482 _ptrBlock(NULL) {
1483 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001484}
1485
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001486RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001487}
1488
1489const RTCPUtility::RTCPCommonHeader*
1490RTCPUtility::RTCPPacketIterator::Begin()
1491{
1492 _ptrBlock = _ptrBegin;
1493
1494 return Iterate();
1495}
1496
1497const RTCPUtility::RTCPCommonHeader*
1498RTCPUtility::RTCPPacketIterator::Iterate()
1499{
1500 const bool success = RTCPParseCommonHeader(_ptrBlock, _ptrEnd, _header);
1501 if (!success)
1502 {
1503 _ptrBlock = NULL;
1504 return NULL;
1505 }
1506 _ptrBlock += _header.LengthInOctets;
1507
1508 if (_ptrBlock > _ptrEnd)
1509 {
1510 _ptrBlock = NULL;
1511 return NULL;
1512 }
1513
1514 return &_header;
1515}
1516
1517const RTCPUtility::RTCPCommonHeader*
1518RTCPUtility::RTCPPacketIterator::Current()
1519{
1520 if (!_ptrBlock)
1521 {
1522 return NULL;
1523 }
1524
1525 return &_header;
1526}
1527} // namespace webrtc