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

#include <stddef.h>
#include <stdint.h>

#include <initializer_list>
#include <utility>
#include <vector>

#include "api/array_view.h"
#include "api/scoped_refptr.h"
#include "api/video/encoded_image.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "modules/rtp_rtcp/source/rtp_packetizer_av1_test_helper.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
#include "test/gmock.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

using ::testing::Each;
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::Le;
using ::testing::SizeIs;

constexpr uint8_t kNewCodedVideoSequenceBit = 0b00'00'1000;

// Wrapper around rtp_packet to make it look like container of payload bytes.
struct RtpPayload {
  using value_type = rtc::ArrayView<const uint8_t>::value_type;
  using const_iterator = rtc::ArrayView<const uint8_t>::const_iterator;

  RtpPayload() : rtp_packet(/*extensions=*/nullptr) {}
  RtpPayload& operator=(RtpPayload&&) = default;
  RtpPayload(RtpPayload&&) = default;

  const_iterator begin() const { return rtp_packet.payload().begin(); }
  const_iterator end() const { return rtp_packet.payload().end(); }
  const uint8_t* data() const { return rtp_packet.payload().data(); }
  size_t size() const { return rtp_packet.payload().size(); }

  uint8_t aggregation_header() const { return rtp_packet.payload()[0]; }

  RtpPacketToSend rtp_packet;
};

// Wrapper around frame pointer to make it look like container of bytes with
// nullptr frame look like empty container.
class Av1Frame {
 public:
  using value_type = uint8_t;
  using const_iterator = const uint8_t*;

  explicit Av1Frame(rtc::scoped_refptr<EncodedImageBuffer> frame)
      : frame_(std::move(frame)) {}

  const_iterator begin() const { return frame_ ? frame_->data() : nullptr; }
  const_iterator end() const {
    return frame_ ? (frame_->data() + frame_->size()) : nullptr;
  }

 private:
  rtc::scoped_refptr<EncodedImageBuffer> frame_;
};

std::vector<RtpPayload> Packetize(
    rtc::ArrayView<const uint8_t> payload,
    RtpPacketizer::PayloadSizeLimits limits,
    bool even_distribution,
    VideoFrameType frame_type = VideoFrameType::kVideoFrameDelta,
    bool is_last_frame_in_picture = true) {
  // Run code under test.
  RtpPacketizerAv1 packetizer(payload, limits, frame_type,
                              is_last_frame_in_picture, even_distribution);
  // Convert result into structure that is easier to run expectation against.
  std::vector<RtpPayload> result(packetizer.NumPackets());
  for (RtpPayload& rtp_payload : result) {
    EXPECT_TRUE(packetizer.NextPacket(&rtp_payload.rtp_packet));
  }
  return result;
}

Av1Frame ReassembleFrame(rtc::ArrayView<const RtpPayload> rtp_payloads) {
  std::vector<rtc::ArrayView<const uint8_t>> payloads(rtp_payloads.size());
  for (size_t i = 0; i < rtp_payloads.size(); ++i) {
    payloads[i] = rtp_payloads[i];
  }
  return Av1Frame(VideoRtpDepacketizerAv1().AssembleFrame(payloads));
}

class RtpPacketizerAv1Test : public ::testing::TestWithParam<bool> {};

TEST_P(RtpPacketizerAv1Test, EmptyPayload) {
  RtpPacketizer::PayloadSizeLimits limits;
  RtpPacketizerAv1 packetizer({}, limits, VideoFrameType::kVideoFrameKey, true,
                              GetParam());
  EXPECT_EQ(packetizer.NumPackets(), 0u);
}

TEST_P(RtpPacketizerAv1Test, PacketizeOneObuWithoutSizeAndExtension) {
  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
                                   .WithoutSize()
                                   .WithPayload({1, 2, 3, 4, 5, 6, 7})});
  EXPECT_THAT(Packetize(kFrame, {}, GetParam()),
              ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
                                      kAv1ObuTypeFrame, 1, 2, 3, 4, 5, 6, 7)));
}

TEST_P(RtpPacketizerAv1Test, PacketizeOneObuWithoutSizeWithExtension) {
  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
                                   .WithoutSize()
                                   .WithExtension(kAv1ObuExtensionS1T1)
                                   .WithPayload({2, 3, 4, 5, 6, 7})});
  EXPECT_THAT(
      Packetize(kFrame, {}, GetParam()),
      ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
                              kAv1ObuTypeFrame | kAv1ObuExtensionPresentBit,
                              kAv1ObuExtensionS1T1, 2, 3, 4, 5, 6, 7)));
}

TEST_P(RtpPacketizerAv1Test, RemovesObuSizeFieldWithoutExtension) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeFrame).WithPayload({11, 12, 13, 14, 15, 16, 17})});
  EXPECT_THAT(
      Packetize(kFrame, {}, GetParam()),
      ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
                              kAv1ObuTypeFrame, 11, 12, 13, 14, 15, 16, 17)));
}

TEST_P(RtpPacketizerAv1Test, RemovesObuSizeFieldWithExtension) {
  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
                                   .WithExtension(kAv1ObuExtensionS1T1)
                                   .WithPayload({1, 2, 3, 4, 5, 6, 7})});
  EXPECT_THAT(
      Packetize(kFrame, {}, GetParam()),
      ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
                              kAv1ObuTypeFrame | kAv1ObuExtensionPresentBit,
                              kAv1ObuExtensionS1T1, 1, 2, 3, 4, 5, 6, 7)));
}

TEST_P(RtpPacketizerAv1Test,
       OmitsSizeForLastObuWhenThreeObusFitsIntoThePacket) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
       Av1Obu(kAv1ObuTypeMetadata).WithPayload({11, 12, 13, 14}),
       Av1Obu(kAv1ObuTypeFrame).WithPayload({21, 22, 23, 24, 25, 26})});
  EXPECT_THAT(Packetize(kFrame, {}, GetParam()),
              ElementsAre(ElementsAre(
                  0b00'11'0000,  // aggregation header
                  7, kAv1ObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6,  //
                  5, kAv1ObuTypeMetadata, 11, 12, 13, 14,          //
                  kAv1ObuTypeFrame, 21, 22, 23, 24, 25, 26)));
}

TEST_P(RtpPacketizerAv1Test, UseSizeForAllObusWhenFourObusFitsIntoThePacket) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
       Av1Obu(kAv1ObuTypeMetadata).WithPayload({11, 12, 13, 14}),
       Av1Obu(kAv1ObuTypeFrameHeader).WithPayload({21, 22, 23}),
       Av1Obu(kAv1ObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});
  EXPECT_THAT(Packetize(kFrame, {}, GetParam()),
              ElementsAre(ElementsAre(
                  0b00'00'0000,  // aggregation header
                  7, kAv1ObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6,  //
                  5, kAv1ObuTypeMetadata, 11, 12, 13, 14,          //
                  4, kAv1ObuTypeFrameHeader, 21, 22, 23,           //
                  7, kAv1ObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
}

TEST_P(RtpPacketizerAv1Test, DiscardsTemporalDelimiterAndTileListObu) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeTemporalDelimiter), Av1Obu(kAv1ObuTypeMetadata),
       Av1Obu(kAv1ObuTypeTileList).WithPayload({1, 2, 3, 4, 5, 6}),
       Av1Obu(kAv1ObuTypeFrameHeader).WithPayload({21, 22, 23}),
       Av1Obu(kAv1ObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});

  EXPECT_THAT(
      Packetize(kFrame, {}, GetParam()),
      ElementsAre(ElementsAre(0b00'11'0000,  // aggregation header
                              1,
                              kAv1ObuTypeMetadata,  //
                              4, kAv1ObuTypeFrameHeader, 21, 22,
                              23,  //
                              kAv1ObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
}

TEST_P(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPacketForceSplitObuHeader) {
  // Craft expected payloads so that there is only one way to split original
  // frame into two packets.
  const uint8_t kExpectPayload1[6] = {
      0b01'10'0000,  // aggregation_header
      3,
      kAv1ObuTypeFrameHeader | kAv1ObuExtensionPresentBit,
      kAv1ObuExtensionS1T1,
      21,  //
      kAv1ObuTypeTileGroup | kAv1ObuExtensionPresentBit};
  const uint8_t kExpectPayload2[6] = {0b10'01'0000,  // aggregation_header
                                      kAv1ObuExtensionS1T1, 11, 12, 13, 14};
  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrameHeader)
                                   .WithExtension(kAv1ObuExtensionS1T1)
                                   .WithPayload({21}),
                               Av1Obu(kAv1ObuTypeTileGroup)
                                   .WithExtension(kAv1ObuExtensionS1T1)
                                   .WithPayload({11, 12, 13, 14})});

  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 6;
  auto payloads = Packetize(kFrame, limits, GetParam());
  EXPECT_THAT(payloads, ElementsAre(ElementsAreArray(kExpectPayload1),
                                    ElementsAreArray(kExpectPayload2)));
}

TEST_P(RtpPacketizerAv1Test,
       SetsNbitAtTheFirstPacketOfAKeyFrameWithSequenceHeader) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 6;
  auto packets =
      Packetize(kFrame, limits, GetParam(), VideoFrameType::kVideoFrameKey);
  ASSERT_THAT(packets, SizeIs(2));
  EXPECT_TRUE(packets[0].aggregation_header() & kNewCodedVideoSequenceBit);
  EXPECT_FALSE(packets[1].aggregation_header() & kNewCodedVideoSequenceBit);
}

TEST_P(RtpPacketizerAv1Test,
       DoesntSetNbitAtThePacketsOfAKeyFrameWithoutSequenceHeader) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7})});
  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 6;
  auto packets =
      Packetize(kFrame, limits, GetParam(), VideoFrameType::kVideoFrameKey);
  ASSERT_THAT(packets, SizeIs(2));
  EXPECT_FALSE(packets[0].aggregation_header() & kNewCodedVideoSequenceBit);
  EXPECT_FALSE(packets[1].aggregation_header() & kNewCodedVideoSequenceBit);
}

TEST_P(RtpPacketizerAv1Test, DoesntSetNbitAtThePacketsOfADeltaFrame) {
  // Even when that delta frame starts with a (redundant) sequence header.
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 6;
  auto packets =
      Packetize(kFrame, limits, GetParam(), VideoFrameType::kVideoFrameDelta);
  ASSERT_THAT(packets, SizeIs(2));
  EXPECT_FALSE(packets[0].aggregation_header() & kNewCodedVideoSequenceBit);
  EXPECT_FALSE(packets[1].aggregation_header() & kNewCodedVideoSequenceBit);
}

// There are multiple valid reasonable ways to split payload into multiple
// packets, do not validate current choice, instead use RtpDepacketizer
// to validate frame is reconstracted to the same one. Note: since
// RtpDepacketizer always inserts obu_size fields in the output, use frame where
// each obu has obu_size fields for more streight forward validation.
TEST_P(RtpPacketizerAv1Test, SplitSingleObuIntoTwoPackets) {
  auto kFrame =
      BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
                         .WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});

  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 8;
  auto payloads = Packetize(kFrame, limits, GetParam());
  EXPECT_THAT(payloads, ElementsAre(SizeIs(Le(8u)), SizeIs(Le(8u))));

  // Use RtpDepacketizer to validate the split.
  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
}

TEST_P(RtpPacketizerAv1Test, SplitSingleObuIntoManyPackets) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1200, 27))});

  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 100;
  auto payloads = Packetize(kFrame, limits, GetParam());
  EXPECT_THAT(payloads, SizeIs(13u));
  EXPECT_THAT(payloads, Each(SizeIs(Le(100u))));

  // Use RtpDepacketizer to validate the split.
  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
}

TEST_P(RtpPacketizerAv1Test, SetMarkerBitForLastPacketInEndOfPictureFrame) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});

  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 100;
  auto payloads =
      Packetize(kFrame, limits, GetParam(), VideoFrameType::kVideoFrameDelta,
                /*is_last_frame_in_picture=*/true);
  ASSERT_THAT(payloads, SizeIs(3u));
  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
  EXPECT_TRUE(payloads[2].rtp_packet.Marker());
}

TEST_P(RtpPacketizerAv1Test,
       DoesntSetMarkerBitForPacketsNotInEndOfPictureFrame) {
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});

  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 100;
  auto payloads =
      Packetize(kFrame, limits, GetParam(), VideoFrameType::kVideoFrameDelta,
                /*is_last_frame_in_picture=*/false);
  ASSERT_THAT(payloads, SizeIs(3u));
  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
  EXPECT_FALSE(payloads[2].rtp_packet.Marker());
}

TEST_P(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPackets) {
  // 2nd OBU is too large to fit into one packet, so its head would be in the
  // same packet as the 1st OBU.
  auto kFrame = BuildAv1Frame(
      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({11, 12}),
       Av1Obu(kAv1ObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7, 8, 9})});

  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 8;
  auto payloads = Packetize(kFrame, limits, GetParam());
  EXPECT_THAT(payloads, ElementsAre(SizeIs(Le(8u)), SizeIs(Le(8u))));

  // Use RtpDepacketizer to validate the split.
  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
}

TEST_P(RtpPacketizerAv1Test,
       SplitSingleObuIntoTwoPacketsBecauseOfSinglePacketLimit) {
  auto kFrame =
      BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
                         .WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});
  RtpPacketizer::PayloadSizeLimits limits;
  limits.max_payload_len = 10;
  limits.single_packet_reduction_len = 8;
  auto payloads = Packetize(kFrame, limits, GetParam());
  EXPECT_THAT(payloads, ElementsAre(SizeIs(Le(10u)), SizeIs(Le(10u))));

  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
}

INSTANTIATE_TEST_SUITE_P(bool, RtpPacketizerAv1Test, ::testing::Bool());

TEST(RtpPacketizerAv1TestEven, EvenDistributionDiffers) {
  auto kFrame = BuildAv1Frame({
      Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1206, 0)),
      Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1476, 0)),
      Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1431, 0)),
  });
  EXPECT_THAT(
      Packetize(kFrame, {}, /*even_distribution=*/false),
      ElementsAre(SizeIs(1200), SizeIs(1200), SizeIs(1200), SizeIs(523)));

  EXPECT_THAT(
      Packetize(kFrame, {}, /*even_distribution=*/true),
      ElementsAre(SizeIs(1032), SizeIs(1032), SizeIs(1032), SizeIs(1028)));
}

}  // namespace
}  // namespace webrtc
