/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef MODULES_AUDIO_CODING_NETEQ_PACKET_H_
#define MODULES_AUDIO_CODING_NETEQ_PACKET_H_

#include <stdint.h>

#include <list>
#include <memory>

#include "api/audio_codecs/audio_decoder.h"
#include "api/rtp_packet_info.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"

namespace webrtc {

// Struct for holding RTP packets.
struct Packet {
  struct Priority {
    Priority() : codec_level(0), red_level(0) {}
    Priority(int codec_level, int red_level)
        : codec_level(codec_level), red_level(red_level) {
      CheckInvariant();
    }

    int codec_level;
    int red_level;

    // Priorities are sorted low-to-high, first on the level the codec
    // prioritizes it, then on the level of RED packet it is; i.e. if it is a
    // primary or secondary payload of a RED packet. For example: with Opus, an
    // Fec packet (which the decoder prioritizes lower than a regular packet)
    // will not be used if there is _any_ RED payload for the same
    // timeframe. The highest priority packet will have levels {0, 0}. Negative
    // priorities are not allowed.
    bool operator<(const Priority& b) const {
      CheckInvariant();
      b.CheckInvariant();
      if (codec_level == b.codec_level)
        return red_level < b.red_level;

      return codec_level < b.codec_level;
    }
    bool operator==(const Priority& b) const {
      CheckInvariant();
      b.CheckInvariant();
      return codec_level == b.codec_level && red_level == b.red_level;
    }
    bool operator!=(const Priority& b) const { return !(*this == b); }
    bool operator>(const Priority& b) const { return b < *this; }
    bool operator<=(const Priority& b) const { return !(b > *this); }
    bool operator>=(const Priority& b) const { return !(b < *this); }

   private:
    void CheckInvariant() const {
      RTC_DCHECK_GE(codec_level, 0);
      RTC_DCHECK_GE(red_level, 0);
    }
  };

  uint32_t timestamp;
  uint16_t sequence_number;
  uint8_t payload_type;
  // Datagram excluding RTP header and header extension.
  rtc::Buffer payload;
  Priority priority;
  RtpPacketInfo packet_info;
  std::unique_ptr<TickTimer::Stopwatch> waiting_time;
  std::unique_ptr<AudioDecoder::EncodedAudioFrame> frame;

  Packet();
  Packet(Packet&& b);
  ~Packet();

  // Packets should generally be moved around but sometimes it's useful to make
  // a copy, for example for testing purposes. NOTE: Will only work for
  // un-parsed packets, i.e. |frame| must be unset. The payload will, however,
  // be copied. |waiting_time| will also not be copied.
  Packet Clone() const;

  Packet& operator=(Packet&& b);

  // Comparison operators. Establish a packet ordering based on (1) timestamp,
  // (2) sequence number and (3) redundancy.
  // Timestamp and sequence numbers are compared taking wrap-around into
  // account. For two packets with the same sequence number and timestamp a
  // primary payload is considered "smaller" than a secondary.
  bool operator==(const Packet& rhs) const {
    return (this->timestamp == rhs.timestamp &&
            this->sequence_number == rhs.sequence_number &&
            this->priority == rhs.priority);
  }
  bool operator!=(const Packet& rhs) const { return !operator==(rhs); }
  bool operator<(const Packet& rhs) const {
    if (this->timestamp == rhs.timestamp) {
      if (this->sequence_number == rhs.sequence_number) {
        // Timestamp and sequence numbers are identical - deem the left hand
        // side to be "smaller" (i.e., "earlier") if it has higher priority.
        return this->priority < rhs.priority;
      }
      return (static_cast<uint16_t>(rhs.sequence_number -
                                    this->sequence_number) < 0xFFFF / 2);
    }
    return (static_cast<uint32_t>(rhs.timestamp - this->timestamp) <
            0xFFFFFFFF / 2);
  }
  bool operator>(const Packet& rhs) const { return rhs.operator<(*this); }
  bool operator<=(const Packet& rhs) const { return !operator>(rhs); }
  bool operator>=(const Packet& rhs) const { return !operator<(rhs); }

  bool empty() const { return !frame && payload.empty(); }
};

// A list of packets.
typedef std::list<Packet> PacketList;

}  // namespace webrtc
#endif  // MODULES_AUDIO_CODING_NETEQ_PACKET_H_
