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