blob: 4e37cf3716d916c7ecb1bfd6185b1790dfa15f5f [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 {
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +000020
21NackStats::NackStats()
22 : max_sequence_number_(0),
23 requests_(0),
24 unique_requests_(0) {}
25
26NackStats::~NackStats() {}
27
28void NackStats::ReportRequest(uint16_t sequence_number) {
29 if (requests_ == 0 ||
30 webrtc::IsNewerSequenceNumber(sequence_number, max_sequence_number_)) {
31 max_sequence_number_ = sequence_number;
32 ++unique_requests_;
33 }
34 ++requests_;
35}
36
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000037uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) {
38 return (ntp_sec << 16) + (ntp_frac >> 16);
39} // end RTCPUtility
40}
41
42// RTCPParserV2 : currently read only
pbos@webrtc.org2f446732013-04-08 11:08:41 +000043RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
niklase@google.com470e71d2011-07-07 08:21:25 +000044 size_t rtcpDataLength,
45 bool rtcpReducedSizeEnable)
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000046 : _ptrRTCPDataBegin(rtcpData),
47 _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
48 _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
49 _validPacket(false),
50 _ptrRTCPData(rtcpData),
51 _ptrRTCPBlockEnd(NULL),
Erik Språng242e22b2015-05-11 10:17:43 +020052 _state(ParseState::State_TopLevel),
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000053 _numberOfBlocks(0),
Erik Språng242e22b2015-05-11 10:17:43 +020054 _packetType(RTCPPacketTypes::kInvalid) {
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000055 Validate();
niklase@google.com470e71d2011-07-07 08:21:25 +000056}
57
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000058RTCPUtility::RTCPParserV2::~RTCPParserV2() {
niklase@google.com470e71d2011-07-07 08:21:25 +000059}
60
61ptrdiff_t
62RTCPUtility::RTCPParserV2::LengthLeft() const
63{
64 return (_ptrRTCPDataEnd- _ptrRTCPData);
65}
66
67RTCPUtility::RTCPPacketTypes
68RTCPUtility::RTCPParserV2::PacketType() const
69{
70 return _packetType;
71}
72
73const RTCPUtility::RTCPPacket&
74RTCPUtility::RTCPParserV2::Packet() const
75{
76 return _packet;
77}
78
79RTCPUtility::RTCPPacketTypes
80RTCPUtility::RTCPParserV2::Begin()
81{
82 _ptrRTCPData = _ptrRTCPDataBegin;
83
84 return Iterate();
85}
86
87RTCPUtility::RTCPPacketTypes
88RTCPUtility::RTCPParserV2::Iterate()
89{
90 // Reset packet type
Erik Språng242e22b2015-05-11 10:17:43 +020091 _packetType = RTCPPacketTypes::kInvalid;
niklase@google.com470e71d2011-07-07 08:21:25 +000092
93 if (IsValid())
94 {
95 switch (_state)
96 {
Erik Språng242e22b2015-05-11 10:17:43 +020097 case ParseState::State_TopLevel:
niklase@google.com470e71d2011-07-07 08:21:25 +000098 IterateTopLevel();
99 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200100 case ParseState::State_ReportBlockItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000101 IterateReportBlockItem();
102 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200103 case ParseState::State_SDESChunk:
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 IterateSDESChunk();
105 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200106 case ParseState::State_BYEItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 IterateBYEItem();
108 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200109 case ParseState::State_ExtendedJitterItem:
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000110 IterateExtendedJitterItem();
111 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200112 case ParseState::State_RTPFB_NACKItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000113 IterateNACKItem();
114 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200115 case ParseState::State_RTPFB_TMMBRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 IterateTMMBRItem();
117 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200118 case ParseState::State_RTPFB_TMMBNItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000119 IterateTMMBNItem();
120 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200121 case ParseState::State_PSFB_SLIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000122 IterateSLIItem();
123 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200124 case ParseState::State_PSFB_RPSIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 IterateRPSIItem();
126 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200127 case ParseState::State_PSFB_FIRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 IterateFIRItem();
129 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200130 case ParseState::State_PSFB_AppItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000131 IteratePsfbAppItem();
132 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200133 case ParseState::State_PSFB_REMBItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000134 IteratePsfbREMBItem();
135 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200136 case ParseState::State_XRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000137 IterateXrItem();
138 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200139 case ParseState::State_XR_DLLRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000140 IterateXrDlrrItem();
141 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200142 case ParseState::State_AppItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000143 IterateAppItem();
144 break;
145 default:
146 assert(false); // Invalid state!
147 break;
148 }
149 }
150 return _packetType;
151}
152
153void
154RTCPUtility::RTCPParserV2::IterateTopLevel()
155{
156 for (;;)
157 {
158 RTCPCommonHeader header;
159
160 const bool success = RTCPParseCommonHeader(_ptrRTCPData,
161 _ptrRTCPDataEnd,
162 header);
163
164 if (!success)
165 {
166 return;
167 }
168 _ptrRTCPBlockEnd = _ptrRTCPData + header.LengthInOctets;
169 if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
170 {
171 // Bad block!
172 return;
173 }
174
175 switch (header.PT)
176 {
177 case PT_SR:
178 {
179 // number of Report blocks
180 _numberOfBlocks = header.IC;
181 ParseSR();
182 return;
183 }
184 case PT_RR:
185 {
186 // number of Report blocks
187 _numberOfBlocks = header.IC;
188 ParseRR();
189 return;
190 }
191 case PT_SDES:
192 {
193 // number of SDES blocks
194 _numberOfBlocks = header.IC;
195 const bool ok = ParseSDES();
196 if (!ok)
197 {
198 // Nothing supported found, continue to next block!
199 break;
200 }
201 return;
202 }
203 case PT_BYE:
204 {
205 _numberOfBlocks = header.IC;
206 const bool ok = ParseBYE();
207 if (!ok)
208 {
209 // Nothing supported found, continue to next block!
210 break;
211 }
212 return;
213 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000214 case PT_IJ:
215 {
216 // number of Report blocks
217 _numberOfBlocks = header.IC;
218 ParseIJ();
219 return;
220 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 case PT_RTPFB: // Fall through!
222 case PT_PSFB:
223 {
224 const bool ok = ParseFBCommon(header);
225 if (!ok)
226 {
227 // Nothing supported found, continue to next block!
228 break;
229 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000230 return;
231 }
232 case PT_APP:
233 {
234 const bool ok = ParseAPP(header);
235 if (!ok)
236 {
237 // Nothing supported found, continue to next block!
238 break;
239 }
240 return;
241 }
242 case PT_XR:
243 {
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000244 const bool ok = ParseXr();
niklase@google.com470e71d2011-07-07 08:21:25 +0000245 if (!ok)
246 {
247 // Nothing supported found, continue to next block!
248 break;
249 }
250 return;
251 }
252 default:
253 // Not supported! Skip!
254 EndCurrentBlock();
255 break;
256 }
257 }
258}
259
260void
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000261RTCPUtility::RTCPParserV2::IterateXrItem()
262{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000263 const bool success = ParseXrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000264 if (!success)
265 {
266 Iterate();
267 }
268}
269
270void
271RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
272{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000273 const bool success = ParseXrDlrrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000274 if (!success)
275 {
276 Iterate();
277 }
278}
279
280void
niklase@google.com470e71d2011-07-07 08:21:25 +0000281RTCPUtility::RTCPParserV2::IterateReportBlockItem()
282{
283 const bool success = ParseReportBlockItem();
284 if (!success)
285 {
286 Iterate();
287 }
288}
289
290void
291RTCPUtility::RTCPParserV2::IterateSDESChunk()
292{
293 const bool success = ParseSDESChunk();
294 if (!success)
295 {
296 Iterate();
297 }
298}
299
300void
301RTCPUtility::RTCPParserV2::IterateBYEItem()
302{
303 const bool success = ParseBYEItem();
304 if (!success)
305 {
306 Iterate();
307 }
308}
309
310void
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000311RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
312{
313 const bool success = ParseIJItem();
314 if (!success)
315 {
316 Iterate();
317 }
318}
319
320void
niklase@google.com470e71d2011-07-07 08:21:25 +0000321RTCPUtility::RTCPParserV2::IterateNACKItem()
322{
323 const bool success = ParseNACKItem();
324 if (!success)
325 {
326 Iterate();
327 }
328}
329
330void
331RTCPUtility::RTCPParserV2::IterateTMMBRItem()
332{
333 const bool success = ParseTMMBRItem();
334 if (!success)
335 {
336 Iterate();
337 }
338}
339
340void
341RTCPUtility::RTCPParserV2::IterateTMMBNItem()
342{
343 const bool success = ParseTMMBNItem();
344 if (!success)
345 {
346 Iterate();
347 }
348}
349
350void
351RTCPUtility::RTCPParserV2::IterateSLIItem()
352{
353 const bool success = ParseSLIItem();
354 if (!success)
355 {
356 Iterate();
357 }
358}
359
360void
361RTCPUtility::RTCPParserV2::IterateRPSIItem()
362{
363 const bool success = ParseRPSIItem();
364 if (!success)
365 {
366 Iterate();
367 }
368}
369
370void
371RTCPUtility::RTCPParserV2::IterateFIRItem()
372{
373 const bool success = ParseFIRItem();
374 if (!success)
375 {
376 Iterate();
377 }
378}
379
380void
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000381RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
382{
383 const bool success = ParsePsfbAppItem();
384 if (!success)
385 {
386 Iterate();
387 }
388}
389
390void
391RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
392{
393 const bool success = ParsePsfbREMBItem();
394 if (!success)
395 {
396 Iterate();
397 }
398}
399
400void
niklase@google.com470e71d2011-07-07 08:21:25 +0000401RTCPUtility::RTCPParserV2::IterateAppItem()
402{
403 const bool success = ParseAPPItem();
404 if (!success)
405 {
406 Iterate();
407 }
408}
409
410void
411RTCPUtility::RTCPParserV2::Validate()
412{
413 if (_ptrRTCPData == NULL)
414 {
415 return; // NOT VALID
416 }
417
418 RTCPCommonHeader header;
419 const bool success = RTCPParseCommonHeader(_ptrRTCPDataBegin,
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000420 _ptrRTCPDataEnd,
421 header);
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
423 if (!success)
424 {
425 return; // NOT VALID!
426 }
427
428 // * if (!reducedSize) : first packet must be RR or SR.
429 //
430 // * The padding bit (P) should be zero for the first packet of a
431 // compound RTCP packet because padding should only be applied,
432 // if it is needed, to the last packet. (NOT CHECKED!)
433 //
434 // * The length fields of the individual RTCP packets must add up
435 // to the overall length of the compound RTCP packet as
436 // received. This is a fairly strong check. (NOT CHECKED!)
437
438 if (!_RTCPReducedSizeEnable)
439 {
440 if ((header.PT != PT_SR) && (header.PT != PT_RR))
441 {
442 return; // NOT VALID
443 }
444 }
445
446 _validPacket = true;
447}
448
449bool
450RTCPUtility::RTCPParserV2::IsValid() const
451{
452 return _validPacket;
453}
454
455void
456RTCPUtility::RTCPParserV2::EndCurrentBlock()
457{
458 _ptrRTCPData = _ptrRTCPBlockEnd;
459}
460
461bool
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000462RTCPUtility::RTCPParseCommonHeader( const uint8_t* ptrDataBegin,
463 const uint8_t* ptrDataEnd,
niklase@google.com470e71d2011-07-07 08:21:25 +0000464 RTCPCommonHeader& parsedHeader)
465{
466 if (!ptrDataBegin || !ptrDataEnd)
467 {
468 return false;
469 }
470
471 // 0 1 2 3
472 // 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
473 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
474 // |V=2|P| IC | PT | length |
475 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
476 //
477 // Common header for all RTCP packets, 4 octets.
478
479 if ((ptrDataEnd - ptrDataBegin) < 4)
480 {
481 return false;
482 }
483
484 parsedHeader.V = ptrDataBegin[0] >> 6;
485 parsedHeader.P = ((ptrDataBegin[0] & 0x20) == 0) ? false : true;
486 parsedHeader.IC = ptrDataBegin[0] & 0x1f;
487 parsedHeader.PT = ptrDataBegin[1];
488
489 parsedHeader.LengthInOctets = (ptrDataBegin[2] << 8) + ptrDataBegin[3] + 1;
490 parsedHeader.LengthInOctets *= 4;
491
492 if(parsedHeader.LengthInOctets == 0)
493 {
494 return false;
495 }
496 // Check if RTP version field == 2
497 if (parsedHeader.V != 2)
498 {
499 return false;
500 }
501
502 return true;
503}
504
505bool
506RTCPUtility::RTCPParserV2::ParseRR()
507{
508 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
509
510 if (length < 8)
511 {
512 return false;
513 }
514
515
516 _ptrRTCPData += 4; // Skip header
517
Erik Språng242e22b2015-05-11 10:17:43 +0200518 _packetType = RTCPPacketTypes::kRr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000519
520 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
521 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
522 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
523 _packet.RR.SenderSSRC += *_ptrRTCPData++;
524
525 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
526
527 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200528 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
530 return true;
531}
532
533bool
534RTCPUtility::RTCPParserV2::ParseSR()
535{
536 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
537
538 if (length < 28)
539 {
540 EndCurrentBlock();
541 return false;
542 }
543
544 _ptrRTCPData += 4; // Skip header
545
Erik Språng242e22b2015-05-11 10:17:43 +0200546 _packetType = RTCPPacketTypes::kSr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000547
548 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
549 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
550 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
551 _packet.SR.SenderSSRC += *_ptrRTCPData++;
552
553 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
554 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
555 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
556 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
557
558 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
559 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
560 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
561 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
562
563 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
564 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
565 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
566 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
567
568 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
569 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
570 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
571 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
572
573 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
574 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
575 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
576 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
577
578 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
579
580 // State transition
581 if(_numberOfBlocks != 0)
582 {
Erik Språng242e22b2015-05-11 10:17:43 +0200583 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000584 }else
585 {
586 // don't go to state report block item if 0 report blocks
Erik Språng242e22b2015-05-11 10:17:43 +0200587 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000588 EndCurrentBlock();
589 }
590 return true;
591}
592
593bool
594RTCPUtility::RTCPParserV2::ParseReportBlockItem()
595{
596 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
597
598 if (length < 24 || _numberOfBlocks <= 0)
599 {
Erik Språng242e22b2015-05-11 10:17:43 +0200600 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
602 EndCurrentBlock();
603 return false;
604 }
605 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
606 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
607 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
608 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
609
610 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
611
612 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
613 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
614 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
615
616 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
617 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
618 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
619 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
620
621 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
622 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
623 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
624 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
625
626 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
627 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
628 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
629 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
630
631 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
632 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
633 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
634 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
635
636 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200637 _packetType = RTCPPacketTypes::kReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000638 return true;
639}
640
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000641/* From RFC 5450: Transmission Time Offsets in RTP Streams.
642 0 1 2 3
643 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
644 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
645 hdr |V=2|P| RC | PT=IJ=195 | length |
646 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
647 | inter-arrival jitter |
648 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
649 . .
650 . .
651 . .
652 | inter-arrival jitter |
653 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
654*/
655
656bool
657RTCPUtility::RTCPParserV2::ParseIJ()
658{
659 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
660
661 if (length < 4)
662 {
663 return false;
664 }
665
666 _ptrRTCPData += 4; // Skip header
667
Erik Språng242e22b2015-05-11 10:17:43 +0200668 _packetType = RTCPPacketTypes::kExtendedIj;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000669
670 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200671 _state = ParseState::State_ExtendedJitterItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000672 return true;
673}
674
675bool
676RTCPUtility::RTCPParserV2::ParseIJItem()
677{
678 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
679
680 if (length < 4 || _numberOfBlocks <= 0)
681 {
Erik Språng242e22b2015-05-11 10:17:43 +0200682 _state = ParseState::State_TopLevel;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000683 EndCurrentBlock();
684 return false;
685 }
686
687 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
688 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
689 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
690 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
691
692 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200693 _packetType = RTCPPacketTypes::kExtendedIjItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000694 return true;
695}
696
niklase@google.com470e71d2011-07-07 08:21:25 +0000697bool
698RTCPUtility::RTCPParserV2::ParseSDES()
699{
700 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
701
702 if (length < 8)
703 {
Erik Språng242e22b2015-05-11 10:17:43 +0200704 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000705
706 EndCurrentBlock();
707 return false;
708 }
709 _ptrRTCPData += 4; // Skip header
710
Erik Språng242e22b2015-05-11 10:17:43 +0200711 _state = ParseState::State_SDESChunk;
712 _packetType = RTCPPacketTypes::kSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000713 return true;
714}
715
716bool
717RTCPUtility::RTCPParserV2::ParseSDESChunk()
718{
719 if(_numberOfBlocks <= 0)
720 {
Erik Språng242e22b2015-05-11 10:17:43 +0200721 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000722
723 EndCurrentBlock();
724 return false;
725 }
726 _numberOfBlocks--;
727
728 // Find CName item in a SDES chunk.
729 while (_ptrRTCPData < _ptrRTCPBlockEnd)
730 {
731 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
732 if (dataLen < 4)
733 {
Erik Språng242e22b2015-05-11 10:17:43 +0200734 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000735
736 EndCurrentBlock();
737 return false;
738 }
739
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000740 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000741 SSRC += *_ptrRTCPData++ << 16;
742 SSRC += *_ptrRTCPData++ << 8;
743 SSRC += *_ptrRTCPData++;
744
745 const bool foundCname = ParseSDESItem();
746 if (foundCname)
747 {
748 _packet.CName.SenderSSRC = SSRC; // Add SSRC
749 return true;
750 }
751 }
Erik Språng242e22b2015-05-11 10:17:43 +0200752 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000753
754 EndCurrentBlock();
755 return false;
756}
757
758bool
759RTCPUtility::RTCPParserV2::ParseSDESItem()
760{
761 // Find CName
762 // Only the CNAME item is mandatory. RFC 3550 page 46
763 bool foundCName = false;
764
765 size_t itemOctetsRead = 0;
766 while (_ptrRTCPData < _ptrRTCPBlockEnd)
767 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000768 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000769 ++itemOctetsRead;
770
771 if (tag == 0)
772 {
773 // End tag! 4 oct aligned
774 while ((itemOctetsRead++ % 4) != 0)
775 {
776 ++_ptrRTCPData;
777 }
778 return foundCName;
779 }
780
781 if (_ptrRTCPData < _ptrRTCPBlockEnd)
782 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000784 ++itemOctetsRead;
785
786 if (tag == 1)
787 {
788 // CNAME
789
790 // Sanity
791 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
792 {
Erik Språng242e22b2015-05-11 10:17:43 +0200793 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000794
795 EndCurrentBlock();
796 return false;
797 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000798 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000799 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000800 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000801 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000802 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
803 {
804 // Illegal char
Erik Språng242e22b2015-05-11 10:17:43 +0200805 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000806
807 EndCurrentBlock();
808 return false;
809 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000810 _packet.CName.CName[i] = c;
811 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000812 // Make sure we are null terminated.
813 _packet.CName.CName[i] = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200814 _packetType = RTCPPacketTypes::kSdesChunk;
niklase@google.com470e71d2011-07-07 08:21:25 +0000815
816 foundCName = true;
817 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000818 _ptrRTCPData += len;
819 itemOctetsRead += len;
820 }
821 }
822
823 // No end tag found!
Erik Språng242e22b2015-05-11 10:17:43 +0200824 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000825
826 EndCurrentBlock();
827 return false;
828}
829
830bool
831RTCPUtility::RTCPParserV2::ParseBYE()
832{
833 _ptrRTCPData += 4; // Skip header
834
Erik Språng242e22b2015-05-11 10:17:43 +0200835 _state = ParseState::State_BYEItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000836
837 return ParseBYEItem();
838}
839
840bool
841RTCPUtility::RTCPParserV2::ParseBYEItem()
842{
843 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
844 if (length < 4 || _numberOfBlocks == 0)
845 {
Erik Språng242e22b2015-05-11 10:17:43 +0200846 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000847
848 EndCurrentBlock();
849 return false;
850 }
851
Erik Språng242e22b2015-05-11 10:17:43 +0200852 _packetType = RTCPPacketTypes::kBye;
niklase@google.com470e71d2011-07-07 08:21:25 +0000853
854 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
855 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
856 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
857 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
858
859 // we can have several CSRCs attached
860
861 // sanity
862 if(length >= 4*_numberOfBlocks)
863 {
864 _ptrRTCPData += (_numberOfBlocks -1)*4;
865 }
866 _numberOfBlocks = 0;
867
868 return true;
869}
870/*
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000871 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +0000872 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
873 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
874 |V=2|P|reserved | PT=XR=207 | length |
875 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
876 | SSRC |
877 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
878 : report blocks :
879 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
880*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000881bool RTCPUtility::RTCPParserV2::ParseXr()
niklase@google.com470e71d2011-07-07 08:21:25 +0000882{
883 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000884 if (length < 8)
885 {
886 EndCurrentBlock();
887 return false;
888 }
889
890 _ptrRTCPData += 4; // Skip header
891
892 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
893 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
894 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
895 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
896
Erik Språng242e22b2015-05-11 10:17:43 +0200897 _packetType = RTCPPacketTypes::kXrHeader;
898 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000899 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000900}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000901
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000902/* Extended report block format (RFC 3611).
903 BT: block type.
904 block length: length of report block in 32-bits words minus one (including
905 the header).
niklase@google.com470e71d2011-07-07 08:21:25 +0000906 0 1 2 3
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000907 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 +0000908 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 | BT | type-specific | block length |
910 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911 : type-specific block contents :
912 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000914bool RTCPUtility::RTCPParserV2::ParseXrItem() {
915 const int kBlockHeaderLengthInBytes = 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000916 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000917 if (length < kBlockHeaderLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200918 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000919 EndCurrentBlock();
920 return false;
921 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000922
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000923 uint8_t block_type = *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000924 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000925
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000926 uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
927 block_length_in_4bytes += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000929 switch (block_type) {
930 case kBtReceiverReferenceTime:
931 return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
932 case kBtDlrr:
933 return ParseXrDlrr(block_length_in_4bytes);
934 case kBtVoipMetric:
935 return ParseXrVoipMetricItem(block_length_in_4bytes);
936 default:
937 return ParseXrUnsupportedBlockType(block_length_in_4bytes);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000938 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000939}
940
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000941/* Receiver Reference Time Report Block.
942 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000943 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
944 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
945 | BT=4 | reserved | block length = 2 |
946 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
947 | NTP timestamp, most significant word |
948 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
949 | NTP timestamp, least significant word |
950 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
951*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000952bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
953 int block_length_4bytes) {
954 const int kBlockLengthIn4Bytes = 2;
955 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000956 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000957 if (block_length_4bytes != kBlockLengthIn4Bytes ||
958 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200959 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000960 EndCurrentBlock();
961 return false;
962 }
963
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000964 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
965 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
966 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
967 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000968
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000969 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
970 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
971 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
972 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000973
Erik Språng242e22b2015-05-11 10:17:43 +0200974 _packetType = RTCPPacketTypes::kXrReceiverReferenceTime;
975 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000976 return true;
977}
978
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000979/* DLRR Report Block.
980 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000981 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
982 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
983 | BT=5 | reserved | block length |
984 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
985 | SSRC_1 (SSRC of first receiver) | sub-
986 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
987 | last RR (LRR) | 1
988 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
989 | delay since last RR (DLRR) |
990 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
991 | SSRC_2 (SSRC of second receiver) | sub-
992 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
993 : ... : 2
994 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
995*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000996bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
997 const int kSubBlockLengthIn4Bytes = 3;
998 if (block_length_4bytes < 0 ||
999 (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001000 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001001 EndCurrentBlock();
1002 return false;
1003 }
Erik Språng242e22b2015-05-11 10:17:43 +02001004 _packetType = RTCPPacketTypes::kXrDlrrReportBlock;
1005 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001006 _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
1007 return true;
1008}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001009
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001010bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001011 if (_numberOfBlocks == 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001012 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001013 return false;
1014 }
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001015 const int kSubBlockLengthInBytes = 12;
1016 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1017 if (length < kSubBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001018 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001019 EndCurrentBlock();
1020 return false;
1021 }
1022
1023 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1024 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1025 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1026 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1027
1028 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1029 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1030 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1031 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1032
1033 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1034 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1035 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1036 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1037
Erik Språng242e22b2015-05-11 10:17:43 +02001038 _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001039 --_numberOfBlocks;
Erik Språng242e22b2015-05-11 10:17:43 +02001040 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001041 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001042}
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001043/* VoIP Metrics Report Block.
1044 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +00001045 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
1046 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1047 | BT=7 | reserved | block length = 8 |
1048 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1049 | SSRC of source |
1050 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1051 | loss rate | discard rate | burst density | gap density |
1052 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1053 | burst duration | gap duration |
1054 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1055 | round trip delay | end system delay |
1056 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1057 | signal level | noise level | RERL | Gmin |
1058 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1059 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1060 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1061 | RX config | reserved | JB nominal |
1062 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1063 | JB maximum | JB abs max |
1064 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1065*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001066
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001067bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
1068 const int kBlockLengthIn4Bytes = 8;
1069 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
1070 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1071 if (block_length_4bytes != kBlockLengthIn4Bytes ||
1072 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001073 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001074 EndCurrentBlock();
1075 return false;
1076 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001077
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001078 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1079 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1080 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1081 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001082
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001083 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1084 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1085 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1086 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001087
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001088 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1089 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001090
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001091 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1092 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001093
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001094 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1095 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001096
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001097 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1098 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001099
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001100 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1101 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1102 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1103 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1104 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1105 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1106 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1107 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1108 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1109 _ptrRTCPData++; // skip reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001110
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001111 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1112 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001113
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001114 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1115 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001116
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001117 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1118 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001119
Erik Språng242e22b2015-05-11 10:17:43 +02001120 _packetType = RTCPPacketTypes::kXrVoipMetric;
1121 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001122 return true;
1123}
niklase@google.com470e71d2011-07-07 08:21:25 +00001124
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001125bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
1126 int block_length_4bytes) {
1127 const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
1128 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1129 if (length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001130 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001131 EndCurrentBlock();
1132 return false;
1133 }
1134 // Skip block.
1135 _ptrRTCPData += kBlockLengthInBytes;
Erik Språng242e22b2015-05-11 10:17:43 +02001136 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001137 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001138}
1139
1140bool
1141RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
1142{
1143 assert((header.PT == PT_RTPFB) || (header.PT == PT_PSFB)); // Parser logic check
1144
1145 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1146
1147 if (length < 12) // 4 * 3, RFC4585 section 6.1
1148 {
1149 EndCurrentBlock();
1150 return false;
1151 }
1152
1153 _ptrRTCPData += 4; // Skip RTCP header
1154
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001155 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001156 senderSSRC += *_ptrRTCPData++ << 16;
1157 senderSSRC += *_ptrRTCPData++ << 8;
1158 senderSSRC += *_ptrRTCPData++;
1159
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001160 uint32_t mediaSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001161 mediaSSRC += *_ptrRTCPData++ << 16;
1162 mediaSSRC += *_ptrRTCPData++ << 8;
1163 mediaSSRC += *_ptrRTCPData++;
1164
1165 if (header.PT == PT_RTPFB)
1166 {
1167 // Transport layer feedback
1168
1169 switch (header.IC)
1170 {
1171 case 1:
1172 {
1173 // NACK
Erik Språng242e22b2015-05-11 10:17:43 +02001174 _packetType = RTCPPacketTypes::kRtpfbNack;
niklase@google.com470e71d2011-07-07 08:21:25 +00001175 _packet.NACK.SenderSSRC = senderSSRC;
1176 _packet.NACK.MediaSSRC = mediaSSRC;
1177
Erik Språng242e22b2015-05-11 10:17:43 +02001178 _state = ParseState::State_RTPFB_NACKItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001179
1180 return true;
1181 }
1182 case 2:
1183 {
1184 // used to be ACK is this code point, which is removed
1185 // conficts with http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
1186 break;
1187 }
1188 case 3:
1189 {
1190 // TMMBR
Erik Språng242e22b2015-05-11 10:17:43 +02001191 _packetType = RTCPPacketTypes::kRtpfbTmmbr;
niklase@google.com470e71d2011-07-07 08:21:25 +00001192 _packet.TMMBR.SenderSSRC = senderSSRC;
1193 _packet.TMMBR.MediaSSRC = mediaSSRC;
1194
Erik Språng242e22b2015-05-11 10:17:43 +02001195 _state = ParseState::State_RTPFB_TMMBRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001196
1197 return true;
1198 }
1199 case 4:
1200 {
1201 // TMMBN
Erik Språng242e22b2015-05-11 10:17:43 +02001202 _packetType = RTCPPacketTypes::kRtpfbTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001203 _packet.TMMBN.SenderSSRC = senderSSRC;
1204 _packet.TMMBN.MediaSSRC = mediaSSRC;
1205
Erik Språng242e22b2015-05-11 10:17:43 +02001206 _state = ParseState::State_RTPFB_TMMBNItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001207
1208 return true;
1209 }
1210 case 5:
1211 {
1212 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1213 // draft-perkins-avt-rapid-rtp-sync-03.txt
1214 // trigger a new RTCP SR
Erik Språng242e22b2015-05-11 10:17:43 +02001215 _packetType = RTCPPacketTypes::kRtpfbSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +00001216
1217 // Note: No state transition, SR REQ is empty!
1218 return true;
1219 }
1220 default:
1221 break;
1222 }
1223 EndCurrentBlock();
1224 return false;
1225 }
1226 else if (header.PT == PT_PSFB)
1227 {
1228 // Payload specific feedback
1229 switch (header.IC)
1230 {
1231 case 1:
1232 // PLI
Erik Språng242e22b2015-05-11 10:17:43 +02001233 _packetType = RTCPPacketTypes::kPsfbPli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001234 _packet.PLI.SenderSSRC = senderSSRC;
1235 _packet.PLI.MediaSSRC = mediaSSRC;
1236
1237 // Note: No state transition, PLI FCI is empty!
1238 return true;
1239 case 2:
1240 // SLI
Erik Språng242e22b2015-05-11 10:17:43 +02001241 _packetType = RTCPPacketTypes::kPsfbSli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001242 _packet.SLI.SenderSSRC = senderSSRC;
1243 _packet.SLI.MediaSSRC = mediaSSRC;
1244
Erik Språng242e22b2015-05-11 10:17:43 +02001245 _state = ParseState::State_PSFB_SLIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001246
1247 return true;
1248 case 3:
Erik Språng242e22b2015-05-11 10:17:43 +02001249 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001250 _packet.RPSI.SenderSSRC = senderSSRC;
1251 _packet.RPSI.MediaSSRC = mediaSSRC;
1252
Erik Språng242e22b2015-05-11 10:17:43 +02001253 _state = ParseState::State_PSFB_RPSIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001254 return true;
1255 case 4:
1256 // FIR
Erik Språng242e22b2015-05-11 10:17:43 +02001257 _packetType = RTCPPacketTypes::kPsfbFir;
niklase@google.com470e71d2011-07-07 08:21:25 +00001258 _packet.FIR.SenderSSRC = senderSSRC;
1259 _packet.FIR.MediaSSRC = mediaSSRC;
1260
Erik Språng242e22b2015-05-11 10:17:43 +02001261 _state = ParseState::State_PSFB_FIRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001262 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001263 case 15:
Erik Språng242e22b2015-05-11 10:17:43 +02001264 _packetType = RTCPPacketTypes::kPsfbApp;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001265 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1266 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001267
Erik Språng242e22b2015-05-11 10:17:43 +02001268 _state = ParseState::State_PSFB_AppItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001269 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001270 default:
1271 break;
1272 }
1273
1274 EndCurrentBlock();
1275 return false;
1276 }
1277 else
1278 {
1279 assert(false);
1280
1281 EndCurrentBlock();
1282 return false;
1283 }
1284}
1285
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001286bool RTCPUtility::RTCPParserV2::ParseRPSIItem() {
1287
1288 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI).
1289 //
1290 // 0 1 2 3
1291 // 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
1292 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1293 // | PB |0| Payload Type| Native RPSI bit string |
1294 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1295 // | defined per codec ... | Padding (0) |
1296 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
niklase@google.com470e71d2011-07-07 08:21:25 +00001297
1298 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1299
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001300 if (length < 4) {
Erik Språng242e22b2015-05-11 10:17:43 +02001301 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001302
1303 EndCurrentBlock();
1304 return false;
1305 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001306 if (length > 2 + RTCP_RPSI_DATA_SIZE) {
Erik Språng242e22b2015-05-11 10:17:43 +02001307 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001308
1309 EndCurrentBlock();
1310 return false;
1311 }
1312
Erik Språng242e22b2015-05-11 10:17:43 +02001313 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001314
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001315 uint8_t padding_bits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001316 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1317
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001318 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
1319 _ptrRTCPData += length - 2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001320
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001321 _packet.RPSI.NumberOfValidBits =
1322 static_cast<uint16_t>(length - 2) * 8 - padding_bits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001323 return true;
1324}
1325
1326bool
1327RTCPUtility::RTCPParserV2::ParseNACKItem()
1328{
1329 // RFC 4585 6.2.1. Generic NACK
1330
1331 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1332
1333 if (length < 4)
1334 {
Erik Språng242e22b2015-05-11 10:17:43 +02001335 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001336
1337 EndCurrentBlock();
1338 return false;
1339 }
1340
Erik Språng242e22b2015-05-11 10:17:43 +02001341 _packetType = RTCPPacketTypes::kRtpfbNackItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001342
1343 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1344 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1345
1346 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1347 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1348
1349 return true;
1350}
1351
1352bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001353RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1354{
1355 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1356
1357 if (length < 4)
1358 {
Erik Språng242e22b2015-05-11 10:17:43 +02001359 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001360
1361 EndCurrentBlock();
1362 return false;
1363 }
1364 if(*_ptrRTCPData++ != 'R')
1365 {
Erik Språng242e22b2015-05-11 10:17:43 +02001366 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001367
1368 EndCurrentBlock();
1369 return false;
1370 }
1371 if(*_ptrRTCPData++ != 'E')
1372 {
Erik Språng242e22b2015-05-11 10:17:43 +02001373 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001374
1375 EndCurrentBlock();
1376 return false;
1377 }
1378 if(*_ptrRTCPData++ != 'M')
1379 {
Erik Språng242e22b2015-05-11 10:17:43 +02001380 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001381
1382 EndCurrentBlock();
1383 return false;
1384 }
1385 if(*_ptrRTCPData++ != 'B')
1386 {
Erik Språng242e22b2015-05-11 10:17:43 +02001387 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001388
1389 EndCurrentBlock();
1390 return false;
1391 }
Erik Språng242e22b2015-05-11 10:17:43 +02001392 _packetType = RTCPPacketTypes::kPsfbRemb;
1393 _state = ParseState::State_PSFB_REMBItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001394 return true;
1395}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001396
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001397bool
1398RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1399{
1400 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1401
1402 if (length < 4)
1403 {
Erik Språng242e22b2015-05-11 10:17:43 +02001404 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001405
1406 EndCurrentBlock();
1407 return false;
1408 }
1409
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001410 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001411 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001412
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001413 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001414 brMantissa += (_ptrRTCPData[1] << 8);
1415 brMantissa += (_ptrRTCPData[2]);
1416
1417 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001418 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001419
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001420 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1421 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1422 {
Erik Språng242e22b2015-05-11 10:17:43 +02001423 _state = ParseState::State_TopLevel;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001424
1425 EndCurrentBlock();
1426 return false;
1427 }
1428
Erik Språng242e22b2015-05-11 10:17:43 +02001429 _packetType = RTCPPacketTypes::kPsfbRembItem;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001430
1431 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1432 {
1433 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1434 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1435 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1436 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1437 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001438 return true;
1439}
1440
1441bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001442RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1443{
1444 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1445
1446 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1447
1448 if (length < 8)
1449 {
Erik Språng242e22b2015-05-11 10:17:43 +02001450 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001451
1452 EndCurrentBlock();
1453 return false;
1454 }
1455
Erik Språng242e22b2015-05-11 10:17:43 +02001456 _packetType = RTCPPacketTypes::kRtpfbTmmbrItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001457
1458 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1459 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1460 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1461 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1462
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001463 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001464
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001465 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001466 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1467 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1468
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001469 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001470 measuredOH += _ptrRTCPData[3];
1471
1472 _ptrRTCPData += 4; // Fwd read data
1473
1474 _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1475 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1476
1477 return true;
1478}
1479
1480bool
1481RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1482{
1483 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1484
1485 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1486
1487 if (length < 8)
1488 {
Erik Språng242e22b2015-05-11 10:17:43 +02001489 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001490
1491 EndCurrentBlock();
1492 return false;
1493 }
1494
Erik Språng242e22b2015-05-11 10:17:43 +02001495 _packetType = RTCPPacketTypes::kRtpfbTmmbnItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001496
1497 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1498 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1499 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1500 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1501
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001502 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001503
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001504 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001505 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1506 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1507
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001508 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001509 measuredOH += _ptrRTCPData[3];
1510
1511 _ptrRTCPData += 4; // Fwd read data
1512
1513 _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1514 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1515
1516 return true;
1517}
1518
1519bool
1520RTCPUtility::RTCPParserV2::ParseSLIItem()
1521{
1522 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1523 /*
1524 0 1 2 3
1525 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
1526 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1527 | First | Number | PictureID |
1528 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1529 */
1530
1531 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1532
1533 if (length < 4)
1534 {
Erik Språng242e22b2015-05-11 10:17:43 +02001535 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001536
1537 EndCurrentBlock();
1538 return false;
1539 }
Erik Språng242e22b2015-05-11 10:17:43 +02001540 _packetType = RTCPPacketTypes::kPsfbSliItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001541
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001542 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001543 buffer = *_ptrRTCPData++ << 24;
1544 buffer += *_ptrRTCPData++ << 16;
1545 buffer += *_ptrRTCPData++ << 8;
1546 buffer += *_ptrRTCPData++;
1547
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001548 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1549 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1550 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001551
1552 return true;
1553}
1554
1555bool
1556RTCPUtility::RTCPParserV2::ParseFIRItem()
1557{
1558 // RFC 5104 4.3.1. Full Intra Request (FIR)
1559
1560 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1561
1562 if (length < 8)
1563 {
Erik Språng242e22b2015-05-11 10:17:43 +02001564 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001565
1566 EndCurrentBlock();
1567 return false;
1568 }
1569
Erik Språng242e22b2015-05-11 10:17:43 +02001570 _packetType = RTCPPacketTypes::kPsfbFirItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001571
1572 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1573 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1574 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1575 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1576
1577 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1578 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1579 return true;
1580}
1581
1582bool
1583RTCPUtility::RTCPParserV2::ParseAPP( const RTCPCommonHeader& header)
1584{
1585 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1586
1587 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1588 {
1589 EndCurrentBlock();
1590 return false;
1591 }
1592
1593 _ptrRTCPData += 4; // Skip RTCP header
1594
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001595 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001596 senderSSRC += *_ptrRTCPData++ << 16;
1597 senderSSRC += *_ptrRTCPData++ << 8;
1598 senderSSRC += *_ptrRTCPData++;
1599
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001600 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001601 name += *_ptrRTCPData++ << 16;
1602 name += *_ptrRTCPData++ << 8;
1603 name += *_ptrRTCPData++;
1604
1605 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1606
Erik Språng242e22b2015-05-11 10:17:43 +02001607 _packetType = RTCPPacketTypes::kApp;
niklase@google.com470e71d2011-07-07 08:21:25 +00001608
1609 _packet.APP.SubType = header.IC;
1610 _packet.APP.Name = name;
1611
Erik Språng242e22b2015-05-11 10:17:43 +02001612 _state = ParseState::State_AppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001613 return true;
1614}
1615
1616bool
1617RTCPUtility::RTCPParserV2::ParseAPPItem()
1618{
1619 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1620 if (length < 4)
1621 {
Erik Språng242e22b2015-05-11 10:17:43 +02001622 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001623
1624 EndCurrentBlock();
1625 return false;
1626 }
Erik Språng242e22b2015-05-11 10:17:43 +02001627 _packetType = RTCPPacketTypes::kAppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001628
1629 if(length > kRtcpAppCode_DATA_SIZE)
1630 {
1631 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1632 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1633 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1634 }else
1635 {
1636 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001637 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001638 _ptrRTCPData += length;
1639 }
1640 return true;
1641}
1642
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001643RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001644 size_t rtcpDataLength)
1645 : _ptrBegin(rtcpData),
1646 _ptrEnd(rtcpData + rtcpDataLength),
1647 _ptrBlock(NULL) {
1648 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001649}
1650
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001651RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001652}
1653
1654const RTCPUtility::RTCPCommonHeader*
1655RTCPUtility::RTCPPacketIterator::Begin()
1656{
1657 _ptrBlock = _ptrBegin;
1658
1659 return Iterate();
1660}
1661
1662const RTCPUtility::RTCPCommonHeader*
1663RTCPUtility::RTCPPacketIterator::Iterate()
1664{
1665 const bool success = RTCPParseCommonHeader(_ptrBlock, _ptrEnd, _header);
1666 if (!success)
1667 {
1668 _ptrBlock = NULL;
1669 return NULL;
1670 }
1671 _ptrBlock += _header.LengthInOctets;
1672
1673 if (_ptrBlock > _ptrEnd)
1674 {
1675 _ptrBlock = NULL;
1676 return NULL;
1677 }
1678
1679 return &_header;
1680}
1681
1682const RTCPUtility::RTCPCommonHeader*
1683RTCPUtility::RTCPPacketIterator::Current()
1684{
1685 if (!_ptrBlock)
1686 {
1687 return NULL;
1688 }
1689
1690 return &_header;
1691}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001692} // namespace webrtc