blob: 34f3f25a889e4f5d6eefc55ad52508d5c89277f3 [file] [log] [blame]
// 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_