/*
 *  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.
 */

#include "RTPFile.h"

#include <stdlib.h>

#ifdef WIN32
#   include <Winsock2.h>
#else
#   include <arpa/inet.h>
#endif

#include "audio_coding_module.h"
#include "engine_configurations.h"
#include "rw_lock_wrapper.h"
// TODO(tlegrand): Consider removing usage of gtest.
#include "testing/gtest/include/gtest/gtest.h"

namespace webrtc {

void RTPStream::ParseRTPHeader(WebRtcRTPHeader* rtpInfo,
                               const uint8_t* rtpHeader) {
  rtpInfo->header.payloadType = rtpHeader[1];
  rtpInfo->header.sequenceNumber = (static_cast<uint16_t>(rtpHeader[2]) << 8) |
      rtpHeader[3];
  rtpInfo->header.timestamp = (static_cast<uint32_t>(rtpHeader[4]) << 24) |
      (static_cast<uint32_t>(rtpHeader[5]) << 16) |
      (static_cast<uint32_t>(rtpHeader[6]) << 8) | rtpHeader[7];
  rtpInfo->header.ssrc = (static_cast<uint32_t>(rtpHeader[8]) << 24) |
      (static_cast<uint32_t>(rtpHeader[9]) << 16) |
      (static_cast<uint32_t>(rtpHeader[10]) << 8) | rtpHeader[11];
}

void RTPStream::MakeRTPheader(uint8_t* rtpHeader, uint8_t payloadType,
                              int16_t seqNo, uint32_t timeStamp,
                              uint32_t ssrc) {
  rtpHeader[0] = (unsigned char) 0x80;
  rtpHeader[1] = (unsigned char) (payloadType & 0xFF);
  rtpHeader[2] = (unsigned char) ((seqNo >> 8) & 0xFF);
  rtpHeader[3] = (unsigned char) ((seqNo) & 0xFF);
  rtpHeader[4] = (unsigned char) ((timeStamp >> 24) & 0xFF);
  rtpHeader[5] = (unsigned char) ((timeStamp >> 16) & 0xFF);

  rtpHeader[6] = (unsigned char) ((timeStamp >> 8) & 0xFF);
  rtpHeader[7] = (unsigned char) (timeStamp & 0xFF);

  rtpHeader[8] = (unsigned char) ((ssrc >> 24) & 0xFF);
  rtpHeader[9] = (unsigned char) ((ssrc >> 16) & 0xFF);

  rtpHeader[10] = (unsigned char) ((ssrc >> 8) & 0xFF);
  rtpHeader[11] = (unsigned char) (ssrc & 0xFF);
}

RTPPacket::RTPPacket(uint8_t payloadType, uint32_t timeStamp, int16_t seqNo,
                     const uint8_t* payloadData, uint16_t payloadSize,
                     uint32_t frequency)
    : payloadType(payloadType),
      timeStamp(timeStamp),
      seqNo(seqNo),
      payloadSize(payloadSize),
      frequency(frequency) {
  if (payloadSize > 0) {
    this->payloadData = new uint8_t[payloadSize];
    memcpy(this->payloadData, payloadData, payloadSize);
  }
}

RTPPacket::~RTPPacket() {
  delete[] payloadData;
}

RTPBuffer::RTPBuffer() {
  _queueRWLock = RWLockWrapper::CreateRWLock();
}

RTPBuffer::~RTPBuffer() {
  delete _queueRWLock;
}

void RTPBuffer::Write(const uint8_t payloadType, const uint32_t timeStamp,
                      const int16_t seqNo, const uint8_t* payloadData,
                      const uint16_t payloadSize, uint32_t frequency) {
  RTPPacket *packet = new RTPPacket(payloadType, timeStamp, seqNo, payloadData,
                                    payloadSize, frequency);
  _queueRWLock->AcquireLockExclusive();
  _rtpQueue.push(packet);
  _queueRWLock->ReleaseLockExclusive();
}

uint16_t RTPBuffer::Read(WebRtcRTPHeader* rtpInfo, uint8_t* payloadData,
                         uint16_t payloadSize, uint32_t* offset) {
  _queueRWLock->AcquireLockShared();
  RTPPacket *packet = _rtpQueue.front();
  _rtpQueue.pop();
  _queueRWLock->ReleaseLockShared();
  rtpInfo->header.markerBit = 1;
  rtpInfo->header.payloadType = packet->payloadType;
  rtpInfo->header.sequenceNumber = packet->seqNo;
  rtpInfo->header.ssrc = 0;
  rtpInfo->header.timestamp = packet->timeStamp;
  if (packet->payloadSize > 0 && payloadSize >= packet->payloadSize) {
    memcpy(payloadData, packet->payloadData, packet->payloadSize);
  } else {
    return 0;
  }
  *offset = (packet->timeStamp / (packet->frequency / 1000));

  return packet->payloadSize;
}

bool RTPBuffer::EndOfFile() const {
  _queueRWLock->AcquireLockShared();
  bool eof = _rtpQueue.empty();
  _queueRWLock->ReleaseLockShared();
  return eof;
}

void RTPFile::Open(const char *filename, const char *mode) {
  if ((_rtpFile = fopen(filename, mode)) == NULL) {
    printf("Cannot write file %s.\n", filename);
    ADD_FAILURE() << "Unable to write file";
    exit(1);
  }
}

void RTPFile::Close() {
  if (_rtpFile != NULL) {
    fclose(_rtpFile);
    _rtpFile = NULL;
  }
}

void RTPFile::WriteHeader() {
  // Write data in a format that NetEQ and RTP Play can parse
  fprintf(_rtpFile, "#!RTPencode%s\n", "1.0");
  uint32_t dummy_variable = 0;
  // should be converted to network endian format, but does not matter when 0
  if (fwrite(&dummy_variable, 4, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(&dummy_variable, 4, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(&dummy_variable, 4, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(&dummy_variable, 2, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(&dummy_variable, 2, 1, _rtpFile) != 1) {
    return;
  }
  fflush(_rtpFile);
}

void RTPFile::ReadHeader() {
  uint32_t start_sec, start_usec, source;
  uint16_t port, padding;
  char fileHeader[40];
  EXPECT_TRUE(fgets(fileHeader, 40, _rtpFile) != 0);
  EXPECT_EQ(1u, fread(&start_sec, 4, 1, _rtpFile));
  start_sec = ntohl(start_sec);
  EXPECT_EQ(1u, fread(&start_usec, 4, 1, _rtpFile));
  start_usec = ntohl(start_usec);
  EXPECT_EQ(1u, fread(&source, 4, 1, _rtpFile));
  source = ntohl(source);
  EXPECT_EQ(1u, fread(&port, 2, 1, _rtpFile));
  port = ntohs(port);
  EXPECT_EQ(1u, fread(&padding, 2, 1, _rtpFile));
  padding = ntohs(padding);
}

void RTPFile::Write(const uint8_t payloadType, const uint32_t timeStamp,
                    const int16_t seqNo, const uint8_t* payloadData,
                    const uint16_t payloadSize, uint32_t frequency) {
  /* write RTP packet to file */
  uint8_t rtpHeader[12];
  MakeRTPheader(rtpHeader, payloadType, seqNo, timeStamp, 0);
  uint16_t lengthBytes = htons(12 + payloadSize + 8);
  uint16_t plen = htons(12 + payloadSize);
  uint32_t offsetMs;

  offsetMs = (timeStamp / (frequency / 1000));
  offsetMs = htonl(offsetMs);
  if (fwrite(&lengthBytes, 2, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(&plen, 2, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(&offsetMs, 4, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(rtpHeader, 12, 1, _rtpFile) != 1) {
    return;
  }
  if (fwrite(payloadData, 1, payloadSize, _rtpFile) != payloadSize) {
    return;
  }
}

uint16_t RTPFile::Read(WebRtcRTPHeader* rtpInfo, uint8_t* payloadData,
                       uint16_t payloadSize, uint32_t* offset) {
  uint16_t lengthBytes;
  uint16_t plen;
  uint8_t rtpHeader[12];
  size_t read_len = fread(&lengthBytes, 2, 1, _rtpFile);
  /* Check if we have reached end of file. */
  if ((read_len == 0) && feof(_rtpFile)) {
    _rtpEOF = true;
    return 0;
  }
  EXPECT_EQ(1u, fread(&plen, 2, 1, _rtpFile));
  EXPECT_EQ(1u, fread(offset, 4, 1, _rtpFile));
  lengthBytes = ntohs(lengthBytes);
  plen = ntohs(plen);
  *offset = ntohl(*offset);
  EXPECT_GT(plen, 11);

  EXPECT_EQ(1u, fread(rtpHeader, 12, 1, _rtpFile));
  ParseRTPHeader(rtpInfo, rtpHeader);
  rtpInfo->type.Audio.isCNG = false;
  rtpInfo->type.Audio.channel = 1;
  EXPECT_EQ(lengthBytes, plen + 8);

  if (plen == 0) {
    return 0;
  }
  if (lengthBytes < 20) {
    return 0;
  }
  if (payloadSize < (lengthBytes - 20)) {
    return 0;
  }
  lengthBytes -= 20;
  EXPECT_EQ(lengthBytes, fread(payloadData, 1, lengthBytes, _rtpFile));
  return lengthBytes;
}

}  // namespace webrtc
