blob: 6c1deb467ef787de5947df7d70ef4384c56204fd [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
Erik Språng6b8d3552015-09-24 15:06:57 +020011#include "webrtc/base/checks.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000012#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020013#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000014
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000015#include <assert.h>
16#include <math.h> // ceil
17#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000018
sprang73a93e82015-09-14 12:50:39 -070019#include "webrtc/base/checks.h"
20#include "webrtc/base/logging.h"
21#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
22
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000024
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000025namespace RTCPUtility {
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +000026
27NackStats::NackStats()
28 : max_sequence_number_(0),
29 requests_(0),
30 unique_requests_(0) {}
31
32NackStats::~NackStats() {}
33
34void NackStats::ReportRequest(uint16_t sequence_number) {
35 if (requests_ == 0 ||
36 webrtc::IsNewerSequenceNumber(sequence_number, max_sequence_number_)) {
37 max_sequence_number_ = sequence_number;
38 ++unique_requests_;
39 }
40 ++requests_;
41}
42
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000043uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) {
44 return (ntp_sec << 16) + (ntp_frac >> 16);
45} // end RTCPUtility
46}
47
48// RTCPParserV2 : currently read only
pbos@webrtc.org2f446732013-04-08 11:08:41 +000049RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
niklase@google.com470e71d2011-07-07 08:21:25 +000050 size_t rtcpDataLength,
51 bool rtcpReducedSizeEnable)
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000052 : _ptrRTCPDataBegin(rtcpData),
53 _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
54 _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
55 _validPacket(false),
56 _ptrRTCPData(rtcpData),
57 _ptrRTCPBlockEnd(NULL),
Erik Språng242e22b2015-05-11 10:17:43 +020058 _state(ParseState::State_TopLevel),
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000059 _numberOfBlocks(0),
Erik Språng6b8d3552015-09-24 15:06:57 +020060 num_skipped_blocks_(0),
Erik Språng242e22b2015-05-11 10:17:43 +020061 _packetType(RTCPPacketTypes::kInvalid) {
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000062 Validate();
niklase@google.com470e71d2011-07-07 08:21:25 +000063}
64
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000065RTCPUtility::RTCPParserV2::~RTCPParserV2() {
niklase@google.com470e71d2011-07-07 08:21:25 +000066}
67
68ptrdiff_t
69RTCPUtility::RTCPParserV2::LengthLeft() const
70{
71 return (_ptrRTCPDataEnd- _ptrRTCPData);
72}
73
74RTCPUtility::RTCPPacketTypes
75RTCPUtility::RTCPParserV2::PacketType() const
76{
77 return _packetType;
78}
79
80const RTCPUtility::RTCPPacket&
81RTCPUtility::RTCPParserV2::Packet() const
82{
83 return _packet;
84}
85
Erik Språng6b8d3552015-09-24 15:06:57 +020086rtcp::RtcpPacket* RTCPUtility::RTCPParserV2::ReleaseRtcpPacket() {
87 return rtcp_packet_.release();
88}
niklase@google.com470e71d2011-07-07 08:21:25 +000089RTCPUtility::RTCPPacketTypes
90RTCPUtility::RTCPParserV2::Begin()
91{
92 _ptrRTCPData = _ptrRTCPDataBegin;
93
94 return Iterate();
95}
96
97RTCPUtility::RTCPPacketTypes
98RTCPUtility::RTCPParserV2::Iterate()
99{
100 // Reset packet type
Erik Språng242e22b2015-05-11 10:17:43 +0200101 _packetType = RTCPPacketTypes::kInvalid;
niklase@google.com470e71d2011-07-07 08:21:25 +0000102
103 if (IsValid())
104 {
105 switch (_state)
106 {
Erik Språng242e22b2015-05-11 10:17:43 +0200107 case ParseState::State_TopLevel:
niklase@google.com470e71d2011-07-07 08:21:25 +0000108 IterateTopLevel();
109 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200110 case ParseState::State_ReportBlockItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 IterateReportBlockItem();
112 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200113 case ParseState::State_SDESChunk:
niklase@google.com470e71d2011-07-07 08:21:25 +0000114 IterateSDESChunk();
115 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200116 case ParseState::State_BYEItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 IterateBYEItem();
118 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200119 case ParseState::State_ExtendedJitterItem:
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000120 IterateExtendedJitterItem();
121 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200122 case ParseState::State_RTPFB_NACKItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 IterateNACKItem();
124 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200125 case ParseState::State_RTPFB_TMMBRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000126 IterateTMMBRItem();
127 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200128 case ParseState::State_RTPFB_TMMBNItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 IterateTMMBNItem();
130 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200131 case ParseState::State_PSFB_SLIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000132 IterateSLIItem();
133 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200134 case ParseState::State_PSFB_RPSIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000135 IterateRPSIItem();
136 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200137 case ParseState::State_PSFB_FIRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000138 IterateFIRItem();
139 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200140 case ParseState::State_PSFB_AppItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000141 IteratePsfbAppItem();
142 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200143 case ParseState::State_PSFB_REMBItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000144 IteratePsfbREMBItem();
145 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200146 case ParseState::State_XRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000147 IterateXrItem();
148 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200149 case ParseState::State_XR_DLLRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000150 IterateXrDlrrItem();
151 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200152 case ParseState::State_AppItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000153 IterateAppItem();
154 break;
155 default:
Erik Språng6b8d3552015-09-24 15:06:57 +0200156 RTC_NOTREACHED() << "Invalid state!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 break;
158 }
159 }
160 return _packetType;
161}
162
163void
164RTCPUtility::RTCPParserV2::IterateTopLevel()
165{
166 for (;;)
167 {
sprang73a93e82015-09-14 12:50:39 -0700168 RtcpCommonHeader header;
169 if (_ptrRTCPDataEnd <= _ptrRTCPData)
170 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
sprang73a93e82015-09-14 12:50:39 -0700172 if (!RtcpParseCommonHeader(_ptrRTCPData, _ptrRTCPDataEnd - _ptrRTCPData,
173 &header)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 return;
175 }
sprang73a93e82015-09-14 12:50:39 -0700176 _ptrRTCPBlockEnd = _ptrRTCPData + header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +0000177 if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
178 {
Erik Språng6b8d3552015-09-24 15:06:57 +0200179 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 return;
181 }
182
sprang73a93e82015-09-14 12:50:39 -0700183 switch (header.packet_type) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000184 case PT_SR:
185 {
186 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700187 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 ParseSR();
189 return;
190 }
191 case PT_RR:
192 {
193 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700194 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 ParseRR();
196 return;
197 }
198 case PT_SDES:
199 {
200 // number of SDES blocks
sprang73a93e82015-09-14 12:50:39 -0700201 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202 const bool ok = ParseSDES();
203 if (!ok)
204 {
205 // Nothing supported found, continue to next block!
206 break;
207 }
208 return;
209 }
210 case PT_BYE:
211 {
sprang73a93e82015-09-14 12:50:39 -0700212 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 const bool ok = ParseBYE();
214 if (!ok)
215 {
216 // Nothing supported found, continue to next block!
217 break;
218 }
219 return;
220 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000221 case PT_IJ:
222 {
223 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700224 _numberOfBlocks = header.count_or_format;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000225 ParseIJ();
226 return;
227 }
Erik Språng6b8d3552015-09-24 15:06:57 +0200228 case PT_RTPFB:
229 FALLTHROUGH();
niklase@google.com470e71d2011-07-07 08:21:25 +0000230 case PT_PSFB:
231 {
Erik Språng6b8d3552015-09-24 15:06:57 +0200232 if (!ParseFBCommon(header)) {
233 // Nothing supported found, continue to next block!
234 break;
235 }
236 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237 }
238 case PT_APP:
239 {
240 const bool ok = ParseAPP(header);
241 if (!ok)
242 {
243 // Nothing supported found, continue to next block!
244 break;
245 }
246 return;
247 }
248 case PT_XR:
249 {
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000250 const bool ok = ParseXr();
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 if (!ok)
252 {
253 // Nothing supported found, continue to next block!
254 break;
255 }
256 return;
257 }
258 default:
259 // Not supported! Skip!
Erik Språng6b8d3552015-09-24 15:06:57 +0200260 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000261 EndCurrentBlock();
262 break;
263 }
264 }
265}
266
267void
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000268RTCPUtility::RTCPParserV2::IterateXrItem()
269{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000270 const bool success = ParseXrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000271 if (!success)
272 {
273 Iterate();
274 }
275}
276
277void
278RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
279{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000280 const bool success = ParseXrDlrrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000281 if (!success)
282 {
283 Iterate();
284 }
285}
286
287void
niklase@google.com470e71d2011-07-07 08:21:25 +0000288RTCPUtility::RTCPParserV2::IterateReportBlockItem()
289{
290 const bool success = ParseReportBlockItem();
291 if (!success)
292 {
293 Iterate();
294 }
295}
296
297void
298RTCPUtility::RTCPParserV2::IterateSDESChunk()
299{
300 const bool success = ParseSDESChunk();
301 if (!success)
302 {
303 Iterate();
304 }
305}
306
307void
308RTCPUtility::RTCPParserV2::IterateBYEItem()
309{
310 const bool success = ParseBYEItem();
311 if (!success)
312 {
313 Iterate();
314 }
315}
316
317void
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000318RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
319{
320 const bool success = ParseIJItem();
321 if (!success)
322 {
323 Iterate();
324 }
325}
326
327void
niklase@google.com470e71d2011-07-07 08:21:25 +0000328RTCPUtility::RTCPParserV2::IterateNACKItem()
329{
330 const bool success = ParseNACKItem();
331 if (!success)
332 {
333 Iterate();
334 }
335}
336
337void
338RTCPUtility::RTCPParserV2::IterateTMMBRItem()
339{
340 const bool success = ParseTMMBRItem();
341 if (!success)
342 {
343 Iterate();
344 }
345}
346
347void
348RTCPUtility::RTCPParserV2::IterateTMMBNItem()
349{
350 const bool success = ParseTMMBNItem();
351 if (!success)
352 {
353 Iterate();
354 }
355}
356
357void
358RTCPUtility::RTCPParserV2::IterateSLIItem()
359{
360 const bool success = ParseSLIItem();
361 if (!success)
362 {
363 Iterate();
364 }
365}
366
367void
368RTCPUtility::RTCPParserV2::IterateRPSIItem()
369{
370 const bool success = ParseRPSIItem();
371 if (!success)
372 {
373 Iterate();
374 }
375}
376
377void
378RTCPUtility::RTCPParserV2::IterateFIRItem()
379{
380 const bool success = ParseFIRItem();
381 if (!success)
382 {
383 Iterate();
384 }
385}
386
387void
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000388RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
389{
390 const bool success = ParsePsfbAppItem();
391 if (!success)
392 {
393 Iterate();
394 }
395}
396
397void
398RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
399{
400 const bool success = ParsePsfbREMBItem();
401 if (!success)
402 {
403 Iterate();
404 }
405}
406
407void
niklase@google.com470e71d2011-07-07 08:21:25 +0000408RTCPUtility::RTCPParserV2::IterateAppItem()
409{
410 const bool success = ParseAPPItem();
411 if (!success)
412 {
413 Iterate();
414 }
415}
416
417void
418RTCPUtility::RTCPParserV2::Validate()
419{
sprang73a93e82015-09-14 12:50:39 -0700420 if (_ptrRTCPData == nullptr)
421 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
sprang73a93e82015-09-14 12:50:39 -0700423 RtcpCommonHeader header;
424 if (_ptrRTCPDataEnd <= _ptrRTCPDataBegin)
425 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
sprang73a93e82015-09-14 12:50:39 -0700427 if (!RtcpParseCommonHeader(_ptrRTCPDataBegin,
428 _ptrRTCPDataEnd - _ptrRTCPDataBegin, &header))
429 return; // NOT VALID!
niklase@google.com470e71d2011-07-07 08:21:25 +0000430
431 // * if (!reducedSize) : first packet must be RR or SR.
432 //
433 // * The padding bit (P) should be zero for the first packet of a
434 // compound RTCP packet because padding should only be applied,
435 // if it is needed, to the last packet. (NOT CHECKED!)
436 //
437 // * The length fields of the individual RTCP packets must add up
438 // to the overall length of the compound RTCP packet as
439 // received. This is a fairly strong check. (NOT CHECKED!)
440
441 if (!_RTCPReducedSizeEnable)
442 {
sprang73a93e82015-09-14 12:50:39 -0700443 if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000444 return; // NOT VALID
445 }
446 }
447
448 _validPacket = true;
449}
450
451bool
452RTCPUtility::RTCPParserV2::IsValid() const
453{
454 return _validPacket;
455}
456
457void
458RTCPUtility::RTCPParserV2::EndCurrentBlock()
459{
460 _ptrRTCPData = _ptrRTCPBlockEnd;
461}
462
sprang73a93e82015-09-14 12:50:39 -0700463// 0 1 2 3
464// 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
465// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
466// |V=2|P| IC | PT | length |
467// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
468//
469// Common header for all RTCP packets, 4 octets.
470
471bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet,
472 size_t size_bytes,
473 RtcpCommonHeader* parsed_header) {
henrikg91d6ede2015-09-17 00:24:34 -0700474 RTC_DCHECK(parsed_header != nullptr);
sprang73a93e82015-09-14 12:50:39 -0700475 if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) {
476 LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte"
477 << (size_bytes != 1 ? "s" : "")
478 << ") remaining in buffer to parse RTCP header (4 bytes).";
479 return false;
480 }
481
482 const uint8_t kRtcpVersion = 2;
483 uint8_t version = packet[0] >> 6;
484 if (version != kRtcpVersion) {
485 LOG(LS_WARNING) << "Invalid RTCP header: Version must be "
486 << static_cast<int>(kRtcpVersion) << " but was "
487 << static_cast<int>(version);
488 return false;
489 }
490
491 bool has_padding = (packet[0] & 0x20) != 0;
492 uint8_t format = packet[0] & 0x1F;
493 uint8_t packet_type = packet[1];
494 size_t packet_size_words =
495 ByteReader<uint16_t>::ReadBigEndian(&packet[2]) + 1;
496
497 if (size_bytes < packet_size_words * 4) {
498 LOG(LS_WARNING) << "Buffer too small (" << size_bytes
499 << " bytes) to fit an RtcpPacket of " << packet_size_words
500 << " 32bit words.";
501 return false;
502 }
503
504 size_t payload_size = packet_size_words * 4;
505 size_t padding_bytes = 0;
506 if (has_padding) {
507 if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) {
508 LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload "
509 "size specified.";
510 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 }
512
sprang73a93e82015-09-14 12:50:39 -0700513 padding_bytes = packet[payload_size - 1];
514 if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) {
515 LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
516 << padding_bytes << ") for a packet size of "
517 << payload_size << "bytes.";
518 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000519 }
sprang73a93e82015-09-14 12:50:39 -0700520 payload_size -= padding_bytes;
521 }
522 payload_size -= RtcpCommonHeader::kHeaderSizeBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000523
sprang73a93e82015-09-14 12:50:39 -0700524 parsed_header->version = kRtcpVersion;
525 parsed_header->count_or_format = format;
526 parsed_header->packet_type = packet_type;
527 parsed_header->payload_size_bytes = payload_size;
528 parsed_header->padding_bytes = padding_bytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
sprang73a93e82015-09-14 12:50:39 -0700530 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
533bool
534RTCPUtility::RTCPParserV2::ParseRR()
535{
536 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
537
538 if (length < 8)
539 {
540 return false;
541 }
542
543
544 _ptrRTCPData += 4; // Skip header
545
Erik Språng242e22b2015-05-11 10:17:43 +0200546 _packetType = RTCPPacketTypes::kRr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000547
548 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
549 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
550 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
551 _packet.RR.SenderSSRC += *_ptrRTCPData++;
552
553 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
554
555 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200556 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000557
558 return true;
559}
560
561bool
562RTCPUtility::RTCPParserV2::ParseSR()
563{
564 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
565
566 if (length < 28)
567 {
568 EndCurrentBlock();
569 return false;
570 }
571
572 _ptrRTCPData += 4; // Skip header
573
Erik Språng242e22b2015-05-11 10:17:43 +0200574 _packetType = RTCPPacketTypes::kSr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
576 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
577 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
578 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
579 _packet.SR.SenderSSRC += *_ptrRTCPData++;
580
581 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
582 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
583 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
584 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
585
586 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
587 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
588 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
589 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
590
591 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
592 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
593 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
594 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
595
596 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
597 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
598 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
599 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
600
601 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
602 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
603 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
604 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
605
606 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
607
608 // State transition
609 if(_numberOfBlocks != 0)
610 {
Erik Språng242e22b2015-05-11 10:17:43 +0200611 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000612 }else
613 {
614 // don't go to state report block item if 0 report blocks
Erik Språng242e22b2015-05-11 10:17:43 +0200615 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000616 EndCurrentBlock();
617 }
618 return true;
619}
620
621bool
622RTCPUtility::RTCPParserV2::ParseReportBlockItem()
623{
624 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
625
626 if (length < 24 || _numberOfBlocks <= 0)
627 {
Erik Språng242e22b2015-05-11 10:17:43 +0200628 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000629
630 EndCurrentBlock();
631 return false;
632 }
633 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
634 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
635 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
636 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
637
638 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
639
640 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
641 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
642 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
643
644 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
645 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
646 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
647 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
648
649 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
650 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
651 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
652 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
653
654 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
655 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
656 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
657 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
658
659 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
660 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
661 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
662 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
663
664 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200665 _packetType = RTCPPacketTypes::kReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000666 return true;
667}
668
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000669/* From RFC 5450: Transmission Time Offsets in RTP Streams.
670 0 1 2 3
671 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
672 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
673 hdr |V=2|P| RC | PT=IJ=195 | length |
674 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675 | inter-arrival jitter |
676 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
677 . .
678 . .
679 . .
680 | inter-arrival jitter |
681 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
682*/
683
684bool
685RTCPUtility::RTCPParserV2::ParseIJ()
686{
687 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
688
689 if (length < 4)
690 {
691 return false;
692 }
693
694 _ptrRTCPData += 4; // Skip header
695
Erik Språng242e22b2015-05-11 10:17:43 +0200696 _packetType = RTCPPacketTypes::kExtendedIj;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000697
698 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200699 _state = ParseState::State_ExtendedJitterItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000700 return true;
701}
702
703bool
704RTCPUtility::RTCPParserV2::ParseIJItem()
705{
706 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
707
708 if (length < 4 || _numberOfBlocks <= 0)
709 {
Erik Språng242e22b2015-05-11 10:17:43 +0200710 _state = ParseState::State_TopLevel;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000711 EndCurrentBlock();
712 return false;
713 }
714
715 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
716 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
717 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
718 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
719
720 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200721 _packetType = RTCPPacketTypes::kExtendedIjItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000722 return true;
723}
724
niklase@google.com470e71d2011-07-07 08:21:25 +0000725bool
726RTCPUtility::RTCPParserV2::ParseSDES()
727{
728 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
729
730 if (length < 8)
731 {
Erik Språng242e22b2015-05-11 10:17:43 +0200732 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000733
734 EndCurrentBlock();
735 return false;
736 }
737 _ptrRTCPData += 4; // Skip header
738
Erik Språng242e22b2015-05-11 10:17:43 +0200739 _state = ParseState::State_SDESChunk;
740 _packetType = RTCPPacketTypes::kSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000741 return true;
742}
743
744bool
745RTCPUtility::RTCPParserV2::ParseSDESChunk()
746{
747 if(_numberOfBlocks <= 0)
748 {
Erik Språng242e22b2015-05-11 10:17:43 +0200749 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000750
751 EndCurrentBlock();
752 return false;
753 }
754 _numberOfBlocks--;
755
756 // Find CName item in a SDES chunk.
757 while (_ptrRTCPData < _ptrRTCPBlockEnd)
758 {
759 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
760 if (dataLen < 4)
761 {
Erik Språng242e22b2015-05-11 10:17:43 +0200762 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000763
764 EndCurrentBlock();
765 return false;
766 }
767
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000768 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000769 SSRC += *_ptrRTCPData++ << 16;
770 SSRC += *_ptrRTCPData++ << 8;
771 SSRC += *_ptrRTCPData++;
772
773 const bool foundCname = ParseSDESItem();
774 if (foundCname)
775 {
776 _packet.CName.SenderSSRC = SSRC; // Add SSRC
777 return true;
778 }
779 }
Erik Språng242e22b2015-05-11 10:17:43 +0200780 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000781
782 EndCurrentBlock();
783 return false;
784}
785
786bool
787RTCPUtility::RTCPParserV2::ParseSDESItem()
788{
789 // Find CName
790 // Only the CNAME item is mandatory. RFC 3550 page 46
791 bool foundCName = false;
792
793 size_t itemOctetsRead = 0;
794 while (_ptrRTCPData < _ptrRTCPBlockEnd)
795 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000796 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000797 ++itemOctetsRead;
798
799 if (tag == 0)
800 {
801 // End tag! 4 oct aligned
802 while ((itemOctetsRead++ % 4) != 0)
803 {
804 ++_ptrRTCPData;
805 }
806 return foundCName;
807 }
808
809 if (_ptrRTCPData < _ptrRTCPBlockEnd)
810 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000811 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000812 ++itemOctetsRead;
813
814 if (tag == 1)
815 {
816 // CNAME
817
818 // Sanity
819 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
820 {
Erik Språng242e22b2015-05-11 10:17:43 +0200821 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000822
823 EndCurrentBlock();
824 return false;
825 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000826 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000827 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000828 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000829 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000830 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
831 {
832 // Illegal char
Erik Språng242e22b2015-05-11 10:17:43 +0200833 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000834
835 EndCurrentBlock();
836 return false;
837 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000838 _packet.CName.CName[i] = c;
839 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000840 // Make sure we are null terminated.
841 _packet.CName.CName[i] = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200842 _packetType = RTCPPacketTypes::kSdesChunk;
niklase@google.com470e71d2011-07-07 08:21:25 +0000843
844 foundCName = true;
845 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000846 _ptrRTCPData += len;
847 itemOctetsRead += len;
848 }
849 }
850
851 // No end tag found!
Erik Språng242e22b2015-05-11 10:17:43 +0200852 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000853
854 EndCurrentBlock();
855 return false;
856}
857
858bool
859RTCPUtility::RTCPParserV2::ParseBYE()
860{
861 _ptrRTCPData += 4; // Skip header
862
Erik Språng242e22b2015-05-11 10:17:43 +0200863 _state = ParseState::State_BYEItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000864
865 return ParseBYEItem();
866}
867
868bool
869RTCPUtility::RTCPParserV2::ParseBYEItem()
870{
871 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
872 if (length < 4 || _numberOfBlocks == 0)
873 {
Erik Språng242e22b2015-05-11 10:17:43 +0200874 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000875
876 EndCurrentBlock();
877 return false;
878 }
879
Erik Språng242e22b2015-05-11 10:17:43 +0200880 _packetType = RTCPPacketTypes::kBye;
niklase@google.com470e71d2011-07-07 08:21:25 +0000881
882 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
883 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
884 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
885 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
886
887 // we can have several CSRCs attached
888
889 // sanity
890 if(length >= 4*_numberOfBlocks)
891 {
892 _ptrRTCPData += (_numberOfBlocks -1)*4;
893 }
894 _numberOfBlocks = 0;
895
896 return true;
897}
898/*
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000899 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +0000900 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
901 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
902 |V=2|P|reserved | PT=XR=207 | length |
903 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
904 | SSRC |
905 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
906 : report blocks :
907 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
908*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000909bool RTCPUtility::RTCPParserV2::ParseXr()
niklase@google.com470e71d2011-07-07 08:21:25 +0000910{
911 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000912 if (length < 8)
913 {
914 EndCurrentBlock();
915 return false;
916 }
917
918 _ptrRTCPData += 4; // Skip header
919
920 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
921 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
922 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
923 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
924
Erik Språng242e22b2015-05-11 10:17:43 +0200925 _packetType = RTCPPacketTypes::kXrHeader;
926 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000927 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000929
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000930/* Extended report block format (RFC 3611).
931 BT: block type.
932 block length: length of report block in 32-bits words minus one (including
933 the header).
niklase@google.com470e71d2011-07-07 08:21:25 +0000934 0 1 2 3
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000935 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 +0000936 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
937 | BT | type-specific | block length |
938 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
939 : type-specific block contents :
940 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
941*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000942bool RTCPUtility::RTCPParserV2::ParseXrItem() {
943 const int kBlockHeaderLengthInBytes = 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000944 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000945 if (length < kBlockHeaderLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200946 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000947 EndCurrentBlock();
948 return false;
949 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000950
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000951 uint8_t block_type = *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000952 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000953
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000954 uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
955 block_length_in_4bytes += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000956
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000957 switch (block_type) {
958 case kBtReceiverReferenceTime:
959 return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
960 case kBtDlrr:
961 return ParseXrDlrr(block_length_in_4bytes);
962 case kBtVoipMetric:
963 return ParseXrVoipMetricItem(block_length_in_4bytes);
964 default:
965 return ParseXrUnsupportedBlockType(block_length_in_4bytes);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000966 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000967}
968
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000969/* Receiver Reference Time Report Block.
970 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000971 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
972 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
973 | BT=4 | reserved | block length = 2 |
974 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
975 | NTP timestamp, most significant word |
976 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
977 | NTP timestamp, least significant word |
978 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
979*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000980bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
981 int block_length_4bytes) {
982 const int kBlockLengthIn4Bytes = 2;
983 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000984 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000985 if (block_length_4bytes != kBlockLengthIn4Bytes ||
986 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200987 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000988 EndCurrentBlock();
989 return false;
990 }
991
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000992 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
993 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
994 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
995 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000996
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000997 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
998 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
999 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
1000 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001001
Erik Språng242e22b2015-05-11 10:17:43 +02001002 _packetType = RTCPPacketTypes::kXrReceiverReferenceTime;
1003 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001004 return true;
1005}
1006
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001007/* DLRR Report Block.
1008 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001009 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
1010 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1011 | BT=5 | reserved | block length |
1012 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1013 | SSRC_1 (SSRC of first receiver) | sub-
1014 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1015 | last RR (LRR) | 1
1016 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1017 | delay since last RR (DLRR) |
1018 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1019 | SSRC_2 (SSRC of second receiver) | sub-
1020 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1021 : ... : 2
1022 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1023*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001024bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
1025 const int kSubBlockLengthIn4Bytes = 3;
1026 if (block_length_4bytes < 0 ||
1027 (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001028 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001029 EndCurrentBlock();
1030 return false;
1031 }
Erik Språng242e22b2015-05-11 10:17:43 +02001032 _packetType = RTCPPacketTypes::kXrDlrrReportBlock;
1033 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001034 _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
1035 return true;
1036}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001037
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001038bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001039 if (_numberOfBlocks == 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001040 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001041 return false;
1042 }
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001043 const int kSubBlockLengthInBytes = 12;
1044 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1045 if (length < kSubBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001046 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001047 EndCurrentBlock();
1048 return false;
1049 }
1050
1051 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1052 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1053 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1054 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1055
1056 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1057 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1058 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1059 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1060
1061 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1062 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1063 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1064 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1065
Erik Språng242e22b2015-05-11 10:17:43 +02001066 _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001067 --_numberOfBlocks;
Erik Språng242e22b2015-05-11 10:17:43 +02001068 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001069 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001070}
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001071/* VoIP Metrics Report Block.
1072 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +00001073 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
1074 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1075 | BT=7 | reserved | block length = 8 |
1076 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1077 | SSRC of source |
1078 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1079 | loss rate | discard rate | burst density | gap density |
1080 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1081 | burst duration | gap duration |
1082 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1083 | round trip delay | end system delay |
1084 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1085 | signal level | noise level | RERL | Gmin |
1086 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1087 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1088 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1089 | RX config | reserved | JB nominal |
1090 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1091 | JB maximum | JB abs max |
1092 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1093*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001094
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001095bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
1096 const int kBlockLengthIn4Bytes = 8;
1097 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
1098 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1099 if (block_length_4bytes != kBlockLengthIn4Bytes ||
1100 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001101 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001102 EndCurrentBlock();
1103 return false;
1104 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001105
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001106 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1107 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1108 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1109 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001110
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001111 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1112 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1113 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1114 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001115
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001116 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1117 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001118
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001119 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1120 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001122 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1123 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001124
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001125 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1126 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001127
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001128 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1129 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1130 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1131 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1132 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1133 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1134 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1135 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1136 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1137 _ptrRTCPData++; // skip reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001138
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001139 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1140 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001141
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001142 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1143 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001144
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001145 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1146 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001147
Erik Språng242e22b2015-05-11 10:17:43 +02001148 _packetType = RTCPPacketTypes::kXrVoipMetric;
1149 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001150 return true;
1151}
niklase@google.com470e71d2011-07-07 08:21:25 +00001152
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001153bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
1154 int block_length_4bytes) {
1155 const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
1156 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1157 if (length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001158 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001159 EndCurrentBlock();
1160 return false;
1161 }
1162 // Skip block.
1163 _ptrRTCPData += kBlockLengthInBytes;
Erik Språng242e22b2015-05-11 10:17:43 +02001164 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001165 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001166}
1167
sprang73a93e82015-09-14 12:50:39 -07001168bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001169 RTC_CHECK((header.packet_type == PT_RTPFB) ||
1170 (header.packet_type == PT_PSFB)); // Parser logic check
niklase@google.com470e71d2011-07-07 08:21:25 +00001171
1172 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1173
Erik Språng6b8d3552015-09-24 15:06:57 +02001174 // 4 * 3, RFC4585 section 6.1
1175 if (length < 12) {
1176 LOG(LS_WARNING)
1177 << "Invalid RTCP packet: Too little data (" << length
1178 << " bytes) left in buffer to parse a 12 byte RTPFB/PSFB message.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001179 return false;
1180 }
1181
1182 _ptrRTCPData += 4; // Skip RTCP header
1183
Erik Språng6b8d3552015-09-24 15:06:57 +02001184 uint32_t senderSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1185 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001186
Erik Språng6b8d3552015-09-24 15:06:57 +02001187 uint32_t mediaSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1188 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001189
sprang73a93e82015-09-14 12:50:39 -07001190 if (header.packet_type == PT_RTPFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001191 // Transport layer feedback
1192
sprang73a93e82015-09-14 12:50:39 -07001193 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001194 case 1:
1195 {
1196 // NACK
Erik Språng242e22b2015-05-11 10:17:43 +02001197 _packetType = RTCPPacketTypes::kRtpfbNack;
niklase@google.com470e71d2011-07-07 08:21:25 +00001198 _packet.NACK.SenderSSRC = senderSSRC;
1199 _packet.NACK.MediaSSRC = mediaSSRC;
1200
Erik Språng242e22b2015-05-11 10:17:43 +02001201 _state = ParseState::State_RTPFB_NACKItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001202
1203 return true;
1204 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001205 case 3:
1206 {
1207 // TMMBR
Erik Språng242e22b2015-05-11 10:17:43 +02001208 _packetType = RTCPPacketTypes::kRtpfbTmmbr;
niklase@google.com470e71d2011-07-07 08:21:25 +00001209 _packet.TMMBR.SenderSSRC = senderSSRC;
1210 _packet.TMMBR.MediaSSRC = mediaSSRC;
1211
Erik Språng242e22b2015-05-11 10:17:43 +02001212 _state = ParseState::State_RTPFB_TMMBRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001213
1214 return true;
1215 }
1216 case 4:
1217 {
1218 // TMMBN
Erik Språng242e22b2015-05-11 10:17:43 +02001219 _packetType = RTCPPacketTypes::kRtpfbTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 _packet.TMMBN.SenderSSRC = senderSSRC;
1221 _packet.TMMBN.MediaSSRC = mediaSSRC;
1222
Erik Språng242e22b2015-05-11 10:17:43 +02001223 _state = ParseState::State_RTPFB_TMMBNItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001224
1225 return true;
1226 }
1227 case 5:
1228 {
1229 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1230 // draft-perkins-avt-rapid-rtp-sync-03.txt
1231 // trigger a new RTCP SR
Erik Språng242e22b2015-05-11 10:17:43 +02001232 _packetType = RTCPPacketTypes::kRtpfbSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +00001233
1234 // Note: No state transition, SR REQ is empty!
1235 return true;
1236 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001237 case 15: {
1238 _packetType = RTCPPacketTypes::kTransportFeedback;
1239 rtcp_packet_ =
1240 rtcp::TransportFeedback::ParseFrom(_ptrRTCPData - 12, length);
1241 // Since we parse the whole packet here, keep the TopLevel state and
1242 // just end the current block.
1243 if (rtcp_packet_.get()) {
1244 EndCurrentBlock();
1245 return true;
1246 }
1247 break;
1248 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001249 default:
1250 break;
1251 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001252 // Unsupported RTPFB message. Skip and move to next block.
1253 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001254 return false;
sprang73a93e82015-09-14 12:50:39 -07001255 } else if (header.packet_type == PT_PSFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001256 // Payload specific feedback
sprang73a93e82015-09-14 12:50:39 -07001257 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001258 case 1:
1259 // PLI
Erik Språng242e22b2015-05-11 10:17:43 +02001260 _packetType = RTCPPacketTypes::kPsfbPli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001261 _packet.PLI.SenderSSRC = senderSSRC;
1262 _packet.PLI.MediaSSRC = mediaSSRC;
1263
1264 // Note: No state transition, PLI FCI is empty!
1265 return true;
1266 case 2:
1267 // SLI
Erik Språng242e22b2015-05-11 10:17:43 +02001268 _packetType = RTCPPacketTypes::kPsfbSli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001269 _packet.SLI.SenderSSRC = senderSSRC;
1270 _packet.SLI.MediaSSRC = mediaSSRC;
1271
Erik Språng242e22b2015-05-11 10:17:43 +02001272 _state = ParseState::State_PSFB_SLIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001273
1274 return true;
1275 case 3:
Erik Språng242e22b2015-05-11 10:17:43 +02001276 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001277 _packet.RPSI.SenderSSRC = senderSSRC;
1278 _packet.RPSI.MediaSSRC = mediaSSRC;
1279
Erik Språng242e22b2015-05-11 10:17:43 +02001280 _state = ParseState::State_PSFB_RPSIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001281 return true;
1282 case 4:
1283 // FIR
Erik Språng242e22b2015-05-11 10:17:43 +02001284 _packetType = RTCPPacketTypes::kPsfbFir;
niklase@google.com470e71d2011-07-07 08:21:25 +00001285 _packet.FIR.SenderSSRC = senderSSRC;
1286 _packet.FIR.MediaSSRC = mediaSSRC;
1287
Erik Språng242e22b2015-05-11 10:17:43 +02001288 _state = ParseState::State_PSFB_FIRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001289 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001290 case 15:
Erik Språng242e22b2015-05-11 10:17:43 +02001291 _packetType = RTCPPacketTypes::kPsfbApp;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001292 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1293 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001294
Erik Språng242e22b2015-05-11 10:17:43 +02001295 _state = ParseState::State_PSFB_AppItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001296 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001297 default:
1298 break;
1299 }
1300
niklase@google.com470e71d2011-07-07 08:21:25 +00001301 return false;
1302 }
1303 else
1304 {
Erik Språng6b8d3552015-09-24 15:06:57 +02001305 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +00001306 return false;
1307 }
1308}
1309
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001310bool RTCPUtility::RTCPParserV2::ParseRPSIItem() {
1311
1312 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI).
1313 //
1314 // 0 1 2 3
1315 // 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
1316 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1317 // | PB |0| Payload Type| Native RPSI bit string |
1318 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1319 // | defined per codec ... | Padding (0) |
1320 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
niklase@google.com470e71d2011-07-07 08:21:25 +00001321
1322 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1323
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001324 if (length < 4) {
Erik Språng242e22b2015-05-11 10:17:43 +02001325 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001326
1327 EndCurrentBlock();
1328 return false;
1329 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001330 if (length > 2 + RTCP_RPSI_DATA_SIZE) {
Erik Språng242e22b2015-05-11 10:17:43 +02001331 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001332
1333 EndCurrentBlock();
1334 return false;
1335 }
1336
Erik Språng242e22b2015-05-11 10:17:43 +02001337 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001338
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001339 uint8_t padding_bits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001340 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1341
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001342 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
1343 _ptrRTCPData += length - 2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001344
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001345 _packet.RPSI.NumberOfValidBits =
1346 static_cast<uint16_t>(length - 2) * 8 - padding_bits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001347 return true;
1348}
1349
1350bool
1351RTCPUtility::RTCPParserV2::ParseNACKItem()
1352{
1353 // RFC 4585 6.2.1. Generic NACK
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;
niklase@google.com470e71d2011-07-07 08:21:25 +00001360
1361 EndCurrentBlock();
1362 return false;
1363 }
1364
Erik Språng242e22b2015-05-11 10:17:43 +02001365 _packetType = RTCPPacketTypes::kRtpfbNackItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001366
1367 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1368 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1369
1370 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1371 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1372
1373 return true;
1374}
1375
1376bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001377RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1378{
1379 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1380
1381 if (length < 4)
1382 {
Erik Språng242e22b2015-05-11 10:17:43 +02001383 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001384
1385 EndCurrentBlock();
1386 return false;
1387 }
1388 if(*_ptrRTCPData++ != 'R')
1389 {
Erik Språng242e22b2015-05-11 10:17:43 +02001390 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001391
1392 EndCurrentBlock();
1393 return false;
1394 }
1395 if(*_ptrRTCPData++ != 'E')
1396 {
Erik Språng242e22b2015-05-11 10:17:43 +02001397 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001398
1399 EndCurrentBlock();
1400 return false;
1401 }
1402 if(*_ptrRTCPData++ != 'M')
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 if(*_ptrRTCPData++ != 'B')
1410 {
Erik Språng242e22b2015-05-11 10:17:43 +02001411 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001412
1413 EndCurrentBlock();
1414 return false;
1415 }
Erik Språng242e22b2015-05-11 10:17:43 +02001416 _packetType = RTCPPacketTypes::kPsfbRemb;
1417 _state = ParseState::State_PSFB_REMBItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001418 return true;
1419}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001420
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001421bool
1422RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1423{
1424 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1425
1426 if (length < 4)
1427 {
Erik Språng242e22b2015-05-11 10:17:43 +02001428 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001429
1430 EndCurrentBlock();
1431 return false;
1432 }
1433
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001434 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001435 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001436
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001437 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001438 brMantissa += (_ptrRTCPData[1] << 8);
1439 brMantissa += (_ptrRTCPData[2]);
1440
1441 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001442 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001443
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001444 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1445 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1446 {
Erik Språng242e22b2015-05-11 10:17:43 +02001447 _state = ParseState::State_TopLevel;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001448
1449 EndCurrentBlock();
1450 return false;
1451 }
1452
Erik Språng242e22b2015-05-11 10:17:43 +02001453 _packetType = RTCPPacketTypes::kPsfbRembItem;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001454
1455 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1456 {
1457 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1458 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1459 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1460 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1461 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001462 return true;
1463}
1464
1465bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001466RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1467{
1468 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1469
1470 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1471
1472 if (length < 8)
1473 {
Erik Språng242e22b2015-05-11 10:17:43 +02001474 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001475
1476 EndCurrentBlock();
1477 return false;
1478 }
1479
Erik Språng242e22b2015-05-11 10:17:43 +02001480 _packetType = RTCPPacketTypes::kRtpfbTmmbrItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001481
1482 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1483 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1484 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1485 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1486
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001487 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001488
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001489 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001490 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1491 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1492
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001493 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001494 measuredOH += _ptrRTCPData[3];
1495
1496 _ptrRTCPData += 4; // Fwd read data
1497
1498 _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1499 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1500
1501 return true;
1502}
1503
1504bool
1505RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1506{
1507 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1508
1509 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1510
1511 if (length < 8)
1512 {
Erik Språng242e22b2015-05-11 10:17:43 +02001513 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001514
1515 EndCurrentBlock();
1516 return false;
1517 }
1518
Erik Språng242e22b2015-05-11 10:17:43 +02001519 _packetType = RTCPPacketTypes::kRtpfbTmmbnItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001520
1521 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1522 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1523 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1524 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1525
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001526 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001527
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001528 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001529 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1530 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1531
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001532 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001533 measuredOH += _ptrRTCPData[3];
1534
1535 _ptrRTCPData += 4; // Fwd read data
1536
1537 _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1538 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1539
1540 return true;
1541}
1542
1543bool
1544RTCPUtility::RTCPParserV2::ParseSLIItem()
1545{
1546 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1547 /*
1548 0 1 2 3
1549 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
1550 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1551 | First | Number | PictureID |
1552 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1553 */
1554
1555 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1556
1557 if (length < 4)
1558 {
Erik Språng242e22b2015-05-11 10:17:43 +02001559 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001560
1561 EndCurrentBlock();
1562 return false;
1563 }
Erik Språng242e22b2015-05-11 10:17:43 +02001564 _packetType = RTCPPacketTypes::kPsfbSliItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001565
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001566 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001567 buffer = *_ptrRTCPData++ << 24;
1568 buffer += *_ptrRTCPData++ << 16;
1569 buffer += *_ptrRTCPData++ << 8;
1570 buffer += *_ptrRTCPData++;
1571
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001572 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1573 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1574 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001575
1576 return true;
1577}
1578
1579bool
1580RTCPUtility::RTCPParserV2::ParseFIRItem()
1581{
1582 // RFC 5104 4.3.1. Full Intra Request (FIR)
1583
1584 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1585
1586 if (length < 8)
1587 {
Erik Språng242e22b2015-05-11 10:17:43 +02001588 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001589
1590 EndCurrentBlock();
1591 return false;
1592 }
1593
Erik Språng242e22b2015-05-11 10:17:43 +02001594 _packetType = RTCPPacketTypes::kPsfbFirItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001595
1596 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1597 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1598 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1599 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1600
1601 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1602 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1603 return true;
1604}
1605
sprang73a93e82015-09-14 12:50:39 -07001606bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001607 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1608
1609 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1610 {
1611 EndCurrentBlock();
1612 return false;
1613 }
1614
1615 _ptrRTCPData += 4; // Skip RTCP header
1616
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001617 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001618 senderSSRC += *_ptrRTCPData++ << 16;
1619 senderSSRC += *_ptrRTCPData++ << 8;
1620 senderSSRC += *_ptrRTCPData++;
1621
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001622 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001623 name += *_ptrRTCPData++ << 16;
1624 name += *_ptrRTCPData++ << 8;
1625 name += *_ptrRTCPData++;
1626
1627 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1628
Erik Språng242e22b2015-05-11 10:17:43 +02001629 _packetType = RTCPPacketTypes::kApp;
niklase@google.com470e71d2011-07-07 08:21:25 +00001630
sprang73a93e82015-09-14 12:50:39 -07001631 _packet.APP.SubType = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +00001632 _packet.APP.Name = name;
1633
Erik Språng242e22b2015-05-11 10:17:43 +02001634 _state = ParseState::State_AppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001635 return true;
1636}
1637
1638bool
1639RTCPUtility::RTCPParserV2::ParseAPPItem()
1640{
1641 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1642 if (length < 4)
1643 {
Erik Språng242e22b2015-05-11 10:17:43 +02001644 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001645
1646 EndCurrentBlock();
1647 return false;
1648 }
Erik Språng242e22b2015-05-11 10:17:43 +02001649 _packetType = RTCPPacketTypes::kAppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001650
1651 if(length > kRtcpAppCode_DATA_SIZE)
1652 {
1653 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1654 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1655 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1656 }else
1657 {
1658 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001659 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001660 _ptrRTCPData += length;
1661 }
1662 return true;
1663}
1664
Erik Språng6b8d3552015-09-24 15:06:57 +02001665size_t RTCPUtility::RTCPParserV2::NumSkippedBlocks() const {
1666 return num_skipped_blocks_;
1667}
1668
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001669RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001670 size_t rtcpDataLength)
1671 : _ptrBegin(rtcpData),
1672 _ptrEnd(rtcpData + rtcpDataLength),
1673 _ptrBlock(NULL) {
1674 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001675}
1676
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001677RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001678}
1679
sprang73a93e82015-09-14 12:50:39 -07001680const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001681 _ptrBlock = _ptrBegin;
1682
1683 return Iterate();
1684}
1685
sprang73a93e82015-09-14 12:50:39 -07001686const RTCPUtility::RtcpCommonHeader*
1687RTCPUtility::RTCPPacketIterator::Iterate() {
1688 if ((_ptrEnd <= _ptrBlock) ||
1689 !RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) {
1690 _ptrBlock = nullptr;
1691 return nullptr;
1692 }
1693 _ptrBlock += _header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +00001694
sprang73a93e82015-09-14 12:50:39 -07001695 if (_ptrBlock > _ptrEnd) {
1696 _ptrBlock = nullptr;
1697 return nullptr;
1698 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001699
sprang73a93e82015-09-14 12:50:39 -07001700 return &_header;
niklase@google.com470e71d2011-07-07 08:21:25 +00001701}
1702
sprang73a93e82015-09-14 12:50:39 -07001703const RTCPUtility::RtcpCommonHeader*
1704RTCPUtility::RTCPPacketIterator::Current() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001705 if (!_ptrBlock)
1706 {
1707 return NULL;
1708 }
1709
1710 return &_header;
1711}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001712} // namespace webrtc