/*
 *  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 "modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h"

#include "test/gtest.h"

namespace webrtc {

namespace test {

constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;

RtpFormatVp8TestHelper::RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr)
    : packet_(kNoExtensions),
      payload_data_(NULL),
      data_ptr_(NULL),
      fragmentation_(NULL),
      hdr_info_(hdr),
      payload_start_(0),
      payload_size_(0),
      sloppy_partitioning_(false),
      inited_(false) {}

RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() {
  delete fragmentation_;
  delete [] payload_data_;
}

bool RtpFormatVp8TestHelper::Init(const size_t* partition_sizes,
                                  size_t num_partitions) {
  if (inited_) return false;
  fragmentation_ = new RTPFragmentationHeader;
  fragmentation_->VerifyAndAllocateFragmentationHeader(num_partitions);
  payload_size_ = 0;
  // Calculate sum payload size.
  for (size_t p = 0; p < num_partitions; ++p) {
    payload_size_ += partition_sizes[p];
  }
  payload_data_ = new uint8_t[payload_size_];
  size_t j = 0;
  // Loop through the partitions again.
  for (size_t p = 0; p < num_partitions; ++p) {
    fragmentation_->fragmentationLength[p] = partition_sizes[p];
    fragmentation_->fragmentationOffset[p] = j;
    for (size_t i = 0; i < partition_sizes[p]; ++i) {
      assert(j < payload_size_);
      payload_data_[j++] = p;  // Set the payload value to the partition index.
    }
  }
  data_ptr_ = payload_data_;
  inited_ = true;
  return true;
}

void RtpFormatVp8TestHelper::GetAllPacketsAndCheck(
    RtpPacketizerVp8* packetizer,
    const size_t* expected_sizes,
    const int* expected_part,
    const bool* expected_frag_start,
    size_t expected_num_packets) {
  ASSERT_TRUE(inited_);
  for (size_t i = 0; i < expected_num_packets; ++i) {
    std::ostringstream ss;
    ss << "Checking packet " << i;
    SCOPED_TRACE(ss.str());
    EXPECT_TRUE(packetizer->NextPacket(&packet_));
    CheckPacket(expected_sizes[i], i + 1 == expected_num_packets,
                expected_frag_start[i]);
  }
}

// Payload descriptor
//       0 1 2 3 4 5 6 7
//      +-+-+-+-+-+-+-+-+
//      |X|R|N|S|PartID | (REQUIRED)
//      +-+-+-+-+-+-+-+-+
// X:   |I|L|T|K|  RSV  | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+
// I:   |   PictureID   | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+
// L:   |   TL0PICIDX   | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+
// T/K: | TID | KEYIDX  | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+

// First octet tests.
#define EXPECT_BIT_EQ(x, n, a) EXPECT_EQ((((x) >> (n)) & 0x1), a)

#define EXPECT_RSV_ZERO(x) EXPECT_EQ(((x) & 0xE0), 0)

#define EXPECT_BIT_X_EQ(x, a) EXPECT_BIT_EQ(x, 7, a)

#define EXPECT_BIT_N_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)

#define EXPECT_BIT_S_EQ(x, a) EXPECT_BIT_EQ(x, 4, a)

#define EXPECT_PART_ID_EQ(x, a) EXPECT_EQ(((x) & 0x0F), a)

// Extension fields tests
#define EXPECT_BIT_I_EQ(x, a) EXPECT_BIT_EQ(x, 7, a)

#define EXPECT_BIT_L_EQ(x, a) EXPECT_BIT_EQ(x, 6, a)

#define EXPECT_BIT_T_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)

#define EXPECT_BIT_K_EQ(x, a) EXPECT_BIT_EQ(x, 4, a)

#define EXPECT_TID_EQ(x, a) EXPECT_EQ((((x) & 0xC0) >> 6), a)

#define EXPECT_BIT_Y_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)

#define EXPECT_KEYIDX_EQ(x, a) EXPECT_EQ(((x) & 0x1F), a)

void RtpFormatVp8TestHelper::CheckHeader(bool frag_start) {
  payload_start_ = 1;
  rtc::ArrayView<const uint8_t> buffer = packet_.payload();
  EXPECT_BIT_EQ(buffer[0], 6, 0);  // Check reserved bit.

  if (hdr_info_->pictureId != kNoPictureId ||
      hdr_info_->temporalIdx != kNoTemporalIdx ||
      hdr_info_->tl0PicIdx != kNoTl0PicIdx ||
      hdr_info_->keyIdx != kNoKeyIdx) {
    EXPECT_BIT_X_EQ(buffer[0], 1);
    ++payload_start_;
    CheckPictureID();
    CheckTl0PicIdx();
    CheckTIDAndKeyIdx();
  } else {
    EXPECT_BIT_X_EQ(buffer[0], 0);
  }

  EXPECT_BIT_N_EQ(buffer[0], hdr_info_->nonReference ? 1 : 0);
  EXPECT_BIT_S_EQ(buffer[0], frag_start ? 1 : 0);

  // Check partition index.
  if (!sloppy_partitioning_) {
    // The test payload data is constructed such that the payload value is the
    // same as the partition index.
    EXPECT_EQ(buffer[0] & 0x0F, buffer[payload_start_]);
  } else {
    // Partition should be set to 0.
    EXPECT_EQ(buffer[0] & 0x0F, 0);
  }
}

// Verify that the I bit and the PictureID field are both set in accordance
// with the information in hdr_info_->pictureId.
void RtpFormatVp8TestHelper::CheckPictureID() {
  auto buffer = packet_.payload();
  if (hdr_info_->pictureId != kNoPictureId) {
    EXPECT_BIT_I_EQ(buffer[1], 1);
    EXPECT_BIT_EQ(buffer[payload_start_], 7, 1);
    EXPECT_EQ(buffer[payload_start_] & 0x7F,
              (hdr_info_->pictureId >> 8) & 0x7F);
    EXPECT_EQ(buffer[payload_start_ + 1], hdr_info_->pictureId & 0xFF);
    payload_start_ += 2;
  } else {
    EXPECT_BIT_I_EQ(buffer[1], 0);
  }
}

// Verify that the L bit and the TL0PICIDX field are both set in accordance
// with the information in hdr_info_->tl0PicIdx.
void RtpFormatVp8TestHelper::CheckTl0PicIdx() {
  auto buffer = packet_.payload();
  if (hdr_info_->tl0PicIdx != kNoTl0PicIdx) {
    EXPECT_BIT_L_EQ(buffer[1], 1);
    EXPECT_EQ(buffer[payload_start_], hdr_info_->tl0PicIdx);
    ++payload_start_;
  } else {
    EXPECT_BIT_L_EQ(buffer[1], 0);
  }
}

// Verify that the T bit and the TL0PICIDX field, and the K bit and KEYIDX
// field are all set in accordance with the information in
// hdr_info_->temporalIdx and hdr_info_->keyIdx, respectively.
void RtpFormatVp8TestHelper::CheckTIDAndKeyIdx() {
  auto buffer = packet_.payload();
  if (hdr_info_->temporalIdx == kNoTemporalIdx &&
      hdr_info_->keyIdx == kNoKeyIdx) {
    EXPECT_BIT_T_EQ(buffer[1], 0);
    EXPECT_BIT_K_EQ(buffer[1], 0);
    return;
  }
  if (hdr_info_->temporalIdx != kNoTemporalIdx) {
    EXPECT_BIT_T_EQ(buffer[1], 1);
    EXPECT_TID_EQ(buffer[payload_start_], hdr_info_->temporalIdx);
    EXPECT_BIT_Y_EQ(buffer[payload_start_], hdr_info_->layerSync ? 1 : 0);
  } else {
    EXPECT_BIT_T_EQ(buffer[1], 0);
    EXPECT_TID_EQ(buffer[payload_start_], 0);
    EXPECT_BIT_Y_EQ(buffer[payload_start_], 0);
  }
  if (hdr_info_->keyIdx != kNoKeyIdx) {
    EXPECT_BIT_K_EQ(buffer[1], 1);
    EXPECT_KEYIDX_EQ(buffer[payload_start_], hdr_info_->keyIdx);
  } else {
    EXPECT_BIT_K_EQ(buffer[1], 0);
    EXPECT_KEYIDX_EQ(buffer[payload_start_], 0);
  }
  ++payload_start_;
}

// Verify that the payload (i.e., after the headers) of the packet stored in
// buffer_ is identical to the expected (as found in data_ptr_).
void RtpFormatVp8TestHelper::CheckPayload() {
  auto buffer = packet_.payload();
  size_t payload_end = buffer.size();
  for (size_t i = payload_start_; i < payload_end; ++i, ++data_ptr_)
    EXPECT_EQ(buffer[i], *data_ptr_);
}

// Verify that the input variable "last" agrees with the position of data_ptr_.
// If data_ptr_ has advanced payload_size_ bytes from the start (payload_data_)
// we are at the end and last should be true. Otherwise, it should be false.
void RtpFormatVp8TestHelper::CheckLast(bool last) const {
  EXPECT_EQ(last, data_ptr_ == payload_data_ + payload_size_);
}

// Verify the contents of a packet. Check the length versus expected_bytes,
// the header, payload, and "last" flag.
void RtpFormatVp8TestHelper::CheckPacket(size_t expect_bytes,
                                         bool last,
                                         bool frag_start) {
  EXPECT_EQ(expect_bytes, packet_.payload_size());
  CheckHeader(frag_start);
  CheckPayload();
  CheckLast(last);
}

}  // namespace test

}  // namespace webrtc
