/*
 *  Copyright (c) 2014 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.
 */

#include "webrtc/modules/audio_coding/neteq/tools/packet.h"

#include <string.h>

#include <memory>

#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
#include "webrtc/rtc_base/checks.h"

namespace webrtc {
namespace test {

Packet::Packet(uint8_t* packet_memory,
               size_t allocated_bytes,
               double time_ms,
               const RtpHeaderParser& parser)
    : payload_memory_(packet_memory),
      payload_(NULL),
      packet_length_bytes_(allocated_bytes),
      payload_length_bytes_(0),
      virtual_packet_length_bytes_(allocated_bytes),
      virtual_payload_length_bytes_(0),
      time_ms_(time_ms) {
  valid_header_ = ParseHeader(parser);
}

Packet::Packet(uint8_t* packet_memory,
               size_t allocated_bytes,
               size_t virtual_packet_length_bytes,
               double time_ms,
               const RtpHeaderParser& parser)
    : payload_memory_(packet_memory),
      payload_(NULL),
      packet_length_bytes_(allocated_bytes),
      payload_length_bytes_(0),
      virtual_packet_length_bytes_(virtual_packet_length_bytes),
      virtual_payload_length_bytes_(0),
      time_ms_(time_ms) {
  valid_header_ = ParseHeader(parser);
}

Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
    : payload_memory_(packet_memory),
      payload_(NULL),
      packet_length_bytes_(allocated_bytes),
      payload_length_bytes_(0),
      virtual_packet_length_bytes_(allocated_bytes),
      virtual_payload_length_bytes_(0),
      time_ms_(time_ms) {
  std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
  valid_header_ = ParseHeader(*parser);
}

Packet::Packet(uint8_t* packet_memory,
               size_t allocated_bytes,
               size_t virtual_packet_length_bytes,
               double time_ms)
    : payload_memory_(packet_memory),
      payload_(NULL),
      packet_length_bytes_(allocated_bytes),
      payload_length_bytes_(0),
      virtual_packet_length_bytes_(virtual_packet_length_bytes),
      virtual_payload_length_bytes_(0),
      time_ms_(time_ms) {
  std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
  valid_header_ = ParseHeader(*parser);
}

Packet::~Packet() = default;

bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
  //
  //  0                   1                    2                   3
  //  0 1 2 3 4 5 6 7 8 9 0 1 2 3  4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  // |1|   block PT  |  timestamp offset         |   block length    |
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  // |1|    ...                                                      |
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  // |0|   block PT  |
  // +-+-+-+-+-+-+-+-+
  //

  assert(payload_);
  const uint8_t* payload_ptr = payload_;
  const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;

  // Find all RED headers with the extension bit set to 1. That is, all headers
  // but the last one.
  while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
    RTPHeader* header = new RTPHeader;
    CopyToHeader(header);
    header->payloadType = payload_ptr[0] & 0x7F;
    uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
    header->timestamp -= offset;
    headers->push_front(header);
    payload_ptr += 4;
  }
  // Last header.
  assert(payload_ptr < payload_end_ptr);
  if (payload_ptr >= payload_end_ptr) {
    return false;  // Payload too short.
  }
  RTPHeader* header = new RTPHeader;
  CopyToHeader(header);
  header->payloadType = payload_ptr[0] & 0x7F;
  headers->push_front(header);
  return true;
}

void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
  while (!headers->empty()) {
    delete headers->front();
    headers->pop_front();
  }
}

bool Packet::ParseHeader(const RtpHeaderParser& parser) {
  bool valid_header = parser.Parse(
      payload_memory_.get(), static_cast<int>(packet_length_bytes_), &header_);
  // Special case for dummy packets that have padding marked in the RTP header.
  // This causes the RTP header parser to report failure, but is fine in this
  // context.
  const bool header_only_with_padding =
      (header_.headerLength == packet_length_bytes_ &&
       header_.paddingLength > 0);
  if (!valid_header && !header_only_with_padding) {
    return false;
  }
  assert(header_.headerLength <= packet_length_bytes_);
  payload_ = &payload_memory_[header_.headerLength];
  assert(packet_length_bytes_ >= header_.headerLength);
  payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
  RTC_CHECK_GE(virtual_packet_length_bytes_, packet_length_bytes_);
  assert(virtual_packet_length_bytes_ >= header_.headerLength);
  virtual_payload_length_bytes_ =
      virtual_packet_length_bytes_ - header_.headerLength;
  return true;
}

void Packet::CopyToHeader(RTPHeader* destination) const {
  destination->markerBit = header_.markerBit;
  destination->payloadType = header_.payloadType;
  destination->sequenceNumber = header_.sequenceNumber;
  destination->timestamp = header_.timestamp;
  destination->ssrc = header_.ssrc;
  destination->numCSRCs = header_.numCSRCs;
  destination->paddingLength = header_.paddingLength;
  destination->headerLength = header_.headerLength;
  destination->payload_type_frequency = header_.payload_type_frequency;
  memcpy(&destination->arrOfCSRCs,
         &header_.arrOfCSRCs,
         sizeof(header_.arrOfCSRCs));
  memcpy(
      &destination->extension, &header_.extension, sizeof(header_.extension));
}

}  // namespace test
}  // namespace webrtc
