blob: 667352529e34b18f20aff4c5b20a4ec4cbd72474 [file] [log] [blame]
// Copyright 2014 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_NET_RTCP_RTCP_UTILITY_H_
#define MEDIA_CAST_NET_RTCP_RTCP_UTILITY_H_
#include <stddef.h>
#include <stdint.h>
#include "base/big_endian.h"
#include "base/macros.h"
#include "media/cast/logging/logging_defines.h"
#include "media/cast/net/cast_transport_config.h"
#include "media/cast/net/rtcp/rtcp_defines.h"
namespace media {
namespace cast {
// RFC 3550 page 44, including end null.
static const size_t kRtcpCnameSize = 256;
static const uint32_t kCast = ('C' << 24) + ('A' << 16) + ('S' << 8) + 'T';
static const uint32_t kCst2 = ('C' << 24) + ('S' << 16) + ('T' << 8) + '2';
static const uint8_t kReceiverLogSubtype = 2;
static const size_t kRtcpMaxReceiverLogMessages = 256;
static const size_t kRtcpMaxCastLossFields = 100;
struct RtcpCommonHeader {
uint8_t V; // Version.
bool P; // Padding.
uint8_t IC; // Item count / subtype.
uint8_t PT; // Packet Type.
size_t length_in_octets;
};
class RtcpParser {
public:
RtcpParser(uint32_t local_ssrc, uint32_t remote_ssrc);
RtcpParser(const RtcpParser&) = delete;
RtcpParser& operator=(const RtcpParser&) = delete;
~RtcpParser();
// Gets/Sets the ID of the latest frame that could possibly be ACK'ed. This
// is used when expanding truncated frame IDs during Parse(). This only needs
// to be called if the client uses cast_message().
FrameId max_valid_frame_id() const { return max_valid_frame_id_; }
void SetMaxValidFrameId(FrameId max_valid_frame_id);
// Parse the RTCP packet.
bool Parse(base::BigEndianReader* reader);
bool has_sender_report() const { return has_sender_report_; }
const RtcpSenderInfo& sender_report() const {
return sender_report_;
}
bool has_last_report() const { return has_last_report_; }
uint32_t last_report() const { return last_report_; }
uint32_t delay_since_last_report() const { return delay_since_last_report_; }
bool has_receiver_log() const { return !receiver_log_.empty(); }
const RtcpReceiverLogMessage& receiver_log() const { return receiver_log_; }
RtcpReceiverLogMessage* mutable_receiver_log() { return & receiver_log_; }
bool has_cast_message() const { return has_cast_message_; }
const RtcpCastMessage& cast_message() const { return cast_message_; }
RtcpCastMessage* mutable_cast_message() { return &cast_message_; }
// Return if successfully parsed the extended feedback.
bool has_cst2_message() const { return has_cst2_message_; }
bool has_receiver_reference_time_report() const {
return has_receiver_reference_time_report_;
}
const RtcpReceiverReferenceTimeReport&
receiver_reference_time_report() const {
return receiver_reference_time_report_;
}
bool has_picture_loss_indicator() const {
return has_picture_loss_indicator_;
}
private:
bool ParseCommonHeader(base::BigEndianReader* reader,
RtcpCommonHeader* parsed_header);
bool ParseSR(base::BigEndianReader* reader, const RtcpCommonHeader& header);
bool ParseRR(base::BigEndianReader* reader, const RtcpCommonHeader& header);
bool ParseReportBlock(base::BigEndianReader* reader);
bool ParsePli(base::BigEndianReader* reader, const RtcpCommonHeader& header);
bool ParseApplicationDefined(base::BigEndianReader* reader,
const RtcpCommonHeader& header);
bool ParseCastReceiverLogFrameItem(base::BigEndianReader* reader);
bool ParseFeedbackCommon(base::BigEndianReader* reader,
const RtcpCommonHeader& header);
bool ParseExtendedReport(base::BigEndianReader* reader,
const RtcpCommonHeader& header);
bool ParseExtendedReportReceiverReferenceTimeReport(
base::BigEndianReader* reader,
uint32_t remote_ssrc);
bool ParseExtendedReportDelaySinceLastReceiverReport(
base::BigEndianReader* reader);
const uint32_t local_ssrc_;
const uint32_t remote_ssrc_;
bool has_sender_report_;
RtcpSenderInfo sender_report_;
uint32_t last_report_;
uint32_t delay_since_last_report_;
bool has_last_report_;
// |receiver_log_| is a vector vector, no need for has_*.
RtcpReceiverLogMessage receiver_log_;
bool has_cast_message_;
RtcpCastMessage cast_message_;
bool has_cst2_message_;
bool has_receiver_reference_time_report_;
RtcpReceiverReferenceTimeReport receiver_reference_time_report_;
// Tracks recently-parsed RTP timestamps so that the truncated values can be
// re-expanded into full-form.
RtpTimeTicks last_parsed_sr_rtp_timestamp_;
RtpTimeTicks last_parsed_frame_log_rtp_timestamp_;
// The maximum possible re-expanded frame ID value.
FrameId max_valid_frame_id_;
// Indicates if sender received the Pli message from the receiver.
bool has_picture_loss_indicator_;
};
// 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_t ConvertEventTypeToWireFormat(CastLoggingEvent event);
// The inverse of |ConvertEventTypeToWireFormat()|.
CastLoggingEvent TranslateToLogEventFromWireFormat(uint8_t event);
// Splits an NTP timestamp having a microsecond timebase into the standard two
// 32-bit integer wire format.
void ConvertTimeToFractions(int64_t ntp_time_us,
uint32_t* seconds,
uint32_t* fractions);
// Maps a base::TimeTicks value to an NTP timestamp comprised of two components.
void ConvertTimeTicksToNtp(const base::TimeTicks& time,
uint32_t* ntp_seconds,
uint32_t* ntp_fractions);
// Create a NTP diff from seconds and fractions of seconds; delay_fraction is
// fractions of a second where 0x80000000 is half a second.
uint32_t ConvertToNtpDiff(uint32_t delay_seconds, uint32_t delay_fraction);
// Maps an NTP timestamp, comprised of two components, to a base::TimeTicks
// value.
base::TimeTicks ConvertNtpToTimeTicks(uint32_t ntp_seconds,
uint32_t ntp_fractions);
bool IsRtcpPacket(const uint8_t* packet, size_t length);
uint32_t GetSsrcOfSender(const uint8_t* rtcp_buffer, size_t length);
} // namespace cast
} // namespace media
#endif // MEDIA_CAST_NET_RTCP_RTCP_UTILITY_H_