blob: 47a63315acb39ed1122af69ace7c41fe34788d03 [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
sprang73a93e82015-09-14 12:50:39 -070017#include "webrtc/base/checks.h"
18#include "webrtc/base/logging.h"
19#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
20
niklase@google.com470e71d2011-07-07 08:21:25 +000021namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000022
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000023namespace RTCPUtility {
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +000024
25NackStats::NackStats()
26 : max_sequence_number_(0),
27 requests_(0),
28 unique_requests_(0) {}
29
30NackStats::~NackStats() {}
31
32void NackStats::ReportRequest(uint16_t sequence_number) {
33 if (requests_ == 0 ||
34 webrtc::IsNewerSequenceNumber(sequence_number, max_sequence_number_)) {
35 max_sequence_number_ = sequence_number;
36 ++unique_requests_;
37 }
38 ++requests_;
39}
40
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000041uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) {
42 return (ntp_sec << 16) + (ntp_frac >> 16);
43} // end RTCPUtility
44}
45
46// RTCPParserV2 : currently read only
pbos@webrtc.org2f446732013-04-08 11:08:41 +000047RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
niklase@google.com470e71d2011-07-07 08:21:25 +000048 size_t rtcpDataLength,
49 bool rtcpReducedSizeEnable)
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000050 : _ptrRTCPDataBegin(rtcpData),
51 _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
52 _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
53 _validPacket(false),
54 _ptrRTCPData(rtcpData),
55 _ptrRTCPBlockEnd(NULL),
Erik Språng242e22b2015-05-11 10:17:43 +020056 _state(ParseState::State_TopLevel),
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000057 _numberOfBlocks(0),
Erik Språng242e22b2015-05-11 10:17:43 +020058 _packetType(RTCPPacketTypes::kInvalid) {
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000059 Validate();
niklase@google.com470e71d2011-07-07 08:21:25 +000060}
61
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000062RTCPUtility::RTCPParserV2::~RTCPParserV2() {
niklase@google.com470e71d2011-07-07 08:21:25 +000063}
64
65ptrdiff_t
66RTCPUtility::RTCPParserV2::LengthLeft() const
67{
68 return (_ptrRTCPDataEnd- _ptrRTCPData);
69}
70
71RTCPUtility::RTCPPacketTypes
72RTCPUtility::RTCPParserV2::PacketType() const
73{
74 return _packetType;
75}
76
77const RTCPUtility::RTCPPacket&
78RTCPUtility::RTCPParserV2::Packet() const
79{
80 return _packet;
81}
82
83RTCPUtility::RTCPPacketTypes
84RTCPUtility::RTCPParserV2::Begin()
85{
86 _ptrRTCPData = _ptrRTCPDataBegin;
87
88 return Iterate();
89}
90
91RTCPUtility::RTCPPacketTypes
92RTCPUtility::RTCPParserV2::Iterate()
93{
94 // Reset packet type
Erik Språng242e22b2015-05-11 10:17:43 +020095 _packetType = RTCPPacketTypes::kInvalid;
niklase@google.com470e71d2011-07-07 08:21:25 +000096
97 if (IsValid())
98 {
99 switch (_state)
100 {
Erik Språng242e22b2015-05-11 10:17:43 +0200101 case ParseState::State_TopLevel:
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 IterateTopLevel();
103 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200104 case ParseState::State_ReportBlockItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 IterateReportBlockItem();
106 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200107 case ParseState::State_SDESChunk:
niklase@google.com470e71d2011-07-07 08:21:25 +0000108 IterateSDESChunk();
109 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200110 case ParseState::State_BYEItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 IterateBYEItem();
112 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200113 case ParseState::State_ExtendedJitterItem:
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000114 IterateExtendedJitterItem();
115 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200116 case ParseState::State_RTPFB_NACKItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 IterateNACKItem();
118 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200119 case ParseState::State_RTPFB_TMMBRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000120 IterateTMMBRItem();
121 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200122 case ParseState::State_RTPFB_TMMBNItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 IterateTMMBNItem();
124 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200125 case ParseState::State_PSFB_SLIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000126 IterateSLIItem();
127 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200128 case ParseState::State_PSFB_RPSIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 IterateRPSIItem();
130 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200131 case ParseState::State_PSFB_FIRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000132 IterateFIRItem();
133 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200134 case ParseState::State_PSFB_AppItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000135 IteratePsfbAppItem();
136 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200137 case ParseState::State_PSFB_REMBItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000138 IteratePsfbREMBItem();
139 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200140 case ParseState::State_XRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000141 IterateXrItem();
142 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200143 case ParseState::State_XR_DLLRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000144 IterateXrDlrrItem();
145 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200146 case ParseState::State_AppItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000147 IterateAppItem();
148 break;
149 default:
150 assert(false); // Invalid state!
151 break;
152 }
153 }
154 return _packetType;
155}
156
157void
158RTCPUtility::RTCPParserV2::IterateTopLevel()
159{
160 for (;;)
161 {
sprang73a93e82015-09-14 12:50:39 -0700162 RtcpCommonHeader header;
163 if (_ptrRTCPDataEnd <= _ptrRTCPData)
164 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
sprang73a93e82015-09-14 12:50:39 -0700166 if (!RtcpParseCommonHeader(_ptrRTCPData, _ptrRTCPDataEnd - _ptrRTCPData,
167 &header)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000168 return;
169 }
sprang73a93e82015-09-14 12:50:39 -0700170 _ptrRTCPBlockEnd = _ptrRTCPData + header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
172 {
173 // Bad block!
174 return;
175 }
176
sprang73a93e82015-09-14 12:50:39 -0700177 switch (header.packet_type) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 case PT_SR:
179 {
180 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700181 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 ParseSR();
183 return;
184 }
185 case PT_RR:
186 {
187 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700188 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000189 ParseRR();
190 return;
191 }
192 case PT_SDES:
193 {
194 // number of SDES blocks
sprang73a93e82015-09-14 12:50:39 -0700195 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196 const bool ok = ParseSDES();
197 if (!ok)
198 {
199 // Nothing supported found, continue to next block!
200 break;
201 }
202 return;
203 }
204 case PT_BYE:
205 {
sprang73a93e82015-09-14 12:50:39 -0700206 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207 const bool ok = ParseBYE();
208 if (!ok)
209 {
210 // Nothing supported found, continue to next block!
211 break;
212 }
213 return;
214 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000215 case PT_IJ:
216 {
217 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700218 _numberOfBlocks = header.count_or_format;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000219 ParseIJ();
220 return;
221 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000222 case PT_RTPFB: // Fall through!
223 case PT_PSFB:
224 {
225 const bool ok = ParseFBCommon(header);
226 if (!ok)
227 {
228 // Nothing supported found, continue to next block!
229 break;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 return;
232 }
233 case PT_APP:
234 {
235 const bool ok = ParseAPP(header);
236 if (!ok)
237 {
238 // Nothing supported found, continue to next block!
239 break;
240 }
241 return;
242 }
243 case PT_XR:
244 {
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000245 const bool ok = ParseXr();
niklase@google.com470e71d2011-07-07 08:21:25 +0000246 if (!ok)
247 {
248 // Nothing supported found, continue to next block!
249 break;
250 }
251 return;
252 }
253 default:
254 // Not supported! Skip!
255 EndCurrentBlock();
256 break;
257 }
258 }
259}
260
261void
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000262RTCPUtility::RTCPParserV2::IterateXrItem()
263{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000264 const bool success = ParseXrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000265 if (!success)
266 {
267 Iterate();
268 }
269}
270
271void
272RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
273{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000274 const bool success = ParseXrDlrrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000275 if (!success)
276 {
277 Iterate();
278 }
279}
280
281void
niklase@google.com470e71d2011-07-07 08:21:25 +0000282RTCPUtility::RTCPParserV2::IterateReportBlockItem()
283{
284 const bool success = ParseReportBlockItem();
285 if (!success)
286 {
287 Iterate();
288 }
289}
290
291void
292RTCPUtility::RTCPParserV2::IterateSDESChunk()
293{
294 const bool success = ParseSDESChunk();
295 if (!success)
296 {
297 Iterate();
298 }
299}
300
301void
302RTCPUtility::RTCPParserV2::IterateBYEItem()
303{
304 const bool success = ParseBYEItem();
305 if (!success)
306 {
307 Iterate();
308 }
309}
310
311void
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000312RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
313{
314 const bool success = ParseIJItem();
315 if (!success)
316 {
317 Iterate();
318 }
319}
320
321void
niklase@google.com470e71d2011-07-07 08:21:25 +0000322RTCPUtility::RTCPParserV2::IterateNACKItem()
323{
324 const bool success = ParseNACKItem();
325 if (!success)
326 {
327 Iterate();
328 }
329}
330
331void
332RTCPUtility::RTCPParserV2::IterateTMMBRItem()
333{
334 const bool success = ParseTMMBRItem();
335 if (!success)
336 {
337 Iterate();
338 }
339}
340
341void
342RTCPUtility::RTCPParserV2::IterateTMMBNItem()
343{
344 const bool success = ParseTMMBNItem();
345 if (!success)
346 {
347 Iterate();
348 }
349}
350
351void
352RTCPUtility::RTCPParserV2::IterateSLIItem()
353{
354 const bool success = ParseSLIItem();
355 if (!success)
356 {
357 Iterate();
358 }
359}
360
361void
362RTCPUtility::RTCPParserV2::IterateRPSIItem()
363{
364 const bool success = ParseRPSIItem();
365 if (!success)
366 {
367 Iterate();
368 }
369}
370
371void
372RTCPUtility::RTCPParserV2::IterateFIRItem()
373{
374 const bool success = ParseFIRItem();
375 if (!success)
376 {
377 Iterate();
378 }
379}
380
381void
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000382RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
383{
384 const bool success = ParsePsfbAppItem();
385 if (!success)
386 {
387 Iterate();
388 }
389}
390
391void
392RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
393{
394 const bool success = ParsePsfbREMBItem();
395 if (!success)
396 {
397 Iterate();
398 }
399}
400
401void
niklase@google.com470e71d2011-07-07 08:21:25 +0000402RTCPUtility::RTCPParserV2::IterateAppItem()
403{
404 const bool success = ParseAPPItem();
405 if (!success)
406 {
407 Iterate();
408 }
409}
410
411void
412RTCPUtility::RTCPParserV2::Validate()
413{
sprang73a93e82015-09-14 12:50:39 -0700414 if (_ptrRTCPData == nullptr)
415 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
sprang73a93e82015-09-14 12:50:39 -0700417 RtcpCommonHeader header;
418 if (_ptrRTCPDataEnd <= _ptrRTCPDataBegin)
419 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
sprang73a93e82015-09-14 12:50:39 -0700421 if (!RtcpParseCommonHeader(_ptrRTCPDataBegin,
422 _ptrRTCPDataEnd - _ptrRTCPDataBegin, &header))
423 return; // NOT VALID!
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
425 // * if (!reducedSize) : first packet must be RR or SR.
426 //
427 // * The padding bit (P) should be zero for the first packet of a
428 // compound RTCP packet because padding should only be applied,
429 // if it is needed, to the last packet. (NOT CHECKED!)
430 //
431 // * The length fields of the individual RTCP packets must add up
432 // to the overall length of the compound RTCP packet as
433 // received. This is a fairly strong check. (NOT CHECKED!)
434
435 if (!_RTCPReducedSizeEnable)
436 {
sprang73a93e82015-09-14 12:50:39 -0700437 if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000438 return; // NOT VALID
439 }
440 }
441
442 _validPacket = true;
443}
444
445bool
446RTCPUtility::RTCPParserV2::IsValid() const
447{
448 return _validPacket;
449}
450
451void
452RTCPUtility::RTCPParserV2::EndCurrentBlock()
453{
454 _ptrRTCPData = _ptrRTCPBlockEnd;
455}
456
sprang73a93e82015-09-14 12:50:39 -0700457// 0 1 2 3
458// 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
459// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460// |V=2|P| IC | PT | length |
461// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
462//
463// Common header for all RTCP packets, 4 octets.
464
465bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet,
466 size_t size_bytes,
467 RtcpCommonHeader* parsed_header) {
468 DCHECK(parsed_header != nullptr);
469 if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) {
470 LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte"
471 << (size_bytes != 1 ? "s" : "")
472 << ") remaining in buffer to parse RTCP header (4 bytes).";
473 return false;
474 }
475
476 const uint8_t kRtcpVersion = 2;
477 uint8_t version = packet[0] >> 6;
478 if (version != kRtcpVersion) {
479 LOG(LS_WARNING) << "Invalid RTCP header: Version must be "
480 << static_cast<int>(kRtcpVersion) << " but was "
481 << static_cast<int>(version);
482 return false;
483 }
484
485 bool has_padding = (packet[0] & 0x20) != 0;
486 uint8_t format = packet[0] & 0x1F;
487 uint8_t packet_type = packet[1];
488 size_t packet_size_words =
489 ByteReader<uint16_t>::ReadBigEndian(&packet[2]) + 1;
490
491 if (size_bytes < packet_size_words * 4) {
492 LOG(LS_WARNING) << "Buffer too small (" << size_bytes
493 << " bytes) to fit an RtcpPacket of " << packet_size_words
494 << " 32bit words.";
495 return false;
496 }
497
498 size_t payload_size = packet_size_words * 4;
499 size_t padding_bytes = 0;
500 if (has_padding) {
501 if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) {
502 LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload "
503 "size specified.";
504 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000505 }
506
sprang73a93e82015-09-14 12:50:39 -0700507 padding_bytes = packet[payload_size - 1];
508 if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) {
509 LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
510 << padding_bytes << ") for a packet size of "
511 << payload_size << "bytes.";
512 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000513 }
sprang73a93e82015-09-14 12:50:39 -0700514 payload_size -= padding_bytes;
515 }
516 payload_size -= RtcpCommonHeader::kHeaderSizeBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000517
sprang73a93e82015-09-14 12:50:39 -0700518 parsed_header->version = kRtcpVersion;
519 parsed_header->count_or_format = format;
520 parsed_header->packet_type = packet_type;
521 parsed_header->payload_size_bytes = payload_size;
522 parsed_header->padding_bytes = padding_bytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000523
sprang73a93e82015-09-14 12:50:39 -0700524 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000525}
526
527bool
528RTCPUtility::RTCPParserV2::ParseRR()
529{
530 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
531
532 if (length < 8)
533 {
534 return false;
535 }
536
537
538 _ptrRTCPData += 4; // Skip header
539
Erik Språng242e22b2015-05-11 10:17:43 +0200540 _packetType = RTCPPacketTypes::kRr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
542 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
543 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
544 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
545 _packet.RR.SenderSSRC += *_ptrRTCPData++;
546
547 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
548
549 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200550 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
552 return true;
553}
554
555bool
556RTCPUtility::RTCPParserV2::ParseSR()
557{
558 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
559
560 if (length < 28)
561 {
562 EndCurrentBlock();
563 return false;
564 }
565
566 _ptrRTCPData += 4; // Skip header
567
Erik Språng242e22b2015-05-11 10:17:43 +0200568 _packetType = RTCPPacketTypes::kSr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000569
570 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
571 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
572 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
573 _packet.SR.SenderSSRC += *_ptrRTCPData++;
574
575 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
576 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
577 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
578 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
579
580 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
581 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
582 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
583 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
584
585 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
586 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
587 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
588 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
589
590 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
591 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
592 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
593 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
594
595 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
596 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
597 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
598 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
599
600 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
601
602 // State transition
603 if(_numberOfBlocks != 0)
604 {
Erik Språng242e22b2015-05-11 10:17:43 +0200605 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000606 }else
607 {
608 // don't go to state report block item if 0 report blocks
Erik Språng242e22b2015-05-11 10:17:43 +0200609 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000610 EndCurrentBlock();
611 }
612 return true;
613}
614
615bool
616RTCPUtility::RTCPParserV2::ParseReportBlockItem()
617{
618 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
619
620 if (length < 24 || _numberOfBlocks <= 0)
621 {
Erik Språng242e22b2015-05-11 10:17:43 +0200622 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
624 EndCurrentBlock();
625 return false;
626 }
627 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
628 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
629 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
630 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
631
632 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
633
634 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
635 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
636 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
637
638 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
639 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
640 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
641 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
642
643 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
644 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
645 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
646 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
647
648 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
649 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
650 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
651 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
652
653 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
654 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
655 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
656 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
657
658 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200659 _packetType = RTCPPacketTypes::kReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 return true;
661}
662
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000663/* From RFC 5450: Transmission Time Offsets in RTP Streams.
664 0 1 2 3
665 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
666 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
667 hdr |V=2|P| RC | PT=IJ=195 | length |
668 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
669 | inter-arrival jitter |
670 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
671 . .
672 . .
673 . .
674 | inter-arrival jitter |
675 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676*/
677
678bool
679RTCPUtility::RTCPParserV2::ParseIJ()
680{
681 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
682
683 if (length < 4)
684 {
685 return false;
686 }
687
688 _ptrRTCPData += 4; // Skip header
689
Erik Språng242e22b2015-05-11 10:17:43 +0200690 _packetType = RTCPPacketTypes::kExtendedIj;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000691
692 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200693 _state = ParseState::State_ExtendedJitterItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000694 return true;
695}
696
697bool
698RTCPUtility::RTCPParserV2::ParseIJItem()
699{
700 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
701
702 if (length < 4 || _numberOfBlocks <= 0)
703 {
Erik Språng242e22b2015-05-11 10:17:43 +0200704 _state = ParseState::State_TopLevel;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000705 EndCurrentBlock();
706 return false;
707 }
708
709 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
710 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
711 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
712 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
713
714 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200715 _packetType = RTCPPacketTypes::kExtendedIjItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000716 return true;
717}
718
niklase@google.com470e71d2011-07-07 08:21:25 +0000719bool
720RTCPUtility::RTCPParserV2::ParseSDES()
721{
722 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
723
724 if (length < 8)
725 {
Erik Språng242e22b2015-05-11 10:17:43 +0200726 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000727
728 EndCurrentBlock();
729 return false;
730 }
731 _ptrRTCPData += 4; // Skip header
732
Erik Språng242e22b2015-05-11 10:17:43 +0200733 _state = ParseState::State_SDESChunk;
734 _packetType = RTCPPacketTypes::kSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000735 return true;
736}
737
738bool
739RTCPUtility::RTCPParserV2::ParseSDESChunk()
740{
741 if(_numberOfBlocks <= 0)
742 {
Erik Språng242e22b2015-05-11 10:17:43 +0200743 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000744
745 EndCurrentBlock();
746 return false;
747 }
748 _numberOfBlocks--;
749
750 // Find CName item in a SDES chunk.
751 while (_ptrRTCPData < _ptrRTCPBlockEnd)
752 {
753 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
754 if (dataLen < 4)
755 {
Erik Språng242e22b2015-05-11 10:17:43 +0200756 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000757
758 EndCurrentBlock();
759 return false;
760 }
761
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000762 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000763 SSRC += *_ptrRTCPData++ << 16;
764 SSRC += *_ptrRTCPData++ << 8;
765 SSRC += *_ptrRTCPData++;
766
767 const bool foundCname = ParseSDESItem();
768 if (foundCname)
769 {
770 _packet.CName.SenderSSRC = SSRC; // Add SSRC
771 return true;
772 }
773 }
Erik Språng242e22b2015-05-11 10:17:43 +0200774 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000775
776 EndCurrentBlock();
777 return false;
778}
779
780bool
781RTCPUtility::RTCPParserV2::ParseSDESItem()
782{
783 // Find CName
784 // Only the CNAME item is mandatory. RFC 3550 page 46
785 bool foundCName = false;
786
787 size_t itemOctetsRead = 0;
788 while (_ptrRTCPData < _ptrRTCPBlockEnd)
789 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000790 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000791 ++itemOctetsRead;
792
793 if (tag == 0)
794 {
795 // End tag! 4 oct aligned
796 while ((itemOctetsRead++ % 4) != 0)
797 {
798 ++_ptrRTCPData;
799 }
800 return foundCName;
801 }
802
803 if (_ptrRTCPData < _ptrRTCPBlockEnd)
804 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000805 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000806 ++itemOctetsRead;
807
808 if (tag == 1)
809 {
810 // CNAME
811
812 // Sanity
813 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
814 {
Erik Språng242e22b2015-05-11 10:17:43 +0200815 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000816
817 EndCurrentBlock();
818 return false;
819 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000820 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000821 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000822 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000823 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000824 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
825 {
826 // Illegal char
Erik Språng242e22b2015-05-11 10:17:43 +0200827 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000828
829 EndCurrentBlock();
830 return false;
831 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000832 _packet.CName.CName[i] = c;
833 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000834 // Make sure we are null terminated.
835 _packet.CName.CName[i] = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200836 _packetType = RTCPPacketTypes::kSdesChunk;
niklase@google.com470e71d2011-07-07 08:21:25 +0000837
838 foundCName = true;
839 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000840 _ptrRTCPData += len;
841 itemOctetsRead += len;
842 }
843 }
844
845 // No end tag found!
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
852bool
853RTCPUtility::RTCPParserV2::ParseBYE()
854{
855 _ptrRTCPData += 4; // Skip header
856
Erik Språng242e22b2015-05-11 10:17:43 +0200857 _state = ParseState::State_BYEItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000858
859 return ParseBYEItem();
860}
861
862bool
863RTCPUtility::RTCPParserV2::ParseBYEItem()
864{
865 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
866 if (length < 4 || _numberOfBlocks == 0)
867 {
Erik Språng242e22b2015-05-11 10:17:43 +0200868 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000869
870 EndCurrentBlock();
871 return false;
872 }
873
Erik Språng242e22b2015-05-11 10:17:43 +0200874 _packetType = RTCPPacketTypes::kBye;
niklase@google.com470e71d2011-07-07 08:21:25 +0000875
876 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
877 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
878 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
879 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
880
881 // we can have several CSRCs attached
882
883 // sanity
884 if(length >= 4*_numberOfBlocks)
885 {
886 _ptrRTCPData += (_numberOfBlocks -1)*4;
887 }
888 _numberOfBlocks = 0;
889
890 return true;
891}
892/*
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000893 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +0000894 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
895 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
896 |V=2|P|reserved | PT=XR=207 | length |
897 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
898 | SSRC |
899 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
900 : report blocks :
901 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
902*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000903bool RTCPUtility::RTCPParserV2::ParseXr()
niklase@google.com470e71d2011-07-07 08:21:25 +0000904{
905 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000906 if (length < 8)
907 {
908 EndCurrentBlock();
909 return false;
910 }
911
912 _ptrRTCPData += 4; // Skip header
913
914 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
915 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
916 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
917 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
918
Erik Språng242e22b2015-05-11 10:17:43 +0200919 _packetType = RTCPPacketTypes::kXrHeader;
920 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000921 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000922}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000923
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000924/* Extended report block format (RFC 3611).
925 BT: block type.
926 block length: length of report block in 32-bits words minus one (including
927 the header).
niklase@google.com470e71d2011-07-07 08:21:25 +0000928 0 1 2 3
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000929 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 +0000930 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
931 | BT | type-specific | block length |
932 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
933 : type-specific block contents :
934 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
935*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000936bool RTCPUtility::RTCPParserV2::ParseXrItem() {
937 const int kBlockHeaderLengthInBytes = 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000938 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000939 if (length < kBlockHeaderLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200940 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000941 EndCurrentBlock();
942 return false;
943 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000944
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000945 uint8_t block_type = *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000946 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000947
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000948 uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
949 block_length_in_4bytes += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000950
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000951 switch (block_type) {
952 case kBtReceiverReferenceTime:
953 return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
954 case kBtDlrr:
955 return ParseXrDlrr(block_length_in_4bytes);
956 case kBtVoipMetric:
957 return ParseXrVoipMetricItem(block_length_in_4bytes);
958 default:
959 return ParseXrUnsupportedBlockType(block_length_in_4bytes);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000960 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000961}
962
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000963/* Receiver Reference Time Report Block.
964 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000965 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
966 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
967 | BT=4 | reserved | block length = 2 |
968 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
969 | NTP timestamp, most significant word |
970 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
971 | NTP timestamp, least significant word |
972 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
973*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000974bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
975 int block_length_4bytes) {
976 const int kBlockLengthIn4Bytes = 2;
977 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000978 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000979 if (block_length_4bytes != kBlockLengthIn4Bytes ||
980 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200981 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000982 EndCurrentBlock();
983 return false;
984 }
985
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000986 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
987 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
988 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
989 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000990
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000991 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
992 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
993 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
994 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000995
Erik Språng242e22b2015-05-11 10:17:43 +0200996 _packetType = RTCPPacketTypes::kXrReceiverReferenceTime;
997 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000998 return true;
999}
1000
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001001/* DLRR Report Block.
1002 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001003 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
1004 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1005 | BT=5 | reserved | block length |
1006 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1007 | SSRC_1 (SSRC of first receiver) | sub-
1008 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1009 | last RR (LRR) | 1
1010 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1011 | delay since last RR (DLRR) |
1012 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1013 | SSRC_2 (SSRC of second receiver) | sub-
1014 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1015 : ... : 2
1016 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1017*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001018bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
1019 const int kSubBlockLengthIn4Bytes = 3;
1020 if (block_length_4bytes < 0 ||
1021 (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001022 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001023 EndCurrentBlock();
1024 return false;
1025 }
Erik Språng242e22b2015-05-11 10:17:43 +02001026 _packetType = RTCPPacketTypes::kXrDlrrReportBlock;
1027 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001028 _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
1029 return true;
1030}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001031
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001032bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001033 if (_numberOfBlocks == 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001034 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001035 return false;
1036 }
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001037 const int kSubBlockLengthInBytes = 12;
1038 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1039 if (length < kSubBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001040 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001041 EndCurrentBlock();
1042 return false;
1043 }
1044
1045 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1046 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1047 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1048 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1049
1050 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1051 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1052 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1053 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1054
1055 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1056 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1057 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1058 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1059
Erik Språng242e22b2015-05-11 10:17:43 +02001060 _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001061 --_numberOfBlocks;
Erik Språng242e22b2015-05-11 10:17:43 +02001062 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001063 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001064}
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001065/* VoIP Metrics Report Block.
1066 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +00001067 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
1068 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1069 | BT=7 | reserved | block length = 8 |
1070 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1071 | SSRC of source |
1072 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1073 | loss rate | discard rate | burst density | gap density |
1074 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1075 | burst duration | gap duration |
1076 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1077 | round trip delay | end system delay |
1078 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1079 | signal level | noise level | RERL | Gmin |
1080 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1081 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1082 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1083 | RX config | reserved | JB nominal |
1084 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1085 | JB maximum | JB abs max |
1086 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1087*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001088
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001089bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
1090 const int kBlockLengthIn4Bytes = 8;
1091 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
1092 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1093 if (block_length_4bytes != kBlockLengthIn4Bytes ||
1094 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001095 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001096 EndCurrentBlock();
1097 return false;
1098 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001099
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001100 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1101 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1102 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1103 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001104
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001105 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1106 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1107 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1108 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001109
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001110 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1111 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001112
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001113 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1114 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001115
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001116 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1117 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001118
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001119 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1120 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001122 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1123 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1124 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1125 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1126 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1127 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1128 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1129 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1130 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1131 _ptrRTCPData++; // skip reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001132
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001133 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1134 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001135
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001136 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1137 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001138
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001139 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1140 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001141
Erik Språng242e22b2015-05-11 10:17:43 +02001142 _packetType = RTCPPacketTypes::kXrVoipMetric;
1143 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001144 return true;
1145}
niklase@google.com470e71d2011-07-07 08:21:25 +00001146
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001147bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
1148 int block_length_4bytes) {
1149 const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
1150 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1151 if (length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001152 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001153 EndCurrentBlock();
1154 return false;
1155 }
1156 // Skip block.
1157 _ptrRTCPData += kBlockLengthInBytes;
Erik Språng242e22b2015-05-11 10:17:43 +02001158 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001159 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001160}
1161
sprang73a93e82015-09-14 12:50:39 -07001162bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) {
1163 assert((header.packet_type == PT_RTPFB) ||
1164 (header.packet_type == PT_PSFB)); // Parser logic check
niklase@google.com470e71d2011-07-07 08:21:25 +00001165
1166 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1167
1168 if (length < 12) // 4 * 3, RFC4585 section 6.1
1169 {
1170 EndCurrentBlock();
1171 return false;
1172 }
1173
1174 _ptrRTCPData += 4; // Skip RTCP header
1175
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001176 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001177 senderSSRC += *_ptrRTCPData++ << 16;
1178 senderSSRC += *_ptrRTCPData++ << 8;
1179 senderSSRC += *_ptrRTCPData++;
1180
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001181 uint32_t mediaSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001182 mediaSSRC += *_ptrRTCPData++ << 16;
1183 mediaSSRC += *_ptrRTCPData++ << 8;
1184 mediaSSRC += *_ptrRTCPData++;
1185
sprang73a93e82015-09-14 12:50:39 -07001186 if (header.packet_type == PT_RTPFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001187 // Transport layer feedback
1188
sprang73a93e82015-09-14 12:50:39 -07001189 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001190 case 1:
1191 {
1192 // NACK
Erik Språng242e22b2015-05-11 10:17:43 +02001193 _packetType = RTCPPacketTypes::kRtpfbNack;
niklase@google.com470e71d2011-07-07 08:21:25 +00001194 _packet.NACK.SenderSSRC = senderSSRC;
1195 _packet.NACK.MediaSSRC = mediaSSRC;
1196
Erik Språng242e22b2015-05-11 10:17:43 +02001197 _state = ParseState::State_RTPFB_NACKItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001198
1199 return true;
1200 }
1201 case 2:
1202 {
1203 // used to be ACK is this code point, which is removed
1204 // conficts with http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
1205 break;
1206 }
1207 case 3:
1208 {
1209 // TMMBR
Erik Språng242e22b2015-05-11 10:17:43 +02001210 _packetType = RTCPPacketTypes::kRtpfbTmmbr;
niklase@google.com470e71d2011-07-07 08:21:25 +00001211 _packet.TMMBR.SenderSSRC = senderSSRC;
1212 _packet.TMMBR.MediaSSRC = mediaSSRC;
1213
Erik Språng242e22b2015-05-11 10:17:43 +02001214 _state = ParseState::State_RTPFB_TMMBRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001215
1216 return true;
1217 }
1218 case 4:
1219 {
1220 // TMMBN
Erik Språng242e22b2015-05-11 10:17:43 +02001221 _packetType = RTCPPacketTypes::kRtpfbTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 _packet.TMMBN.SenderSSRC = senderSSRC;
1223 _packet.TMMBN.MediaSSRC = mediaSSRC;
1224
Erik Språng242e22b2015-05-11 10:17:43 +02001225 _state = ParseState::State_RTPFB_TMMBNItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001226
1227 return true;
1228 }
1229 case 5:
1230 {
1231 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1232 // draft-perkins-avt-rapid-rtp-sync-03.txt
1233 // trigger a new RTCP SR
Erik Språng242e22b2015-05-11 10:17:43 +02001234 _packetType = RTCPPacketTypes::kRtpfbSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +00001235
1236 // Note: No state transition, SR REQ is empty!
1237 return true;
1238 }
1239 default:
1240 break;
1241 }
1242 EndCurrentBlock();
1243 return false;
sprang73a93e82015-09-14 12:50:39 -07001244 } else if (header.packet_type == PT_PSFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001245 // Payload specific feedback
sprang73a93e82015-09-14 12:50:39 -07001246 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001247 case 1:
1248 // PLI
Erik Språng242e22b2015-05-11 10:17:43 +02001249 _packetType = RTCPPacketTypes::kPsfbPli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001250 _packet.PLI.SenderSSRC = senderSSRC;
1251 _packet.PLI.MediaSSRC = mediaSSRC;
1252
1253 // Note: No state transition, PLI FCI is empty!
1254 return true;
1255 case 2:
1256 // SLI
Erik Språng242e22b2015-05-11 10:17:43 +02001257 _packetType = RTCPPacketTypes::kPsfbSli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001258 _packet.SLI.SenderSSRC = senderSSRC;
1259 _packet.SLI.MediaSSRC = mediaSSRC;
1260
Erik Språng242e22b2015-05-11 10:17:43 +02001261 _state = ParseState::State_PSFB_SLIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001262
1263 return true;
1264 case 3:
Erik Språng242e22b2015-05-11 10:17:43 +02001265 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001266 _packet.RPSI.SenderSSRC = senderSSRC;
1267 _packet.RPSI.MediaSSRC = mediaSSRC;
1268
Erik Språng242e22b2015-05-11 10:17:43 +02001269 _state = ParseState::State_PSFB_RPSIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001270 return true;
1271 case 4:
1272 // FIR
Erik Språng242e22b2015-05-11 10:17:43 +02001273 _packetType = RTCPPacketTypes::kPsfbFir;
niklase@google.com470e71d2011-07-07 08:21:25 +00001274 _packet.FIR.SenderSSRC = senderSSRC;
1275 _packet.FIR.MediaSSRC = mediaSSRC;
1276
Erik Språng242e22b2015-05-11 10:17:43 +02001277 _state = ParseState::State_PSFB_FIRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001279 case 15:
Erik Språng242e22b2015-05-11 10:17:43 +02001280 _packetType = RTCPPacketTypes::kPsfbApp;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001281 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1282 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001283
Erik Språng242e22b2015-05-11 10:17:43 +02001284 _state = ParseState::State_PSFB_AppItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001285 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 default:
1287 break;
1288 }
1289
1290 EndCurrentBlock();
1291 return false;
1292 }
1293 else
1294 {
1295 assert(false);
1296
1297 EndCurrentBlock();
1298 return false;
1299 }
1300}
1301
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001302bool RTCPUtility::RTCPParserV2::ParseRPSIItem() {
1303
1304 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI).
1305 //
1306 // 0 1 2 3
1307 // 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
1308 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1309 // | PB |0| Payload Type| Native RPSI bit string |
1310 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1311 // | defined per codec ... | Padding (0) |
1312 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
niklase@google.com470e71d2011-07-07 08:21:25 +00001313
1314 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1315
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001316 if (length < 4) {
Erik Språng242e22b2015-05-11 10:17:43 +02001317 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001318
1319 EndCurrentBlock();
1320 return false;
1321 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001322 if (length > 2 + RTCP_RPSI_DATA_SIZE) {
Erik Språng242e22b2015-05-11 10:17:43 +02001323 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001324
1325 EndCurrentBlock();
1326 return false;
1327 }
1328
Erik Språng242e22b2015-05-11 10:17:43 +02001329 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001330
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001331 uint8_t padding_bits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001332 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1333
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001334 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
1335 _ptrRTCPData += length - 2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001336
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001337 _packet.RPSI.NumberOfValidBits =
1338 static_cast<uint16_t>(length - 2) * 8 - padding_bits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001339 return true;
1340}
1341
1342bool
1343RTCPUtility::RTCPParserV2::ParseNACKItem()
1344{
1345 // RFC 4585 6.2.1. Generic NACK
1346
1347 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1348
1349 if (length < 4)
1350 {
Erik Språng242e22b2015-05-11 10:17:43 +02001351 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001352
1353 EndCurrentBlock();
1354 return false;
1355 }
1356
Erik Språng242e22b2015-05-11 10:17:43 +02001357 _packetType = RTCPPacketTypes::kRtpfbNackItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001358
1359 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1360 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1361
1362 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1363 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1364
1365 return true;
1366}
1367
1368bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001369RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1370{
1371 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1372
1373 if (length < 4)
1374 {
Erik Språng242e22b2015-05-11 10:17:43 +02001375 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001376
1377 EndCurrentBlock();
1378 return false;
1379 }
1380 if(*_ptrRTCPData++ != 'R')
1381 {
Erik Språng242e22b2015-05-11 10:17:43 +02001382 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001383
1384 EndCurrentBlock();
1385 return false;
1386 }
1387 if(*_ptrRTCPData++ != 'E')
1388 {
Erik Språng242e22b2015-05-11 10:17:43 +02001389 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001390
1391 EndCurrentBlock();
1392 return false;
1393 }
1394 if(*_ptrRTCPData++ != 'M')
1395 {
Erik Språng242e22b2015-05-11 10:17:43 +02001396 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001397
1398 EndCurrentBlock();
1399 return false;
1400 }
1401 if(*_ptrRTCPData++ != 'B')
1402 {
Erik Språng242e22b2015-05-11 10:17:43 +02001403 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001404
1405 EndCurrentBlock();
1406 return false;
1407 }
Erik Språng242e22b2015-05-11 10:17:43 +02001408 _packetType = RTCPPacketTypes::kPsfbRemb;
1409 _state = ParseState::State_PSFB_REMBItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001410 return true;
1411}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001412
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001413bool
1414RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1415{
1416 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1417
1418 if (length < 4)
1419 {
Erik Språng242e22b2015-05-11 10:17:43 +02001420 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001421
1422 EndCurrentBlock();
1423 return false;
1424 }
1425
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001426 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001427 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001428
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001429 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001430 brMantissa += (_ptrRTCPData[1] << 8);
1431 brMantissa += (_ptrRTCPData[2]);
1432
1433 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001434 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001435
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001436 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1437 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1438 {
Erik Språng242e22b2015-05-11 10:17:43 +02001439 _state = ParseState::State_TopLevel;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001440
1441 EndCurrentBlock();
1442 return false;
1443 }
1444
Erik Språng242e22b2015-05-11 10:17:43 +02001445 _packetType = RTCPPacketTypes::kPsfbRembItem;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001446
1447 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1448 {
1449 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1450 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1451 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1452 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1453 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001454 return true;
1455}
1456
1457bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001458RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1459{
1460 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1461
1462 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1463
1464 if (length < 8)
1465 {
Erik Språng242e22b2015-05-11 10:17:43 +02001466 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001467
1468 EndCurrentBlock();
1469 return false;
1470 }
1471
Erik Språng242e22b2015-05-11 10:17:43 +02001472 _packetType = RTCPPacketTypes::kRtpfbTmmbrItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001473
1474 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1475 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1476 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1477 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1478
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001479 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001480
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001481 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001482 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1483 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1484
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001485 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001486 measuredOH += _ptrRTCPData[3];
1487
1488 _ptrRTCPData += 4; // Fwd read data
1489
1490 _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1491 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1492
1493 return true;
1494}
1495
1496bool
1497RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1498{
1499 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1500
1501 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1502
1503 if (length < 8)
1504 {
Erik Språng242e22b2015-05-11 10:17:43 +02001505 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001506
1507 EndCurrentBlock();
1508 return false;
1509 }
1510
Erik Språng242e22b2015-05-11 10:17:43 +02001511 _packetType = RTCPPacketTypes::kRtpfbTmmbnItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001512
1513 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1514 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1515 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1516 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1517
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001518 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001519
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001520 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001521 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1522 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1523
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001524 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001525 measuredOH += _ptrRTCPData[3];
1526
1527 _ptrRTCPData += 4; // Fwd read data
1528
1529 _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1530 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1531
1532 return true;
1533}
1534
1535bool
1536RTCPUtility::RTCPParserV2::ParseSLIItem()
1537{
1538 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1539 /*
1540 0 1 2 3
1541 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
1542 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1543 | First | Number | PictureID |
1544 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1545 */
1546
1547 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1548
1549 if (length < 4)
1550 {
Erik Språng242e22b2015-05-11 10:17:43 +02001551 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001552
1553 EndCurrentBlock();
1554 return false;
1555 }
Erik Språng242e22b2015-05-11 10:17:43 +02001556 _packetType = RTCPPacketTypes::kPsfbSliItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001557
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001558 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001559 buffer = *_ptrRTCPData++ << 24;
1560 buffer += *_ptrRTCPData++ << 16;
1561 buffer += *_ptrRTCPData++ << 8;
1562 buffer += *_ptrRTCPData++;
1563
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001564 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1565 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1566 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001567
1568 return true;
1569}
1570
1571bool
1572RTCPUtility::RTCPParserV2::ParseFIRItem()
1573{
1574 // RFC 5104 4.3.1. Full Intra Request (FIR)
1575
1576 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1577
1578 if (length < 8)
1579 {
Erik Språng242e22b2015-05-11 10:17:43 +02001580 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001581
1582 EndCurrentBlock();
1583 return false;
1584 }
1585
Erik Språng242e22b2015-05-11 10:17:43 +02001586 _packetType = RTCPPacketTypes::kPsfbFirItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001587
1588 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1589 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1590 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1591 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1592
1593 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1594 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1595 return true;
1596}
1597
sprang73a93e82015-09-14 12:50:39 -07001598bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001599 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1600
1601 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1602 {
1603 EndCurrentBlock();
1604 return false;
1605 }
1606
1607 _ptrRTCPData += 4; // Skip RTCP header
1608
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001609 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001610 senderSSRC += *_ptrRTCPData++ << 16;
1611 senderSSRC += *_ptrRTCPData++ << 8;
1612 senderSSRC += *_ptrRTCPData++;
1613
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001614 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001615 name += *_ptrRTCPData++ << 16;
1616 name += *_ptrRTCPData++ << 8;
1617 name += *_ptrRTCPData++;
1618
1619 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1620
Erik Språng242e22b2015-05-11 10:17:43 +02001621 _packetType = RTCPPacketTypes::kApp;
niklase@google.com470e71d2011-07-07 08:21:25 +00001622
sprang73a93e82015-09-14 12:50:39 -07001623 _packet.APP.SubType = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +00001624 _packet.APP.Name = name;
1625
Erik Språng242e22b2015-05-11 10:17:43 +02001626 _state = ParseState::State_AppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001627 return true;
1628}
1629
1630bool
1631RTCPUtility::RTCPParserV2::ParseAPPItem()
1632{
1633 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1634 if (length < 4)
1635 {
Erik Språng242e22b2015-05-11 10:17:43 +02001636 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001637
1638 EndCurrentBlock();
1639 return false;
1640 }
Erik Språng242e22b2015-05-11 10:17:43 +02001641 _packetType = RTCPPacketTypes::kAppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001642
1643 if(length > kRtcpAppCode_DATA_SIZE)
1644 {
1645 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1646 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1647 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1648 }else
1649 {
1650 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001651 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001652 _ptrRTCPData += length;
1653 }
1654 return true;
1655}
1656
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001657RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001658 size_t rtcpDataLength)
1659 : _ptrBegin(rtcpData),
1660 _ptrEnd(rtcpData + rtcpDataLength),
1661 _ptrBlock(NULL) {
1662 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001663}
1664
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001665RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001666}
1667
sprang73a93e82015-09-14 12:50:39 -07001668const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001669 _ptrBlock = _ptrBegin;
1670
1671 return Iterate();
1672}
1673
sprang73a93e82015-09-14 12:50:39 -07001674const RTCPUtility::RtcpCommonHeader*
1675RTCPUtility::RTCPPacketIterator::Iterate() {
1676 if ((_ptrEnd <= _ptrBlock) ||
1677 !RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) {
1678 _ptrBlock = nullptr;
1679 return nullptr;
1680 }
1681 _ptrBlock += _header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +00001682
sprang73a93e82015-09-14 12:50:39 -07001683 if (_ptrBlock > _ptrEnd) {
1684 _ptrBlock = nullptr;
1685 return nullptr;
1686 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001687
sprang73a93e82015-09-14 12:50:39 -07001688 return &_header;
niklase@google.com470e71d2011-07-07 08:21:25 +00001689}
1690
sprang73a93e82015-09-14 12:50:39 -07001691const RTCPUtility::RtcpCommonHeader*
1692RTCPUtility::RTCPPacketIterator::Current() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001693 if (!_ptrBlock)
1694 {
1695 return NULL;
1696 }
1697
1698 return &_header;
1699}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001700} // namespace webrtc