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 { return field_type_; }
31 const RtcpField& RtcpParser::Field() const { return field_; }
33 RtcpFieldTypes RtcpParser::Begin() {
34 rtcp_data_ = rtcp_data_begin_;
38 RtcpFieldTypes RtcpParser::Iterate() {
40 field_type_ = kRtcpNotValidCode;
43 return kRtcpNotValidCode;
49 case kStateReportBlock:
50 IterateReportBlockItem();
58 case kStateApplicationSpecificCastReceiverFrameLog:
59 IterateCastReceiverLogFrame();
61 case kStateApplicationSpecificCastReceiverEventLog:
62 IterateCastReceiverLogEvent();
64 case kStateApplicationSpecificCastSenderLog:
65 IterateCastSenderLog();
67 case kStateExtendedReportBlock:
68 IterateExtendedReportItem();
70 case kStateExtendedReportDelaySinceLastReceiverReport:
71 IterateExtendedReportDelaySinceLastReceiverReportItem();
73 case kStateGenericRtpFeedbackNack:
76 case kStatePayloadSpecificRpsi:
79 case kStatePayloadSpecificFir:
82 case kStatePayloadSpecificApplication:
83 IteratePayloadSpecificAppItem();
85 case kStatePayloadSpecificRemb:
86 IteratePayloadSpecificRembItem();
88 case kStatePayloadSpecificCast:
89 IteratePayloadSpecificCastItem();
91 case kStatePayloadSpecificCastNack:
92 IteratePayloadSpecificCastNackItem();
98 void RtcpParser::IterateTopLevel() {
100 RtcpCommonHeader header;
102 bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
106 rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
108 if (rtcp_block_end_ > rtcp_data_end_)
109 return; // Bad block!
112 case transport::kPacketTypeSenderReport:
113 // number of Report blocks
114 number_of_blocks_ = header.IC;
117 case transport::kPacketTypeReceiverReport:
118 // number of Report blocks
119 number_of_blocks_ = header.IC;
122 case transport::kPacketTypeSdes:
123 // number of Sdes blocks
124 number_of_blocks_ = header.IC;
126 break; // Nothing supported found, continue to next block!
129 case transport::kPacketTypeBye:
130 number_of_blocks_ = header.IC;
132 // Nothing supported found, continue to next block!
136 case transport::kPacketTypeApplicationDefined:
137 if (!ParseApplicationDefined(header.IC)) {
138 // Nothing supported found, continue to next block!
142 case transport::kPacketTypeGenericRtpFeedback: // Fall through!
143 case transport::kPacketTypePayloadSpecific:
144 if (!ParseFeedBackCommon(header)) {
145 // Nothing supported found, continue to next block!
149 case transport::kPacketTypeXr:
150 if (!ParseExtendedReport()) {
151 break; // Nothing supported found, continue to next block!
155 // Not supported! Skip!
162 void RtcpParser::IterateReportBlockItem() {
163 bool success = ParseReportBlockItem();
168 void RtcpParser::IterateSdesItem() {
169 bool success = ParseSdesItem();
174 void RtcpParser::IterateByeItem() {
175 bool success = ParseByeItem();
180 void RtcpParser::IterateExtendedReportItem() {
181 bool success = ParseExtendedReportItem();
186 void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
187 bool success = ParseExtendedReportDelaySinceLastReceiverReport();
192 void RtcpParser::IterateNackItem() {
193 bool success = ParseNackItem();
198 void RtcpParser::IterateRpsiItem() {
199 bool success = ParseRpsiItem();
204 void RtcpParser::IterateFirItem() {
205 bool success = ParseFirItem();
210 void RtcpParser::IteratePayloadSpecificAppItem() {
211 bool success = ParsePayloadSpecificAppItem();
216 void RtcpParser::IteratePayloadSpecificRembItem() {
217 bool success = ParsePayloadSpecificRembItem();
222 void RtcpParser::IteratePayloadSpecificCastItem() {
223 bool success = ParsePayloadSpecificCastItem();
228 void RtcpParser::IteratePayloadSpecificCastNackItem() {
229 bool success = ParsePayloadSpecificCastNackItem();
234 void RtcpParser::IterateCastReceiverLogFrame() {
235 bool success = ParseCastReceiverLogFrameItem();
240 void RtcpParser::IterateCastReceiverLogEvent() {
241 bool success = ParseCastReceiverLogEventItem();
246 void RtcpParser::IterateCastSenderLog() {
247 bool success = ParseCastSenderLogItem();
252 void RtcpParser::Validate() {
253 if (rtcp_data_ == NULL)
256 RtcpCommonHeader header;
258 RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header);
261 return; // NOT VALID!
263 valid_packet_ = true;
266 bool RtcpParser::IsValid() const { return valid_packet_; }
268 void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; }
270 bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
271 const uint8* data_end,
272 RtcpCommonHeader* parsed_header) const {
273 if (!data_begin || !data_end)
277 // 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
278 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279 // |V=2|P| IC | PT | length |
280 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
282 // Common header for all Rtcp packets, 4 octets.
284 if ((data_end - data_begin) < 4)
287 parsed_header->V = data_begin[0] >> 6;
288 parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
289 parsed_header->IC = data_begin[0] & 0x1f;
290 parsed_header->PT = data_begin[1];
292 parsed_header->length_in_octets =
293 ((data_begin[2] << 8) + data_begin[3] + 1) * 4;
295 if (parsed_header->length_in_octets == 0)
298 // Check if RTP version field == 2.
299 if (parsed_header->V != 2)
305 bool RtcpParser::ParseRR() {
306 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
310 field_type_ = kRtcpRrCode;
312 net::BigEndianReader big_endian_reader(rtcp_data_, length);
313 big_endian_reader.Skip(4); // Skip header
314 big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
315 field_.receiver_report.number_of_report_blocks = number_of_blocks_;
319 state_ = kStateReportBlock;
323 bool RtcpParser::ParseSR() {
324 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
329 field_type_ = kRtcpSrCode;
331 net::BigEndianReader big_endian_reader(rtcp_data_, length);
332 big_endian_reader.Skip(4); // Skip header
333 big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
334 big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
335 big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant);
336 big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp);
337 big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count);
338 big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count);
339 field_.sender_report.number_of_report_blocks = number_of_blocks_;
342 if (number_of_blocks_ != 0) {
344 state_ = kStateReportBlock;
346 // Don't go to state report block item if 0 report blocks.
347 state_ = kStateTopLevel;
353 bool RtcpParser::ParseReportBlockItem() {
354 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
355 if (length < 24 || number_of_blocks_ <= 0) {
356 state_ = kStateTopLevel;
361 net::BigEndianReader big_endian_reader(rtcp_data_, length);
362 big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
363 big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
365 uint8 temp_number_of_packets_lost;
366 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
367 field_.report_block_item.cumulative_number_of_packets_lost =
368 temp_number_of_packets_lost << 16;
369 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
370 field_.report_block_item.cumulative_number_of_packets_lost +=
371 temp_number_of_packets_lost << 8;
372 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
373 field_.report_block_item.cumulative_number_of_packets_lost +=
374 temp_number_of_packets_lost;
376 big_endian_reader.ReadU32(
377 &field_.report_block_item.extended_highest_sequence_number);
378 big_endian_reader.ReadU32(&field_.report_block_item.jitter);
379 big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report);
380 big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report);
384 field_type_ = kRtcpReportBlockItemCode;
388 bool RtcpParser::ParseSdes() {
389 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
392 state_ = kStateTopLevel;
396 rtcp_data_ += 4; // Skip header
399 field_type_ = kRtcpSdesCode;
403 bool RtcpParser::ParseSdesItem() {
404 if (number_of_blocks_ <= 0) {
405 state_ = kStateTopLevel;
411 // Find c_name item in a Sdes chunk.
412 while (rtcp_data_ < rtcp_block_end_) {
413 ptrdiff_t data_length = rtcp_block_end_ - rtcp_data_;
414 if (data_length < 4) {
415 state_ = kStateTopLevel;
421 net::BigEndianReader big_endian_reader(rtcp_data_, data_length);
422 big_endian_reader.ReadU32(&ssrc);
425 bool found_c_name = ParseSdesTypes();
427 field_.c_name.sender_ssrc = ssrc;
431 state_ = kStateTopLevel;
436 bool RtcpParser::ParseSdesTypes() {
437 // Only the c_name item is mandatory. RFC 3550 page 46.
438 bool found_c_name = false;
439 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
440 net::BigEndianReader big_endian_reader(rtcp_data_, length);
442 while (big_endian_reader.remaining() > 0) {
444 big_endian_reader.ReadU8(&tag);
447 // End tag! 4 octet aligned.
448 rtcp_data_ = rtcp_block_end_;
452 if (big_endian_reader.remaining() > 0) {
454 big_endian_reader.ReadU8(&len);
456 if (tag == 1) { // c_name.
458 if (big_endian_reader.remaining() < len) {
459 state_ = kStateTopLevel;
464 for (; i < len; ++i) {
466 big_endian_reader.ReadU8(&c);
467 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\')) {
469 state_ = kStateTopLevel;
473 field_.c_name.name[i] = c;
475 // Make sure we are null terminated.
476 field_.c_name.name[i] = 0;
477 field_type_ = kRtcpSdesChunkCode;
480 big_endian_reader.Skip(len);
485 state_ = kStateTopLevel;
490 bool RtcpParser::ParseBye() {
491 rtcp_data_ += 4; // Skip header.
493 return ParseByeItem();
496 bool RtcpParser::ParseByeItem() {
497 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
498 if (length < 4 || number_of_blocks_ == 0) {
499 state_ = kStateTopLevel;
504 field_type_ = kRtcpByeCode;
506 net::BigEndianReader big_endian_reader(rtcp_data_, length);
507 big_endian_reader.ReadU32(&field_.bye.sender_ssrc);
510 // We can have several CSRCs attached.
511 if (length >= 4 * number_of_blocks_) {
512 rtcp_data_ += (number_of_blocks_ - 1) * 4;
514 number_of_blocks_ = 0;
518 bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
519 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
521 !(subtype == kSenderLogSubtype || subtype == kReceiverLogSubtype)) {
522 state_ = kStateTopLevel;
530 net::BigEndianReader big_endian_reader(rtcp_data_, length);
531 big_endian_reader.Skip(4); // Skip header.
532 big_endian_reader.ReadU32(&sender_ssrc);
533 big_endian_reader.ReadU32(&name);
536 state_ = kStateTopLevel;
542 case kSenderLogSubtype:
543 state_ = kStateApplicationSpecificCastSenderLog;
544 field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
545 field_.cast_sender_log.sender_ssrc = sender_ssrc;
547 case kReceiverLogSubtype:
548 state_ = kStateApplicationSpecificCastReceiverFrameLog;
549 field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
550 field_.cast_receiver_log.sender_ssrc = sender_ssrc;
558 bool RtcpParser::ParseCastReceiverLogFrameItem() {
559 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
561 state_ = kStateTopLevel;
565 uint32 rtp_timestamp;
567 net::BigEndianReader big_endian_reader(rtcp_data_, length);
568 big_endian_reader.ReadU32(&rtp_timestamp);
569 big_endian_reader.ReadU32(&data);
573 field_.cast_receiver_log.rtp_timestamp = rtp_timestamp;
574 // We have 24 LSB of the event timestamp base on the wire.
575 field_.cast_receiver_log.event_timestamp_base = data & 0xffffff;
577 number_of_blocks_ = 1 + static_cast<uint8>(data >> 24);
578 state_ = kStateApplicationSpecificCastReceiverEventLog;
579 field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode;
583 bool RtcpParser::ParseCastReceiverLogEventItem() {
584 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
586 state_ = kStateTopLevel;
590 if (number_of_blocks_ == 0) {
591 // Continue parsing the next receiver frame event.
592 state_ = kStateApplicationSpecificCastReceiverFrameLog;
597 uint16 delay_delta_or_packet_id;
598 uint16 event_type_and_timestamp_delta;
599 net::BigEndianReader big_endian_reader(rtcp_data_, length);
600 big_endian_reader.ReadU16(&delay_delta_or_packet_id);
601 big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
605 field_.cast_receiver_log.event =
606 static_cast<uint8>(event_type_and_timestamp_delta >> 12);
607 field_.cast_receiver_log.delay_delta_or_packet_id = delay_delta_or_packet_id;
608 field_.cast_receiver_log.event_timestamp_delta =
609 event_type_and_timestamp_delta & 0xfff;
611 field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode;
615 bool RtcpParser::ParseCastSenderLogItem() {
616 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
619 state_ = kStateTopLevel;
624 net::BigEndianReader big_endian_reader(rtcp_data_, length);
625 big_endian_reader.ReadU32(&data);
629 field_.cast_sender_log.status = static_cast<uint8>(data >> 24);
630 // We have 24 LSB of the RTP timestamp on the wire.
631 field_.cast_sender_log.rtp_timestamp = data & 0xffffff;
632 field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
636 bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
637 DCHECK((header.PT == transport::kPacketTypeGenericRtpFeedback) ||
638 (header.PT == transport::kPacketTypePayloadSpecific))
641 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
643 if (length < 12) { // 4 * 3, RFC4585 section 6.1
650 net::BigEndianReader big_endian_reader(rtcp_data_, length);
651 big_endian_reader.Skip(4); // Skip header.
652 big_endian_reader.ReadU32(&sender_ssrc);
653 big_endian_reader.ReadU32(&media_ssrc);
657 if (header.PT == transport::kPacketTypeGenericRtpFeedback) {
658 // Transport layer feedback
662 field_type_ = kRtcpGenericRtpFeedbackNackCode;
663 field_.nack.sender_ssrc = sender_ssrc;
664 field_.nack.media_ssrc = media_ssrc;
665 state_ = kStateGenericRtpFeedbackNack;
668 // Used to be ACK is this code point, which is removed conficts with
669 // http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
678 // RFC 6051 RTCP-sender_report-REQ Rapid Synchronisation of RTP Flows
679 // Trigger a new Rtcp sender_report
680 field_type_ = kRtcpGenericRtpFeedbackSrReqCode;
682 // Note: No state transition, sender report REQ is empty!
690 } else if (header.PT == transport::kPacketTypePayloadSpecific) {
691 // Payload specific feedback
695 field_type_ = kRtcpPayloadSpecificPliCode;
696 field_.pli.sender_ssrc = sender_ssrc;
697 field_.pli.media_ssrc = media_ssrc;
699 // Note: No state transition, PLI FCI is empty!
705 field_type_ = kRtcpPayloadSpecificRpsiCode;
706 field_.rpsi.sender_ssrc = sender_ssrc;
707 field_.rpsi.media_ssrc = media_ssrc;
708 state_ = kStatePayloadSpecificRpsi;
714 field_type_ = kRtcpPayloadSpecificAppCode;
715 field_.application_specific.sender_ssrc = sender_ssrc;
716 field_.application_specific.media_ssrc = media_ssrc;
717 state_ = kStatePayloadSpecificApplication;
726 DCHECK(false) << "Invalid state";
732 bool RtcpParser::ParseRpsiItem() {
733 // RFC 4585 6.3.3. Reference Picture Selection Indication (rpsi)
736 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
737 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
738 | PB |0| Payload Type| Native rpsi bit string |
739 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
740 | defined per codec ... | Padding (0) |
741 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
743 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
746 state_ = kStateTopLevel;
750 if (length > 2 + kRtcpRpsiDataSize) {
751 state_ = kStateTopLevel;
756 field_type_ = kRtcpPayloadSpecificRpsiCode;
759 net::BigEndianReader big_endian_reader(rtcp_data_, length);
760 big_endian_reader.ReadU8(&padding_bits);
761 big_endian_reader.ReadU8(&field_.rpsi.payload_type);
762 big_endian_reader.ReadBytes(&field_.rpsi.native_bit_string, length - 2);
763 field_.rpsi.number_of_valid_bits =
764 static_cast<uint16>(length - 2) * 8 - padding_bits;
766 rtcp_data_ += length;
770 bool RtcpParser::ParseNackItem() {
771 // RFC 4585 6.2.1. Generic Nack
773 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
775 state_ = kStateTopLevel;
780 field_type_ = kRtcpGenericRtpFeedbackNackItemCode;
782 net::BigEndianReader big_endian_reader(rtcp_data_, length);
783 big_endian_reader.ReadU16(&field_.nack_item.packet_id);
784 big_endian_reader.ReadU16(&field_.nack_item.bitmask);
789 bool RtcpParser::ParsePayloadSpecificAppItem() {
790 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
793 state_ = kStateTopLevel;
798 net::BigEndianReader big_endian_reader(rtcp_data_, length);
799 big_endian_reader.ReadU32(&name);
803 field_type_ = kRtcpPayloadSpecificRembCode;
804 state_ = kStatePayloadSpecificRemb;
806 } else if (name == kCast) {
807 field_type_ = kRtcpPayloadSpecificCastCode;
808 state_ = kStatePayloadSpecificCast;
811 state_ = kStateTopLevel;
816 bool RtcpParser::ParsePayloadSpecificRembItem() {
817 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
820 state_ = kStateTopLevel;
825 net::BigEndianReader big_endian_reader(rtcp_data_, length);
826 big_endian_reader.ReadU8(&field_.remb_item.number_of_ssrcs);
831 big_endian_reader.ReadU8(&byte_1);
832 big_endian_reader.ReadU8(&byte_2);
833 big_endian_reader.ReadU8(&byte_3);
836 uint8 br_exp = (byte_1 >> 2) & 0x3F;
837 uint32 br_mantissa = ((byte_1 & 0x03) << 16) + (byte_2 << 8) + byte_3;
838 field_.remb_item.bitrate = (br_mantissa << br_exp);
840 ptrdiff_t length_ssrcs = rtcp_block_end_ - rtcp_data_;
841 if (length_ssrcs < 4 * field_.remb_item.number_of_ssrcs) {
842 state_ = kStateTopLevel;
847 field_type_ = kRtcpPayloadSpecificRembItemCode;
849 for (int i = 0; i < field_.remb_item.number_of_ssrcs; i++) {
850 big_endian_reader.ReadU32(&field_.remb_item.ssrcs[i]);
855 bool RtcpParser::ParsePayloadSpecificCastItem() {
856 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
858 state_ = kStateTopLevel;
862 field_type_ = kRtcpPayloadSpecificCastCode;
864 net::BigEndianReader big_endian_reader(rtcp_data_, length);
865 big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
866 big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
870 if (field_.cast_item.number_of_lost_fields != 0) {
872 state_ = kStatePayloadSpecificCastNack;
874 // Don't go to state cast nack item if got 0 fields.
875 state_ = kStateTopLevel;
881 bool RtcpParser::ParsePayloadSpecificCastNackItem() {
882 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
884 state_ = kStateTopLevel;
888 field_type_ = kRtcpPayloadSpecificCastNackItemCode;
890 net::BigEndianReader big_endian_reader(rtcp_data_, length);
891 big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
892 big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
893 big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
899 bool RtcpParser::ParseFirItem() {
900 // RFC 5104 4.3.1. Full Intra Request (fir)
901 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
904 state_ = kStateTopLevel;
908 field_type_ = kRtcpPayloadSpecificFirItemCode;
910 net::BigEndianReader big_endian_reader(rtcp_data_, length);
911 big_endian_reader.ReadU32(&field_.fir_item.ssrc);
912 big_endian_reader.ReadU8(&field_.fir_item.command_sequence_number);
918 bool RtcpParser::ParseExtendedReport() {
919 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
923 field_type_ = kRtcpXrCode;
925 net::BigEndianReader big_endian_reader(rtcp_data_, length);
926 big_endian_reader.Skip(4); // Skip header.
927 big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
931 state_ = kStateExtendedReportBlock;
935 bool RtcpParser::ParseExtendedReportItem() {
936 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
938 state_ = kStateTopLevel;
945 net::BigEndianReader big_endian_reader(rtcp_data_, length);
946 big_endian_reader.ReadU8(&block_type);
947 big_endian_reader.Skip(1); // Ignore reserved.
948 big_endian_reader.ReadU16(&block_length);
952 switch (block_type) {
954 if (block_length != 2) {
955 // Invalid block length.
956 state_ = kStateTopLevel;
960 return ParseExtendedReportReceiverReferenceTimeReport();
962 if (block_length % 3 != 0) {
963 // Invalid block length.
964 state_ = kStateTopLevel;
968 if (block_length >= 3) {
969 number_of_blocks_ = block_length / 3;
970 state_ = kStateExtendedReportDelaySinceLastReceiverReport;
971 return ParseExtendedReportDelaySinceLastReceiverReport();
975 if (length < block_length * 4) {
976 state_ = kStateTopLevel;
980 field_type_ = kRtcpXrUnknownItemCode;
981 rtcp_data_ += block_length * 4;
986 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
987 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
989 state_ = kStateTopLevel;
994 net::BigEndianReader big_endian_reader(rtcp_data_, length);
995 big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
996 big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
1000 field_type_ = kRtcpXrRrtrCode;
1004 bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
1005 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
1007 state_ = kStateTopLevel;
1011 if (number_of_blocks_ == 0) {
1012 // Continue parsing the extended report block.
1013 state_ = kStateExtendedReportBlock;
1017 net::BigEndianReader big_endian_reader(rtcp_data_, length);
1018 big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
1019 big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
1020 big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
1024 number_of_blocks_--;
1025 field_type_ = kRtcpXrDlrrCode;
1030 } // namespace media