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