blob: 9acab735e500a07f28f6b6feaea22df46d994c0a [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
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001269bool RTCPUtility::RTCPParserV2::ParseRPSIItem() {
1270
1271 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI).
1272 //
1273 // 0 1 2 3
1274 // 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
1275 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1276 // | PB |0| Payload Type| Native RPSI bit string |
1277 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1278 // | defined per codec ... | Padding (0) |
1279 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
niklase@google.com470e71d2011-07-07 08:21:25 +00001280
1281 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1282
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001283 if (length < 4) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 _state = State_TopLevel;
1285
1286 EndCurrentBlock();
1287 return false;
1288 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001289 if (length > 2 + RTCP_RPSI_DATA_SIZE) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001290 _state = State_TopLevel;
1291
1292 EndCurrentBlock();
1293 return false;
1294 }
1295
1296 _packetType = kRtcpPsfbRpsiCode;
1297
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001298 uint8_t padding_bits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001299 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1300
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001301 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
1302 _ptrRTCPData += length - 2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001303
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001304 _packet.RPSI.NumberOfValidBits =
1305 static_cast<uint16_t>(length - 2) * 8 - padding_bits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001306 return true;
1307}
1308
1309bool
1310RTCPUtility::RTCPParserV2::ParseNACKItem()
1311{
1312 // RFC 4585 6.2.1. Generic NACK
1313
1314 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1315
1316 if (length < 4)
1317 {
1318 _state = State_TopLevel;
1319
1320 EndCurrentBlock();
1321 return false;
1322 }
1323
1324 _packetType = kRtcpRtpfbNackItemCode;
1325
1326 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1327 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1328
1329 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1330 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1331
1332 return true;
1333}
1334
1335bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001336RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1337{
1338 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1339
1340 if (length < 4)
1341 {
1342 _state = State_TopLevel;
1343
1344 EndCurrentBlock();
1345 return false;
1346 }
1347 if(*_ptrRTCPData++ != 'R')
1348 {
1349 _state = State_TopLevel;
1350
1351 EndCurrentBlock();
1352 return false;
1353 }
1354 if(*_ptrRTCPData++ != 'E')
1355 {
1356 _state = State_TopLevel;
1357
1358 EndCurrentBlock();
1359 return false;
1360 }
1361 if(*_ptrRTCPData++ != 'M')
1362 {
1363 _state = State_TopLevel;
1364
1365 EndCurrentBlock();
1366 return false;
1367 }
1368 if(*_ptrRTCPData++ != 'B')
1369 {
1370 _state = State_TopLevel;
1371
1372 EndCurrentBlock();
1373 return false;
1374 }
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001375 _packetType = kRtcpPsfbRembCode;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001376 _state = State_PSFB_REMBItem;
1377 return true;
1378}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001379
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001380bool
1381RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1382{
1383 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1384
1385 if (length < 4)
1386 {
1387 _state = State_TopLevel;
1388
1389 EndCurrentBlock();
1390 return false;
1391 }
1392
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001393 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001394 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001395
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001396 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001397 brMantissa += (_ptrRTCPData[1] << 8);
1398 brMantissa += (_ptrRTCPData[2]);
1399
1400 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001401 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001402
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001403 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1404 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1405 {
1406 _state = State_TopLevel;
1407
1408 EndCurrentBlock();
1409 return false;
1410 }
1411
1412 _packetType = kRtcpPsfbRembItemCode;
1413
1414 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1415 {
1416 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1417 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1418 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1419 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1420 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001421 return true;
1422}
1423
1424bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001425RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1426{
1427 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1428
1429 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1430
1431 if (length < 8)
1432 {
1433 _state = State_TopLevel;
1434
1435 EndCurrentBlock();
1436 return false;
1437 }
1438
1439 _packetType = kRtcpRtpfbTmmbrItemCode;
1440
1441 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1442 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1443 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1444 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1445
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001446 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001447
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001448 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001449 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1450 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1451
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001452 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001453 measuredOH += _ptrRTCPData[3];
1454
1455 _ptrRTCPData += 4; // Fwd read data
1456
1457 _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1458 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1459
1460 return true;
1461}
1462
1463bool
1464RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1465{
1466 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1467
1468 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1469
1470 if (length < 8)
1471 {
1472 _state = State_TopLevel;
1473
1474 EndCurrentBlock();
1475 return false;
1476 }
1477
1478 _packetType = kRtcpRtpfbTmmbnItemCode;
1479
1480 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1481 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1482 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1483 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1484
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001485 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001486
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001487 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001488 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1489 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1490
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001491 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001492 measuredOH += _ptrRTCPData[3];
1493
1494 _ptrRTCPData += 4; // Fwd read data
1495
1496 _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1497 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1498
1499 return true;
1500}
1501
1502bool
1503RTCPUtility::RTCPParserV2::ParseSLIItem()
1504{
1505 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1506 /*
1507 0 1 2 3
1508 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
1509 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1510 | First | Number | PictureID |
1511 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1512 */
1513
1514 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1515
1516 if (length < 4)
1517 {
1518 _state = State_TopLevel;
1519
1520 EndCurrentBlock();
1521 return false;
1522 }
1523 _packetType = kRtcpPsfbSliItemCode;
1524
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001525 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001526 buffer = *_ptrRTCPData++ << 24;
1527 buffer += *_ptrRTCPData++ << 16;
1528 buffer += *_ptrRTCPData++ << 8;
1529 buffer += *_ptrRTCPData++;
1530
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001531 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1532 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1533 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001534
1535 return true;
1536}
1537
1538bool
1539RTCPUtility::RTCPParserV2::ParseFIRItem()
1540{
1541 // RFC 5104 4.3.1. Full Intra Request (FIR)
1542
1543 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1544
1545 if (length < 8)
1546 {
1547 _state = State_TopLevel;
1548
1549 EndCurrentBlock();
1550 return false;
1551 }
1552
1553 _packetType = kRtcpPsfbFirItemCode;
1554
1555 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1556 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1557 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1558 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1559
1560 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1561 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1562 return true;
1563}
1564
1565bool
1566RTCPUtility::RTCPParserV2::ParseAPP( const RTCPCommonHeader& header)
1567{
1568 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1569
1570 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1571 {
1572 EndCurrentBlock();
1573 return false;
1574 }
1575
1576 _ptrRTCPData += 4; // Skip RTCP header
1577
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001578 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001579 senderSSRC += *_ptrRTCPData++ << 16;
1580 senderSSRC += *_ptrRTCPData++ << 8;
1581 senderSSRC += *_ptrRTCPData++;
1582
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001583 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001584 name += *_ptrRTCPData++ << 16;
1585 name += *_ptrRTCPData++ << 8;
1586 name += *_ptrRTCPData++;
1587
1588 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1589
1590 _packetType = kRtcpAppCode;
1591
1592 _packet.APP.SubType = header.IC;
1593 _packet.APP.Name = name;
1594
1595 _state = State_AppItem;
1596 return true;
1597}
1598
1599bool
1600RTCPUtility::RTCPParserV2::ParseAPPItem()
1601{
1602 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1603 if (length < 4)
1604 {
1605 _state = State_TopLevel;
1606
1607 EndCurrentBlock();
1608 return false;
1609 }
1610 _packetType = kRtcpAppItemCode;
1611
1612 if(length > kRtcpAppCode_DATA_SIZE)
1613 {
1614 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1615 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1616 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1617 }else
1618 {
1619 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001620 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001621 _ptrRTCPData += length;
1622 }
1623 return true;
1624}
1625
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001626RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001627 size_t rtcpDataLength)
1628 : _ptrBegin(rtcpData),
1629 _ptrEnd(rtcpData + rtcpDataLength),
1630 _ptrBlock(NULL) {
1631 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001632}
1633
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001634RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001635}
1636
1637const RTCPUtility::RTCPCommonHeader*
1638RTCPUtility::RTCPPacketIterator::Begin()
1639{
1640 _ptrBlock = _ptrBegin;
1641
1642 return Iterate();
1643}
1644
1645const RTCPUtility::RTCPCommonHeader*
1646RTCPUtility::RTCPPacketIterator::Iterate()
1647{
1648 const bool success = RTCPParseCommonHeader(_ptrBlock, _ptrEnd, _header);
1649 if (!success)
1650 {
1651 _ptrBlock = NULL;
1652 return NULL;
1653 }
1654 _ptrBlock += _header.LengthInOctets;
1655
1656 if (_ptrBlock > _ptrEnd)
1657 {
1658 _ptrBlock = NULL;
1659 return NULL;
1660 }
1661
1662 return &_header;
1663}
1664
1665const RTCPUtility::RTCPCommonHeader*
1666RTCPUtility::RTCPPacketIterator::Current()
1667{
1668 if (!_ptrBlock)
1669 {
1670 return NULL;
1671 }
1672
1673 return &_header;
1674}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001675} // namespace webrtc