1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/cast/rtcp/rtcp_utility.h"
7 #include "base/logging.h"
8 #include "media/cast/transport/cast_transport_defines.h"
9 #include "net/base/big_endian.h"
14 RtcpParser::RtcpParser(const uint8* rtcpData, size_t rtcpDataLength)
15 : rtcp_data_begin_(rtcpData),
16 rtcp_data_end_(rtcpData + rtcpDataLength),
19 rtcp_block_end_(NULL),
20 state_(kStateTopLevel),
22 field_type_(kRtcpNotValidCode) {
23 memset(&field_, 0, sizeof(field_));
27 RtcpParser::~RtcpParser() {}
29 RtcpFieldTypes RtcpParser::FieldType() const {
33 const RtcpField& RtcpParser::Field() const {
37 RtcpFieldTypes RtcpParser::Begin() {
38 rtcp_data_ = rtcp_data_begin_;
42 RtcpFieldTypes RtcpParser::Iterate() {
44 field_type_ = kRtcpNotValidCode;
46 if (!IsValid()) return kRtcpNotValidCode;
52 case kStateReportBlock:
53 IterateReportBlockItem();
61 case kStateApplicationSpecificCastReceiverFrameLog:
62 IterateCastReceiverLogFrame();
64 case kStateApplicationSpecificCastReceiverEventLog:
65 IterateCastReceiverLogEvent();
67 case kStateApplicationSpecificCastSenderLog:
68 IterateCastSenderLog();
70 case kStateExtendedReportBlock:
71 IterateExtendedReportItem();
73 case kStateExtendedReportDelaySinceLastReceiverReport:
74 IterateExtendedReportDelaySinceLastReceiverReportItem();
76 case kStateGenericRtpFeedbackNack:
79 case kStatePayloadSpecificRpsi:
82 case kStatePayloadSpecificFir:
85 case kStatePayloadSpecificApplication:
86 IteratePayloadSpecificAppItem();
88 case kStatePayloadSpecificRemb:
89 IteratePayloadSpecificRembItem();
91 case kStatePayloadSpecificCast:
92 IteratePayloadSpecificCastItem();
94 case kStatePayloadSpecificCastNack:
95 IteratePayloadSpecificCastNackItem();
101 void RtcpParser::IterateTopLevel() {
103 RtcpCommonHeader header;
105 bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
106 if (!success) return;
108 rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
110 if (rtcp_block_end_ > rtcp_data_end_) return; // Bad block!
113 case transport::kPacketTypeSenderReport:
114 // number of Report blocks
115 number_of_blocks_ = header.IC;
118 case transport::kPacketTypeReceiverReport:
119 // number of Report blocks
120 number_of_blocks_ = header.IC;
123 case transport::kPacketTypeSdes:
124 // number of Sdes blocks
125 number_of_blocks_ = header.IC;
127 break; // Nothing supported found, continue to next block!
130 case transport::kPacketTypeBye:
131 number_of_blocks_ = header.IC;
133 // Nothing supported found, continue to next block!
137 case transport::kPacketTypeApplicationDefined:
138 if (!ParseApplicationDefined(header.IC)) {
139 // Nothing supported found, continue to next block!
143 case transport::kPacketTypeGenericRtpFeedback: // Fall through!
144 case transport::kPacketTypePayloadSpecific:
145 if (!ParseFeedBackCommon(header)) {
146 // Nothing supported found, continue to next block!
150 case transport::kPacketTypeXr:
151 if (!ParseExtendedReport()) {
152 break; // Nothing supported found, continue to next block!
156 // Not supported! Skip!
163 void RtcpParser::IterateReportBlockItem() {
164 bool success = ParseReportBlockItem();
165 if (!success) Iterate();
168 void RtcpParser::IterateSdesItem() {
169 bool success = ParseSdesItem();
170 if (!success) Iterate();
173 void RtcpParser::IterateByeItem() {
174 bool success = ParseByeItem();
175 if (!success) Iterate();
178 void RtcpParser::IterateExtendedReportItem() {
179 bool success = ParseExtendedReportItem();
180 if (!success) Iterate();
183 void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
184 bool success = ParseExtendedReportDelaySinceLastReceiverReport();
185 if (!success) Iterate();
188 void RtcpParser::IterateNackItem() {
189 bool success = ParseNackItem();
190 if (!success) Iterate();
193 void RtcpParser::IterateRpsiItem() {
194 bool success = ParseRpsiItem();
195 if (!success) Iterate();
198 void RtcpParser::IterateFirItem() {
199 bool success = ParseFirItem();
200 if (!success) Iterate();
203 void RtcpParser::IteratePayloadSpecificAppItem() {
204 bool success = ParsePayloadSpecificAppItem();
205 if (!success) Iterate();
208 void RtcpParser::IteratePayloadSpecificRembItem() {
209 bool success = ParsePayloadSpecificRembItem();
210 if (!success) Iterate();
213 void RtcpParser::IteratePayloadSpecificCastItem() {
214 bool success = ParsePayloadSpecificCastItem();
215 if (!success) Iterate();
218 void RtcpParser::IteratePayloadSpecificCastNackItem() {
219 bool success = ParsePayloadSpecificCastNackItem();
220 if (!success) Iterate();
223 void RtcpParser::IterateCastReceiverLogFrame() {
224 bool success = ParseCastReceiverLogFrameItem();
225 if (!success) Iterate();
228 void RtcpParser::IterateCastReceiverLogEvent() {
229 bool success = ParseCastReceiverLogEventItem();
230 if (!success) Iterate();
233 void RtcpParser::IterateCastSenderLog() {
234 bool success = ParseCastSenderLogItem();
235 if (!success) Iterate();
238 void RtcpParser::Validate() {
239 if (rtcp_data_ == NULL) return; // NOT VALID
241 RtcpCommonHeader header;
242 bool success = RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_,
245 if (!success) return; // NOT VALID!
247 valid_packet_ = true;
250 bool RtcpParser::IsValid() const {
251 return valid_packet_;
254 void RtcpParser::EndCurrentBlock() {
255 rtcp_data_ = rtcp_block_end_;
258 bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
259 const uint8* data_end,
260 RtcpCommonHeader* parsed_header) const {
261 if (!data_begin || !data_end) return false;
264 // 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
265 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 // |V=2|P| IC | PT | length |
267 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269 // Common header for all Rtcp packets, 4 octets.
271 if ((data_end - data_begin) < 4) return false;
273 parsed_header->V = data_begin[0] >> 6;
274 parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
275 parsed_header->IC = data_begin[0] & 0x1f;
276 parsed_header->PT = data_begin[1];
278 parsed_header->length_in_octets =
279 ((data_begin[2] << 8) + data_begin[3] + 1) * 4;
281 if (parsed_header->length_in_octets == 0) return false;
283 // Check if RTP version field == 2.
284 if (parsed_header->V != 2) return false;
289 bool RtcpParser::ParseRR() {
290 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
291 if (length < 8) return false;
293 field_type_ = kRtcpRrCode;
295 net::BigEndianReader big_endian_reader(rtcp_data_, length);
296 big_endian_reader.Skip(4); // Skip header
297 big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
298 field_.receiver_report.number_of_report_blocks = number_of_blocks_;
302 state_ = kStateReportBlock;
306 bool RtcpParser::ParseSR() {
307 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
312 field_type_ = kRtcpSrCode;
314 net::BigEndianReader big_endian_reader(rtcp_data_, length);
315 big_endian_reader.Skip(4); // Skip header
316 big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
317 big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
318 big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant);
319 big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp);
320 big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count);
321 big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count);
322 field_.sender_report.number_of_report_blocks = number_of_blocks_;
325 if (number_of_blocks_ != 0) {
327 state_ = kStateReportBlock;
329 // Don't go to state report block item if 0 report blocks.
330 state_ = kStateTopLevel;
336 bool RtcpParser::ParseReportBlockItem() {
337 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
338 if (length < 24 || number_of_blocks_ <= 0) {
339 state_ = kStateTopLevel;
344 net::BigEndianReader big_endian_reader(rtcp_data_, length);
345 big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
346 big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
348 uint8 temp_number_of_packets_lost;
349 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
350 field_.report_block_item.cumulative_number_of_packets_lost =
351 temp_number_of_packets_lost << 16;
352 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
353 field_.report_block_item.cumulative_number_of_packets_lost +=
354 temp_number_of_packets_lost << 8;
355 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
356 field_.report_block_item.cumulative_number_of_packets_lost +=
357 temp_number_of_packets_lost;
359 big_endian_reader.ReadU32(
360 &field_.report_block_item.extended_highest_sequence_number);
361 big_endian_reader.ReadU32(&field_.report_block_item.jitter);
362 big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report);
363 big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report);
367 field_type_ = kRtcpReportBlockItemCode;
371 bool RtcpParser::ParseSdes() {
372 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
375 state_ = kStateTopLevel;
379 rtcp_data_ += 4; // Skip header
382 field_type_ = kRtcpSdesCode;
386 bool RtcpParser::ParseSdesItem() {
387 if (number_of_blocks_ <= 0) {
388 state_ = kStateTopLevel;
394 // Find c_name item in a Sdes chunk.
395 while (rtcp_data_ < rtcp_block_end_) {
396 ptrdiff_t data_length = rtcp_block_end_ - rtcp_data_;
397 if (data_length < 4) {
398 state_ = kStateTopLevel;
404 net::BigEndianReader big_endian_reader(rtcp_data_, data_length);
405 big_endian_reader.ReadU32(&ssrc);
408 bool found_c_name = ParseSdesTypes();
410 field_.c_name.sender_ssrc = ssrc;
414 state_ = kStateTopLevel;
419 bool RtcpParser::ParseSdesTypes() {
420 // Only the c_name item is mandatory. RFC 3550 page 46.
421 bool found_c_name = false;
422 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
423 net::BigEndianReader big_endian_reader(rtcp_data_, length);
425 while (big_endian_reader.remaining() > 0) {
427 big_endian_reader.ReadU8(&tag);
430 // End tag! 4 octet aligned.
431 rtcp_data_ = rtcp_block_end_;
435 if (big_endian_reader.remaining() > 0) {
437 big_endian_reader.ReadU8(&len);
439 if (tag == 1) { // c_name.
441 if (big_endian_reader.remaining() < len) {
442 state_ = kStateTopLevel;
447 for (; i < len; ++i) {
449 big_endian_reader.ReadU8(&c);
450 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\')) {
452 state_ = kStateTopLevel;
456 field_.c_name.name[i] = c;
458 // Make sure we are null terminated.
459 field_.c_name.name[i] = 0;
460 field_type_ = kRtcpSdesChunkCode;
463 big_endian_reader.Skip(len);
468 state_ = kStateTopLevel;
473 bool RtcpParser::ParseBye() {
474 rtcp_data_ += 4; // Skip header.
476 return ParseByeItem();
479 bool RtcpParser::ParseByeItem() {
480 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
481 if (length < 4 || number_of_blocks_ == 0) {
482 state_ = kStateTopLevel;
487 field_type_ = kRtcpByeCode;
489 net::BigEndianReader big_endian_reader(rtcp_data_, length);
490 big_endian_reader.ReadU32(&field_.bye.sender_ssrc);
493 // We can have several CSRCs attached.
494 if (length >= 4 * number_of_blocks_) {
495 rtcp_data_ += (number_of_blocks_ - 1) * 4;
497 number_of_blocks_ = 0;
501 bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
502 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
504 !(subtype == kSenderLogSubtype || subtype == kReceiverLogSubtype)) {
505 state_ = kStateTopLevel;
513 net::BigEndianReader big_endian_reader(rtcp_data_, length);
514 big_endian_reader.Skip(4); // Skip header.
515 big_endian_reader.ReadU32(&sender_ssrc);
516 big_endian_reader.ReadU32(&name);
519 state_ = kStateTopLevel;
525 case kSenderLogSubtype:
526 state_ = kStateApplicationSpecificCastSenderLog;
527 field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
528 field_.cast_sender_log.sender_ssrc = sender_ssrc;
530 case kReceiverLogSubtype:
531 state_ = kStateApplicationSpecificCastReceiverFrameLog;
532 field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
533 field_.cast_receiver_log.sender_ssrc = sender_ssrc;
541 bool RtcpParser::ParseCastReceiverLogFrameItem() {
542 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
544 state_ = kStateTopLevel;
548 uint32 rtp_timestamp;
550 net::BigEndianReader big_endian_reader(rtcp_data_, length);
551 big_endian_reader.ReadU32(&rtp_timestamp);
552 big_endian_reader.ReadU32(&data);
556 field_.cast_receiver_log.rtp_timestamp = rtp_timestamp;
557 // We have 24 LSB of the event timestamp base on the wire.
558 field_.cast_receiver_log.event_timestamp_base = data & 0xffffff;
560 number_of_blocks_ = 1 + static_cast<uint8>(data >> 24);
561 state_ = kStateApplicationSpecificCastReceiverEventLog;
562 field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode;
566 bool RtcpParser::ParseCastReceiverLogEventItem() {
567 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
569 state_ = kStateTopLevel;
573 if (number_of_blocks_ == 0) {
574 // Continue parsing the next receiver frame event.
575 state_ = kStateApplicationSpecificCastReceiverFrameLog;
580 uint16 delay_delta_or_packet_id;
581 uint16 event_type_and_timestamp_delta;
582 net::BigEndianReader big_endian_reader(rtcp_data_, length);
583 big_endian_reader.ReadU16(&delay_delta_or_packet_id);
584 big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
588 field_.cast_receiver_log.event =
589 static_cast<uint8>(event_type_and_timestamp_delta >> 12);
590 field_.cast_receiver_log.delay_delta_or_packet_id = delay_delta_or_packet_id;
591 field_.cast_receiver_log.event_timestamp_delta =
592 event_type_and_timestamp_delta & 0xfff;
594 field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode;
598 bool RtcpParser::ParseCastSenderLogItem() {
599 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
602 state_ = kStateTopLevel;
607 net::BigEndianReader big_endian_reader(rtcp_data_, length);
608 big_endian_reader.ReadU32(&data);
612 field_.cast_sender_log.status = static_cast<uint8>(data >> 24);
613 // We have 24 LSB of the RTP timestamp on the wire.
614 field_.cast_sender_log.rtp_timestamp = data & 0xffffff;
615 field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
619 bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
620 DCHECK((header.PT == transport::kPacketTypeGenericRtpFeedback) ||
621 (header.PT == transport::kPacketTypePayloadSpecific)) <<
624 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
626 if (length < 12) { // 4 * 3, RFC4585 section 6.1
633 net::BigEndianReader big_endian_reader(rtcp_data_, length);
634 big_endian_reader.Skip(4); // Skip header.
635 big_endian_reader.ReadU32(&sender_ssrc);
636 big_endian_reader.ReadU32(&media_ssrc);
640 if (header.PT == transport::kPacketTypeGenericRtpFeedback) {
641 // Transport layer feedback
645 field_type_ = kRtcpGenericRtpFeedbackNackCode;
646 field_.nack.sender_ssrc = sender_ssrc;
647 field_.nack.media_ssrc = media_ssrc;
648 state_ = kStateGenericRtpFeedbackNack;
651 // Used to be ACK is this code point, which is removed conficts with
652 // http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
661 // RFC 6051 RTCP-sender_report-REQ Rapid Synchronisation of RTP Flows
662 // Trigger a new Rtcp sender_report
663 field_type_ = kRtcpGenericRtpFeedbackSrReqCode;
665 // Note: No state transition, sender report REQ is empty!
673 } else if (header.PT == transport::kPacketTypePayloadSpecific) {
674 // Payload specific feedback
678 field_type_ = kRtcpPayloadSpecificPliCode;
679 field_.pli.sender_ssrc = sender_ssrc;
680 field_.pli.media_ssrc = media_ssrc;
682 // Note: No state transition, PLI FCI is empty!
688 field_type_ = kRtcpPayloadSpecificRpsiCode;
689 field_.rpsi.sender_ssrc = sender_ssrc;
690 field_.rpsi.media_ssrc = media_ssrc;
691 state_ = kStatePayloadSpecificRpsi;
697 field_type_ = kRtcpPayloadSpecificAppCode;
698 field_.application_specific.sender_ssrc = sender_ssrc;
699 field_.application_specific.media_ssrc = media_ssrc;
700 state_ = kStatePayloadSpecificApplication;
709 DCHECK(false) << "Invalid state";
715 bool RtcpParser::ParseRpsiItem() {
716 // RFC 4585 6.3.3. Reference Picture Selection Indication (rpsi)
719 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
720 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
721 | PB |0| Payload Type| Native rpsi bit string |
722 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
723 | defined per codec ... | Padding (0) |
724 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
726 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
729 state_ = kStateTopLevel;
733 if (length > 2 + kRtcpRpsiDataSize) {
734 state_ = kStateTopLevel;
739 field_type_ = kRtcpPayloadSpecificRpsiCode;
742 net::BigEndianReader big_endian_reader(rtcp_data_, length);
743 big_endian_reader.ReadU8(&padding_bits);
744 big_endian_reader.ReadU8(&field_.rpsi.payload_type);
745 big_endian_reader.ReadBytes(&field_.rpsi.native_bit_string, length - 2);
746 field_.rpsi.number_of_valid_bits =
747 static_cast<uint16>(length - 2) * 8 - padding_bits;
749 rtcp_data_ += length;
753 bool RtcpParser::ParseNackItem() {
754 // RFC 4585 6.2.1. Generic Nack
756 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
758 state_ = kStateTopLevel;
763 field_type_ = kRtcpGenericRtpFeedbackNackItemCode;
765 net::BigEndianReader big_endian_reader(rtcp_data_, length);
766 big_endian_reader.ReadU16(&field_.nack_item.packet_id);
767 big_endian_reader.ReadU16(&field_.nack_item.bitmask);
772 bool RtcpParser::ParsePayloadSpecificAppItem() {
773 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
776 state_ = kStateTopLevel;
781 net::BigEndianReader big_endian_reader(rtcp_data_, length);
782 big_endian_reader.ReadU32(&name);
786 field_type_ = kRtcpPayloadSpecificRembCode;
787 state_ = kStatePayloadSpecificRemb;
789 } else if (name == kCast) {
790 field_type_ = kRtcpPayloadSpecificCastCode;
791 state_ = kStatePayloadSpecificCast;
794 state_ = kStateTopLevel;
799 bool RtcpParser::ParsePayloadSpecificRembItem() {
800 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
803 state_ = kStateTopLevel;
808 net::BigEndianReader big_endian_reader(rtcp_data_, length);
809 big_endian_reader.ReadU8(&field_.remb_item.number_of_ssrcs);
814 big_endian_reader.ReadU8(&byte_1);
815 big_endian_reader.ReadU8(&byte_2);
816 big_endian_reader.ReadU8(&byte_3);
819 uint8 br_exp = (byte_1 >> 2) & 0x3F;
820 uint32 br_mantissa = ((byte_1 & 0x03) << 16) + (byte_2 << 8) + byte_3;
821 field_.remb_item.bitrate = (br_mantissa << br_exp);
823 ptrdiff_t length_ssrcs = rtcp_block_end_ - rtcp_data_;
824 if (length_ssrcs < 4 * field_.remb_item.number_of_ssrcs) {
825 state_ = kStateTopLevel;
830 field_type_ = kRtcpPayloadSpecificRembItemCode;
832 for (int i = 0; i < field_.remb_item.number_of_ssrcs; i++) {
833 big_endian_reader.ReadU32(&field_.remb_item.ssrcs[i]);
838 bool RtcpParser::ParsePayloadSpecificCastItem() {
839 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
841 state_ = kStateTopLevel;
845 field_type_ = kRtcpPayloadSpecificCastCode;
847 net::BigEndianReader big_endian_reader(rtcp_data_, length);
848 big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
849 big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
853 if (field_.cast_item.number_of_lost_fields != 0) {
855 state_ = kStatePayloadSpecificCastNack;
857 // Don't go to state cast nack item if got 0 fields.
858 state_ = kStateTopLevel;
864 bool RtcpParser::ParsePayloadSpecificCastNackItem() {
865 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
867 state_ = kStateTopLevel;
871 field_type_ = kRtcpPayloadSpecificCastNackItemCode;
873 net::BigEndianReader big_endian_reader(rtcp_data_, length);
874 big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
875 big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
876 big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
882 bool RtcpParser::ParseFirItem() {
883 // RFC 5104 4.3.1. Full Intra Request (fir)
884 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
887 state_ = kStateTopLevel;
891 field_type_ = kRtcpPayloadSpecificFirItemCode;
893 net::BigEndianReader big_endian_reader(rtcp_data_, length);
894 big_endian_reader.ReadU32(&field_.fir_item.ssrc);
895 big_endian_reader.ReadU8(&field_.fir_item.command_sequence_number);
901 bool RtcpParser::ParseExtendedReport() {
902 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
903 if (length < 8) return false;
905 field_type_ = kRtcpXrCode;
907 net::BigEndianReader big_endian_reader(rtcp_data_, length);
908 big_endian_reader.Skip(4); // Skip header.
909 big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
913 state_ = kStateExtendedReportBlock;
917 bool RtcpParser::ParseExtendedReportItem() {
918 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
920 state_ = kStateTopLevel;
927 net::BigEndianReader big_endian_reader(rtcp_data_, length);
928 big_endian_reader.ReadU8(&block_type);
929 big_endian_reader.Skip(1); // Ignore reserved.
930 big_endian_reader.ReadU16(&block_length);
934 switch (block_type) {
936 if (block_length != 2) {
937 // Invalid block length.
938 state_ = kStateTopLevel;
942 return ParseExtendedReportReceiverReferenceTimeReport();
944 if (block_length % 3 != 0) {
945 // Invalid block length.
946 state_ = kStateTopLevel;
950 if (block_length >= 3) {
951 number_of_blocks_ = block_length / 3;
952 state_ = kStateExtendedReportDelaySinceLastReceiverReport;
953 return ParseExtendedReportDelaySinceLastReceiverReport();
957 if (length < block_length * 4) {
958 state_ = kStateTopLevel;
962 field_type_ = kRtcpXrUnknownItemCode;
963 rtcp_data_ += block_length * 4;
968 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
969 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
971 state_ = kStateTopLevel;
976 net::BigEndianReader big_endian_reader(rtcp_data_, length);
977 big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
978 big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
982 field_type_ = kRtcpXrRrtrCode;
986 bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
987 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
989 state_ = kStateTopLevel;
993 if (number_of_blocks_ == 0) {
994 // Continue parsing the extended report block.
995 state_ = kStateExtendedReportBlock;
999 net::BigEndianReader big_endian_reader(rtcp_data_, length);
1000 big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
1001 big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
1002 big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
1006 number_of_blocks_--;
1007 field_type_ = kRtcpXrDlrrCode;
1012 } // namespace media