blob: 2c26fa79db3f0df45fd49e43575b5641d1f3aadc [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
raphael.kubo.da.costaec7b0092016-11-07 10:45:55 -0800436 // * 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!)
niklase@google.com470e71d2011-07-07 08:21:25 +0000445
raphael.kubo.da.costaec7b0092016-11-07 10:45:55 -0800446 if (!_RTCPReducedSizeEnable) {
447 if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR))
448 return; // NOT VALID
449 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000450
raphael.kubo.da.costaec7b0092016-11-07 10:45:55 -0800451 _validPacket = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000452}
453
454bool
455RTCPUtility::RTCPParserV2::IsValid() const
456{
457 return _validPacket;
458}
459
460void
461RTCPUtility::RTCPParserV2::EndCurrentBlock()
462{
463 _ptrRTCPData = _ptrRTCPBlockEnd;
464}
465
sprang73a93e82015-09-14 12:50:39 -0700466// 0 1 2 3
467// 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
468// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
469// |V=2|P| IC | PT | length |
470// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
471//
472// Common header for all RTCP packets, 4 octets.
473
474bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet,
475 size_t size_bytes,
476 RtcpCommonHeader* parsed_header) {
henrikg91d6ede2015-09-17 00:24:34 -0700477 RTC_DCHECK(parsed_header != nullptr);
sprang73a93e82015-09-14 12:50:39 -0700478 if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) {
479 LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte"
480 << (size_bytes != 1 ? "s" : "")
481 << ") remaining in buffer to parse RTCP header (4 bytes).";
482 return false;
483 }
484
485 const uint8_t kRtcpVersion = 2;
486 uint8_t version = packet[0] >> 6;
487 if (version != kRtcpVersion) {
488 LOG(LS_WARNING) << "Invalid RTCP header: Version must be "
489 << static_cast<int>(kRtcpVersion) << " but was "
490 << static_cast<int>(version);
491 return false;
492 }
493
494 bool has_padding = (packet[0] & 0x20) != 0;
495 uint8_t format = packet[0] & 0x1F;
496 uint8_t packet_type = packet[1];
497 size_t packet_size_words =
498 ByteReader<uint16_t>::ReadBigEndian(&packet[2]) + 1;
499
500 if (size_bytes < packet_size_words * 4) {
501 LOG(LS_WARNING) << "Buffer too small (" << size_bytes
502 << " bytes) to fit an RtcpPacket of " << packet_size_words
503 << " 32bit words.";
504 return false;
505 }
506
507 size_t payload_size = packet_size_words * 4;
508 size_t padding_bytes = 0;
509 if (has_padding) {
510 if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) {
511 LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload "
512 "size specified.";
513 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000514 }
515
sprang73a93e82015-09-14 12:50:39 -0700516 padding_bytes = packet[payload_size - 1];
517 if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) {
518 LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
519 << padding_bytes << ") for a packet size of "
520 << payload_size << "bytes.";
521 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000522 }
sprang73a93e82015-09-14 12:50:39 -0700523 payload_size -= padding_bytes;
524 }
525 payload_size -= RtcpCommonHeader::kHeaderSizeBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526
sprang73a93e82015-09-14 12:50:39 -0700527 parsed_header->version = kRtcpVersion;
528 parsed_header->count_or_format = format;
529 parsed_header->packet_type = packet_type;
530 parsed_header->payload_size_bytes = payload_size;
531 parsed_header->padding_bytes = padding_bytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
sprang73a93e82015-09-14 12:50:39 -0700533 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000534}
535
536bool
537RTCPUtility::RTCPParserV2::ParseRR()
538{
539 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
540
541 if (length < 8)
542 {
543 return false;
544 }
545
546
547 _ptrRTCPData += 4; // Skip header
548
Erik Språng242e22b2015-05-11 10:17:43 +0200549 _packetType = RTCPPacketTypes::kRr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000550
551 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
552 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
553 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
554 _packet.RR.SenderSSRC += *_ptrRTCPData++;
555
556 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
557
558 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200559 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000560
561 return true;
562}
563
564bool
565RTCPUtility::RTCPParserV2::ParseSR()
566{
567 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
568
569 if (length < 28)
570 {
571 EndCurrentBlock();
572 return false;
573 }
574
575 _ptrRTCPData += 4; // Skip header
576
Erik Språng242e22b2015-05-11 10:17:43 +0200577 _packetType = RTCPPacketTypes::kSr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000578
579 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
580 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
581 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
582 _packet.SR.SenderSSRC += *_ptrRTCPData++;
583
584 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
585 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
586 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
587 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
588
589 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
590 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
591 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
592 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
593
594 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
595 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
596 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
597 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
598
599 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
600 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
601 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
602 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
603
604 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
605 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
606 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
607 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
608
609 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
610
611 // State transition
612 if(_numberOfBlocks != 0)
613 {
Erik Språng242e22b2015-05-11 10:17:43 +0200614 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000615 }else
616 {
617 // don't go to state report block item if 0 report blocks
Erik Språng242e22b2015-05-11 10:17:43 +0200618 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000619 EndCurrentBlock();
620 }
621 return true;
622}
623
624bool
625RTCPUtility::RTCPParserV2::ParseReportBlockItem()
626{
627 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
628
629 if (length < 24 || _numberOfBlocks <= 0)
630 {
Erik Språng242e22b2015-05-11 10:17:43 +0200631 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
633 EndCurrentBlock();
634 return false;
635 }
636 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
637 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
638 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
639 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
640
641 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
642
643 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
644 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
645 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
646
647 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
648 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
649 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
650 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
651
652 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
653 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
654 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
655 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
656
657 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
658 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
659 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
660 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
661
662 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
663 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
664 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
665 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
666
667 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200668 _packetType = RTCPPacketTypes::kReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000669 return true;
670}
671
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000672/* From RFC 5450: Transmission Time Offsets in RTP Streams.
673 0 1 2 3
674 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
675 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676 hdr |V=2|P| RC | PT=IJ=195 | length |
677 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
678 | inter-arrival jitter |
679 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
680 . .
681 . .
682 . .
683 | inter-arrival jitter |
684 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
685*/
686
687bool
688RTCPUtility::RTCPParserV2::ParseIJ()
689{
690 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
691
692 if (length < 4)
693 {
694 return false;
695 }
696
697 _ptrRTCPData += 4; // Skip header
698
Erik Språng242e22b2015-05-11 10:17:43 +0200699 _packetType = RTCPPacketTypes::kExtendedIj;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000700
701 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200702 _state = ParseState::State_ExtendedJitterItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000703 return true;
704}
705
706bool
707RTCPUtility::RTCPParserV2::ParseIJItem()
708{
709 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
710
711 if (length < 4 || _numberOfBlocks <= 0)
712 {
Erik Språng242e22b2015-05-11 10:17:43 +0200713 _state = ParseState::State_TopLevel;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000714 EndCurrentBlock();
715 return false;
716 }
717
718 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
719 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
720 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
721 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
722
723 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200724 _packetType = RTCPPacketTypes::kExtendedIjItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000725 return true;
726}
727
niklase@google.com470e71d2011-07-07 08:21:25 +0000728bool
729RTCPUtility::RTCPParserV2::ParseSDES()
730{
731 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
732
733 if (length < 8)
734 {
Erik Språng242e22b2015-05-11 10:17:43 +0200735 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000736
737 EndCurrentBlock();
738 return false;
739 }
740 _ptrRTCPData += 4; // Skip header
741
Erik Språng242e22b2015-05-11 10:17:43 +0200742 _state = ParseState::State_SDESChunk;
743 _packetType = RTCPPacketTypes::kSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000744 return true;
745}
746
747bool
748RTCPUtility::RTCPParserV2::ParseSDESChunk()
749{
750 if(_numberOfBlocks <= 0)
751 {
Erik Språng242e22b2015-05-11 10:17:43 +0200752 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000753
754 EndCurrentBlock();
755 return false;
756 }
757 _numberOfBlocks--;
758
759 // Find CName item in a SDES chunk.
760 while (_ptrRTCPData < _ptrRTCPBlockEnd)
761 {
762 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
763 if (dataLen < 4)
764 {
Erik Språng242e22b2015-05-11 10:17:43 +0200765 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000766
767 EndCurrentBlock();
768 return false;
769 }
770
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000771 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000772 SSRC += *_ptrRTCPData++ << 16;
773 SSRC += *_ptrRTCPData++ << 8;
774 SSRC += *_ptrRTCPData++;
775
776 const bool foundCname = ParseSDESItem();
777 if (foundCname)
778 {
779 _packet.CName.SenderSSRC = SSRC; // Add SSRC
780 return true;
781 }
782 }
Erik Språng242e22b2015-05-11 10:17:43 +0200783 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000784
785 EndCurrentBlock();
786 return false;
787}
788
789bool
790RTCPUtility::RTCPParserV2::ParseSDESItem()
791{
792 // Find CName
793 // Only the CNAME item is mandatory. RFC 3550 page 46
794 bool foundCName = false;
795
796 size_t itemOctetsRead = 0;
797 while (_ptrRTCPData < _ptrRTCPBlockEnd)
798 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000799 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000800 ++itemOctetsRead;
801
802 if (tag == 0)
803 {
804 // End tag! 4 oct aligned
805 while ((itemOctetsRead++ % 4) != 0)
806 {
807 ++_ptrRTCPData;
808 }
809 return foundCName;
810 }
811
812 if (_ptrRTCPData < _ptrRTCPBlockEnd)
813 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000814 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000815 ++itemOctetsRead;
816
817 if (tag == 1)
818 {
819 // CNAME
820
821 // Sanity
822 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
823 {
Erik Språng242e22b2015-05-11 10:17:43 +0200824 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000825
826 EndCurrentBlock();
827 return false;
828 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000829 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000830 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000831 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000832 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000833 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
834 {
835 // Illegal char
Erik Språng242e22b2015-05-11 10:17:43 +0200836 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000837
838 EndCurrentBlock();
839 return false;
840 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000841 _packet.CName.CName[i] = c;
842 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000843 // Make sure we are null terminated.
844 _packet.CName.CName[i] = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200845 _packetType = RTCPPacketTypes::kSdesChunk;
niklase@google.com470e71d2011-07-07 08:21:25 +0000846
847 foundCName = true;
848 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000849 _ptrRTCPData += len;
850 itemOctetsRead += len;
851 }
852 }
853
854 // No end tag found!
Erik Språng242e22b2015-05-11 10:17:43 +0200855 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000856
857 EndCurrentBlock();
858 return false;
859}
860
861bool
862RTCPUtility::RTCPParserV2::ParseBYE()
863{
864 _ptrRTCPData += 4; // Skip header
865
Erik Språng242e22b2015-05-11 10:17:43 +0200866 _state = ParseState::State_BYEItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000867
868 return ParseBYEItem();
869}
870
871bool
872RTCPUtility::RTCPParserV2::ParseBYEItem()
873{
874 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
875 if (length < 4 || _numberOfBlocks == 0)
876 {
Erik Språng242e22b2015-05-11 10:17:43 +0200877 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000878
879 EndCurrentBlock();
880 return false;
881 }
882
Erik Språng242e22b2015-05-11 10:17:43 +0200883 _packetType = RTCPPacketTypes::kBye;
niklase@google.com470e71d2011-07-07 08:21:25 +0000884
885 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
886 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
887 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
888 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
889
890 // we can have several CSRCs attached
891
892 // sanity
893 if(length >= 4*_numberOfBlocks)
894 {
895 _ptrRTCPData += (_numberOfBlocks -1)*4;
896 }
897 _numberOfBlocks = 0;
898
899 return true;
900}
901/*
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000902 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +0000903 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
904 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
905 |V=2|P|reserved | PT=XR=207 | length |
906 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
907 | SSRC |
908 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 : report blocks :
910 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000912bool RTCPUtility::RTCPParserV2::ParseXr()
niklase@google.com470e71d2011-07-07 08:21:25 +0000913{
914 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000915 if (length < 8)
916 {
917 EndCurrentBlock();
918 return false;
919 }
920
921 _ptrRTCPData += 4; // Skip header
922
923 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
924 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
925 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
926 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
927
Erik Språng242e22b2015-05-11 10:17:43 +0200928 _packetType = RTCPPacketTypes::kXrHeader;
929 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000930 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000931}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000932
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000933/* Extended report block format (RFC 3611).
934 BT: block type.
935 block length: length of report block in 32-bits words minus one (including
936 the header).
niklase@google.com470e71d2011-07-07 08:21:25 +0000937 0 1 2 3
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000938 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 +0000939 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
940 | BT | type-specific | block length |
941 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942 : type-specific block contents :
943 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000945bool RTCPUtility::RTCPParserV2::ParseXrItem() {
946 const int kBlockHeaderLengthInBytes = 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000947 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000948 if (length < kBlockHeaderLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200949 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000950 EndCurrentBlock();
951 return false;
952 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000953
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000954 uint8_t block_type = *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000955 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000956
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000957 uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
958 block_length_in_4bytes += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000959
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000960 switch (block_type) {
961 case kBtReceiverReferenceTime:
962 return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
963 case kBtDlrr:
964 return ParseXrDlrr(block_length_in_4bytes);
965 case kBtVoipMetric:
966 return ParseXrVoipMetricItem(block_length_in_4bytes);
967 default:
968 return ParseXrUnsupportedBlockType(block_length_in_4bytes);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000969 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000970}
971
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000972/* Receiver Reference Time Report Block.
973 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000974 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
975 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
976 | BT=4 | reserved | block length = 2 |
977 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
978 | NTP timestamp, most significant word |
979 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
980 | NTP timestamp, least significant word |
981 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
982*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000983bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
984 int block_length_4bytes) {
985 const int kBlockLengthIn4Bytes = 2;
986 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000987 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000988 if (block_length_4bytes != kBlockLengthIn4Bytes ||
989 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200990 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000991 EndCurrentBlock();
992 return false;
993 }
994
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000995 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
996 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
997 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
998 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000999
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001000 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
1001 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
1002 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
1003 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001004
Erik Språng242e22b2015-05-11 10:17:43 +02001005 _packetType = RTCPPacketTypes::kXrReceiverReferenceTime;
1006 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001007 return true;
1008}
1009
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001010/* DLRR Report Block.
1011 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001012 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
1013 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1014 | BT=5 | reserved | block length |
1015 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1016 | SSRC_1 (SSRC of first receiver) | sub-
1017 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1018 | last RR (LRR) | 1
1019 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1020 | delay since last RR (DLRR) |
1021 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1022 | SSRC_2 (SSRC of second receiver) | sub-
1023 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1024 : ... : 2
1025 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1026*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001027bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
1028 const int kSubBlockLengthIn4Bytes = 3;
1029 if (block_length_4bytes < 0 ||
1030 (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001031 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001032 EndCurrentBlock();
1033 return false;
1034 }
Erik Språng242e22b2015-05-11 10:17:43 +02001035 _packetType = RTCPPacketTypes::kXrDlrrReportBlock;
1036 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001037 _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
1038 return true;
1039}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001040
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001041bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001042 if (_numberOfBlocks == 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001043 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001044 return false;
1045 }
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001046 const int kSubBlockLengthInBytes = 12;
1047 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1048 if (length < kSubBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001049 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001050 EndCurrentBlock();
1051 return false;
1052 }
1053
1054 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1055 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1056 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1057 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1058
1059 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1060 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1061 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1062 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1063
1064 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1065 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1066 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1067 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1068
Erik Språng242e22b2015-05-11 10:17:43 +02001069 _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001070 --_numberOfBlocks;
Erik Språng242e22b2015-05-11 10:17:43 +02001071 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001072 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001073}
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001074/* VoIP Metrics Report Block.
1075 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +00001076 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
1077 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1078 | BT=7 | reserved | block length = 8 |
1079 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1080 | SSRC of source |
1081 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1082 | loss rate | discard rate | burst density | gap density |
1083 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1084 | burst duration | gap duration |
1085 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1086 | round trip delay | end system delay |
1087 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1088 | signal level | noise level | RERL | Gmin |
1089 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1090 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1091 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1092 | RX config | reserved | JB nominal |
1093 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1094 | JB maximum | JB abs max |
1095 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1096*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001097
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001098bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
1099 const int kBlockLengthIn4Bytes = 8;
1100 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
1101 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1102 if (block_length_4bytes != kBlockLengthIn4Bytes ||
1103 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001104 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001105 EndCurrentBlock();
1106 return false;
1107 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001108
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001109 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1110 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1111 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1112 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001113
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001114 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1115 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1116 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1117 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001118
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001119 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1120 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001122 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1123 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001124
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001125 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1126 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001127
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001128 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1129 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001130
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001131 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1132 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1133 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1134 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1135 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1136 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1137 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1138 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1139 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1140 _ptrRTCPData++; // skip reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001141
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001142 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1143 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001144
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001145 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1146 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001147
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001148 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1149 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001150
Erik Språng242e22b2015-05-11 10:17:43 +02001151 _packetType = RTCPPacketTypes::kXrVoipMetric;
1152 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001153 return true;
1154}
niklase@google.com470e71d2011-07-07 08:21:25 +00001155
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001156bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
1157 int block_length_4bytes) {
1158 const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
1159 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1160 if (length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001161 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001162 EndCurrentBlock();
1163 return false;
1164 }
1165 // Skip block.
1166 _ptrRTCPData += kBlockLengthInBytes;
Erik Språng242e22b2015-05-11 10:17:43 +02001167 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001168 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001169}
1170
sprang73a93e82015-09-14 12:50:39 -07001171bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001172 RTC_CHECK((header.packet_type == PT_RTPFB) ||
1173 (header.packet_type == PT_PSFB)); // Parser logic check
niklase@google.com470e71d2011-07-07 08:21:25 +00001174
1175 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1176
Erik Språng6b8d3552015-09-24 15:06:57 +02001177 // 4 * 3, RFC4585 section 6.1
1178 if (length < 12) {
1179 LOG(LS_WARNING)
1180 << "Invalid RTCP packet: Too little data (" << length
1181 << " bytes) left in buffer to parse a 12 byte RTPFB/PSFB message.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001182 return false;
1183 }
1184
1185 _ptrRTCPData += 4; // Skip RTCP header
1186
Erik Språng6b8d3552015-09-24 15:06:57 +02001187 uint32_t senderSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1188 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001189
Erik Språng6b8d3552015-09-24 15:06:57 +02001190 uint32_t mediaSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1191 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001192
sprang73a93e82015-09-14 12:50:39 -07001193 if (header.packet_type == PT_RTPFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001194 // Transport layer feedback
1195
sprang73a93e82015-09-14 12:50:39 -07001196 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001197 case 1:
1198 {
1199 // NACK
Erik Språng242e22b2015-05-11 10:17:43 +02001200 _packetType = RTCPPacketTypes::kRtpfbNack;
niklase@google.com470e71d2011-07-07 08:21:25 +00001201 _packet.NACK.SenderSSRC = senderSSRC;
1202 _packet.NACK.MediaSSRC = mediaSSRC;
1203
Erik Språng242e22b2015-05-11 10:17:43 +02001204 _state = ParseState::State_RTPFB_NACKItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001205
1206 return true;
1207 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001208 case 3:
1209 {
1210 // TMMBR
Erik Språng242e22b2015-05-11 10:17:43 +02001211 _packetType = RTCPPacketTypes::kRtpfbTmmbr;
niklase@google.com470e71d2011-07-07 08:21:25 +00001212 _packet.TMMBR.SenderSSRC = senderSSRC;
1213 _packet.TMMBR.MediaSSRC = mediaSSRC;
1214
Erik Språng242e22b2015-05-11 10:17:43 +02001215 _state = ParseState::State_RTPFB_TMMBRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001216
1217 return true;
1218 }
1219 case 4:
1220 {
1221 // TMMBN
Erik Språng242e22b2015-05-11 10:17:43 +02001222 _packetType = RTCPPacketTypes::kRtpfbTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001223 _packet.TMMBN.SenderSSRC = senderSSRC;
1224 _packet.TMMBN.MediaSSRC = mediaSSRC;
1225
Erik Språng242e22b2015-05-11 10:17:43 +02001226 _state = ParseState::State_RTPFB_TMMBNItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001227
1228 return true;
1229 }
1230 case 5:
1231 {
1232 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1233 // draft-perkins-avt-rapid-rtp-sync-03.txt
1234 // trigger a new RTCP SR
Erik Språng242e22b2015-05-11 10:17:43 +02001235 _packetType = RTCPPacketTypes::kRtpfbSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +00001236
1237 // Note: No state transition, SR REQ is empty!
1238 return true;
1239 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001240 case 15: {
Erik Språng6b8d3552015-09-24 15:06:57 +02001241 rtcp_packet_ =
1242 rtcp::TransportFeedback::ParseFrom(_ptrRTCPData - 12, length);
1243 // Since we parse the whole packet here, keep the TopLevel state and
1244 // just end the current block.
sprang49f9cdb2015-10-01 03:06:57 -07001245 EndCurrentBlock();
Erik Språng6b8d3552015-09-24 15:06:57 +02001246 if (rtcp_packet_.get()) {
sprang49f9cdb2015-10-01 03:06:57 -07001247 _packetType = RTCPPacketTypes::kTransportFeedback;
Erik Språng6b8d3552015-09-24 15:06:57 +02001248 return true;
1249 }
1250 break;
1251 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001252 default:
1253 break;
1254 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001255 // Unsupported RTPFB message. Skip and move to next block.
1256 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001257 return false;
sprang73a93e82015-09-14 12:50:39 -07001258 } else if (header.packet_type == PT_PSFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001259 // Payload specific feedback
sprang73a93e82015-09-14 12:50:39 -07001260 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001261 case 1:
1262 // PLI
Erik Språng242e22b2015-05-11 10:17:43 +02001263 _packetType = RTCPPacketTypes::kPsfbPli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001264 _packet.PLI.SenderSSRC = senderSSRC;
1265 _packet.PLI.MediaSSRC = mediaSSRC;
1266
1267 // Note: No state transition, PLI FCI is empty!
1268 return true;
1269 case 2:
1270 // SLI
Erik Språng242e22b2015-05-11 10:17:43 +02001271 _packetType = RTCPPacketTypes::kPsfbSli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001272 _packet.SLI.SenderSSRC = senderSSRC;
1273 _packet.SLI.MediaSSRC = mediaSSRC;
1274
Erik Språng242e22b2015-05-11 10:17:43 +02001275 _state = ParseState::State_PSFB_SLIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001276
1277 return true;
1278 case 3:
Erik Språng242e22b2015-05-11 10:17:43 +02001279 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001280 _packet.RPSI.SenderSSRC = senderSSRC;
1281 _packet.RPSI.MediaSSRC = mediaSSRC;
1282
Erik Språng242e22b2015-05-11 10:17:43 +02001283 _state = ParseState::State_PSFB_RPSIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 return true;
1285 case 4:
1286 // FIR
Erik Språng242e22b2015-05-11 10:17:43 +02001287 _packetType = RTCPPacketTypes::kPsfbFir;
niklase@google.com470e71d2011-07-07 08:21:25 +00001288 _packet.FIR.SenderSSRC = senderSSRC;
1289 _packet.FIR.MediaSSRC = mediaSSRC;
1290
Erik Språng242e22b2015-05-11 10:17:43 +02001291 _state = ParseState::State_PSFB_FIRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001292 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001293 case 15:
Erik Språng242e22b2015-05-11 10:17:43 +02001294 _packetType = RTCPPacketTypes::kPsfbApp;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001295 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1296 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001297
Erik Språng242e22b2015-05-11 10:17:43 +02001298 _state = ParseState::State_PSFB_AppItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001299 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001300 default:
1301 break;
1302 }
1303
niklase@google.com470e71d2011-07-07 08:21:25 +00001304 return false;
1305 }
1306 else
1307 {
Erik Språng6b8d3552015-09-24 15:06:57 +02001308 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +00001309 return false;
1310 }
1311}
1312
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001313bool RTCPUtility::RTCPParserV2::ParseRPSIItem() {
1314
1315 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI).
1316 //
1317 // 0 1 2 3
1318 // 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
1319 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1320 // | PB |0| Payload Type| Native RPSI bit string |
1321 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1322 // | defined per codec ... | Padding (0) |
1323 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
niklase@google.com470e71d2011-07-07 08:21:25 +00001324
1325 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1326
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001327 if (length < 4) {
Erik Språng242e22b2015-05-11 10:17:43 +02001328 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001329
1330 EndCurrentBlock();
1331 return false;
1332 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001333 if (length > 2 + RTCP_RPSI_DATA_SIZE) {
Erik Språng242e22b2015-05-11 10:17:43 +02001334 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001335
1336 EndCurrentBlock();
1337 return false;
1338 }
1339
niklase@google.com470e71d2011-07-07 08:21:25 +00001340
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001341 uint8_t padding_bits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001342 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1343
danilchap90a13512016-04-11 10:05:02 -07001344 if (padding_bits > static_cast<uint16_t>(length - 2) * 8) {
1345 _state = ParseState::State_TopLevel;
1346
1347 EndCurrentBlock();
1348 return false;
1349 }
1350
1351 _packetType = RTCPPacketTypes::kPsfbRpsiItem;
1352
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001353 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
1354 _ptrRTCPData += length - 2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001355
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001356 _packet.RPSI.NumberOfValidBits =
1357 static_cast<uint16_t>(length - 2) * 8 - padding_bits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001358 return true;
1359}
1360
1361bool
1362RTCPUtility::RTCPParserV2::ParseNACKItem()
1363{
1364 // RFC 4585 6.2.1. Generic NACK
1365
1366 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1367
1368 if (length < 4)
1369 {
Erik Språng242e22b2015-05-11 10:17:43 +02001370 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001371
1372 EndCurrentBlock();
1373 return false;
1374 }
1375
Erik Språng242e22b2015-05-11 10:17:43 +02001376 _packetType = RTCPPacketTypes::kRtpfbNackItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001377
1378 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1379 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1380
1381 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1382 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1383
1384 return true;
1385}
1386
1387bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001388RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1389{
1390 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1391
1392 if (length < 4)
1393 {
Erik Språng242e22b2015-05-11 10:17:43 +02001394 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001395
1396 EndCurrentBlock();
1397 return false;
1398 }
1399 if(*_ptrRTCPData++ != 'R')
1400 {
Erik Språng242e22b2015-05-11 10:17:43 +02001401 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001402
1403 EndCurrentBlock();
1404 return false;
1405 }
1406 if(*_ptrRTCPData++ != 'E')
1407 {
Erik Språng242e22b2015-05-11 10:17:43 +02001408 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001409
1410 EndCurrentBlock();
1411 return false;
1412 }
1413 if(*_ptrRTCPData++ != 'M')
1414 {
Erik Språng242e22b2015-05-11 10:17:43 +02001415 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001416
1417 EndCurrentBlock();
1418 return false;
1419 }
1420 if(*_ptrRTCPData++ != 'B')
1421 {
Erik Språng242e22b2015-05-11 10:17:43 +02001422 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001423
1424 EndCurrentBlock();
1425 return false;
1426 }
Erik Språng242e22b2015-05-11 10:17:43 +02001427 _packetType = RTCPPacketTypes::kPsfbRemb;
1428 _state = ParseState::State_PSFB_REMBItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001429 return true;
1430}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001431
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001432bool
1433RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1434{
1435 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1436
1437 if (length < 4)
1438 {
Erik Språng242e22b2015-05-11 10:17:43 +02001439 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001440
1441 EndCurrentBlock();
1442 return false;
1443 }
1444
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001445 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001446 const uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001447
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001448 uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 16;
1449 mantissa += (_ptrRTCPData[1] << 8);
1450 mantissa += (_ptrRTCPData[2]);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001451
1452 _ptrRTCPData += 3; // Fwd read data
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001453 uint64_t bitrate_bps = (mantissa << exp);
1454 bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0;
1455 if (shift_overflow || bitrate_bps > kMaxBitrateBps) {
1456 LOG(LS_ERROR) << "Unhandled remb bitrate value : " << mantissa
1457 << "*2^" << static_cast<int>(exp);
1458 _state = ParseState::State_TopLevel;
1459 EndCurrentBlock();
1460 return false;
1461 }
1462 _packet.REMBItem.BitRate = bitrate_bps;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001463
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001464 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1465 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1466 {
Erik Språng242e22b2015-05-11 10:17:43 +02001467 _state = ParseState::State_TopLevel;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001468
1469 EndCurrentBlock();
1470 return false;
1471 }
1472
Erik Språng242e22b2015-05-11 10:17:43 +02001473 _packetType = RTCPPacketTypes::kPsfbRembItem;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001474
1475 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1476 {
1477 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1478 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1479 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1480 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1481 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001482 return true;
1483}
1484
1485bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001486RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1487{
1488 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1489
1490 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1491
1492 if (length < 8)
1493 {
Erik Språng242e22b2015-05-11 10:17:43 +02001494 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001495
1496 EndCurrentBlock();
1497 return false;
1498 }
1499
Erik Språng242e22b2015-05-11 10:17:43 +02001500 _packetType = RTCPPacketTypes::kRtpfbTmmbrItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001501
1502 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1503 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1504 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1505 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1506
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001507 uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001508
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001509 uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 15;
1510 mantissa += (_ptrRTCPData[1] << 7);
1511 mantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001512
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001513 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001514 measuredOH += _ptrRTCPData[3];
1515
1516 _ptrRTCPData += 4; // Fwd read data
1517
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001518 uint64_t bitrate_bps = (mantissa << exp);
1519 bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0;
1520 if (shift_overflow || bitrate_bps > kMaxBitrateBps) {
1521 LOG(LS_ERROR) << "Unhandled tmmbr bitrate value : " << mantissa
1522 << "*2^" << static_cast<int>(exp);
1523 _state = ParseState::State_TopLevel;
1524 EndCurrentBlock();
1525 return false;
1526 }
1527
1528 _packet.TMMBRItem.MaxTotalMediaBitRate = bitrate_bps / 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001529 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1530
1531 return true;
1532}
1533
1534bool
1535RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1536{
1537 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1538
1539 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1540
1541 if (length < 8)
1542 {
Erik Språng242e22b2015-05-11 10:17:43 +02001543 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001544
1545 EndCurrentBlock();
1546 return false;
1547 }
1548
Erik Språng242e22b2015-05-11 10:17:43 +02001549 _packetType = RTCPPacketTypes::kRtpfbTmmbnItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001550
1551 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1552 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1553 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1554 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1555
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001556 uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001557
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001558 uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 15;
1559 mantissa += (_ptrRTCPData[1] << 7);
1560 mantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001561
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001562 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001563 measuredOH += _ptrRTCPData[3];
1564
1565 _ptrRTCPData += 4; // Fwd read data
1566
Danil Chapovalovee6e4272016-04-19 12:15:10 +02001567 uint64_t bitrate_bps = (mantissa << exp);
1568 bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0;
1569 if (shift_overflow || bitrate_bps > kMaxBitrateBps) {
1570 LOG(LS_ERROR) << "Unhandled tmmbn bitrate value : " << mantissa
1571 << "*2^" << static_cast<int>(exp);
1572 _state = ParseState::State_TopLevel;
1573 EndCurrentBlock();
1574 return false;
1575 }
1576
1577 _packet.TMMBNItem.MaxTotalMediaBitRate = bitrate_bps / 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001578 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1579
1580 return true;
1581}
1582
1583bool
1584RTCPUtility::RTCPParserV2::ParseSLIItem()
1585{
1586 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1587 /*
1588 0 1 2 3
1589 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
1590 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1591 | First | Number | PictureID |
1592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1593 */
1594
1595 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1596
1597 if (length < 4)
1598 {
Erik Språng242e22b2015-05-11 10:17:43 +02001599 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001600
1601 EndCurrentBlock();
1602 return false;
1603 }
Erik Språng242e22b2015-05-11 10:17:43 +02001604 _packetType = RTCPPacketTypes::kPsfbSliItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001605
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001606 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001607 buffer = *_ptrRTCPData++ << 24;
1608 buffer += *_ptrRTCPData++ << 16;
1609 buffer += *_ptrRTCPData++ << 8;
1610 buffer += *_ptrRTCPData++;
1611
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001612 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1613 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1614 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001615
1616 return true;
1617}
1618
1619bool
1620RTCPUtility::RTCPParserV2::ParseFIRItem()
1621{
1622 // RFC 5104 4.3.1. Full Intra Request (FIR)
1623
1624 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1625
1626 if (length < 8)
1627 {
Erik Språng242e22b2015-05-11 10:17:43 +02001628 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001629
1630 EndCurrentBlock();
1631 return false;
1632 }
1633
Erik Språng242e22b2015-05-11 10:17:43 +02001634 _packetType = RTCPPacketTypes::kPsfbFirItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001635
1636 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1637 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1638 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1639 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1640
1641 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1642 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1643 return true;
1644}
1645
sprang73a93e82015-09-14 12:50:39 -07001646bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001647 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1648
1649 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1650 {
1651 EndCurrentBlock();
1652 return false;
1653 }
1654
1655 _ptrRTCPData += 4; // Skip RTCP header
1656
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001657 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001658 senderSSRC += *_ptrRTCPData++ << 16;
1659 senderSSRC += *_ptrRTCPData++ << 8;
1660 senderSSRC += *_ptrRTCPData++;
1661
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001662 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001663 name += *_ptrRTCPData++ << 16;
1664 name += *_ptrRTCPData++ << 8;
1665 name += *_ptrRTCPData++;
1666
1667 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1668
Erik Språng242e22b2015-05-11 10:17:43 +02001669 _packetType = RTCPPacketTypes::kApp;
niklase@google.com470e71d2011-07-07 08:21:25 +00001670
sprang73a93e82015-09-14 12:50:39 -07001671 _packet.APP.SubType = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +00001672 _packet.APP.Name = name;
1673
Erik Språng242e22b2015-05-11 10:17:43 +02001674 _state = ParseState::State_AppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001675 return true;
1676}
1677
1678bool
1679RTCPUtility::RTCPParserV2::ParseAPPItem()
1680{
1681 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1682 if (length < 4)
1683 {
Erik Språng242e22b2015-05-11 10:17:43 +02001684 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001685
1686 EndCurrentBlock();
1687 return false;
1688 }
Erik Språng242e22b2015-05-11 10:17:43 +02001689 _packetType = RTCPPacketTypes::kAppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001690
1691 if(length > kRtcpAppCode_DATA_SIZE)
1692 {
1693 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1694 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1695 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1696 }else
1697 {
1698 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001699 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001700 _ptrRTCPData += length;
1701 }
1702 return true;
1703}
1704
Erik Språng6b8d3552015-09-24 15:06:57 +02001705size_t RTCPUtility::RTCPParserV2::NumSkippedBlocks() const {
1706 return num_skipped_blocks_;
1707}
1708
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001709RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001710 size_t rtcpDataLength)
1711 : _ptrBegin(rtcpData),
1712 _ptrEnd(rtcpData + rtcpDataLength),
1713 _ptrBlock(NULL) {
1714 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001715}
1716
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001717RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001718}
1719
sprang73a93e82015-09-14 12:50:39 -07001720const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001721 _ptrBlock = _ptrBegin;
1722
1723 return Iterate();
1724}
1725
sprang73a93e82015-09-14 12:50:39 -07001726const RTCPUtility::RtcpCommonHeader*
1727RTCPUtility::RTCPPacketIterator::Iterate() {
1728 if ((_ptrEnd <= _ptrBlock) ||
1729 !RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) {
1730 _ptrBlock = nullptr;
1731 return nullptr;
1732 }
1733 _ptrBlock += _header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +00001734
sprang73a93e82015-09-14 12:50:39 -07001735 if (_ptrBlock > _ptrEnd) {
1736 _ptrBlock = nullptr;
1737 return nullptr;
1738 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001739
sprang73a93e82015-09-14 12:50:39 -07001740 return &_header;
niklase@google.com470e71d2011-07-07 08:21:25 +00001741}
1742
sprang73a93e82015-09-14 12:50:39 -07001743const RTCPUtility::RtcpCommonHeader*
1744RTCPUtility::RTCPPacketIterator::Current() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001745 if (!_ptrBlock)
1746 {
1747 return NULL;
1748 }
1749
1750 return &_header;
1751}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001752} // namespace webrtc