blob: 705a38b01619427bd2b73f1a8a63e38b98edb436 [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 {
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000227 const bool ok = ParseXr();
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 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{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000246 const bool success = ParseXrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000247 if (!success)
248 {
249 Iterate();
250 }
251}
252
253void
254RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
255{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000256 const bool success = ParseXrDlrrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000257 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/*
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000854 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +0000855 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*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000864bool RTCPUtility::RTCPParserV2::ParseXr()
niklase@google.com470e71d2011-07-07 08:21:25 +0000865{
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
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000885/* Extended report block format (RFC 3611).
886 BT: block type.
887 block length: length of report block in 32-bits words minus one (including
888 the header).
niklase@google.com470e71d2011-07-07 08:21:25 +0000889 0 1 2 3
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000890 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
niklase@google.com470e71d2011-07-07 08:21:25 +0000891 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
892 | BT | type-specific | block length |
893 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
894 : type-specific block contents :
895 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
896*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000897bool RTCPUtility::RTCPParserV2::ParseXrItem() {
898 const int kBlockHeaderLengthInBytes = 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000899 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000900 if (length < kBlockHeaderLengthInBytes) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000901 _state = State_TopLevel;
902 EndCurrentBlock();
903 return false;
904 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000905
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000906 uint8_t block_type = *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000907 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000908
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000909 uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
910 block_length_in_4bytes += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000911
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000912 switch (block_type) {
913 case kBtReceiverReferenceTime:
914 return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
915 case kBtDlrr:
916 return ParseXrDlrr(block_length_in_4bytes);
917 case kBtVoipMetric:
918 return ParseXrVoipMetricItem(block_length_in_4bytes);
919 default:
920 return ParseXrUnsupportedBlockType(block_length_in_4bytes);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000921 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000922}
923
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000924/* Receiver Reference Time Report Block.
925 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000926 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
927 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
928 | BT=4 | reserved | block length = 2 |
929 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
930 | NTP timestamp, most significant word |
931 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
932 | NTP timestamp, least significant word |
933 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
934*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000935bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
936 int block_length_4bytes) {
937 const int kBlockLengthIn4Bytes = 2;
938 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000939 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000940 if (block_length_4bytes != kBlockLengthIn4Bytes ||
941 length < kBlockLengthInBytes) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000942 _state = State_TopLevel;
943 EndCurrentBlock();
944 return false;
945 }
946
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000947 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
948 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
949 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
950 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000951
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000952 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
953 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
954 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
955 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000956
957 _packetType = kRtcpXrReceiverReferenceTimeCode;
958 _state = State_XRItem;
959 return true;
960}
961
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000962/* DLRR Report Block.
963 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000964 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
965 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
966 | BT=5 | reserved | block length |
967 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
968 | SSRC_1 (SSRC of first receiver) | sub-
969 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
970 | last RR (LRR) | 1
971 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
972 | delay since last RR (DLRR) |
973 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
974 | SSRC_2 (SSRC of second receiver) | sub-
975 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
976 : ... : 2
977 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
978*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000979bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
980 const int kSubBlockLengthIn4Bytes = 3;
981 if (block_length_4bytes < 0 ||
982 (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
983 _state = State_TopLevel;
984 EndCurrentBlock();
985 return false;
986 }
987 _packetType = kRtcpXrDlrrReportBlockCode;
988 _state = State_XR_DLLRItem;
989 _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
990 return true;
991}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000992
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000993bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000994 if (_numberOfBlocks == 0) {
995 _state = State_XRItem;
996 return false;
997 }
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000998 const int kSubBlockLengthInBytes = 12;
999 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1000 if (length < kSubBlockLengthInBytes) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001001 _state = State_TopLevel;
1002 EndCurrentBlock();
1003 return false;
1004 }
1005
1006 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1007 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1008 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1009 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1010
1011 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1012 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1013 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1014 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1015
1016 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1017 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1018 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1019 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1020
1021 _packetType = kRtcpXrDlrrReportBlockItemCode;
1022 --_numberOfBlocks;
1023 _state = State_XR_DLLRItem;
1024 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001025}
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001026/* VoIP Metrics Report Block.
1027 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +00001028 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
1029 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1030 | BT=7 | reserved | block length = 8 |
1031 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1032 | SSRC of source |
1033 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1034 | loss rate | discard rate | burst density | gap density |
1035 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1036 | burst duration | gap duration |
1037 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1038 | round trip delay | end system delay |
1039 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1040 | signal level | noise level | RERL | Gmin |
1041 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1042 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1043 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1044 | RX config | reserved | JB nominal |
1045 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1046 | JB maximum | JB abs max |
1047 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1048*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001049
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001050bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
1051 const int kBlockLengthIn4Bytes = 8;
1052 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
1053 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1054 if (block_length_4bytes != kBlockLengthIn4Bytes ||
1055 length < kBlockLengthInBytes) {
1056 _state = State_TopLevel;
1057 EndCurrentBlock();
1058 return false;
1059 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001060
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001061 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1062 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1063 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1064 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001065
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001066 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1067 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1068 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1069 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001070
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001071 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1072 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001073
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001074 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1075 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001076
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001077 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1078 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001079
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001080 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1081 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001082
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001083 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1084 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1085 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1086 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1087 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1088 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1089 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1090 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1091 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1092 _ptrRTCPData++; // skip reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001093
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001094 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1095 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001096
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001097 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1098 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001099
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001100 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1101 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001102
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001103 _packetType = kRtcpXrVoipMetricCode;
1104 _state = State_XRItem;
1105 return true;
1106}
niklase@google.com470e71d2011-07-07 08:21:25 +00001107
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001108bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
1109 int block_length_4bytes) {
1110 const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
1111 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1112 if (length < kBlockLengthInBytes) {
1113 _state = State_TopLevel;
1114 EndCurrentBlock();
1115 return false;
1116 }
1117 // Skip block.
1118 _ptrRTCPData += kBlockLengthInBytes;
1119 _state = State_XRItem;
1120 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121}
1122
1123bool
1124RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
1125{
1126 assert((header.PT == PT_RTPFB) || (header.PT == PT_PSFB)); // Parser logic check
1127
1128 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1129
1130 if (length < 12) // 4 * 3, RFC4585 section 6.1
1131 {
1132 EndCurrentBlock();
1133 return false;
1134 }
1135
1136 _ptrRTCPData += 4; // Skip RTCP header
1137
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001138 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001139 senderSSRC += *_ptrRTCPData++ << 16;
1140 senderSSRC += *_ptrRTCPData++ << 8;
1141 senderSSRC += *_ptrRTCPData++;
1142
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001143 uint32_t mediaSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001144 mediaSSRC += *_ptrRTCPData++ << 16;
1145 mediaSSRC += *_ptrRTCPData++ << 8;
1146 mediaSSRC += *_ptrRTCPData++;
1147
1148 if (header.PT == PT_RTPFB)
1149 {
1150 // Transport layer feedback
1151
1152 switch (header.IC)
1153 {
1154 case 1:
1155 {
1156 // NACK
1157 _packetType = kRtcpRtpfbNackCode;
1158 _packet.NACK.SenderSSRC = senderSSRC;
1159 _packet.NACK.MediaSSRC = mediaSSRC;
1160
1161 _state = State_RTPFB_NACKItem;
1162
1163 return true;
1164 }
1165 case 2:
1166 {
1167 // used to be ACK is this code point, which is removed
1168 // conficts with http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
1169 break;
1170 }
1171 case 3:
1172 {
1173 // TMMBR
1174 _packetType = kRtcpRtpfbTmmbrCode;
1175 _packet.TMMBR.SenderSSRC = senderSSRC;
1176 _packet.TMMBR.MediaSSRC = mediaSSRC;
1177
1178 _state = State_RTPFB_TMMBRItem;
1179
1180 return true;
1181 }
1182 case 4:
1183 {
1184 // TMMBN
1185 _packetType = kRtcpRtpfbTmmbnCode;
1186 _packet.TMMBN.SenderSSRC = senderSSRC;
1187 _packet.TMMBN.MediaSSRC = mediaSSRC;
1188
1189 _state = State_RTPFB_TMMBNItem;
1190
1191 return true;
1192 }
1193 case 5:
1194 {
1195 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1196 // draft-perkins-avt-rapid-rtp-sync-03.txt
1197 // trigger a new RTCP SR
1198 _packetType = kRtcpRtpfbSrReqCode;
1199
1200 // Note: No state transition, SR REQ is empty!
1201 return true;
1202 }
1203 default:
1204 break;
1205 }
1206 EndCurrentBlock();
1207 return false;
1208 }
1209 else if (header.PT == PT_PSFB)
1210 {
1211 // Payload specific feedback
1212 switch (header.IC)
1213 {
1214 case 1:
1215 // PLI
1216 _packetType = kRtcpPsfbPliCode;
1217 _packet.PLI.SenderSSRC = senderSSRC;
1218 _packet.PLI.MediaSSRC = mediaSSRC;
1219
1220 // Note: No state transition, PLI FCI is empty!
1221 return true;
1222 case 2:
1223 // SLI
1224 _packetType = kRtcpPsfbSliCode;
1225 _packet.SLI.SenderSSRC = senderSSRC;
1226 _packet.SLI.MediaSSRC = mediaSSRC;
1227
1228 _state = State_PSFB_SLIItem;
1229
1230 return true;
1231 case 3:
1232 _packetType = kRtcpPsfbRpsiCode;
1233 _packet.RPSI.SenderSSRC = senderSSRC;
1234 _packet.RPSI.MediaSSRC = mediaSSRC;
1235
1236 _state = State_PSFB_RPSIItem;
1237 return true;
1238 case 4:
1239 // FIR
1240 _packetType = kRtcpPsfbFirCode;
1241 _packet.FIR.SenderSSRC = senderSSRC;
1242 _packet.FIR.MediaSSRC = mediaSSRC;
1243
1244 _state = State_PSFB_FIRItem;
1245 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001246 case 15:
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001247 _packetType = kRtcpPsfbAppCode;
1248 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1249 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001250
1251 _state = State_PSFB_AppItem;
1252 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001253 default:
1254 break;
1255 }
1256
1257 EndCurrentBlock();
1258 return false;
1259 }
1260 else
1261 {
1262 assert(false);
1263
1264 EndCurrentBlock();
1265 return false;
1266 }
1267}
1268
1269bool
1270RTCPUtility::RTCPParserV2::ParseRPSIItem()
1271{
1272 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI)
1273 /*
1274 0 1 2 3
1275 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
1276 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1277 | PB |0| Payload Type| Native RPSI bit string |
1278 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1279 | defined per codec ... | Padding (0) |
1280 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1281 */
1282
1283 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1284
1285 if (length < 4)
1286 {
1287 _state = State_TopLevel;
1288
1289 EndCurrentBlock();
1290 return false;
1291 }
1292 if(length > 2+RTCP_RPSI_DATA_SIZE)
1293 {
1294 _state = State_TopLevel;
1295
1296 EndCurrentBlock();
1297 return false;
1298 }
1299
1300 _packetType = kRtcpPsfbRpsiCode;
1301
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001302 uint8_t paddingBits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001303 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1304
1305 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length-2);
1306
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001307 _packet.RPSI.NumberOfValidBits = uint16_t(length-2)*8 - paddingBits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001308 return true;
1309}
1310
1311bool
1312RTCPUtility::RTCPParserV2::ParseNACKItem()
1313{
1314 // RFC 4585 6.2.1. Generic NACK
1315
1316 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1317
1318 if (length < 4)
1319 {
1320 _state = State_TopLevel;
1321
1322 EndCurrentBlock();
1323 return false;
1324 }
1325
1326 _packetType = kRtcpRtpfbNackItemCode;
1327
1328 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1329 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1330
1331 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1332 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1333
1334 return true;
1335}
1336
1337bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001338RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1339{
1340 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1341
1342 if (length < 4)
1343 {
1344 _state = State_TopLevel;
1345
1346 EndCurrentBlock();
1347 return false;
1348 }
1349 if(*_ptrRTCPData++ != 'R')
1350 {
1351 _state = State_TopLevel;
1352
1353 EndCurrentBlock();
1354 return false;
1355 }
1356 if(*_ptrRTCPData++ != 'E')
1357 {
1358 _state = State_TopLevel;
1359
1360 EndCurrentBlock();
1361 return false;
1362 }
1363 if(*_ptrRTCPData++ != 'M')
1364 {
1365 _state = State_TopLevel;
1366
1367 EndCurrentBlock();
1368 return false;
1369 }
1370 if(*_ptrRTCPData++ != 'B')
1371 {
1372 _state = State_TopLevel;
1373
1374 EndCurrentBlock();
1375 return false;
1376 }
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001377 _packetType = kRtcpPsfbRembCode;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001378 _state = State_PSFB_REMBItem;
1379 return true;
1380}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001381
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001382bool
1383RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1384{
1385 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1386
1387 if (length < 4)
1388 {
1389 _state = State_TopLevel;
1390
1391 EndCurrentBlock();
1392 return false;
1393 }
1394
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001395 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001396 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001397
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001398 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001399 brMantissa += (_ptrRTCPData[1] << 8);
1400 brMantissa += (_ptrRTCPData[2]);
1401
1402 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001403 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001404
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001405 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1406 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1407 {
1408 _state = State_TopLevel;
1409
1410 EndCurrentBlock();
1411 return false;
1412 }
1413
1414 _packetType = kRtcpPsfbRembItemCode;
1415
1416 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1417 {
1418 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1419 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1420 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1421 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1422 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001423 return true;
1424}
1425
1426bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001427RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1428{
1429 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1430
1431 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1432
1433 if (length < 8)
1434 {
1435 _state = State_TopLevel;
1436
1437 EndCurrentBlock();
1438 return false;
1439 }
1440
1441 _packetType = kRtcpRtpfbTmmbrItemCode;
1442
1443 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1444 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1445 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1446 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1447
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001448 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001449
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001450 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001451 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1452 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1453
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001454 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001455 measuredOH += _ptrRTCPData[3];
1456
1457 _ptrRTCPData += 4; // Fwd read data
1458
1459 _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1460 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1461
1462 return true;
1463}
1464
1465bool
1466RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1467{
1468 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1469
1470 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1471
1472 if (length < 8)
1473 {
1474 _state = State_TopLevel;
1475
1476 EndCurrentBlock();
1477 return false;
1478 }
1479
1480 _packetType = kRtcpRtpfbTmmbnItemCode;
1481
1482 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1483 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1484 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1485 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1486
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001487 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001488
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001489 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001490 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1491 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1492
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001493 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001494 measuredOH += _ptrRTCPData[3];
1495
1496 _ptrRTCPData += 4; // Fwd read data
1497
1498 _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1499 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1500
1501 return true;
1502}
1503
1504bool
1505RTCPUtility::RTCPParserV2::ParseSLIItem()
1506{
1507 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1508 /*
1509 0 1 2 3
1510 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
1511 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1512 | First | Number | PictureID |
1513 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1514 */
1515
1516 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1517
1518 if (length < 4)
1519 {
1520 _state = State_TopLevel;
1521
1522 EndCurrentBlock();
1523 return false;
1524 }
1525 _packetType = kRtcpPsfbSliItemCode;
1526
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001527 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001528 buffer = *_ptrRTCPData++ << 24;
1529 buffer += *_ptrRTCPData++ << 16;
1530 buffer += *_ptrRTCPData++ << 8;
1531 buffer += *_ptrRTCPData++;
1532
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001533 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1534 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1535 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001536
1537 return true;
1538}
1539
1540bool
1541RTCPUtility::RTCPParserV2::ParseFIRItem()
1542{
1543 // RFC 5104 4.3.1. Full Intra Request (FIR)
1544
1545 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1546
1547 if (length < 8)
1548 {
1549 _state = State_TopLevel;
1550
1551 EndCurrentBlock();
1552 return false;
1553 }
1554
1555 _packetType = kRtcpPsfbFirItemCode;
1556
1557 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1558 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1559 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1560 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1561
1562 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1563 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1564 return true;
1565}
1566
1567bool
1568RTCPUtility::RTCPParserV2::ParseAPP( const RTCPCommonHeader& header)
1569{
1570 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1571
1572 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1573 {
1574 EndCurrentBlock();
1575 return false;
1576 }
1577
1578 _ptrRTCPData += 4; // Skip RTCP header
1579
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001580 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001581 senderSSRC += *_ptrRTCPData++ << 16;
1582 senderSSRC += *_ptrRTCPData++ << 8;
1583 senderSSRC += *_ptrRTCPData++;
1584
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001585 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001586 name += *_ptrRTCPData++ << 16;
1587 name += *_ptrRTCPData++ << 8;
1588 name += *_ptrRTCPData++;
1589
1590 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1591
1592 _packetType = kRtcpAppCode;
1593
1594 _packet.APP.SubType = header.IC;
1595 _packet.APP.Name = name;
1596
1597 _state = State_AppItem;
1598 return true;
1599}
1600
1601bool
1602RTCPUtility::RTCPParserV2::ParseAPPItem()
1603{
1604 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1605 if (length < 4)
1606 {
1607 _state = State_TopLevel;
1608
1609 EndCurrentBlock();
1610 return false;
1611 }
1612 _packetType = kRtcpAppItemCode;
1613
1614 if(length > kRtcpAppCode_DATA_SIZE)
1615 {
1616 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1617 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1618 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1619 }else
1620 {
1621 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001622 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001623 _ptrRTCPData += length;
1624 }
1625 return true;
1626}
1627
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001628RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001629 size_t rtcpDataLength)
1630 : _ptrBegin(rtcpData),
1631 _ptrEnd(rtcpData + rtcpDataLength),
1632 _ptrBlock(NULL) {
1633 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001634}
1635
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001636RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001637}
1638
1639const RTCPUtility::RTCPCommonHeader*
1640RTCPUtility::RTCPPacketIterator::Begin()
1641{
1642 _ptrBlock = _ptrBegin;
1643
1644 return Iterate();
1645}
1646
1647const RTCPUtility::RTCPCommonHeader*
1648RTCPUtility::RTCPPacketIterator::Iterate()
1649{
1650 const bool success = RTCPParseCommonHeader(_ptrBlock, _ptrEnd, _header);
1651 if (!success)
1652 {
1653 _ptrBlock = NULL;
1654 return NULL;
1655 }
1656 _ptrBlock += _header.LengthInOctets;
1657
1658 if (_ptrBlock > _ptrEnd)
1659 {
1660 _ptrBlock = NULL;
1661 return NULL;
1662 }
1663
1664 return &_header;
1665}
1666
1667const RTCPUtility::RTCPCommonHeader*
1668RTCPUtility::RTCPPacketIterator::Current()
1669{
1670 if (!_ptrBlock)
1671 {
1672 return NULL;
1673 }
1674
1675 return &_header;
1676}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001677} // namespace webrtc