blob: c4f688aac44f7ac0771fcc3ce7494a997fa06399 [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
Danil Chapovalovee6e4272016-04-19 12:15:10 +020017#include <limits>
18
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"
danilchapb8b6fbb2015-12-10 05:05:27 -080022#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
sprang73a93e82015-09-14 12:50:39 -070023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
Danil Chapovalovee6e4272016-04-19 12:15:10 +020025namespace {
26constexpr uint64_t kMaxBitrateBps = std::numeric_limits<uint32_t>::max();
27} // namespace
niklase@google.com470e71d2011-07-07 08:21:25 +000028
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000029namespace RTCPUtility {
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +000030
31NackStats::NackStats()
32 : max_sequence_number_(0),
33 requests_(0),
34 unique_requests_(0) {}
35
36NackStats::~NackStats() {}
37
38void NackStats::ReportRequest(uint16_t sequence_number) {
39 if (requests_ == 0 ||
40 webrtc::IsNewerSequenceNumber(sequence_number, max_sequence_number_)) {
41 max_sequence_number_ = sequence_number;
42 ++unique_requests_;
43 }
44 ++requests_;
45}
46
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000047uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) {
48 return (ntp_sec << 16) + (ntp_frac >> 16);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000049}
danilchap6a6f0892015-12-10 12:39:08 -080050} // namespace RTCPUtility
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000051
52// RTCPParserV2 : currently read only
pbos@webrtc.org2f446732013-04-08 11:08:41 +000053RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
niklase@google.com470e71d2011-07-07 08:21:25 +000054 size_t rtcpDataLength,
55 bool rtcpReducedSizeEnable)
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000056 : _ptrRTCPDataBegin(rtcpData),
57 _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
58 _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
59 _validPacket(false),
60 _ptrRTCPData(rtcpData),
61 _ptrRTCPBlockEnd(NULL),
Erik Språng242e22b2015-05-11 10:17:43 +020062 _state(ParseState::State_TopLevel),
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000063 _numberOfBlocks(0),
Erik Språng6b8d3552015-09-24 15:06:57 +020064 num_skipped_blocks_(0),
Erik Språng242e22b2015-05-11 10:17:43 +020065 _packetType(RTCPPacketTypes::kInvalid) {
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000066 Validate();
niklase@google.com470e71d2011-07-07 08:21:25 +000067}
68
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000069RTCPUtility::RTCPParserV2::~RTCPParserV2() {
niklase@google.com470e71d2011-07-07 08:21:25 +000070}
71
72ptrdiff_t
73RTCPUtility::RTCPParserV2::LengthLeft() const
74{
75 return (_ptrRTCPDataEnd- _ptrRTCPData);
76}
77
78RTCPUtility::RTCPPacketTypes
79RTCPUtility::RTCPParserV2::PacketType() const
80{
81 return _packetType;
82}
83
84const RTCPUtility::RTCPPacket&
85RTCPUtility::RTCPParserV2::Packet() const
86{
87 return _packet;
88}
89
Erik Språng6b8d3552015-09-24 15:06:57 +020090rtcp::RtcpPacket* RTCPUtility::RTCPParserV2::ReleaseRtcpPacket() {
91 return rtcp_packet_.release();
92}
niklase@google.com470e71d2011-07-07 08:21:25 +000093RTCPUtility::RTCPPacketTypes
94RTCPUtility::RTCPParserV2::Begin()
95{
96 _ptrRTCPData = _ptrRTCPDataBegin;
97
98 return Iterate();
99}
100
101RTCPUtility::RTCPPacketTypes
102RTCPUtility::RTCPParserV2::Iterate()
103{
104 // Reset packet type
Erik Språng242e22b2015-05-11 10:17:43 +0200105 _packetType = RTCPPacketTypes::kInvalid;
niklase@google.com470e71d2011-07-07 08:21:25 +0000106
107 if (IsValid())
108 {
109 switch (_state)
110 {
Erik Språng242e22b2015-05-11 10:17:43 +0200111 case ParseState::State_TopLevel:
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 IterateTopLevel();
113 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200114 case ParseState::State_ReportBlockItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 IterateReportBlockItem();
116 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200117 case ParseState::State_SDESChunk:
niklase@google.com470e71d2011-07-07 08:21:25 +0000118 IterateSDESChunk();
119 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200120 case ParseState::State_BYEItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 IterateBYEItem();
122 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200123 case ParseState::State_ExtendedJitterItem:
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000124 IterateExtendedJitterItem();
125 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200126 case ParseState::State_RTPFB_NACKItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 IterateNACKItem();
128 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200129 case ParseState::State_RTPFB_TMMBRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000130 IterateTMMBRItem();
131 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200132 case ParseState::State_RTPFB_TMMBNItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000133 IterateTMMBNItem();
134 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200135 case ParseState::State_PSFB_SLIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 IterateSLIItem();
137 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200138 case ParseState::State_PSFB_RPSIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 IterateRPSIItem();
140 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200141 case ParseState::State_PSFB_FIRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000142 IterateFIRItem();
143 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200144 case ParseState::State_PSFB_AppItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000145 IteratePsfbAppItem();
146 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200147 case ParseState::State_PSFB_REMBItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000148 IteratePsfbREMBItem();
149 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200150 case ParseState::State_XRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000151 IterateXrItem();
152 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200153 case ParseState::State_XR_DLLRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000154 IterateXrDlrrItem();
155 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200156 case ParseState::State_AppItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 IterateAppItem();
158 break;
159 default:
Erik Språng6b8d3552015-09-24 15:06:57 +0200160 RTC_NOTREACHED() << "Invalid state!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000161 break;
162 }
163 }
164 return _packetType;
165}
166
167void
168RTCPUtility::RTCPParserV2::IterateTopLevel()
169{
170 for (;;)
171 {
sprang73a93e82015-09-14 12:50:39 -0700172 RtcpCommonHeader header;
173 if (_ptrRTCPDataEnd <= _ptrRTCPData)
174 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000175
sprang73a93e82015-09-14 12:50:39 -0700176 if (!RtcpParseCommonHeader(_ptrRTCPData, _ptrRTCPDataEnd - _ptrRTCPData,
177 &header)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 return;
179 }
sprang73a93e82015-09-14 12:50:39 -0700180 _ptrRTCPBlockEnd = _ptrRTCPData + header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +0000181 if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
182 {
Erik Språng6b8d3552015-09-24 15:06:57 +0200183 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000184 return;
185 }
186
sprang73a93e82015-09-14 12:50:39 -0700187 switch (header.packet_type) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 case PT_SR:
189 {
190 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700191 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000192 ParseSR();
193 return;
194 }
195 case PT_RR:
196 {
197 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700198 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199 ParseRR();
200 return;
201 }
202 case PT_SDES:
203 {
204 // number of SDES blocks
sprang73a93e82015-09-14 12:50:39 -0700205 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000206 const bool ok = ParseSDES();
207 if (!ok)
208 {
209 // Nothing supported found, continue to next block!
210 break;
211 }
212 return;
213 }
214 case PT_BYE:
215 {
sprang73a93e82015-09-14 12:50:39 -0700216 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217 const bool ok = ParseBYE();
218 if (!ok)
219 {
220 // Nothing supported found, continue to next block!
221 break;
222 }
223 return;
224 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000225 case PT_IJ:
226 {
227 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700228 _numberOfBlocks = header.count_or_format;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000229 ParseIJ();
230 return;
231 }
Erik Språng6b8d3552015-09-24 15:06:57 +0200232 case PT_RTPFB:
233 FALLTHROUGH();
niklase@google.com470e71d2011-07-07 08:21:25 +0000234 case PT_PSFB:
235 {
Erik Språng6b8d3552015-09-24 15:06:57 +0200236 if (!ParseFBCommon(header)) {
237 // Nothing supported found, continue to next block!
danilchap50da1d32016-03-10 13:13:52 -0800238 EndCurrentBlock();
Erik Språng6b8d3552015-09-24 15:06:57 +0200239 break;
240 }
241 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000242 }
243 case PT_APP:
244 {
245 const bool ok = ParseAPP(header);
246 if (!ok)
247 {
248 // Nothing supported found, continue to next block!
249 break;
250 }
251 return;
252 }
253 case PT_XR:
254 {
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000255 const bool ok = ParseXr();
niklase@google.com470e71d2011-07-07 08:21:25 +0000256 if (!ok)
257 {
258 // Nothing supported found, continue to next block!
259 break;
260 }
261 return;
262 }
263 default:
264 // Not supported! Skip!
Erik Språng6b8d3552015-09-24 15:06:57 +0200265 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000266 EndCurrentBlock();
267 break;
268 }
269 }
270}
271
272void
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000273RTCPUtility::RTCPParserV2::IterateXrItem()
274{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000275 const bool success = ParseXrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000276 if (!success)
277 {
278 Iterate();
279 }
280}
281
282void
283RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
284{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000285 const bool success = ParseXrDlrrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000286 if (!success)
287 {
288 Iterate();
289 }
290}
291
292void
niklase@google.com470e71d2011-07-07 08:21:25 +0000293RTCPUtility::RTCPParserV2::IterateReportBlockItem()
294{
295 const bool success = ParseReportBlockItem();
296 if (!success)
297 {
298 Iterate();
299 }
300}
301
302void
303RTCPUtility::RTCPParserV2::IterateSDESChunk()
304{
305 const bool success = ParseSDESChunk();
306 if (!success)
307 {
308 Iterate();
309 }
310}
311
312void
313RTCPUtility::RTCPParserV2::IterateBYEItem()
314{
315 const bool success = ParseBYEItem();
316 if (!success)
317 {
318 Iterate();
319 }
320}
321
322void
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000323RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
324{
325 const bool success = ParseIJItem();
326 if (!success)
327 {
328 Iterate();
329 }
330}
331
332void
niklase@google.com470e71d2011-07-07 08:21:25 +0000333RTCPUtility::RTCPParserV2::IterateNACKItem()
334{
335 const bool success = ParseNACKItem();
336 if (!success)
337 {
338 Iterate();
339 }
340}
341
342void
343RTCPUtility::RTCPParserV2::IterateTMMBRItem()
344{
345 const bool success = ParseTMMBRItem();
346 if (!success)
347 {
348 Iterate();
349 }
350}
351
352void
353RTCPUtility::RTCPParserV2::IterateTMMBNItem()
354{
355 const bool success = ParseTMMBNItem();
356 if (!success)
357 {
358 Iterate();
359 }
360}
361
362void
363RTCPUtility::RTCPParserV2::IterateSLIItem()
364{
365 const bool success = ParseSLIItem();
366 if (!success)
367 {
368 Iterate();
369 }
370}
371
372void
373RTCPUtility::RTCPParserV2::IterateRPSIItem()
374{
375 const bool success = ParseRPSIItem();
376 if (!success)
377 {
378 Iterate();
379 }
380}
381
382void
383RTCPUtility::RTCPParserV2::IterateFIRItem()
384{
385 const bool success = ParseFIRItem();
386 if (!success)
387 {
388 Iterate();
389 }
390}
391
392void
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000393RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
394{
395 const bool success = ParsePsfbAppItem();
396 if (!success)
397 {
398 Iterate();
399 }
400}
401
402void
403RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
404{
405 const bool success = ParsePsfbREMBItem();
406 if (!success)
407 {
408 Iterate();
409 }
410}
411
412void
niklase@google.com470e71d2011-07-07 08:21:25 +0000413RTCPUtility::RTCPParserV2::IterateAppItem()
414{
415 const bool success = ParseAPPItem();
416 if (!success)
417 {
418 Iterate();
419 }
420}
421
422void
423RTCPUtility::RTCPParserV2::Validate()
424{
sprang73a93e82015-09-14 12:50:39 -0700425 if (_ptrRTCPData == nullptr)
426 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
sprang73a93e82015-09-14 12:50:39 -0700428 RtcpCommonHeader header;
429 if (_ptrRTCPDataEnd <= _ptrRTCPDataBegin)
430 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000431
sprang73a93e82015-09-14 12:50:39 -0700432 if (!RtcpParseCommonHeader(_ptrRTCPDataBegin,
433 _ptrRTCPDataEnd - _ptrRTCPDataBegin, &header))
434 return; // NOT VALID!
niklase@google.com470e71d2011-07-07 08:21:25 +0000435
436 // * if (!reducedSize) : first packet must be RR or SR.
437 //
438 // * The padding bit (P) should be zero for the first packet of a
439 // compound RTCP packet because padding should only be applied,
440 // if it is needed, to the last packet. (NOT CHECKED!)
441 //
442 // * The length fields of the individual RTCP packets must add up
443 // to the overall length of the compound RTCP packet as
444 // received. This is a fairly strong check. (NOT CHECKED!)
445
446 if (!_RTCPReducedSizeEnable)
447 {
sprang73a93e82015-09-14 12:50:39 -0700448 if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000449 return; // NOT VALID
450 }
451 }
452
453 _validPacket = true;
454}
455
456bool
457RTCPUtility::RTCPParserV2::IsValid() const
458{
459 return _validPacket;
460}
461
462void
463RTCPUtility::RTCPParserV2::EndCurrentBlock()
464{
465 _ptrRTCPData = _ptrRTCPBlockEnd;
466}
467
sprang73a93e82015-09-14 12:50:39 -0700468// 0 1 2 3
469// 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
470// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
471// |V=2|P| IC | PT | length |
472// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
473//
474// Common header for all RTCP packets, 4 octets.
475
476bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet,
477 size_t size_bytes,
478 RtcpCommonHeader* parsed_header) {
henrikg91d6ede2015-09-17 00:24:34 -0700479 RTC_DCHECK(parsed_header != nullptr);
sprang73a93e82015-09-14 12:50:39 -0700480 if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) {
481 LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte"
482 << (size_bytes != 1 ? "s" : "")
483 << ") remaining in buffer to parse RTCP header (4 bytes).";
484 return false;
485 }
486
487 const uint8_t kRtcpVersion = 2;
488 uint8_t version = packet[0] >> 6;
489 if (version != kRtcpVersion) {
490 LOG(LS_WARNING) << "Invalid RTCP header: Version must be "
491 << static_cast<int>(kRtcpVersion) << " but was "
492 << static_cast<int>(version);
493 return false;
494 }
495
496 bool has_padding = (packet[0] & 0x20) != 0;
497 uint8_t format = packet[0] & 0x1F;
498 uint8_t packet_type = packet[1];
499 size_t packet_size_words =
500 ByteReader<uint16_t>::ReadBigEndian(&packet[2]) + 1;
501
502 if (size_bytes < packet_size_words * 4) {
503 LOG(LS_WARNING) << "Buffer too small (" << size_bytes
504 << " bytes) to fit an RtcpPacket of " << packet_size_words
505 << " 32bit words.";
506 return false;
507 }
508
509 size_t payload_size = packet_size_words * 4;
510 size_t padding_bytes = 0;
511 if (has_padding) {
512 if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) {
513 LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload "
514 "size specified.";
515 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000516 }
517
sprang73a93e82015-09-14 12:50:39 -0700518 padding_bytes = packet[payload_size - 1];
519 if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) {
520 LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
521 << padding_bytes << ") for a packet size of "
522 << payload_size << "bytes.";
523 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000524 }
sprang73a93e82015-09-14 12:50:39 -0700525 payload_size -= padding_bytes;
526 }
527 payload_size -= RtcpCommonHeader::kHeaderSizeBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000528
sprang73a93e82015-09-14 12:50:39 -0700529 parsed_header->version = kRtcpVersion;
530 parsed_header->count_or_format = format;
531 parsed_header->packet_type = packet_type;
532 parsed_header->payload_size_bytes = payload_size;
533 parsed_header->padding_bytes = padding_bytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000534
sprang73a93e82015-09-14 12:50:39 -0700535 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000536}
537
538bool
539RTCPUtility::RTCPParserV2::ParseRR()
540{
541 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
542
543 if (length < 8)
544 {
545 return false;
546 }
547
548
549 _ptrRTCPData += 4; // Skip header
550
Erik Språng242e22b2015-05-11 10:17:43 +0200551 _packetType = RTCPPacketTypes::kRr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000552
553 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
554 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
555 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
556 _packet.RR.SenderSSRC += *_ptrRTCPData++;
557
558 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
559
560 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200561 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000562
563 return true;
564}
565
566bool
567RTCPUtility::RTCPParserV2::ParseSR()
568{
569 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
570
571 if (length < 28)
572 {
573 EndCurrentBlock();
574 return false;
575 }
576
577 _ptrRTCPData += 4; // Skip header
578
Erik Språng242e22b2015-05-11 10:17:43 +0200579 _packetType = RTCPPacketTypes::kSr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000580
581 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
582 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
583 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
584 _packet.SR.SenderSSRC += *_ptrRTCPData++;
585
586 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
587 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
588 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
589 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
590
591 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
592 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
593 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
594 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
595
596 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
597 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
598 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
599 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
600
601 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
602 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
603 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
604 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
605
606 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
607 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
608 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
609 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
610
611 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
612
613 // State transition
614 if(_numberOfBlocks != 0)
615 {
Erik Språng242e22b2015-05-11 10:17:43 +0200616 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617 }else
618 {
619 // don't go to state report block item if 0 report blocks
Erik Språng242e22b2015-05-11 10:17:43 +0200620 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000621 EndCurrentBlock();
622 }
623 return true;
624}
625
626bool
627RTCPUtility::RTCPParserV2::ParseReportBlockItem()
628{
629 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
630
631 if (length < 24 || _numberOfBlocks <= 0)
632 {
Erik Språng242e22b2015-05-11 10:17:43 +0200633 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
635 EndCurrentBlock();
636 return false;
637 }
638 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
639 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
640 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
641 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
642
643 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
644
645 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
646 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
647 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
648
649 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
650 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
651 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
652 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
653
654 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
655 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
656 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
657 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
658
659 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
660 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
661 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
662 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
663
664 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
665 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
666 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
667 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
668
669 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200670 _packetType = RTCPPacketTypes::kReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000671 return true;
672}
673
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000674/* From RFC 5450: Transmission Time Offsets in RTP Streams.
675 0 1 2 3
676 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
677 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
678 hdr |V=2|P| RC | PT=IJ=195 | length |
679 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
680 | inter-arrival jitter |
681 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
682 . .
683 . .
684 . .
685 | inter-arrival jitter |
686 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
687*/
688
689bool
690RTCPUtility::RTCPParserV2::ParseIJ()
691{
692 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
693
694 if (length < 4)
695 {
696 return false;
697 }
698
699 _ptrRTCPData += 4; // Skip header
700
Erik Språng242e22b2015-05-11 10:17:43 +0200701 _packetType = RTCPPacketTypes::kExtendedIj;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000702
703 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200704 _state = ParseState::State_ExtendedJitterItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000705 return true;
706}
707
708bool
709RTCPUtility::RTCPParserV2::ParseIJItem()
710{
711 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
712
713 if (length < 4 || _numberOfBlocks <= 0)
714 {
Erik Språng242e22b2015-05-11 10:17:43 +0200715 _state = ParseState::State_TopLevel;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000716 EndCurrentBlock();
717 return false;
718 }
719
720 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
721 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
722 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
723 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
724
725 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200726 _packetType = RTCPPacketTypes::kExtendedIjItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000727 return true;
728}
729
niklase@google.com470e71d2011-07-07 08:21:25 +0000730bool
731RTCPUtility::RTCPParserV2::ParseSDES()
732{
733 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
734
735 if (length < 8)
736 {
Erik Språng242e22b2015-05-11 10:17:43 +0200737 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000738
739 EndCurrentBlock();
740 return false;
741 }
742 _ptrRTCPData += 4; // Skip header
743
Erik Språng242e22b2015-05-11 10:17:43 +0200744 _state = ParseState::State_SDESChunk;
745 _packetType = RTCPPacketTypes::kSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000746 return true;
747}
748
749bool
750RTCPUtility::RTCPParserV2::ParseSDESChunk()
751{
752 if(_numberOfBlocks <= 0)
753 {
Erik Språng242e22b2015-05-11 10:17:43 +0200754 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000755
756 EndCurrentBlock();
757 return false;
758 }
759 _numberOfBlocks--;
760
761 // Find CName item in a SDES chunk.
762 while (_ptrRTCPData < _ptrRTCPBlockEnd)
763 {
764 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
765 if (dataLen < 4)
766 {
Erik Språng242e22b2015-05-11 10:17:43 +0200767 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
769 EndCurrentBlock();
770 return false;
771 }
772
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000773 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000774 SSRC += *_ptrRTCPData++ << 16;
775 SSRC += *_ptrRTCPData++ << 8;
776 SSRC += *_ptrRTCPData++;
777
778 const bool foundCname = ParseSDESItem();
779 if (foundCname)
780 {
781 _packet.CName.SenderSSRC = SSRC; // Add SSRC
782 return true;
783 }
784 }
Erik Språng242e22b2015-05-11 10:17:43 +0200785 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000786
787 EndCurrentBlock();
788 return false;
789}
790
791bool
792RTCPUtility::RTCPParserV2::ParseSDESItem()
793{
794 // Find CName
795 // Only the CNAME item is mandatory. RFC 3550 page 46
796 bool foundCName = false;
797
798 size_t itemOctetsRead = 0;
799 while (_ptrRTCPData < _ptrRTCPBlockEnd)
800 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000801 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000802 ++itemOctetsRead;
803
804 if (tag == 0)
805 {
806 // End tag! 4 oct aligned
807 while ((itemOctetsRead++ % 4) != 0)
808 {
809 ++_ptrRTCPData;
810 }
811 return foundCName;
812 }
813
814 if (_ptrRTCPData < _ptrRTCPBlockEnd)
815 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000816 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000817 ++itemOctetsRead;
818
819 if (tag == 1)
820 {
821 // CNAME
822
823 // Sanity
824 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
825 {
Erik Språng242e22b2015-05-11 10:17:43 +0200826 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000827
828 EndCurrentBlock();
829 return false;
830 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000831 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000832 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000833 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000834 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000835 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
836 {
837 // Illegal char
Erik Språng242e22b2015-05-11 10:17:43 +0200838 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000839
840 EndCurrentBlock();
841 return false;
842 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000843 _packet.CName.CName[i] = c;
844 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000845 // Make sure we are null terminated.
846 _packet.CName.CName[i] = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200847 _packetType = RTCPPacketTypes::kSdesChunk;
niklase@google.com470e71d2011-07-07 08:21:25 +0000848
849 foundCName = true;
850 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000851 _ptrRTCPData += len;
852 itemOctetsRead += len;
853 }
854 }
855
856 // No end tag found!
Erik Språng242e22b2015-05-11 10:17:43 +0200857 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000858
859 EndCurrentBlock();
860 return false;
861}
862
863bool
864RTCPUtility::RTCPParserV2::ParseBYE()
865{
866 _ptrRTCPData += 4; // Skip header
867
Erik Språng242e22b2015-05-11 10:17:43 +0200868 _state = ParseState::State_BYEItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000869
870 return ParseBYEItem();
871}
872
873bool
874RTCPUtility::RTCPParserV2::ParseBYEItem()
875{
876 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
877 if (length < 4 || _numberOfBlocks == 0)
878 {
Erik Språng242e22b2015-05-11 10:17:43 +0200879 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000880
881 EndCurrentBlock();
882 return false;
883 }
884
Erik Språng242e22b2015-05-11 10:17:43 +0200885 _packetType = RTCPPacketTypes::kBye;
niklase@google.com470e71d2011-07-07 08:21:25 +0000886
887 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
888 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
889 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
890 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
891
892 // we can have several CSRCs attached
893
894 // sanity
895 if(length >= 4*_numberOfBlocks)
896 {
897 _ptrRTCPData += (_numberOfBlocks -1)*4;
898 }
899 _numberOfBlocks = 0;
900
901 return true;
902}
903/*
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000904 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +0000905 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
906 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
907 |V=2|P|reserved | PT=XR=207 | length |
908 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 | SSRC |
910 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911 : report blocks :
912 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000914bool RTCPUtility::RTCPParserV2::ParseXr()
niklase@google.com470e71d2011-07-07 08:21:25 +0000915{
916 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000917 if (length < 8)
918 {
919 EndCurrentBlock();
920 return false;
921 }
922
923 _ptrRTCPData += 4; // Skip header
924
925 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
926 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
927 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
928 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
929
Erik Språng242e22b2015-05-11 10:17:43 +0200930 _packetType = RTCPPacketTypes::kXrHeader;
931 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000932 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000933}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000934
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000935/* Extended report block format (RFC 3611).
936 BT: block type.
937 block length: length of report block in 32-bits words minus one (including
938 the header).
niklase@google.com470e71d2011-07-07 08:21:25 +0000939 0 1 2 3
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000940 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 +0000941 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942 | BT | type-specific | block length |
943 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944 : type-specific block contents :
945 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000947bool RTCPUtility::RTCPParserV2::ParseXrItem() {
948 const int kBlockHeaderLengthInBytes = 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000949 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000950 if (length < kBlockHeaderLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200951 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000952 EndCurrentBlock();
953 return false;
954 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000955
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000956 uint8_t block_type = *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000957 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000958
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000959 uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
960 block_length_in_4bytes += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000961
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000962 switch (block_type) {
963 case kBtReceiverReferenceTime:
964 return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
965 case kBtDlrr:
966 return ParseXrDlrr(block_length_in_4bytes);
967 case kBtVoipMetric:
968 return ParseXrVoipMetricItem(block_length_in_4bytes);
969 default:
970 return ParseXrUnsupportedBlockType(block_length_in_4bytes);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000971 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000972}
973
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000974/* Receiver Reference Time Report Block.
975 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000976 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
977 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
978 | BT=4 | reserved | block length = 2 |
979 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
980 | NTP timestamp, most significant word |
981 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
982 | NTP timestamp, least significant word |
983 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
984*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000985bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
986 int block_length_4bytes) {
987 const int kBlockLengthIn4Bytes = 2;
988 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000989 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000990 if (block_length_4bytes != kBlockLengthIn4Bytes ||
991 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200992 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000993 EndCurrentBlock();
994 return false;
995 }
996
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000997 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
998 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
999 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
1000 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001001
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001002 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
1003 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
1004 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
1005 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001006
Erik Språng242e22b2015-05-11 10:17:43 +02001007 _packetType = RTCPPacketTypes::kXrReceiverReferenceTime;
1008 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001009 return true;
1010}
1011
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001012/* DLRR Report Block.
1013 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001014 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
1015 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1016 | BT=5 | reserved | block length |
1017 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1018 | SSRC_1 (SSRC of first receiver) | sub-
1019 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1020 | last RR (LRR) | 1
1021 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1022 | delay since last RR (DLRR) |
1023 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1024 | SSRC_2 (SSRC of second receiver) | sub-
1025 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1026 : ... : 2
1027 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1028*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001029bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
1030 const int kSubBlockLengthIn4Bytes = 3;
1031 if (block_length_4bytes < 0 ||
1032 (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001033 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001034 EndCurrentBlock();
1035 return false;
1036 }
Erik Språng242e22b2015-05-11 10:17:43 +02001037 _packetType = RTCPPacketTypes::kXrDlrrReportBlock;
1038 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001039 _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
1040 return true;
1041}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001042
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001043bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001044 if (_numberOfBlocks == 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001045 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001046 return false;
1047 }
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001048 const int kSubBlockLengthInBytes = 12;
1049 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1050 if (length < kSubBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001051 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001052 EndCurrentBlock();
1053 return false;
1054 }
1055
1056 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1057 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1058 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1059 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1060
1061 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1062 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1063 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1064 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1065
1066 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1067 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1068 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1069 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1070
Erik Språng242e22b2015-05-11 10:17:43 +02001071 _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001072 --_numberOfBlocks;
Erik Språng242e22b2015-05-11 10:17:43 +02001073 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001074 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001075}
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001076/* VoIP Metrics Report Block.
1077 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +00001078 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
1079 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1080 | BT=7 | reserved | block length = 8 |
1081 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1082 | SSRC of source |
1083 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1084 | loss rate | discard rate | burst density | gap density |
1085 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1086 | burst duration | gap duration |
1087 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1088 | round trip delay | end system delay |
1089 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1090 | signal level | noise level | RERL | Gmin |
1091 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1092 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1093 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1094 | RX config | reserved | JB nominal |
1095 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1096 | JB maximum | JB abs max |
1097 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1098*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001099
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001100bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
1101 const int kBlockLengthIn4Bytes = 8;
1102 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
1103 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1104 if (block_length_4bytes != kBlockLengthIn4Bytes ||
1105 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001106 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001107 EndCurrentBlock();
1108 return false;
1109 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001110
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001111 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1112 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1113 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1114 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001115
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001116 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1117 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1118 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1119 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001120
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001121 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1122 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001123
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001124 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1125 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001126
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001127 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1128 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001129
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001130 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1131 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001132
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001133 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1134 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1135 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1136 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1137 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1138 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1139 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1140 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1141 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1142 _ptrRTCPData++; // skip reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001143
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001144 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1145 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001146
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001147 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1148 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001149
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001150 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1151 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001152
Erik Språng242e22b2015-05-11 10:17:43 +02001153 _packetType = RTCPPacketTypes::kXrVoipMetric;
1154 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001155 return true;
1156}
niklase@google.com470e71d2011-07-07 08:21:25 +00001157
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001158bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
1159 int block_length_4bytes) {
1160 const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
1161 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1162 if (length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001163 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001164 EndCurrentBlock();
1165 return false;
1166 }
1167 // Skip block.
1168 _ptrRTCPData += kBlockLengthInBytes;
Erik Språng242e22b2015-05-11 10:17:43 +02001169 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001170 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001171}
1172
sprang73a93e82015-09-14 12:50:39 -07001173bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001174 RTC_CHECK((header.packet_type == PT_RTPFB) ||
1175 (header.packet_type == PT_PSFB)); // Parser logic check
niklase@google.com470e71d2011-07-07 08:21:25 +00001176
1177 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1178
Erik Språng6b8d3552015-09-24 15:06:57 +02001179 // 4 * 3, RFC4585 section 6.1
1180 if (length < 12) {
1181 LOG(LS_WARNING)
1182 << "Invalid RTCP packet: Too little data (" << length
1183 << " bytes) left in buffer to parse a 12 byte RTPFB/PSFB message.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001184 return false;
1185 }
1186
1187 _ptrRTCPData += 4; // Skip RTCP header
1188
Erik Språng6b8d3552015-09-24 15:06:57 +02001189 uint32_t senderSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1190 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
Erik Språng6b8d3552015-09-24 15:06:57 +02001192 uint32_t mediaSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1193 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001194
sprang73a93e82015-09-14 12:50:39 -07001195 if (header.packet_type == PT_RTPFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001196 // Transport layer feedback
1197
sprang73a93e82015-09-14 12:50:39 -07001198 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001199 case 1:
1200 {
1201 // NACK
Erik Språng242e22b2015-05-11 10:17:43 +02001202 _packetType = RTCPPacketTypes::kRtpfbNack;
niklase@google.com470e71d2011-07-07 08:21:25 +00001203 _packet.NACK.SenderSSRC = senderSSRC;
1204 _packet.NACK.MediaSSRC = mediaSSRC;
1205
Erik Språng242e22b2015-05-11 10:17:43 +02001206 _state = ParseState::State_RTPFB_NACKItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001207
1208 return true;
1209 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001210 case 3:
1211 {
1212 // TMMBR
Erik Språng242e22b2015-05-11 10:17:43 +02001213 _packetType = RTCPPacketTypes::kRtpfbTmmbr;
niklase@google.com470e71d2011-07-07 08:21:25 +00001214 _packet.TMMBR.SenderSSRC = senderSSRC;
1215 _packet.TMMBR.MediaSSRC = mediaSSRC;
1216
Erik Språng242e22b2015-05-11 10:17:43 +02001217 _state = ParseState::State_RTPFB_TMMBRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001218
1219 return true;
1220 }
1221 case 4:
1222 {
1223 // TMMBN
Erik Språng242e22b2015-05-11 10:17:43 +02001224 _packetType = RTCPPacketTypes::kRtpfbTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001225 _packet.TMMBN.SenderSSRC = senderSSRC;
1226 _packet.TMMBN.MediaSSRC = mediaSSRC;
1227
Erik Språng242e22b2015-05-11 10:17:43 +02001228 _state = ParseState::State_RTPFB_TMMBNItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001229
1230 return true;
1231 }
1232 case 5:
1233 {
1234 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1235 // draft-perkins-avt-rapid-rtp-sync-03.txt
1236 // trigger a new RTCP SR
Erik Språng242e22b2015-05-11 10:17:43 +02001237 _packetType = RTCPPacketTypes::kRtpfbSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +00001238
1239 // Note: No state transition, SR REQ is empty!
1240 return true;
1241 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001242 case 15: {
Erik Språng6b8d3552015-09-24 15:06:57 +02001243 rtcp_packet_ =
1244 rtcp::TransportFeedback::ParseFrom(_ptrRTCPData - 12, length);
1245 // Since we parse the whole packet here, keep the TopLevel state and
1246 // just end the current block.
sprang49f9cdb2015-10-01 03:06:57 -07001247 EndCurrentBlock();
Erik Språng6b8d3552015-09-24 15:06:57 +02001248 if (rtcp_packet_.get()) {
sprang49f9cdb2015-10-01 03:06:57 -07001249 _packetType = RTCPPacketTypes::kTransportFeedback;
Erik Språng6b8d3552015-09-24 15:06:57 +02001250 return true;
1251 }
1252 break;
1253 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001254 default:
1255 break;
1256 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001257 // Unsupported RTPFB message. Skip and move to next block.
1258 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001259 return false;
sprang73a93e82015-09-14 12:50:39 -07001260 } else if (header.packet_type == PT_PSFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001261 // Payload specific feedback
sprang73a93e82015-09-14 12:50:39 -07001262 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001263 case 1:
1264 // PLI
Erik Språng242e22b2015-05-11 10:17:43 +02001265 _packetType = RTCPPacketTypes::kPsfbPli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001266 _packet.PLI.SenderSSRC = senderSSRC;
1267 _packet.PLI.MediaSSRC = mediaSSRC;
1268
1269 // Note: No state transition, PLI FCI is empty!
1270 return true;
1271 case 2:
1272 // SLI
Erik Språng242e22b2015-05-11 10:17:43 +02001273 _packetType = RTCPPacketTypes::kPsfbSli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001274 _packet.SLI.SenderSSRC = senderSSRC;
1275 _packet.SLI.MediaSSRC = mediaSSRC;
1276
Erik Språng242e22b2015-05-11 10:17:43 +02001277 _state = ParseState::State_PSFB_SLIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001278
1279 return true;
1280 case 3:
Erik Språng242e22b2015-05-11 10:17:43 +02001281 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001282 _packet.RPSI.SenderSSRC = senderSSRC;
1283 _packet.RPSI.MediaSSRC = mediaSSRC;
1284
Erik Språng242e22b2015-05-11 10:17:43 +02001285 _state = ParseState::State_PSFB_RPSIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 return true;
1287 case 4:
1288 // FIR
Erik Språng242e22b2015-05-11 10:17:43 +02001289 _packetType = RTCPPacketTypes::kPsfbFir;
niklase@google.com470e71d2011-07-07 08:21:25 +00001290 _packet.FIR.SenderSSRC = senderSSRC;
1291 _packet.FIR.MediaSSRC = mediaSSRC;
1292
Erik Språng242e22b2015-05-11 10:17:43 +02001293 _state = ParseState::State_PSFB_FIRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001294 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001295 case 15:
Erik Språng242e22b2015-05-11 10:17:43 +02001296 _packetType = RTCPPacketTypes::kPsfbApp;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001297 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1298 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001299
Erik Språng242e22b2015-05-11 10:17:43 +02001300 _state = ParseState::State_PSFB_AppItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001301 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001302 default:
1303 break;
1304 }
1305
niklase@google.com470e71d2011-07-07 08:21:25 +00001306 return false;
1307 }
1308 else
1309 {
Erik Språng6b8d3552015-09-24 15:06:57 +02001310 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +00001311 return false;
1312 }
1313}
1314
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001315bool RTCPUtility::RTCPParserV2::ParseRPSIItem() {
1316
1317 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI).
1318 //
1319 // 0 1 2 3
1320 // 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
1321 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1322 // | PB |0| Payload Type| Native RPSI bit string |
1323 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1324 // | defined per codec ... | Padding (0) |
1325 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
niklase@google.com470e71d2011-07-07 08:21:25 +00001326
1327 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1328
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001329 if (length < 4) {
Erik Språng242e22b2015-05-11 10:17:43 +02001330 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001331
1332 EndCurrentBlock();
1333 return false;
1334 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001335 if (length > 2 + RTCP_RPSI_DATA_SIZE) {
Erik Språng242e22b2015-05-11 10:17:43 +02001336 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001337
1338 EndCurrentBlock();
1339 return false;
1340 }
1341
niklase@google.com470e71d2011-07-07 08:21:25 +00001342
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001343 uint8_t padding_bits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001344 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1345
danilchap90a13512016-04-11 10:05:02 -07001346 if (padding_bits > static_cast<uint16_t>(length - 2) * 8) {
1347 _state = ParseState::State_TopLevel;
1348
1349 EndCurrentBlock();
1350 return false;
1351 }
1352
1353 _packetType = RTCPPacketTypes::kPsfbRpsiItem;
1354
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001355 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
1356 _ptrRTCPData += length - 2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001357
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001358 _packet.RPSI.NumberOfValidBits =
1359 static_cast<uint16_t>(length - 2) * 8 - padding_bits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001360 return true;
1361}
1362
1363bool
1364RTCPUtility::RTCPParserV2::ParseNACKItem()
1365{
1366 // RFC 4585 6.2.1. Generic NACK
1367
1368 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1369
1370 if (length < 4)
1371 {
Erik Språng242e22b2015-05-11 10:17:43 +02001372 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001373
1374 EndCurrentBlock();
1375 return false;
1376 }
1377
Erik Språng242e22b2015-05-11 10:17:43 +02001378 _packetType = RTCPPacketTypes::kRtpfbNackItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001379
1380 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1381 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1382
1383 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1384 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1385
1386 return true;
1387}
1388
1389bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001390RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1391{
1392 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1393
1394 if (length < 4)
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++ != 'R')
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 }
1408 if(*_ptrRTCPData++ != 'E')
1409 {
Erik Språng242e22b2015-05-11 10:17:43 +02001410 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001411
1412 EndCurrentBlock();
1413 return false;
1414 }
1415 if(*_ptrRTCPData++ != 'M')
1416 {
Erik Språng242e22b2015-05-11 10:17:43 +02001417 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001418
1419 EndCurrentBlock();
1420 return false;
1421 }
1422 if(*_ptrRTCPData++ != 'B')
1423 {
Erik Språng242e22b2015-05-11 10:17:43 +02001424 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001425
1426 EndCurrentBlock();
1427 return false;
1428 }
Erik Språng242e22b2015-05-11 10:17:43 +02001429 _packetType = RTCPPacketTypes::kPsfbRemb;
1430 _state = ParseState::State_PSFB_REMBItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001431 return true;
1432}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001433
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001434bool
1435RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1436{
1437 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1438
1439 if (length < 4)
1440 {
Erik Språng242e22b2015-05-11 10:17:43 +02001441 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001442
1443 EndCurrentBlock();
1444 return false;
1445 }
1446
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001447 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001448 const uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001449
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001450 uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 16;
1451 mantissa += (_ptrRTCPData[1] << 8);
1452 mantissa += (_ptrRTCPData[2]);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001453
1454 _ptrRTCPData += 3; // Fwd read data
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001455 uint64_t bitrate_bps = (mantissa << exp);
1456 bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0;
1457 if (shift_overflow || bitrate_bps > kMaxBitrateBps) {
1458 LOG(LS_ERROR) << "Unhandled remb bitrate value : " << mantissa
1459 << "*2^" << static_cast<int>(exp);
1460 _state = ParseState::State_TopLevel;
1461 EndCurrentBlock();
1462 return false;
1463 }
1464 _packet.REMBItem.BitRate = bitrate_bps;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001465
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001466 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1467 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1468 {
Erik Språng242e22b2015-05-11 10:17:43 +02001469 _state = ParseState::State_TopLevel;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001470
1471 EndCurrentBlock();
1472 return false;
1473 }
1474
Erik Språng242e22b2015-05-11 10:17:43 +02001475 _packetType = RTCPPacketTypes::kPsfbRembItem;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001476
1477 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1478 {
1479 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1480 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1481 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1482 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1483 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001484 return true;
1485}
1486
1487bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001488RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1489{
1490 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1491
1492 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1493
1494 if (length < 8)
1495 {
Erik Språng242e22b2015-05-11 10:17:43 +02001496 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001497
1498 EndCurrentBlock();
1499 return false;
1500 }
1501
Erik Språng242e22b2015-05-11 10:17:43 +02001502 _packetType = RTCPPacketTypes::kRtpfbTmmbrItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001503
1504 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1505 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1506 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1507 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1508
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001509 uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001510
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001511 uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 15;
1512 mantissa += (_ptrRTCPData[1] << 7);
1513 mantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001514
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001515 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001516 measuredOH += _ptrRTCPData[3];
1517
1518 _ptrRTCPData += 4; // Fwd read data
1519
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001520 uint64_t bitrate_bps = (mantissa << exp);
1521 bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0;
1522 if (shift_overflow || bitrate_bps > kMaxBitrateBps) {
1523 LOG(LS_ERROR) << "Unhandled tmmbr bitrate value : " << mantissa
1524 << "*2^" << static_cast<int>(exp);
1525 _state = ParseState::State_TopLevel;
1526 EndCurrentBlock();
1527 return false;
1528 }
1529
1530 _packet.TMMBRItem.MaxTotalMediaBitRate = bitrate_bps / 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001531 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1532
1533 return true;
1534}
1535
1536bool
1537RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1538{
1539 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1540
1541 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1542
1543 if (length < 8)
1544 {
Erik Språng242e22b2015-05-11 10:17:43 +02001545 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001546
1547 EndCurrentBlock();
1548 return false;
1549 }
1550
Erik Språng242e22b2015-05-11 10:17:43 +02001551 _packetType = RTCPPacketTypes::kRtpfbTmmbnItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001552
1553 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1554 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1555 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1556 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1557
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001558 uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001559
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001560 uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 15;
1561 mantissa += (_ptrRTCPData[1] << 7);
1562 mantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001563
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001564 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001565 measuredOH += _ptrRTCPData[3];
1566
1567 _ptrRTCPData += 4; // Fwd read data
1568
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001569 uint64_t bitrate_bps = (mantissa << exp);
1570 bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0;
1571 if (shift_overflow || bitrate_bps > kMaxBitrateBps) {
1572 LOG(LS_ERROR) << "Unhandled tmmbn bitrate value : " << mantissa
1573 << "*2^" << static_cast<int>(exp);
1574 _state = ParseState::State_TopLevel;
1575 EndCurrentBlock();
1576 return false;
1577 }
1578
1579 _packet.TMMBNItem.MaxTotalMediaBitRate = bitrate_bps / 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001580 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1581
1582 return true;
1583}
1584
1585bool
1586RTCPUtility::RTCPParserV2::ParseSLIItem()
1587{
1588 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1589 /*
1590 0 1 2 3
1591 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
1592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1593 | First | Number | PictureID |
1594 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1595 */
1596
1597 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1598
1599 if (length < 4)
1600 {
Erik Språng242e22b2015-05-11 10:17:43 +02001601 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001602
1603 EndCurrentBlock();
1604 return false;
1605 }
Erik Språng242e22b2015-05-11 10:17:43 +02001606 _packetType = RTCPPacketTypes::kPsfbSliItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001607
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001608 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001609 buffer = *_ptrRTCPData++ << 24;
1610 buffer += *_ptrRTCPData++ << 16;
1611 buffer += *_ptrRTCPData++ << 8;
1612 buffer += *_ptrRTCPData++;
1613
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001614 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1615 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1616 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001617
1618 return true;
1619}
1620
1621bool
1622RTCPUtility::RTCPParserV2::ParseFIRItem()
1623{
1624 // RFC 5104 4.3.1. Full Intra Request (FIR)
1625
1626 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1627
1628 if (length < 8)
1629 {
Erik Språng242e22b2015-05-11 10:17:43 +02001630 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001631
1632 EndCurrentBlock();
1633 return false;
1634 }
1635
Erik Språng242e22b2015-05-11 10:17:43 +02001636 _packetType = RTCPPacketTypes::kPsfbFirItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001637
1638 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1639 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1640 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1641 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1642
1643 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1644 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1645 return true;
1646}
1647
sprang73a93e82015-09-14 12:50:39 -07001648bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001649 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1650
1651 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1652 {
1653 EndCurrentBlock();
1654 return false;
1655 }
1656
1657 _ptrRTCPData += 4; // Skip RTCP header
1658
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001659 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001660 senderSSRC += *_ptrRTCPData++ << 16;
1661 senderSSRC += *_ptrRTCPData++ << 8;
1662 senderSSRC += *_ptrRTCPData++;
1663
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001664 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001665 name += *_ptrRTCPData++ << 16;
1666 name += *_ptrRTCPData++ << 8;
1667 name += *_ptrRTCPData++;
1668
1669 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1670
Erik Språng242e22b2015-05-11 10:17:43 +02001671 _packetType = RTCPPacketTypes::kApp;
niklase@google.com470e71d2011-07-07 08:21:25 +00001672
sprang73a93e82015-09-14 12:50:39 -07001673 _packet.APP.SubType = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +00001674 _packet.APP.Name = name;
1675
Erik Språng242e22b2015-05-11 10:17:43 +02001676 _state = ParseState::State_AppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001677 return true;
1678}
1679
1680bool
1681RTCPUtility::RTCPParserV2::ParseAPPItem()
1682{
1683 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1684 if (length < 4)
1685 {
Erik Språng242e22b2015-05-11 10:17:43 +02001686 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001687
1688 EndCurrentBlock();
1689 return false;
1690 }
Erik Språng242e22b2015-05-11 10:17:43 +02001691 _packetType = RTCPPacketTypes::kAppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001692
1693 if(length > kRtcpAppCode_DATA_SIZE)
1694 {
1695 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1696 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1697 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1698 }else
1699 {
1700 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001701 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001702 _ptrRTCPData += length;
1703 }
1704 return true;
1705}
1706
Erik Språng6b8d3552015-09-24 15:06:57 +02001707size_t RTCPUtility::RTCPParserV2::NumSkippedBlocks() const {
1708 return num_skipped_blocks_;
1709}
1710
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001711RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001712 size_t rtcpDataLength)
1713 : _ptrBegin(rtcpData),
1714 _ptrEnd(rtcpData + rtcpDataLength),
1715 _ptrBlock(NULL) {
1716 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001717}
1718
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001719RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001720}
1721
sprang73a93e82015-09-14 12:50:39 -07001722const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001723 _ptrBlock = _ptrBegin;
1724
1725 return Iterate();
1726}
1727
sprang73a93e82015-09-14 12:50:39 -07001728const RTCPUtility::RtcpCommonHeader*
1729RTCPUtility::RTCPPacketIterator::Iterate() {
1730 if ((_ptrEnd <= _ptrBlock) ||
1731 !RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) {
1732 _ptrBlock = nullptr;
1733 return nullptr;
1734 }
1735 _ptrBlock += _header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +00001736
sprang73a93e82015-09-14 12:50:39 -07001737 if (_ptrBlock > _ptrEnd) {
1738 _ptrBlock = nullptr;
1739 return nullptr;
1740 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001741
sprang73a93e82015-09-14 12:50:39 -07001742 return &_header;
niklase@google.com470e71d2011-07-07 08:21:25 +00001743}
1744
sprang73a93e82015-09-14 12:50:39 -07001745const RTCPUtility::RtcpCommonHeader*
1746RTCPUtility::RTCPPacketIterator::Current() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001747 if (!_ptrBlock)
1748 {
1749 return NULL;
1750 }
1751
1752 return &_header;
1753}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001754} // namespace webrtc