blob: eb44a870baea4f21ef1c1e16f6c5e68ac1191a45 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
14#include <math.h> // ceil
15#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
sprang73a93e82015-09-14 12:50:39 -070017#include "webrtc/base/checks.h"
18#include "webrtc/base/logging.h"
19#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
danilchapb8b6fbb2015-12-10 05:05:27 -080020#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
sprang73a93e82015-09-14 12:50:39 -070021
niklase@google.com470e71d2011-07-07 08:21:25 +000022namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000023
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000024namespace RTCPUtility {
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +000025
26NackStats::NackStats()
27 : max_sequence_number_(0),
28 requests_(0),
29 unique_requests_(0) {}
30
31NackStats::~NackStats() {}
32
33void NackStats::ReportRequest(uint16_t sequence_number) {
34 if (requests_ == 0 ||
35 webrtc::IsNewerSequenceNumber(sequence_number, max_sequence_number_)) {
36 max_sequence_number_ = sequence_number;
37 ++unique_requests_;
38 }
39 ++requests_;
40}
41
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000042uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) {
43 return (ntp_sec << 16) + (ntp_frac >> 16);
44} // end RTCPUtility
45}
46
47// RTCPParserV2 : currently read only
pbos@webrtc.org2f446732013-04-08 11:08:41 +000048RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
niklase@google.com470e71d2011-07-07 08:21:25 +000049 size_t rtcpDataLength,
50 bool rtcpReducedSizeEnable)
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000051 : _ptrRTCPDataBegin(rtcpData),
52 _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
53 _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
54 _validPacket(false),
55 _ptrRTCPData(rtcpData),
56 _ptrRTCPBlockEnd(NULL),
Erik Språng242e22b2015-05-11 10:17:43 +020057 _state(ParseState::State_TopLevel),
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000058 _numberOfBlocks(0),
Erik Språng6b8d3552015-09-24 15:06:57 +020059 num_skipped_blocks_(0),
Erik Språng242e22b2015-05-11 10:17:43 +020060 _packetType(RTCPPacketTypes::kInvalid) {
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000061 Validate();
niklase@google.com470e71d2011-07-07 08:21:25 +000062}
63
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +000064RTCPUtility::RTCPParserV2::~RTCPParserV2() {
niklase@google.com470e71d2011-07-07 08:21:25 +000065}
66
67ptrdiff_t
68RTCPUtility::RTCPParserV2::LengthLeft() const
69{
70 return (_ptrRTCPDataEnd- _ptrRTCPData);
71}
72
73RTCPUtility::RTCPPacketTypes
74RTCPUtility::RTCPParserV2::PacketType() const
75{
76 return _packetType;
77}
78
79const RTCPUtility::RTCPPacket&
80RTCPUtility::RTCPParserV2::Packet() const
81{
82 return _packet;
83}
84
Erik Språng6b8d3552015-09-24 15:06:57 +020085rtcp::RtcpPacket* RTCPUtility::RTCPParserV2::ReleaseRtcpPacket() {
86 return rtcp_packet_.release();
87}
niklase@google.com470e71d2011-07-07 08:21:25 +000088RTCPUtility::RTCPPacketTypes
89RTCPUtility::RTCPParserV2::Begin()
90{
91 _ptrRTCPData = _ptrRTCPDataBegin;
92
93 return Iterate();
94}
95
96RTCPUtility::RTCPPacketTypes
97RTCPUtility::RTCPParserV2::Iterate()
98{
99 // Reset packet type
Erik Språng242e22b2015-05-11 10:17:43 +0200100 _packetType = RTCPPacketTypes::kInvalid;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101
102 if (IsValid())
103 {
104 switch (_state)
105 {
Erik Språng242e22b2015-05-11 10:17:43 +0200106 case ParseState::State_TopLevel:
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 IterateTopLevel();
108 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200109 case ParseState::State_ReportBlockItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 IterateReportBlockItem();
111 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200112 case ParseState::State_SDESChunk:
niklase@google.com470e71d2011-07-07 08:21:25 +0000113 IterateSDESChunk();
114 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200115 case ParseState::State_BYEItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 IterateBYEItem();
117 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200118 case ParseState::State_ExtendedJitterItem:
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000119 IterateExtendedJitterItem();
120 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200121 case ParseState::State_RTPFB_NACKItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000122 IterateNACKItem();
123 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200124 case ParseState::State_RTPFB_TMMBRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 IterateTMMBRItem();
126 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200127 case ParseState::State_RTPFB_TMMBNItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 IterateTMMBNItem();
129 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200130 case ParseState::State_PSFB_SLIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 IterateSLIItem();
132 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200133 case ParseState::State_PSFB_RPSIItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000134 IterateRPSIItem();
135 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200136 case ParseState::State_PSFB_FIRItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 IterateFIRItem();
138 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200139 case ParseState::State_PSFB_AppItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000140 IteratePsfbAppItem();
141 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200142 case ParseState::State_PSFB_REMBItem:
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000143 IteratePsfbREMBItem();
144 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200145 case ParseState::State_XRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000146 IterateXrItem();
147 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200148 case ParseState::State_XR_DLLRItem:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000149 IterateXrDlrrItem();
150 break;
Erik Språng242e22b2015-05-11 10:17:43 +0200151 case ParseState::State_AppItem:
niklase@google.com470e71d2011-07-07 08:21:25 +0000152 IterateAppItem();
153 break;
154 default:
Erik Språng6b8d3552015-09-24 15:06:57 +0200155 RTC_NOTREACHED() << "Invalid state!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 break;
157 }
158 }
159 return _packetType;
160}
161
162void
163RTCPUtility::RTCPParserV2::IterateTopLevel()
164{
165 for (;;)
166 {
sprang73a93e82015-09-14 12:50:39 -0700167 RtcpCommonHeader header;
168 if (_ptrRTCPDataEnd <= _ptrRTCPData)
169 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
sprang73a93e82015-09-14 12:50:39 -0700171 if (!RtcpParseCommonHeader(_ptrRTCPData, _ptrRTCPDataEnd - _ptrRTCPData,
172 &header)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000173 return;
174 }
sprang73a93e82015-09-14 12:50:39 -0700175 _ptrRTCPBlockEnd = _ptrRTCPData + header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +0000176 if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
177 {
Erik Språng6b8d3552015-09-24 15:06:57 +0200178 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 return;
180 }
181
sprang73a93e82015-09-14 12:50:39 -0700182 switch (header.packet_type) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000183 case PT_SR:
184 {
185 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700186 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000187 ParseSR();
188 return;
189 }
190 case PT_RR:
191 {
192 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700193 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194 ParseRR();
195 return;
196 }
197 case PT_SDES:
198 {
199 // number of SDES blocks
sprang73a93e82015-09-14 12:50:39 -0700200 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 const bool ok = ParseSDES();
202 if (!ok)
203 {
204 // Nothing supported found, continue to next block!
205 break;
206 }
207 return;
208 }
209 case PT_BYE:
210 {
sprang73a93e82015-09-14 12:50:39 -0700211 _numberOfBlocks = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212 const bool ok = ParseBYE();
213 if (!ok)
214 {
215 // Nothing supported found, continue to next block!
216 break;
217 }
218 return;
219 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000220 case PT_IJ:
221 {
222 // number of Report blocks
sprang73a93e82015-09-14 12:50:39 -0700223 _numberOfBlocks = header.count_or_format;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000224 ParseIJ();
225 return;
226 }
Erik Språng6b8d3552015-09-24 15:06:57 +0200227 case PT_RTPFB:
228 FALLTHROUGH();
niklase@google.com470e71d2011-07-07 08:21:25 +0000229 case PT_PSFB:
230 {
Erik Språng6b8d3552015-09-24 15:06:57 +0200231 if (!ParseFBCommon(header)) {
232 // Nothing supported found, continue to next block!
233 break;
234 }
235 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000236 }
237 case PT_APP:
238 {
239 const bool ok = ParseAPP(header);
240 if (!ok)
241 {
242 // Nothing supported found, continue to next block!
243 break;
244 }
245 return;
246 }
247 case PT_XR:
248 {
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000249 const bool ok = ParseXr();
niklase@google.com470e71d2011-07-07 08:21:25 +0000250 if (!ok)
251 {
252 // Nothing supported found, continue to next block!
253 break;
254 }
255 return;
256 }
257 default:
258 // Not supported! Skip!
Erik Språng6b8d3552015-09-24 15:06:57 +0200259 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000260 EndCurrentBlock();
261 break;
262 }
263 }
264}
265
266void
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000267RTCPUtility::RTCPParserV2::IterateXrItem()
268{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000269 const bool success = ParseXrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000270 if (!success)
271 {
272 Iterate();
273 }
274}
275
276void
277RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
278{
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000279 const bool success = ParseXrDlrrItem();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000280 if (!success)
281 {
282 Iterate();
283 }
284}
285
286void
niklase@google.com470e71d2011-07-07 08:21:25 +0000287RTCPUtility::RTCPParserV2::IterateReportBlockItem()
288{
289 const bool success = ParseReportBlockItem();
290 if (!success)
291 {
292 Iterate();
293 }
294}
295
296void
297RTCPUtility::RTCPParserV2::IterateSDESChunk()
298{
299 const bool success = ParseSDESChunk();
300 if (!success)
301 {
302 Iterate();
303 }
304}
305
306void
307RTCPUtility::RTCPParserV2::IterateBYEItem()
308{
309 const bool success = ParseBYEItem();
310 if (!success)
311 {
312 Iterate();
313 }
314}
315
316void
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000317RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
318{
319 const bool success = ParseIJItem();
320 if (!success)
321 {
322 Iterate();
323 }
324}
325
326void
niklase@google.com470e71d2011-07-07 08:21:25 +0000327RTCPUtility::RTCPParserV2::IterateNACKItem()
328{
329 const bool success = ParseNACKItem();
330 if (!success)
331 {
332 Iterate();
333 }
334}
335
336void
337RTCPUtility::RTCPParserV2::IterateTMMBRItem()
338{
339 const bool success = ParseTMMBRItem();
340 if (!success)
341 {
342 Iterate();
343 }
344}
345
346void
347RTCPUtility::RTCPParserV2::IterateTMMBNItem()
348{
349 const bool success = ParseTMMBNItem();
350 if (!success)
351 {
352 Iterate();
353 }
354}
355
356void
357RTCPUtility::RTCPParserV2::IterateSLIItem()
358{
359 const bool success = ParseSLIItem();
360 if (!success)
361 {
362 Iterate();
363 }
364}
365
366void
367RTCPUtility::RTCPParserV2::IterateRPSIItem()
368{
369 const bool success = ParseRPSIItem();
370 if (!success)
371 {
372 Iterate();
373 }
374}
375
376void
377RTCPUtility::RTCPParserV2::IterateFIRItem()
378{
379 const bool success = ParseFIRItem();
380 if (!success)
381 {
382 Iterate();
383 }
384}
385
386void
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000387RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
388{
389 const bool success = ParsePsfbAppItem();
390 if (!success)
391 {
392 Iterate();
393 }
394}
395
396void
397RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
398{
399 const bool success = ParsePsfbREMBItem();
400 if (!success)
401 {
402 Iterate();
403 }
404}
405
406void
niklase@google.com470e71d2011-07-07 08:21:25 +0000407RTCPUtility::RTCPParserV2::IterateAppItem()
408{
409 const bool success = ParseAPPItem();
410 if (!success)
411 {
412 Iterate();
413 }
414}
415
416void
417RTCPUtility::RTCPParserV2::Validate()
418{
sprang73a93e82015-09-14 12:50:39 -0700419 if (_ptrRTCPData == nullptr)
420 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
sprang73a93e82015-09-14 12:50:39 -0700422 RtcpCommonHeader header;
423 if (_ptrRTCPDataEnd <= _ptrRTCPDataBegin)
424 return; // NOT VALID
niklase@google.com470e71d2011-07-07 08:21:25 +0000425
sprang73a93e82015-09-14 12:50:39 -0700426 if (!RtcpParseCommonHeader(_ptrRTCPDataBegin,
427 _ptrRTCPDataEnd - _ptrRTCPDataBegin, &header))
428 return; // NOT VALID!
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
430 // * if (!reducedSize) : first packet must be RR or SR.
431 //
432 // * The padding bit (P) should be zero for the first packet of a
433 // compound RTCP packet because padding should only be applied,
434 // if it is needed, to the last packet. (NOT CHECKED!)
435 //
436 // * The length fields of the individual RTCP packets must add up
437 // to the overall length of the compound RTCP packet as
438 // received. This is a fairly strong check. (NOT CHECKED!)
439
440 if (!_RTCPReducedSizeEnable)
441 {
sprang73a93e82015-09-14 12:50:39 -0700442 if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR)) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 return; // NOT VALID
444 }
445 }
446
447 _validPacket = true;
448}
449
450bool
451RTCPUtility::RTCPParserV2::IsValid() const
452{
453 return _validPacket;
454}
455
456void
457RTCPUtility::RTCPParserV2::EndCurrentBlock()
458{
459 _ptrRTCPData = _ptrRTCPBlockEnd;
460}
461
sprang73a93e82015-09-14 12:50:39 -0700462// 0 1 2 3
463// 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
464// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465// |V=2|P| IC | PT | length |
466// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467//
468// Common header for all RTCP packets, 4 octets.
469
470bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet,
471 size_t size_bytes,
472 RtcpCommonHeader* parsed_header) {
henrikg91d6ede2015-09-17 00:24:34 -0700473 RTC_DCHECK(parsed_header != nullptr);
sprang73a93e82015-09-14 12:50:39 -0700474 if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) {
475 LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte"
476 << (size_bytes != 1 ? "s" : "")
477 << ") remaining in buffer to parse RTCP header (4 bytes).";
478 return false;
479 }
480
481 const uint8_t kRtcpVersion = 2;
482 uint8_t version = packet[0] >> 6;
483 if (version != kRtcpVersion) {
484 LOG(LS_WARNING) << "Invalid RTCP header: Version must be "
485 << static_cast<int>(kRtcpVersion) << " but was "
486 << static_cast<int>(version);
487 return false;
488 }
489
490 bool has_padding = (packet[0] & 0x20) != 0;
491 uint8_t format = packet[0] & 0x1F;
492 uint8_t packet_type = packet[1];
493 size_t packet_size_words =
494 ByteReader<uint16_t>::ReadBigEndian(&packet[2]) + 1;
495
496 if (size_bytes < packet_size_words * 4) {
497 LOG(LS_WARNING) << "Buffer too small (" << size_bytes
498 << " bytes) to fit an RtcpPacket of " << packet_size_words
499 << " 32bit words.";
500 return false;
501 }
502
503 size_t payload_size = packet_size_words * 4;
504 size_t padding_bytes = 0;
505 if (has_padding) {
506 if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) {
507 LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload "
508 "size specified.";
509 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000510 }
511
sprang73a93e82015-09-14 12:50:39 -0700512 padding_bytes = packet[payload_size - 1];
513 if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) {
514 LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
515 << padding_bytes << ") for a packet size of "
516 << payload_size << "bytes.";
517 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000518 }
sprang73a93e82015-09-14 12:50:39 -0700519 payload_size -= padding_bytes;
520 }
521 payload_size -= RtcpCommonHeader::kHeaderSizeBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000522
sprang73a93e82015-09-14 12:50:39 -0700523 parsed_header->version = kRtcpVersion;
524 parsed_header->count_or_format = format;
525 parsed_header->packet_type = packet_type;
526 parsed_header->payload_size_bytes = payload_size;
527 parsed_header->padding_bytes = padding_bytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000528
sprang73a93e82015-09-14 12:50:39 -0700529 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530}
531
532bool
533RTCPUtility::RTCPParserV2::ParseRR()
534{
535 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
536
537 if (length < 8)
538 {
539 return false;
540 }
541
542
543 _ptrRTCPData += 4; // Skip header
544
Erik Språng242e22b2015-05-11 10:17:43 +0200545 _packetType = RTCPPacketTypes::kRr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546
547 _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
548 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
549 _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
550 _packet.RR.SenderSSRC += *_ptrRTCPData++;
551
552 _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
553
554 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200555 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000556
557 return true;
558}
559
560bool
561RTCPUtility::RTCPParserV2::ParseSR()
562{
563 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
564
565 if (length < 28)
566 {
567 EndCurrentBlock();
568 return false;
569 }
570
571 _ptrRTCPData += 4; // Skip header
572
Erik Språng242e22b2015-05-11 10:17:43 +0200573 _packetType = RTCPPacketTypes::kSr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
575 _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
576 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
577 _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
578 _packet.SR.SenderSSRC += *_ptrRTCPData++;
579
580 _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
581 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
582 _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
583 _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
584
585 _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
586 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
587 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
588 _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
589
590 _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
591 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
592 _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
593 _packet.SR.RTPTimestamp += *_ptrRTCPData++;
594
595 _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
596 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
597 _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
598 _packet.SR.SenderPacketCount += *_ptrRTCPData++;
599
600 _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
601 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
602 _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
603 _packet.SR.SenderOctetCount += *_ptrRTCPData++;
604
605 _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
606
607 // State transition
608 if(_numberOfBlocks != 0)
609 {
Erik Språng242e22b2015-05-11 10:17:43 +0200610 _state = ParseState::State_ReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000611 }else
612 {
613 // don't go to state report block item if 0 report blocks
Erik Språng242e22b2015-05-11 10:17:43 +0200614 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000615 EndCurrentBlock();
616 }
617 return true;
618}
619
620bool
621RTCPUtility::RTCPParserV2::ParseReportBlockItem()
622{
623 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
624
625 if (length < 24 || _numberOfBlocks <= 0)
626 {
Erik Språng242e22b2015-05-11 10:17:43 +0200627 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000628
629 EndCurrentBlock();
630 return false;
631 }
632 _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
633 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
634 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
635 _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
636
637 _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
638
639 _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
640 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
641 _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
642
643 _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
644 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
645 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
646 _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
647
648 _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
649 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
650 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
651 _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
652
653 _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
654 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
655 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
656 _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
657
658 _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
659 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
660 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
661 _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
662
663 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200664 _packetType = RTCPPacketTypes::kReportBlockItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000665 return true;
666}
667
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000668/* From RFC 5450: Transmission Time Offsets in RTP Streams.
669 0 1 2 3
670 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
671 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
672 hdr |V=2|P| RC | PT=IJ=195 | length |
673 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
674 | inter-arrival jitter |
675 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676 . .
677 . .
678 . .
679 | inter-arrival jitter |
680 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
681*/
682
683bool
684RTCPUtility::RTCPParserV2::ParseIJ()
685{
686 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
687
688 if (length < 4)
689 {
690 return false;
691 }
692
693 _ptrRTCPData += 4; // Skip header
694
Erik Språng242e22b2015-05-11 10:17:43 +0200695 _packetType = RTCPPacketTypes::kExtendedIj;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000696
697 // State transition
Erik Språng242e22b2015-05-11 10:17:43 +0200698 _state = ParseState::State_ExtendedJitterItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000699 return true;
700}
701
702bool
703RTCPUtility::RTCPParserV2::ParseIJItem()
704{
705 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
706
707 if (length < 4 || _numberOfBlocks <= 0)
708 {
Erik Språng242e22b2015-05-11 10:17:43 +0200709 _state = ParseState::State_TopLevel;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000710 EndCurrentBlock();
711 return false;
712 }
713
714 _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
715 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
716 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
717 _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
718
719 _numberOfBlocks--;
Erik Språng242e22b2015-05-11 10:17:43 +0200720 _packetType = RTCPPacketTypes::kExtendedIjItem;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000721 return true;
722}
723
niklase@google.com470e71d2011-07-07 08:21:25 +0000724bool
725RTCPUtility::RTCPParserV2::ParseSDES()
726{
727 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
728
729 if (length < 8)
730 {
Erik Språng242e22b2015-05-11 10:17:43 +0200731 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000732
733 EndCurrentBlock();
734 return false;
735 }
736 _ptrRTCPData += 4; // Skip header
737
Erik Språng242e22b2015-05-11 10:17:43 +0200738 _state = ParseState::State_SDESChunk;
739 _packetType = RTCPPacketTypes::kSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000740 return true;
741}
742
743bool
744RTCPUtility::RTCPParserV2::ParseSDESChunk()
745{
746 if(_numberOfBlocks <= 0)
747 {
Erik Språng242e22b2015-05-11 10:17:43 +0200748 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000749
750 EndCurrentBlock();
751 return false;
752 }
753 _numberOfBlocks--;
754
755 // Find CName item in a SDES chunk.
756 while (_ptrRTCPData < _ptrRTCPBlockEnd)
757 {
758 const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
759 if (dataLen < 4)
760 {
Erik Språng242e22b2015-05-11 10:17:43 +0200761 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000762
763 EndCurrentBlock();
764 return false;
765 }
766
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000767 uint32_t SSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +0000768 SSRC += *_ptrRTCPData++ << 16;
769 SSRC += *_ptrRTCPData++ << 8;
770 SSRC += *_ptrRTCPData++;
771
772 const bool foundCname = ParseSDESItem();
773 if (foundCname)
774 {
775 _packet.CName.SenderSSRC = SSRC; // Add SSRC
776 return true;
777 }
778 }
Erik Språng242e22b2015-05-11 10:17:43 +0200779 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000780
781 EndCurrentBlock();
782 return false;
783}
784
785bool
786RTCPUtility::RTCPParserV2::ParseSDESItem()
787{
788 // Find CName
789 // Only the CNAME item is mandatory. RFC 3550 page 46
790 bool foundCName = false;
791
792 size_t itemOctetsRead = 0;
793 while (_ptrRTCPData < _ptrRTCPBlockEnd)
794 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000795 const uint8_t tag = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000796 ++itemOctetsRead;
797
798 if (tag == 0)
799 {
800 // End tag! 4 oct aligned
801 while ((itemOctetsRead++ % 4) != 0)
802 {
803 ++_ptrRTCPData;
804 }
805 return foundCName;
806 }
807
808 if (_ptrRTCPData < _ptrRTCPBlockEnd)
809 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000810 const uint8_t len = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000811 ++itemOctetsRead;
812
813 if (tag == 1)
814 {
815 // CNAME
816
817 // Sanity
818 if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
819 {
Erik Språng242e22b2015-05-11 10:17:43 +0200820 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000821
822 EndCurrentBlock();
823 return false;
824 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000825 uint8_t i = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000826 for (; i < len; ++i)
niklase@google.com470e71d2011-07-07 08:21:25 +0000827 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000828 const uint8_t c = _ptrRTCPData[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000829 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
830 {
831 // Illegal char
Erik Språng242e22b2015-05-11 10:17:43 +0200832 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000833
834 EndCurrentBlock();
835 return false;
836 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000837 _packet.CName.CName[i] = c;
838 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000839 // Make sure we are null terminated.
840 _packet.CName.CName[i] = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200841 _packetType = RTCPPacketTypes::kSdesChunk;
niklase@google.com470e71d2011-07-07 08:21:25 +0000842
843 foundCName = true;
844 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000845 _ptrRTCPData += len;
846 itemOctetsRead += len;
847 }
848 }
849
850 // No end tag found!
Erik Språng242e22b2015-05-11 10:17:43 +0200851 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000852
853 EndCurrentBlock();
854 return false;
855}
856
857bool
858RTCPUtility::RTCPParserV2::ParseBYE()
859{
860 _ptrRTCPData += 4; // Skip header
861
Erik Språng242e22b2015-05-11 10:17:43 +0200862 _state = ParseState::State_BYEItem;
niklase@google.com470e71d2011-07-07 08:21:25 +0000863
864 return ParseBYEItem();
865}
866
867bool
868RTCPUtility::RTCPParserV2::ParseBYEItem()
869{
870 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
871 if (length < 4 || _numberOfBlocks == 0)
872 {
Erik Språng242e22b2015-05-11 10:17:43 +0200873 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000874
875 EndCurrentBlock();
876 return false;
877 }
878
Erik Språng242e22b2015-05-11 10:17:43 +0200879 _packetType = RTCPPacketTypes::kBye;
niklase@google.com470e71d2011-07-07 08:21:25 +0000880
881 _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
882 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
883 _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
884 _packet.BYE.SenderSSRC += *_ptrRTCPData++;
885
886 // we can have several CSRCs attached
887
888 // sanity
889 if(length >= 4*_numberOfBlocks)
890 {
891 _ptrRTCPData += (_numberOfBlocks -1)*4;
892 }
893 _numberOfBlocks = 0;
894
895 return true;
896}
897/*
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000898 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +0000899 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
900 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
901 |V=2|P|reserved | PT=XR=207 | length |
902 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
903 | SSRC |
904 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
905 : report blocks :
906 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
907*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000908bool RTCPUtility::RTCPParserV2::ParseXr()
niklase@google.com470e71d2011-07-07 08:21:25 +0000909{
910 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000911 if (length < 8)
912 {
913 EndCurrentBlock();
914 return false;
915 }
916
917 _ptrRTCPData += 4; // Skip header
918
919 _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
920 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
921 _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
922 _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
923
Erik Språng242e22b2015-05-11 10:17:43 +0200924 _packetType = RTCPPacketTypes::kXrHeader;
925 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000926 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000927}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000928
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000929/* Extended report block format (RFC 3611).
930 BT: block type.
931 block length: length of report block in 32-bits words minus one (including
932 the header).
niklase@google.com470e71d2011-07-07 08:21:25 +0000933 0 1 2 3
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000934 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 +0000935 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
936 | BT | type-specific | block length |
937 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
938 : type-specific block contents :
939 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
940*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000941bool RTCPUtility::RTCPParserV2::ParseXrItem() {
942 const int kBlockHeaderLengthInBytes = 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000943 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000944 if (length < kBlockHeaderLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200945 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000946 EndCurrentBlock();
947 return false;
948 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000949
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000950 uint8_t block_type = *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000951 _ptrRTCPData++; // Ignore reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +0000952
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000953 uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
954 block_length_in_4bytes += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000955
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000956 switch (block_type) {
957 case kBtReceiverReferenceTime:
958 return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
959 case kBtDlrr:
960 return ParseXrDlrr(block_length_in_4bytes);
961 case kBtVoipMetric:
962 return ParseXrVoipMetricItem(block_length_in_4bytes);
963 default:
964 return ParseXrUnsupportedBlockType(block_length_in_4bytes);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000965 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000966}
967
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000968/* Receiver Reference Time Report Block.
969 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000970 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
971 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
972 | BT=4 | reserved | block length = 2 |
973 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
974 | NTP timestamp, most significant word |
975 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
976 | NTP timestamp, least significant word |
977 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
978*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000979bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
980 int block_length_4bytes) {
981 const int kBlockLengthIn4Bytes = 2;
982 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000983 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000984 if (block_length_4bytes != kBlockLengthIn4Bytes ||
985 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +0200986 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000987 EndCurrentBlock();
988 return false;
989 }
990
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000991 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
992 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
993 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
994 _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000995
asapersson@webrtc.org38599512013-11-12 08:08:26 +0000996 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
997 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
998 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
999 _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001000
Erik Språng242e22b2015-05-11 10:17:43 +02001001 _packetType = RTCPPacketTypes::kXrReceiverReferenceTime;
1002 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001003 return true;
1004}
1005
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001006/* DLRR Report Block.
1007 0 1 2 3
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001008 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
1009 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1010 | BT=5 | reserved | block length |
1011 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1012 | SSRC_1 (SSRC of first receiver) | sub-
1013 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1014 | last RR (LRR) | 1
1015 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1016 | delay since last RR (DLRR) |
1017 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1018 | SSRC_2 (SSRC of second receiver) | sub-
1019 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1020 : ... : 2
1021 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1022*/
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001023bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
1024 const int kSubBlockLengthIn4Bytes = 3;
1025 if (block_length_4bytes < 0 ||
1026 (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001027 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001028 EndCurrentBlock();
1029 return false;
1030 }
Erik Språng242e22b2015-05-11 10:17:43 +02001031 _packetType = RTCPPacketTypes::kXrDlrrReportBlock;
1032 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001033 _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
1034 return true;
1035}
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001036
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001037bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001038 if (_numberOfBlocks == 0) {
Erik Språng242e22b2015-05-11 10:17:43 +02001039 _state = ParseState::State_XRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001040 return false;
1041 }
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001042 const int kSubBlockLengthInBytes = 12;
1043 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1044 if (length < kSubBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001045 _state = ParseState::State_TopLevel;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001046 EndCurrentBlock();
1047 return false;
1048 }
1049
1050 _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
1051 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
1052 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
1053 _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
1054
1055 _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
1056 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
1057 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
1058 _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
1059
1060 _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
1061 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
1062 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
1063 _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
1064
Erik Språng242e22b2015-05-11 10:17:43 +02001065 _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001066 --_numberOfBlocks;
Erik Språng242e22b2015-05-11 10:17:43 +02001067 _state = ParseState::State_XR_DLLRItem;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001068 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001069}
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001070/* VoIP Metrics Report Block.
1071 0 1 2 3
niklase@google.com470e71d2011-07-07 08:21:25 +00001072 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
1073 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1074 | BT=7 | reserved | block length = 8 |
1075 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1076 | SSRC of source |
1077 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1078 | loss rate | discard rate | burst density | gap density |
1079 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1080 | burst duration | gap duration |
1081 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1082 | round trip delay | end system delay |
1083 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1084 | signal level | noise level | RERL | Gmin |
1085 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1086 | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1087 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1088 | RX config | reserved | JB nominal |
1089 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1090 | JB maximum | JB abs max |
1091 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1092*/
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001093
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001094bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
1095 const int kBlockLengthIn4Bytes = 8;
1096 const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
1097 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1098 if (block_length_4bytes != kBlockLengthIn4Bytes ||
1099 length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001100 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001101 EndCurrentBlock();
1102 return false;
1103 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001104
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001105 _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
1106 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
1107 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
1108 _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001109
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001110 _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
1111 _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
1112 _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
1113 _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001114
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001115 _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
1116 _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001117
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001118 _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
1119 _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001120
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001121 _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
1122 _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001123
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001124 _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
1125 _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001126
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001127 _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
1128 _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
1129 _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
1130 _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
1131 _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
1132 _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
1133 _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
1134 _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
1135 _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
1136 _ptrRTCPData++; // skip reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001137
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001138 _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
1139 _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001140
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001141 _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
1142 _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001143
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001144 _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
1145 _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001146
Erik Språng242e22b2015-05-11 10:17:43 +02001147 _packetType = RTCPPacketTypes::kXrVoipMetric;
1148 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001149 return true;
1150}
niklase@google.com470e71d2011-07-07 08:21:25 +00001151
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001152bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
1153 int block_length_4bytes) {
1154 const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
1155 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1156 if (length < kBlockLengthInBytes) {
Erik Språng242e22b2015-05-11 10:17:43 +02001157 _state = ParseState::State_TopLevel;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001158 EndCurrentBlock();
1159 return false;
1160 }
1161 // Skip block.
1162 _ptrRTCPData += kBlockLengthInBytes;
Erik Språng242e22b2015-05-11 10:17:43 +02001163 _state = ParseState::State_XRItem;
asapersson@webrtc.org38599512013-11-12 08:08:26 +00001164 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001165}
1166
sprang73a93e82015-09-14 12:50:39 -07001167bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001168 RTC_CHECK((header.packet_type == PT_RTPFB) ||
1169 (header.packet_type == PT_PSFB)); // Parser logic check
niklase@google.com470e71d2011-07-07 08:21:25 +00001170
1171 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1172
Erik Språng6b8d3552015-09-24 15:06:57 +02001173 // 4 * 3, RFC4585 section 6.1
1174 if (length < 12) {
1175 LOG(LS_WARNING)
1176 << "Invalid RTCP packet: Too little data (" << length
1177 << " bytes) left in buffer to parse a 12 byte RTPFB/PSFB message.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001178 return false;
1179 }
1180
1181 _ptrRTCPData += 4; // Skip RTCP header
1182
Erik Språng6b8d3552015-09-24 15:06:57 +02001183 uint32_t senderSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1184 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001185
Erik Språng6b8d3552015-09-24 15:06:57 +02001186 uint32_t mediaSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
1187 _ptrRTCPData += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001188
sprang73a93e82015-09-14 12:50:39 -07001189 if (header.packet_type == PT_RTPFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001190 // Transport layer feedback
1191
sprang73a93e82015-09-14 12:50:39 -07001192 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001193 case 1:
1194 {
1195 // NACK
Erik Språng242e22b2015-05-11 10:17:43 +02001196 _packetType = RTCPPacketTypes::kRtpfbNack;
niklase@google.com470e71d2011-07-07 08:21:25 +00001197 _packet.NACK.SenderSSRC = senderSSRC;
1198 _packet.NACK.MediaSSRC = mediaSSRC;
1199
Erik Språng242e22b2015-05-11 10:17:43 +02001200 _state = ParseState::State_RTPFB_NACKItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001201
1202 return true;
1203 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001204 case 3:
1205 {
1206 // TMMBR
Erik Språng242e22b2015-05-11 10:17:43 +02001207 _packetType = RTCPPacketTypes::kRtpfbTmmbr;
niklase@google.com470e71d2011-07-07 08:21:25 +00001208 _packet.TMMBR.SenderSSRC = senderSSRC;
1209 _packet.TMMBR.MediaSSRC = mediaSSRC;
1210
Erik Språng242e22b2015-05-11 10:17:43 +02001211 _state = ParseState::State_RTPFB_TMMBRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001212
1213 return true;
1214 }
1215 case 4:
1216 {
1217 // TMMBN
Erik Språng242e22b2015-05-11 10:17:43 +02001218 _packetType = RTCPPacketTypes::kRtpfbTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001219 _packet.TMMBN.SenderSSRC = senderSSRC;
1220 _packet.TMMBN.MediaSSRC = mediaSSRC;
1221
Erik Språng242e22b2015-05-11 10:17:43 +02001222 _state = ParseState::State_RTPFB_TMMBNItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001223
1224 return true;
1225 }
1226 case 5:
1227 {
1228 // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
1229 // draft-perkins-avt-rapid-rtp-sync-03.txt
1230 // trigger a new RTCP SR
Erik Språng242e22b2015-05-11 10:17:43 +02001231 _packetType = RTCPPacketTypes::kRtpfbSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +00001232
1233 // Note: No state transition, SR REQ is empty!
1234 return true;
1235 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001236 case 15: {
Erik Språng6b8d3552015-09-24 15:06:57 +02001237 rtcp_packet_ =
1238 rtcp::TransportFeedback::ParseFrom(_ptrRTCPData - 12, length);
1239 // Since we parse the whole packet here, keep the TopLevel state and
1240 // just end the current block.
sprang49f9cdb2015-10-01 03:06:57 -07001241 EndCurrentBlock();
Erik Språng6b8d3552015-09-24 15:06:57 +02001242 if (rtcp_packet_.get()) {
sprang49f9cdb2015-10-01 03:06:57 -07001243 _packetType = RTCPPacketTypes::kTransportFeedback;
Erik Språng6b8d3552015-09-24 15:06:57 +02001244 return true;
1245 }
1246 break;
1247 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001248 default:
1249 break;
1250 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001251 // Unsupported RTPFB message. Skip and move to next block.
1252 ++num_skipped_blocks_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001253 return false;
sprang73a93e82015-09-14 12:50:39 -07001254 } else if (header.packet_type == PT_PSFB) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001255 // Payload specific feedback
sprang73a93e82015-09-14 12:50:39 -07001256 switch (header.count_or_format) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001257 case 1:
1258 // PLI
Erik Språng242e22b2015-05-11 10:17:43 +02001259 _packetType = RTCPPacketTypes::kPsfbPli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001260 _packet.PLI.SenderSSRC = senderSSRC;
1261 _packet.PLI.MediaSSRC = mediaSSRC;
1262
1263 // Note: No state transition, PLI FCI is empty!
1264 return true;
1265 case 2:
1266 // SLI
Erik Språng242e22b2015-05-11 10:17:43 +02001267 _packetType = RTCPPacketTypes::kPsfbSli;
niklase@google.com470e71d2011-07-07 08:21:25 +00001268 _packet.SLI.SenderSSRC = senderSSRC;
1269 _packet.SLI.MediaSSRC = mediaSSRC;
1270
Erik Språng242e22b2015-05-11 10:17:43 +02001271 _state = ParseState::State_PSFB_SLIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001272
1273 return true;
1274 case 3:
Erik Språng242e22b2015-05-11 10:17:43 +02001275 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 _packet.RPSI.SenderSSRC = senderSSRC;
1277 _packet.RPSI.MediaSSRC = mediaSSRC;
1278
Erik Språng242e22b2015-05-11 10:17:43 +02001279 _state = ParseState::State_PSFB_RPSIItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001280 return true;
1281 case 4:
1282 // FIR
Erik Språng242e22b2015-05-11 10:17:43 +02001283 _packetType = RTCPPacketTypes::kPsfbFir;
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 _packet.FIR.SenderSSRC = senderSSRC;
1285 _packet.FIR.MediaSSRC = mediaSSRC;
1286
Erik Språng242e22b2015-05-11 10:17:43 +02001287 _state = ParseState::State_PSFB_FIRItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001288 return true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001289 case 15:
Erik Språng242e22b2015-05-11 10:17:43 +02001290 _packetType = RTCPPacketTypes::kPsfbApp;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001291 _packet.PSFBAPP.SenderSSRC = senderSSRC;
1292 _packet.PSFBAPP.MediaSSRC = mediaSSRC;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001293
Erik Språng242e22b2015-05-11 10:17:43 +02001294 _state = ParseState::State_PSFB_AppItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001295 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001296 default:
1297 break;
1298 }
1299
niklase@google.com470e71d2011-07-07 08:21:25 +00001300 return false;
1301 }
1302 else
1303 {
Erik Språng6b8d3552015-09-24 15:06:57 +02001304 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +00001305 return false;
1306 }
1307}
1308
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001309bool RTCPUtility::RTCPParserV2::ParseRPSIItem() {
1310
1311 // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI).
1312 //
1313 // 0 1 2 3
1314 // 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
1315 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1316 // | PB |0| Payload Type| Native RPSI bit string |
1317 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1318 // | defined per codec ... | Padding (0) |
1319 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
niklase@google.com470e71d2011-07-07 08:21:25 +00001320
1321 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1322
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001323 if (length < 4) {
Erik Språng242e22b2015-05-11 10:17:43 +02001324 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001325
1326 EndCurrentBlock();
1327 return false;
1328 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001329 if (length > 2 + RTCP_RPSI_DATA_SIZE) {
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 }
1335
Erik Språng242e22b2015-05-11 10:17:43 +02001336 _packetType = RTCPPacketTypes::kPsfbRpsi;
niklase@google.com470e71d2011-07-07 08:21:25 +00001337
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001338 uint8_t padding_bits = *_ptrRTCPData++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001339 _packet.RPSI.PayloadType = *_ptrRTCPData++;
1340
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001341 memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
1342 _ptrRTCPData += length - 2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001343
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001344 _packet.RPSI.NumberOfValidBits =
1345 static_cast<uint16_t>(length - 2) * 8 - padding_bits;
niklase@google.com470e71d2011-07-07 08:21:25 +00001346 return true;
1347}
1348
1349bool
1350RTCPUtility::RTCPParserV2::ParseNACKItem()
1351{
1352 // RFC 4585 6.2.1. Generic NACK
1353
1354 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1355
1356 if (length < 4)
1357 {
Erik Språng242e22b2015-05-11 10:17:43 +02001358 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001359
1360 EndCurrentBlock();
1361 return false;
1362 }
1363
Erik Språng242e22b2015-05-11 10:17:43 +02001364 _packetType = RTCPPacketTypes::kRtpfbNackItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001365
1366 _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
1367 _packet.NACKItem.PacketID += *_ptrRTCPData++;
1368
1369 _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
1370 _packet.NACKItem.BitMask += *_ptrRTCPData++;
1371
1372 return true;
1373}
1374
1375bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001376RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
1377{
1378 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1379
1380 if (length < 4)
1381 {
Erik Språng242e22b2015-05-11 10:17:43 +02001382 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001383
1384 EndCurrentBlock();
1385 return false;
1386 }
1387 if(*_ptrRTCPData++ != 'R')
1388 {
Erik Språng242e22b2015-05-11 10:17:43 +02001389 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001390
1391 EndCurrentBlock();
1392 return false;
1393 }
1394 if(*_ptrRTCPData++ != 'E')
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++ != 'M')
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++ != 'B')
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 }
Erik Språng242e22b2015-05-11 10:17:43 +02001415 _packetType = RTCPPacketTypes::kPsfbRemb;
1416 _state = ParseState::State_PSFB_REMBItem;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001417 return true;
1418}
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001419
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001420bool
1421RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
1422{
1423 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1424
1425 if (length < 4)
1426 {
Erik Språng242e22b2015-05-11 10:17:43 +02001427 _state = ParseState::State_TopLevel;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001428
1429 EndCurrentBlock();
1430 return false;
1431 }
1432
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001433 _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001434 const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001435
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001436 uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001437 brMantissa += (_ptrRTCPData[1] << 8);
1438 brMantissa += (_ptrRTCPData[2]);
1439
1440 _ptrRTCPData += 3; // Fwd read data
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001441 _packet.REMBItem.BitRate = (brMantissa << brExp);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001442
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001443 const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
1444 if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
1445 {
Erik Språng242e22b2015-05-11 10:17:43 +02001446 _state = ParseState::State_TopLevel;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001447
1448 EndCurrentBlock();
1449 return false;
1450 }
1451
Erik Språng242e22b2015-05-11 10:17:43 +02001452 _packetType = RTCPPacketTypes::kPsfbRembItem;
asapersson@webrtc.orga7689702012-04-19 07:01:29 +00001453
1454 for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
1455 {
1456 _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
1457 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
1458 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
1459 _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
1460 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001461 return true;
1462}
1463
1464bool
niklase@google.com470e71d2011-07-07 08:21:25 +00001465RTCPUtility::RTCPParserV2::ParseTMMBRItem()
1466{
1467 // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
1468
1469 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1470
1471 if (length < 8)
1472 {
Erik Språng242e22b2015-05-11 10:17:43 +02001473 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001474
1475 EndCurrentBlock();
1476 return false;
1477 }
1478
Erik Språng242e22b2015-05-11 10:17:43 +02001479 _packetType = RTCPPacketTypes::kRtpfbTmmbrItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001480
1481 _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
1482 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
1483 _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
1484 _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
1485
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001486 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001487
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001488 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001489 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1490 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1491
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001492 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001493 measuredOH += _ptrRTCPData[3];
1494
1495 _ptrRTCPData += 4; // Fwd read data
1496
1497 _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1498 _packet.TMMBRItem.MeasuredOverhead = measuredOH;
1499
1500 return true;
1501}
1502
1503bool
1504RTCPUtility::RTCPParserV2::ParseTMMBNItem()
1505{
1506 // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
1507
1508 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1509
1510 if (length < 8)
1511 {
Erik Språng242e22b2015-05-11 10:17:43 +02001512 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001513
1514 EndCurrentBlock();
1515 return false;
1516 }
1517
Erik Språng242e22b2015-05-11 10:17:43 +02001518 _packetType = RTCPPacketTypes::kRtpfbTmmbnItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001519
1520 _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
1521 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
1522 _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
1523 _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
1524
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001525 uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
niklase@google.com470e71d2011-07-07 08:21:25 +00001526
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001527 uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
niklase@google.com470e71d2011-07-07 08:21:25 +00001528 mxtbrMantissa += (_ptrRTCPData[1] << 7);
1529 mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
1530
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001531 uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001532 measuredOH += _ptrRTCPData[3];
1533
1534 _ptrRTCPData += 4; // Fwd read data
1535
1536 _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
1537 _packet.TMMBNItem.MeasuredOverhead = measuredOH;
1538
1539 return true;
1540}
1541
1542bool
1543RTCPUtility::RTCPParserV2::ParseSLIItem()
1544{
1545 // RFC 5104 6.3.2. Slice Loss Indication (SLI)
1546 /*
1547 0 1 2 3
1548 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
1549 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1550 | First | Number | PictureID |
1551 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1552 */
1553
1554 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1555
1556 if (length < 4)
1557 {
Erik Språng242e22b2015-05-11 10:17:43 +02001558 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001559
1560 EndCurrentBlock();
1561 return false;
1562 }
Erik Språng242e22b2015-05-11 10:17:43 +02001563 _packetType = RTCPPacketTypes::kPsfbSliItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001564
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001565 uint32_t buffer;
niklase@google.com470e71d2011-07-07 08:21:25 +00001566 buffer = *_ptrRTCPData++ << 24;
1567 buffer += *_ptrRTCPData++ << 16;
1568 buffer += *_ptrRTCPData++ << 8;
1569 buffer += *_ptrRTCPData++;
1570
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001571 _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
1572 _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
1573 _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001574
1575 return true;
1576}
1577
1578bool
1579RTCPUtility::RTCPParserV2::ParseFIRItem()
1580{
1581 // RFC 5104 4.3.1. Full Intra Request (FIR)
1582
1583 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1584
1585 if (length < 8)
1586 {
Erik Språng242e22b2015-05-11 10:17:43 +02001587 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001588
1589 EndCurrentBlock();
1590 return false;
1591 }
1592
Erik Språng242e22b2015-05-11 10:17:43 +02001593 _packetType = RTCPPacketTypes::kPsfbFirItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001594
1595 _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
1596 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
1597 _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
1598 _packet.FIRItem.SSRC += *_ptrRTCPData++;
1599
1600 _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
1601 _ptrRTCPData += 3; // Skip "Reserved" bytes.
1602 return true;
1603}
1604
sprang73a93e82015-09-14 12:50:39 -07001605bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001606 ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1607
1608 if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
1609 {
1610 EndCurrentBlock();
1611 return false;
1612 }
1613
1614 _ptrRTCPData += 4; // Skip RTCP header
1615
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001616 uint32_t senderSSRC = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001617 senderSSRC += *_ptrRTCPData++ << 16;
1618 senderSSRC += *_ptrRTCPData++ << 8;
1619 senderSSRC += *_ptrRTCPData++;
1620
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001621 uint32_t name = *_ptrRTCPData++ << 24;
niklase@google.com470e71d2011-07-07 08:21:25 +00001622 name += *_ptrRTCPData++ << 16;
1623 name += *_ptrRTCPData++ << 8;
1624 name += *_ptrRTCPData++;
1625
1626 length = _ptrRTCPBlockEnd - _ptrRTCPData;
1627
Erik Språng242e22b2015-05-11 10:17:43 +02001628 _packetType = RTCPPacketTypes::kApp;
niklase@google.com470e71d2011-07-07 08:21:25 +00001629
sprang73a93e82015-09-14 12:50:39 -07001630 _packet.APP.SubType = header.count_or_format;
niklase@google.com470e71d2011-07-07 08:21:25 +00001631 _packet.APP.Name = name;
1632
Erik Språng242e22b2015-05-11 10:17:43 +02001633 _state = ParseState::State_AppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001634 return true;
1635}
1636
1637bool
1638RTCPUtility::RTCPParserV2::ParseAPPItem()
1639{
1640 const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
1641 if (length < 4)
1642 {
Erik Språng242e22b2015-05-11 10:17:43 +02001643 _state = ParseState::State_TopLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +00001644
1645 EndCurrentBlock();
1646 return false;
1647 }
Erik Språng242e22b2015-05-11 10:17:43 +02001648 _packetType = RTCPPacketTypes::kAppItem;
niklase@google.com470e71d2011-07-07 08:21:25 +00001649
1650 if(length > kRtcpAppCode_DATA_SIZE)
1651 {
1652 memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
1653 _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
1654 _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
1655 }else
1656 {
1657 memcpy(_packet.APP.Data, _ptrRTCPData, length);
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001658 _packet.APP.Size = (uint16_t)length;
niklase@google.com470e71d2011-07-07 08:21:25 +00001659 _ptrRTCPData += length;
1660 }
1661 return true;
1662}
1663
Erik Språng6b8d3552015-09-24 15:06:57 +02001664size_t RTCPUtility::RTCPParserV2::NumSkippedBlocks() const {
1665 return num_skipped_blocks_;
1666}
1667
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001668RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001669 size_t rtcpDataLength)
1670 : _ptrBegin(rtcpData),
1671 _ptrEnd(rtcpData + rtcpDataLength),
1672 _ptrBlock(NULL) {
1673 memset(&_header, 0, sizeof(_header));
niklase@google.com470e71d2011-07-07 08:21:25 +00001674}
1675
pwestin@webrtc.orgaafa5a32012-01-17 07:07:37 +00001676RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001677}
1678
sprang73a93e82015-09-14 12:50:39 -07001679const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001680 _ptrBlock = _ptrBegin;
1681
1682 return Iterate();
1683}
1684
sprang73a93e82015-09-14 12:50:39 -07001685const RTCPUtility::RtcpCommonHeader*
1686RTCPUtility::RTCPPacketIterator::Iterate() {
1687 if ((_ptrEnd <= _ptrBlock) ||
1688 !RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) {
1689 _ptrBlock = nullptr;
1690 return nullptr;
1691 }
1692 _ptrBlock += _header.BlockSize();
niklase@google.com470e71d2011-07-07 08:21:25 +00001693
sprang73a93e82015-09-14 12:50:39 -07001694 if (_ptrBlock > _ptrEnd) {
1695 _ptrBlock = nullptr;
1696 return nullptr;
1697 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001698
sprang73a93e82015-09-14 12:50:39 -07001699 return &_header;
niklase@google.com470e71d2011-07-07 08:21:25 +00001700}
1701
sprang73a93e82015-09-14 12:50:39 -07001702const RTCPUtility::RtcpCommonHeader*
1703RTCPUtility::RTCPPacketIterator::Current() {
niklase@google.com470e71d2011-07-07 08:21:25 +00001704 if (!_ptrBlock)
1705 {
1706 return NULL;
1707 }
1708
1709 return &_header;
1710}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001711} // namespace webrtc