root/media/cast/rtcp/rtcp_utility.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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/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 kSenderLogSubtype = 1;
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;
  uint16 delay_delta_or_packet_id;
  uint16 event_timestamp_delta;
};

struct RtcpFieldApplicationSpecificCastSenderLogItem {
  uint32 sender_ssrc;
  uint8 status;
  uint32 rtp_timestamp;
};

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;
  RtcpFieldApplicationSpecificCastSenderLogItem cast_sender_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,
  kRtcpApplicationSpecificCastSenderLogCode,

  // 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,
    kStateApplicationSpecificCastSenderLog,
    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 IterateCastSenderLog();
  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 ParseCastSenderLogItem();

  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);
};

}  // namespace cast
}  // namespace media

#endif  // MEDIA_CAST_RTCP_RTCP_UTILITY_H_

/* [<][>][^][v][top][bottom][index][help] */