// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef MEDIA_CAST_RTCP_RTCP_UTILITY_H_ #define MEDIA_CAST_RTCP_RTCP_UTILITY_H_ #include "media/cast/cast_config.h" #include "media/cast/cast_defines.h" #include "media/cast/logging/logging_defines.h" #include "media/cast/rtcp/rtcp_defines.h" namespace media { namespace cast { static const int kRtcpRpsiDataSize = 30; // RFC 3550 page 44, including end null. static const size_t kRtcpCnameSize = 256; static const int kRtcpMaxNumberOfRembFeedbackSsrcs = 255; static const uint32 kRemb = ('R' << 24) + ('E' << 16) + ('M' << 8) + 'B'; static const uint32 kCast = ('C' << 24) + ('A' << 16) + ('S' << 8) + 'T'; static const uint8 kReceiverLogSubtype = 2; static const size_t kRtcpMaxReceiverLogMessages = 256; static const size_t kRtcpMaxNackFields = 253; static const size_t kRtcpMaxCastLossFields = 100; struct RtcpFieldReceiverReport { // RFC 3550. uint32 sender_ssrc; uint8 number_of_report_blocks; }; struct RtcpFieldSenderReport { // RFC 3550. uint32 sender_ssrc; uint8 number_of_report_blocks; uint32 ntp_most_significant; uint32 ntp_least_significant; uint32 rtp_timestamp; uint32 sender_packet_count; uint32 sender_octet_count; }; struct RtcpFieldReportBlockItem { // RFC 3550. uint32 ssrc; uint8 fraction_lost; uint32 cumulative_number_of_packets_lost; uint32 extended_highest_sequence_number; uint32 jitter; uint32 last_sender_report; uint32 delay_last_sender_report; }; struct RtcpFieldSdesCName { // RFC 3550 uint32 sender_ssrc; char name[kRtcpCnameSize]; }; struct RtcpFieldBye { // RFC 3550. uint32 sender_ssrc; }; struct RtcpFieldGenericRtpFeedbackNack { // RFC 4585. uint32 sender_ssrc; uint32 media_ssrc; }; struct RtcpFieldGenericRtpFeedbackNackItem { // RFC 4585. uint16 packet_id; uint16 bitmask; }; struct RtcpFieldPayloadSpecificFir { // RFC 5104. uint32 sender_ssrc; uint32 media_ssrc; // zero! }; struct RtcpFieldPayloadSpecificFirItem { // RFC 5104. uint32 ssrc; uint8 command_sequence_number; }; struct RtcpFieldPayloadSpecificPli { // RFC 4585. uint32 sender_ssrc; uint32 media_ssrc; }; struct RtcpFieldPayloadSpecificRpsi { // RFC 4585. uint32 sender_ssrc; uint32 media_ssrc; uint8 payload_type; uint16 number_of_valid_bits; uint8 native_bit_string[kRtcpRpsiDataSize]; }; struct RtcpFieldXr { // RFC 3611. uint32 sender_ssrc; }; struct RtcpFieldXrRrtr { // RFC 3611. uint32 ntp_most_significant; uint32 ntp_least_significant; }; struct RtcpFieldXrDlrr { // RFC 3611. uint32 receivers_ssrc; uint32 last_receiver_report; uint32 delay_last_receiver_report; }; struct RtcpFieldPayloadSpecificApplication { uint32 sender_ssrc; uint32 media_ssrc; }; struct RtcpFieldPayloadSpecificRembItem { uint32 bitrate; uint8 number_of_ssrcs; uint32 ssrcs[kRtcpMaxNumberOfRembFeedbackSsrcs]; }; struct RtcpFieldPayloadSpecificCastItem { uint8 last_frame_id; uint8 number_of_lost_fields; uint16 target_delay_ms; }; struct RtcpFieldPayloadSpecificCastNackItem { uint8 frame_id; uint16 packet_id; uint8 bitmask; }; struct RtcpFieldApplicationSpecificCastReceiverLogItem { uint32 sender_ssrc; uint32 rtp_timestamp; uint32 event_timestamp_base; uint8 event; union { uint16 packet_id; int16 delay_delta; } delay_delta_or_packet_id; uint16 event_timestamp_delta; }; union RtcpField { RtcpFieldReceiverReport receiver_report; RtcpFieldSenderReport sender_report; RtcpFieldReportBlockItem report_block_item; RtcpFieldSdesCName c_name; RtcpFieldBye bye; RtcpFieldXr extended_report; RtcpFieldXrRrtr rrtr; RtcpFieldXrDlrr dlrr; RtcpFieldGenericRtpFeedbackNack nack; RtcpFieldGenericRtpFeedbackNackItem nack_item; RtcpFieldPayloadSpecificPli pli; RtcpFieldPayloadSpecificRpsi rpsi; RtcpFieldPayloadSpecificFir fir; RtcpFieldPayloadSpecificFirItem fir_item; RtcpFieldPayloadSpecificApplication application_specific; RtcpFieldPayloadSpecificRembItem remb_item; RtcpFieldPayloadSpecificCastItem cast_item; RtcpFieldPayloadSpecificCastNackItem cast_nack_item; RtcpFieldApplicationSpecificCastReceiverLogItem cast_receiver_log; }; enum RtcpFieldTypes { kRtcpNotValidCode, // RFC 3550. kRtcpRrCode, kRtcpSrCode, kRtcpReportBlockItemCode, kRtcpSdesCode, kRtcpSdesChunkCode, kRtcpByeCode, // RFC 3611. kRtcpXrCode, kRtcpXrRrtrCode, kRtcpXrDlrrCode, kRtcpXrUnknownItemCode, // RFC 4585. kRtcpGenericRtpFeedbackNackCode, kRtcpGenericRtpFeedbackNackItemCode, kRtcpPayloadSpecificPliCode, kRtcpPayloadSpecificRpsiCode, kRtcpPayloadSpecificAppCode, // Application specific. kRtcpPayloadSpecificRembCode, kRtcpPayloadSpecificRembItemCode, kRtcpPayloadSpecificCastCode, kRtcpPayloadSpecificCastNackItemCode, kRtcpApplicationSpecificCastReceiverLogCode, kRtcpApplicationSpecificCastReceiverLogFrameCode, kRtcpApplicationSpecificCastReceiverLogEventCode, // RFC 5104. kRtcpPayloadSpecificFirCode, kRtcpPayloadSpecificFirItemCode, // RFC 6051. kRtcpGenericRtpFeedbackSrReqCode, }; struct RtcpCommonHeader { uint8 V; // Version. bool P; // Padding. uint8 IC; // Item count / subtype. uint8 PT; // Packet Type. uint16 length_in_octets; }; class RtcpParser { public: RtcpParser(const uint8* rtcp_data, size_t rtcp_length); ~RtcpParser(); RtcpFieldTypes FieldType() const; const RtcpField& Field() const; bool IsValid() const; RtcpFieldTypes Begin(); RtcpFieldTypes Iterate(); private: enum ParseState { kStateTopLevel, // Top level packet kStateReportBlock, // Sender/Receiver report report blocks. kStateSdes, kStateBye, kStateApplicationSpecificCastReceiverFrameLog, kStateApplicationSpecificCastReceiverEventLog, kStateExtendedReportBlock, kStateExtendedReportDelaySinceLastReceiverReport, kStateGenericRtpFeedbackNack, kStatePayloadSpecificRpsi, kStatePayloadSpecificFir, kStatePayloadSpecificApplication, kStatePayloadSpecificRemb, // Application specific Remb. kStatePayloadSpecificCast, // Application specific Cast. kStatePayloadSpecificCastNack, // Application specific Nack for Cast. }; bool RtcpParseCommonHeader(const uint8* begin, const uint8* end, RtcpCommonHeader* parsed_header) const; void IterateTopLevel(); void IterateReportBlockItem(); void IterateSdesItem(); void IterateByeItem(); void IterateCastReceiverLogFrame(); void IterateCastReceiverLogEvent(); void IterateExtendedReportItem(); void IterateExtendedReportDelaySinceLastReceiverReportItem(); void IterateNackItem(); void IterateRpsiItem(); void IterateFirItem(); void IteratePayloadSpecificAppItem(); void IteratePayloadSpecificRembItem(); void IteratePayloadSpecificCastItem(); void IteratePayloadSpecificCastNackItem(); void Validate(); void EndCurrentBlock(); bool ParseRR(); bool ParseSR(); bool ParseReportBlockItem(); bool ParseSdes(); bool ParseSdesItem(); bool ParseSdesTypes(); bool ParseBye(); bool ParseByeItem(); bool ParseApplicationDefined(uint8 subtype); bool ParseCastReceiverLogFrameItem(); bool ParseCastReceiverLogEventItem(); bool ParseExtendedReport(); bool ParseExtendedReportItem(); bool ParseExtendedReportReceiverReferenceTimeReport(); bool ParseExtendedReportDelaySinceLastReceiverReport(); bool ParseFeedBackCommon(const RtcpCommonHeader& header); bool ParseNackItem(); bool ParseRpsiItem(); bool ParseFirItem(); bool ParsePayloadSpecificAppItem(); bool ParsePayloadSpecificRembItem(); bool ParsePayloadSpecificCastItem(); bool ParsePayloadSpecificCastNackItem(); private: const uint8* const rtcp_data_begin_; const uint8* const rtcp_data_end_; bool valid_packet_; const uint8* rtcp_data_; const uint8* rtcp_block_end_; ParseState state_; uint8 number_of_blocks_; RtcpFieldTypes field_type_; RtcpField field_; DISALLOW_COPY_AND_ASSIGN(RtcpParser); }; // Converts a log event type to an integer value. // NOTE: We have only allocated 4 bits to represent the type of event over the // wire. Therefore, this function can only return values from 0 to 15. uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event); // The inverse of |ConvertEventTypeToWireFormat()|. CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event); } // namespace cast } // namespace media #endif // MEDIA_CAST_RTCP_RTCP_UTILITY_H_