// 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_CAST_TRANSPORT_CONFIG_H_
#define MEDIA_CAST_NET_CAST_TRANSPORT_CONFIG_H_

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

#include <memory>
#include <string>

#include "base/callback.h"
#include "base/stl_util.h"
#include "media/cast/common/rtp_time.h"
#include "media/cast/net/cast_transport_defines.h"

namespace media {
namespace cast {

enum Codec {
  CODEC_UNKNOWN,
  CODEC_AUDIO_OPUS,
  CODEC_AUDIO_PCM16,
  CODEC_AUDIO_AAC,
  CODEC_VIDEO_FAKE,
  CODEC_VIDEO_VP8,
  CODEC_VIDEO_H264,
  CODEC_LAST = CODEC_VIDEO_H264
};

struct CastTransportRtpConfig {
  CastTransportRtpConfig();
  ~CastTransportRtpConfig();

  // Identifier refering to this sender.
  uint32_t ssrc;

  // Identifier for incoming RTCP traffic.
  uint32_t feedback_ssrc;

  // RTP payload type enum: Specifies the type/encoding of frame data.
  int rtp_payload_type;

  // The AES crypto key and initialization vector.  Each of these strings
  // contains the data in binary form, of size kAesKeySize.  If they are empty
  // strings, crypto is not being used.
  std::string aes_key;
  std::string aes_iv_mask;
};

// A combination of metadata and data for one encoded frame.  This can contain
// audio data or video data or other.
struct EncodedFrame {
  enum Dependency {
    // "null" value, used to indicate whether |dependency| has been set.
    UNKNOWN_DEPENDENCY,

    // Not decodable without the reference frame indicated by
    // |referenced_frame_id|.
    DEPENDENT,

    // Independently decodable.
    INDEPENDENT,

    // Independently decodable, and no future frames will depend on any frames
    // before this one.
    KEY,

    DEPENDENCY_LAST = KEY
  };

  EncodedFrame();
  virtual ~EncodedFrame();

  // Convenience accessors to data as an array of uint8_t elements.
  const uint8_t* bytes() const {
    return reinterpret_cast<uint8_t*>(
        string_as_array(const_cast<std::string*>(&data)));
  }
  uint8_t* mutable_bytes() {
    return reinterpret_cast<uint8_t*>(string_as_array(&data));
  }

  // Copies all data members except |data| to |dest|.
  // Does not modify |dest->data|.
  void CopyMetadataTo(EncodedFrame* dest) const;

  // This frame's dependency relationship with respect to other frames.
  Dependency dependency;

  // The label associated with this frame.  Implies an ordering relative to
  // other frames in the same stream.
  FrameId frame_id;

  // The label associated with the frame upon which this frame depends.  If
  // this frame does not require any other frame in order to become decodable
  // (e.g., key frames), |referenced_frame_id| must equal |frame_id|.
  FrameId referenced_frame_id;

  // The stream timestamp, on the timeline of the signal data.  For example, RTP
  // timestamps for audio are usually defined as the total number of audio
  // samples encoded in all prior frames.  A playback system uses this value to
  // detect gaps in the stream, and otherwise stretch the signal to match
  // playout targets.
  RtpTimeTicks rtp_timestamp;

  // The common reference clock timestamp for this frame.  This value originates
  // from a sender and is used to provide lip synchronization between streams in
  // a receiver.  Thus, in the sender context, this is set to the time at which
  // the frame was captured/recorded.  In the receiver context, this is set to
  // the target playout time.  Over a sequence of frames, this time value is
  // expected to drift with respect to the elapsed time implied by the RTP
  // timestamps; and it may not necessarily increment with precise regularity.
  base::TimeTicks reference_time;

  // Playout delay for this and all future frames. Used by the Adaptive
  // Playout delay extension. Zero means no change.
  uint16_t new_playout_delay_ms;

  // The encoded signal data.
  std::string data;
};

typedef base::Callback<void(std::unique_ptr<Packet> packet)>
    PacketReceiverCallback;
typedef base::Callback<bool(std::unique_ptr<Packet> packet)>
    PacketReceiverCallbackWithStatus;

class PacketTransport {
 public:
  // Send a packet to the network. Returns false if the network is blocked
  // and we should wait for |cb| to be called. It is not allowed to called
  // SendPacket again until |cb| has been called. Any other errors that
  // occur will be reported through side channels, in such cases, this function
  // will return true indicating that the channel is not blocked.
  virtual bool SendPacket(PacketRef packet, const base::Closure& cb) = 0;

  // Returns the number of bytes ever sent.
  virtual int64_t GetBytesSent() = 0;

  // Start receiving packets. Pakets are submitted to |packet_receiver|.
  virtual void StartReceiving(
      const PacketReceiverCallbackWithStatus& packet_receiver) = 0;

  // Stop receiving packets.
  virtual void StopReceiving() = 0;

  virtual ~PacketTransport() {}
};

struct RtcpSenderInfo {
  RtcpSenderInfo();
  ~RtcpSenderInfo();
  // First three members are used for lipsync.
  // Last two members are used for rtt.
  uint32_t ntp_seconds;
  uint32_t ntp_fraction;
  RtpTimeTicks rtp_timestamp;
  uint32_t send_packet_count;
  size_t send_octet_count;
};

struct RtcpReportBlock {
  RtcpReportBlock();
  ~RtcpReportBlock();
  uint32_t remote_ssrc;  // SSRC of sender of this report.
  uint32_t media_ssrc;   // SSRC of the RTP packet sender.
  uint8_t fraction_lost;
  uint32_t cumulative_lost;  // 24 bits valid.
  uint32_t extended_high_sequence_number;
  uint32_t jitter;
  uint32_t last_sr;
  uint32_t delay_since_last_sr;
};

struct RtcpDlrrReportBlock {
  RtcpDlrrReportBlock();
  ~RtcpDlrrReportBlock();
  uint32_t last_rr;
  uint32_t delay_since_last_rr;
};

inline bool operator==(RtcpSenderInfo lhs, RtcpSenderInfo rhs) {
  return lhs.ntp_seconds == rhs.ntp_seconds &&
         lhs.ntp_fraction == rhs.ntp_fraction &&
         lhs.rtp_timestamp == rhs.rtp_timestamp &&
         lhs.send_packet_count == rhs.send_packet_count &&
         lhs.send_octet_count == rhs.send_octet_count;
}

}  // namespace cast
}  // namespace media

#endif  // MEDIA_CAST_NET_CAST_TRANSPORT_CONFIG_H_
