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