/*
 *  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 "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;
  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_
