// 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_DEFINES_H_
#define MEDIA_CAST_NET_RTCP_RTCP_DEFINES_H_

#include <stddef.h>
#include <stdint.h>

#include <list>
#include <memory>
#include <utility>
#include <vector>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "media/cast/logging/logging_defines.h"
#include "media/cast/net/cast_transport_defines.h"

namespace media {
namespace cast {

static const size_t kRtcpCastLogHeaderSize = 12;
static const size_t kRtcpReceiverFrameLogSize = 8;
static const size_t kRtcpReceiverEventLogSize = 4;

// The maximum number of Cast receiver events to keep in history for the
// purpose of sending the events through RTCP.
// The number chosen should be more than the number of events that can be
// stored in a RTCP packet.
const size_t kReceiverRtcpEventHistorySize = 512;

enum RtcpPacketFields {
  kPacketTypeLow = 194,  // SMPTE time-code mapping.
  kPacketTypeSenderReport = 200,
  kPacketTypeReceiverReport = 201,
  kPacketTypeApplicationDefined = 204,
  kPacketTypeGenericRtpFeedback = 205,
  kPacketTypePayloadSpecific = 206,
  kPacketTypeXr = 207,
  kPacketTypeHigh = 210,  // Port Mapping.
};

// Handle the per frame ACK and NACK messages.
struct RtcpCastMessage {
  explicit RtcpCastMessage(uint32_t ssrc);
  RtcpCastMessage();
  ~RtcpCastMessage();

  uint32_t remote_ssrc;
  FrameId ack_frame_id;
  uint16_t target_delay_ms;
  MissingFramesAndPacketsMap missing_frames_and_packets;
  // This wrap-around counter is incremented by one for each ACK/NACK Cast
  // packet sent.
  uint8_t feedback_count;
  // The set of received frames that have frame IDs strictly equal to or larger
  // than |ack_frame_id + 2|.
  std::vector<FrameId> received_later_frames;
};

struct RtcpPliMessage {
  explicit RtcpPliMessage(uint32_t ssrc);
  RtcpPliMessage();

  uint32_t remote_ssrc;
};

// Log messages from receiver to sender.
struct RtcpReceiverEventLogMessage {
  RtcpReceiverEventLogMessage();
  ~RtcpReceiverEventLogMessage();

  CastLoggingEvent type;
  base::TimeTicks event_timestamp;
  base::TimeDelta delay_delta;
  uint16_t packet_id;
};

typedef std::list<RtcpReceiverEventLogMessage> RtcpReceiverEventLogMessages;

struct RtcpReceiverFrameLogMessage {
  explicit RtcpReceiverFrameLogMessage(RtpTimeTicks rtp_timestamp);
  RtcpReceiverFrameLogMessage(const RtcpReceiverFrameLogMessage& other);
  ~RtcpReceiverFrameLogMessage();

  const RtpTimeTicks rtp_timestamp_;
  RtcpReceiverEventLogMessages event_log_messages_;
};

typedef std::list<RtcpReceiverFrameLogMessage> RtcpReceiverLogMessage;

struct RtcpReceiverReferenceTimeReport {
  RtcpReceiverReferenceTimeReport();
  ~RtcpReceiverReferenceTimeReport();

  uint32_t remote_ssrc;
  uint32_t ntp_seconds;
  uint32_t ntp_fraction;
};

inline bool operator==(RtcpReceiverReferenceTimeReport lhs,
                       RtcpReceiverReferenceTimeReport rhs) {
  return lhs.remote_ssrc == rhs.remote_ssrc &&
         lhs.ntp_seconds == rhs.ntp_seconds &&
         lhs.ntp_fraction == rhs.ntp_fraction;
}

// Struct used by raw event subscribers as an intermediate format before
// sending off to the other side via RTCP.
// (i.e., {Sender,Receiver}RtcpEventSubscriber)
struct RtcpEvent {
  RtcpEvent();
  ~RtcpEvent();

  CastLoggingEvent type;

  // Time of event logged.
  base::TimeTicks timestamp;

  // Render/playout delay. Only set for FRAME_PLAYOUT events.
  base::TimeDelta delay_delta;

  // Only set for packet events.
  uint16_t packet_id;
};

// TODO(hubbe): Document members of this struct.
struct RtpReceiverStatistics {
  RtpReceiverStatistics();
  uint8_t fraction_lost;
  uint32_t cumulative_lost;  // 24 bits valid.
  uint32_t extended_high_sequence_number;
  uint32_t jitter;
};

// Created on a RTP receiver to be passed over IPC.
struct RtcpTimeData {
  uint32_t ntp_seconds;
  uint32_t ntp_fraction;
  base::TimeTicks timestamp;
};

// This struct is used to encapsulate all the parameters of the
// SendRtcpFromRtpReceiver for IPC transportation.
struct SendRtcpFromRtpReceiver_Params {
  SendRtcpFromRtpReceiver_Params();
  ~SendRtcpFromRtpReceiver_Params();
  uint32_t ssrc;
  uint32_t sender_ssrc;
  RtcpTimeData time_data;
  std::unique_ptr<RtcpCastMessage> cast_message;
  std::unique_ptr<RtcpPliMessage> pli_message;
  base::TimeDelta target_delay;
  std::unique_ptr<std::vector<std::pair<RtpTimeTicks, RtcpEvent>>> rtcp_events;
  std::unique_ptr<RtpReceiverStatistics> rtp_receiver_statistics;
};


}  // namespace cast
}  // namespace media

#endif  // MEDIA_CAST_NET_RTCP_RTCP_DEFINES_H_
