/*
 *  Copyright (c) 2019 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 "test/pc/e2e/analyzer/video/default_encoded_image_id_injector.h"

#include <utility>

#include "api/video/encoded_image.h"
#include "rtc_base/buffer.h"
#include "test/gtest.h"

namespace webrtc {
namespace test {
namespace {

rtc::Buffer CreateBufferOfSizeNFilledWithValuesFromX(size_t n, uint8_t x) {
  rtc::Buffer buffer(n);
  for (size_t i = 0; i < n; ++i) {
    buffer[i] = static_cast<uint8_t>(x + i);
  }
  return buffer;
}

}  // namespace

TEST(DefaultEncodedImageIdInjector, InjectExtract) {
  DefaultEncodedImageIdInjector injector;

  rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);

  EncodedImage source(buffer.data(), 10, 10);
  source.SetTimestamp(123456789);

  std::pair<uint16_t, EncodedImage> out =
      injector.ExtractId(injector.InjectId(512, source, 1), 2);
  ASSERT_EQ(out.first, 512);
  ASSERT_EQ(out.second.size(), 10ul);
  for (int i = 0; i < 10; ++i) {
    ASSERT_EQ(out.second.data()[i], i + 1);
  }
}

TEST(DefaultEncodedImageIdInjector, Inject3Extract3) {
  DefaultEncodedImageIdInjector injector;

  rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
  rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
  rtc::Buffer buffer3 = CreateBufferOfSizeNFilledWithValuesFromX(10, 21);

  // 1st frame
  EncodedImage source1(buffer1.data(), 10, 10);
  source1.SetTimestamp(123456710);
  // 2nd frame 1st spatial layer
  EncodedImage source2(buffer2.data(), 10, 10);
  source2.SetTimestamp(123456720);
  // 2nd frame 2nd spatial layer
  EncodedImage source3(buffer3.data(), 10, 10);
  source3.SetTimestamp(123456720);

  EncodedImage intermediate1 = injector.InjectId(510, source1, 1);
  EncodedImage intermediate2 = injector.InjectId(520, source2, 1);
  EncodedImage intermediate3 = injector.InjectId(520, source3, 1);

  // Extract ids in different order.
  std::pair<uint16_t, EncodedImage> out3 = injector.ExtractId(intermediate3, 2);
  std::pair<uint16_t, EncodedImage> out1 = injector.ExtractId(intermediate1, 2);
  std::pair<uint16_t, EncodedImage> out2 = injector.ExtractId(intermediate2, 2);

  ASSERT_EQ(out1.first, 510);
  ASSERT_EQ(out1.second.size(), 10ul);
  for (int i = 0; i < 10; ++i) {
    ASSERT_EQ(out1.second.data()[i], i + 1);
  }
  ASSERT_EQ(out2.first, 520);
  ASSERT_EQ(out2.second.size(), 10ul);
  for (int i = 0; i < 10; ++i) {
    ASSERT_EQ(out2.second.data()[i], i + 11);
  }
  ASSERT_EQ(out3.first, 520);
  ASSERT_EQ(out3.second.size(), 10ul);
  for (int i = 0; i < 10; ++i) {
    ASSERT_EQ(out3.second.data()[i], i + 21);
  }
}

TEST(DefaultEncodedImageIdInjector, InjectExtractFromConcatenated) {
  DefaultEncodedImageIdInjector injector;

  rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
  rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
  rtc::Buffer buffer3 = CreateBufferOfSizeNFilledWithValuesFromX(10, 21);

  EncodedImage source1(buffer1.data(), 10, 10);
  source1.SetTimestamp(123456710);
  EncodedImage source2(buffer2.data(), 10, 10);
  source2.SetTimestamp(123456710);
  EncodedImage source3(buffer3.data(), 10, 10);
  source3.SetTimestamp(123456710);

  // Inject id into 3 images with same frame id.
  EncodedImage intermediate1 = injector.InjectId(512, source1, 1);
  EncodedImage intermediate2 = injector.InjectId(512, source2, 1);
  EncodedImage intermediate3 = injector.InjectId(512, source3, 1);

  // Concatenate them into single encoded image, like it can be done in jitter
  // buffer.
  size_t concatenated_length =
      intermediate1.size() + intermediate2.size() + intermediate3.size();
  rtc::Buffer concatenated_buffer;
  concatenated_buffer.AppendData(intermediate1.data(), intermediate1.size());
  concatenated_buffer.AppendData(intermediate2.data(), intermediate2.size());
  concatenated_buffer.AppendData(intermediate3.data(), intermediate3.size());
  EncodedImage concatenated(concatenated_buffer.data(), concatenated_length,
                            concatenated_length);

  // Extract frame id from concatenated image
  std::pair<uint16_t, EncodedImage> out = injector.ExtractId(concatenated, 2);

  ASSERT_EQ(out.first, 512);
  ASSERT_EQ(out.second.size(), 3 * 10ul);
  for (int i = 0; i < 10; ++i) {
    ASSERT_EQ(out.second.data()[i], i + 1);
    ASSERT_EQ(out.second.data()[i + 10], i + 11);
    ASSERT_EQ(out.second.data()[i + 20], i + 21);
  }
}

}  // namespace test
}  // namespace webrtc
