tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rtp_packetizer_av1_unittest.cc (15005B)


      1 /*
      2 *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/rtp_rtcp/source/rtp_packetizer_av1.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <initializer_list>
     16 #include <utility>
     17 #include <vector>
     18 
     19 #include "api/array_view.h"
     20 #include "api/scoped_refptr.h"
     21 #include "api/video/encoded_image.h"
     22 #include "api/video/video_frame_type.h"
     23 #include "modules/rtp_rtcp/source/rtp_format.h"
     24 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
     25 #include "modules/rtp_rtcp/source/rtp_packetizer_av1_test_helper.h"
     26 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
     27 #include "test/gmock.h"
     28 #include "test/gtest.h"
     29 
     30 namespace webrtc {
     31 namespace {
     32 
     33 using ::testing::Each;
     34 using ::testing::ElementsAre;
     35 using ::testing::ElementsAreArray;
     36 using ::testing::Le;
     37 using ::testing::SizeIs;
     38 
     39 constexpr uint8_t kNewCodedVideoSequenceBit = 0b00'00'1000;
     40 
     41 // Wrapper around rtp_packet to make it look like container of payload bytes.
     42 struct RtpPayload {
     43  using value_type = ArrayView<const uint8_t>::value_type;
     44  using const_iterator = ArrayView<const uint8_t>::const_iterator;
     45 
     46  RtpPayload() : rtp_packet(/*extensions=*/nullptr) {}
     47  RtpPayload& operator=(RtpPayload&&) = default;
     48  RtpPayload(RtpPayload&&) = default;
     49 
     50  const_iterator begin() const { return rtp_packet.payload().begin(); }
     51  const_iterator end() const { return rtp_packet.payload().end(); }
     52  const uint8_t* data() const { return rtp_packet.payload().data(); }
     53  size_t size() const { return rtp_packet.payload().size(); }
     54 
     55  uint8_t aggregation_header() const { return rtp_packet.payload()[0]; }
     56 
     57  RtpPacketToSend rtp_packet;
     58 };
     59 
     60 // Wrapper around frame pointer to make it look like container of bytes with
     61 // nullptr frame look like empty container.
     62 class Av1Frame {
     63 public:
     64  using value_type = uint8_t;
     65  using const_iterator = const uint8_t*;
     66 
     67  explicit Av1Frame(scoped_refptr<EncodedImageBuffer> frame)
     68      : frame_(std::move(frame)) {}
     69 
     70  const_iterator begin() const { return frame_ ? frame_->data() : nullptr; }
     71  const_iterator end() const {
     72    return frame_ ? (frame_->data() + frame_->size()) : nullptr;
     73  }
     74 
     75 private:
     76  scoped_refptr<EncodedImageBuffer> frame_;
     77 };
     78 
     79 std::vector<RtpPayload> Packetize(
     80    ArrayView<const uint8_t> payload,
     81    RtpPacketizer::PayloadSizeLimits limits,
     82    VideoFrameType frame_type = VideoFrameType::kVideoFrameDelta,
     83    bool is_last_frame_in_picture = true) {
     84  // Run code under test.
     85  RtpPacketizerAv1 packetizer(payload, limits, frame_type,
     86                              is_last_frame_in_picture);
     87  // Convert result into structure that is easier to run expectation against.
     88  std::vector<RtpPayload> result(packetizer.NumPackets());
     89  for (RtpPayload& rtp_payload : result) {
     90    EXPECT_TRUE(packetizer.NextPacket(&rtp_payload.rtp_packet));
     91  }
     92  return result;
     93 }
     94 
     95 Av1Frame ReassembleFrame(ArrayView<const RtpPayload> rtp_payloads) {
     96  std::vector<ArrayView<const uint8_t>> payloads(rtp_payloads.size());
     97  for (size_t i = 0; i < rtp_payloads.size(); ++i) {
     98    payloads[i] = rtp_payloads[i];
     99  }
    100  return Av1Frame(VideoRtpDepacketizerAv1().AssembleFrame(payloads));
    101 }
    102 
    103 TEST(RtpPacketizerAv1Test, EmptyPayload) {
    104  RtpPacketizer::PayloadSizeLimits limits;
    105  RtpPacketizerAv1 packetizer({}, limits, VideoFrameType::kVideoFrameKey, true);
    106  EXPECT_EQ(packetizer.NumPackets(), 0u);
    107 }
    108 
    109 TEST(RtpPacketizerAv1Test, PacketizeOneObuWithoutSizeAndExtension) {
    110  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
    111                                   .WithoutSize()
    112                                   .WithPayload({1, 2, 3, 4, 5, 6, 7})});
    113  EXPECT_THAT(Packetize(kFrame, {}),
    114              ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
    115                                      kAv1ObuTypeFrame, 1, 2, 3, 4, 5, 6, 7)));
    116 }
    117 
    118 TEST(RtpPacketizerAv1Test, PacketizeOneObuWithoutSizeWithExtension) {
    119  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
    120                                   .WithoutSize()
    121                                   .WithExtension(kAv1ObuExtensionS1T1)
    122                                   .WithPayload({2, 3, 4, 5, 6, 7})});
    123  EXPECT_THAT(
    124      Packetize(kFrame, {}),
    125      ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
    126                              kAv1ObuTypeFrame | kAv1ObuExtensionPresentBit,
    127                              kAv1ObuExtensionS1T1, 2, 3, 4, 5, 6, 7)));
    128 }
    129 
    130 TEST(RtpPacketizerAv1Test, RemovesObuSizeFieldWithoutExtension) {
    131  auto kFrame = BuildAv1Frame(
    132      {Av1Obu(kAv1ObuTypeFrame).WithPayload({11, 12, 13, 14, 15, 16, 17})});
    133  EXPECT_THAT(
    134      Packetize(kFrame, {}),
    135      ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
    136                              kAv1ObuTypeFrame, 11, 12, 13, 14, 15, 16, 17)));
    137 }
    138 
    139 TEST(RtpPacketizerAv1Test, RemovesObuSizeFieldWithExtension) {
    140  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
    141                                   .WithExtension(kAv1ObuExtensionS1T1)
    142                                   .WithPayload({1, 2, 3, 4, 5, 6, 7})});
    143  EXPECT_THAT(
    144      Packetize(kFrame, {}),
    145      ElementsAre(ElementsAre(0b00'01'0000,  // aggregation header
    146                              kAv1ObuTypeFrame | kAv1ObuExtensionPresentBit,
    147                              kAv1ObuExtensionS1T1, 1, 2, 3, 4, 5, 6, 7)));
    148 }
    149 
    150 TEST(RtpPacketizerAv1Test, OmitsSizeForLastObuWhenThreeObusFitsIntoThePacket) {
    151  auto kFrame = BuildAv1Frame(
    152      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
    153       Av1Obu(kAv1ObuTypeMetadata).WithPayload({11, 12, 13, 14}),
    154       Av1Obu(kAv1ObuTypeFrame).WithPayload({21, 22, 23, 24, 25, 26})});
    155  EXPECT_THAT(Packetize(kFrame, {}),
    156              ElementsAre(ElementsAre(
    157                  0b00'11'0000,  // aggregation header
    158                  7, kAv1ObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6,  //
    159                  5, kAv1ObuTypeMetadata, 11, 12, 13, 14,          //
    160                  kAv1ObuTypeFrame, 21, 22, 23, 24, 25, 26)));
    161 }
    162 
    163 TEST(RtpPacketizerAv1Test, UseSizeForAllObusWhenFourObusFitsIntoThePacket) {
    164  auto kFrame = BuildAv1Frame(
    165      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
    166       Av1Obu(kAv1ObuTypeMetadata).WithPayload({11, 12, 13, 14}),
    167       Av1Obu(kAv1ObuTypeFrameHeader).WithPayload({21, 22, 23}),
    168       Av1Obu(kAv1ObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});
    169  EXPECT_THAT(Packetize(kFrame, {}),
    170              ElementsAre(ElementsAre(
    171                  0b00'00'0000,  // aggregation header
    172                  7, kAv1ObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6,  //
    173                  5, kAv1ObuTypeMetadata, 11, 12, 13, 14,          //
    174                  4, kAv1ObuTypeFrameHeader, 21, 22, 23,           //
    175                  7, kAv1ObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
    176 }
    177 
    178 TEST(RtpPacketizerAv1Test, DiscardsTemporalDelimiterAndTileListObu) {
    179  auto kFrame = BuildAv1Frame(
    180      {Av1Obu(kAv1ObuTypeTemporalDelimiter), Av1Obu(kAv1ObuTypeMetadata),
    181       Av1Obu(kAv1ObuTypeTileList).WithPayload({1, 2, 3, 4, 5, 6}),
    182       Av1Obu(kAv1ObuTypeFrameHeader).WithPayload({21, 22, 23}),
    183       Av1Obu(kAv1ObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});
    184 
    185  EXPECT_THAT(
    186      Packetize(kFrame, {}),
    187      ElementsAre(ElementsAre(0b00'11'0000,  // aggregation header
    188                              1,
    189                              kAv1ObuTypeMetadata,  //
    190                              4, kAv1ObuTypeFrameHeader, 21, 22,
    191                              23,  //
    192                              kAv1ObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
    193 }
    194 
    195 TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPacketForceSplitObuHeader) {
    196  // Craft expected payloads so that there is only one way to split original
    197  // frame into two packets.
    198  const uint8_t kExpectPayload1[6] = {
    199      0b01'10'0000,  // aggregation_header
    200      3,
    201      kAv1ObuTypeFrameHeader | kAv1ObuExtensionPresentBit,
    202      kAv1ObuExtensionS1T1,
    203      21,  //
    204      kAv1ObuTypeTileGroup | kAv1ObuExtensionPresentBit};
    205  const uint8_t kExpectPayload2[6] = {0b10'01'0000,  // aggregation_header
    206                                      kAv1ObuExtensionS1T1, 11, 12, 13, 14};
    207  auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrameHeader)
    208                                   .WithExtension(kAv1ObuExtensionS1T1)
    209                                   .WithPayload({21}),
    210                               Av1Obu(kAv1ObuTypeTileGroup)
    211                                   .WithExtension(kAv1ObuExtensionS1T1)
    212                                   .WithPayload({11, 12, 13, 14})});
    213 
    214  RtpPacketizer::PayloadSizeLimits limits;
    215  limits.max_payload_len = 6;
    216  auto payloads = Packetize(kFrame, limits);
    217  EXPECT_THAT(payloads, ElementsAre(ElementsAreArray(kExpectPayload1),
    218                                    ElementsAreArray(kExpectPayload2)));
    219 }
    220 
    221 TEST(RtpPacketizerAv1Test,
    222     SetsNbitAtTheFirstPacketOfAKeyFrameWithSequenceHeader) {
    223  auto kFrame = BuildAv1Frame(
    224      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
    225  RtpPacketizer::PayloadSizeLimits limits;
    226  limits.max_payload_len = 6;
    227  auto packets = Packetize(kFrame, limits, VideoFrameType::kVideoFrameKey);
    228  ASSERT_THAT(packets, SizeIs(2));
    229  EXPECT_TRUE(packets[0].aggregation_header() & kNewCodedVideoSequenceBit);
    230  EXPECT_FALSE(packets[1].aggregation_header() & kNewCodedVideoSequenceBit);
    231 }
    232 
    233 TEST(RtpPacketizerAv1Test,
    234     DoesntSetNbitAtThePacketsOfAKeyFrameWithoutSequenceHeader) {
    235  auto kFrame = BuildAv1Frame(
    236      {Av1Obu(kAv1ObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7})});
    237  RtpPacketizer::PayloadSizeLimits limits;
    238  limits.max_payload_len = 6;
    239  auto packets = Packetize(kFrame, limits, VideoFrameType::kVideoFrameKey);
    240  ASSERT_THAT(packets, SizeIs(2));
    241  EXPECT_FALSE(packets[0].aggregation_header() & kNewCodedVideoSequenceBit);
    242  EXPECT_FALSE(packets[1].aggregation_header() & kNewCodedVideoSequenceBit);
    243 }
    244 
    245 TEST(RtpPacketizerAv1Test, DoesntSetNbitAtThePacketsOfADeltaFrame) {
    246  // Even when that delta frame starts with a (redundant) sequence header.
    247  auto kFrame = BuildAv1Frame(
    248      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
    249  RtpPacketizer::PayloadSizeLimits limits;
    250  limits.max_payload_len = 6;
    251  auto packets = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta);
    252  ASSERT_THAT(packets, SizeIs(2));
    253  EXPECT_FALSE(packets[0].aggregation_header() & kNewCodedVideoSequenceBit);
    254  EXPECT_FALSE(packets[1].aggregation_header() & kNewCodedVideoSequenceBit);
    255 }
    256 
    257 // There are multiple valid reasonable ways to split payload into multiple
    258 // packets, do not validate current choice, instead use RtpDepacketizer
    259 // to validate frame is reconstracted to the same one. Note: since
    260 // RtpDepacketizer always inserts obu_size fields in the output, use frame where
    261 // each obu has obu_size fields for more streight forward validation.
    262 TEST(RtpPacketizerAv1Test, SplitSingleObuIntoTwoPackets) {
    263  auto kFrame =
    264      BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
    265                         .WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});
    266 
    267  RtpPacketizer::PayloadSizeLimits limits;
    268  limits.max_payload_len = 8;
    269  auto payloads = Packetize(kFrame, limits);
    270  EXPECT_THAT(payloads, ElementsAre(SizeIs(Le(8u)), SizeIs(Le(8u))));
    271 
    272  // Use RtpDepacketizer to validate the split.
    273  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
    274 }
    275 
    276 TEST(RtpPacketizerAv1Test, SplitSingleObuIntoManyPackets) {
    277  auto kFrame = BuildAv1Frame(
    278      {Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1200, 27))});
    279 
    280  RtpPacketizer::PayloadSizeLimits limits;
    281  limits.max_payload_len = 100;
    282  auto payloads = Packetize(kFrame, limits);
    283  EXPECT_THAT(payloads, SizeIs(13u));
    284  EXPECT_THAT(payloads, Each(SizeIs(Le(100u))));
    285 
    286  // Use RtpDepacketizer to validate the split.
    287  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
    288 }
    289 
    290 TEST(RtpPacketizerAv1Test, SetMarkerBitForLastPacketInEndOfPictureFrame) {
    291  auto kFrame = BuildAv1Frame(
    292      {Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
    293 
    294  RtpPacketizer::PayloadSizeLimits limits;
    295  limits.max_payload_len = 100;
    296  auto payloads = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta,
    297                            /*is_last_frame_in_picture=*/true);
    298  ASSERT_THAT(payloads, SizeIs(3u));
    299  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
    300  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
    301  EXPECT_TRUE(payloads[2].rtp_packet.Marker());
    302 }
    303 
    304 TEST(RtpPacketizerAv1Test, DoesntSetMarkerBitForPacketsNotInEndOfPictureFrame) {
    305  auto kFrame = BuildAv1Frame(
    306      {Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
    307 
    308  RtpPacketizer::PayloadSizeLimits limits;
    309  limits.max_payload_len = 100;
    310  auto payloads = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta,
    311                            /*is_last_frame_in_picture=*/false);
    312  ASSERT_THAT(payloads, SizeIs(3u));
    313  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
    314  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
    315  EXPECT_FALSE(payloads[2].rtp_packet.Marker());
    316 }
    317 
    318 TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPackets) {
    319  // 2nd OBU is too large to fit into one packet, so its head would be in the
    320  // same packet as the 1st OBU.
    321  auto kFrame = BuildAv1Frame(
    322      {Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({11, 12}),
    323       Av1Obu(kAv1ObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7, 8, 9})});
    324 
    325  RtpPacketizer::PayloadSizeLimits limits;
    326  limits.max_payload_len = 8;
    327  auto payloads = Packetize(kFrame, limits);
    328  EXPECT_THAT(payloads, ElementsAre(SizeIs(Le(8u)), SizeIs(Le(8u))));
    329 
    330  // Use RtpDepacketizer to validate the split.
    331  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
    332 }
    333 
    334 TEST(RtpPacketizerAv1Test,
    335     SplitSingleObuIntoTwoPacketsBecauseOfSinglePacketLimit) {
    336  auto kFrame =
    337      BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
    338                         .WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});
    339  RtpPacketizer::PayloadSizeLimits limits;
    340  limits.max_payload_len = 10;
    341  limits.single_packet_reduction_len = 8;
    342  auto payloads = Packetize(kFrame, limits);
    343  EXPECT_THAT(payloads, ElementsAre(SizeIs(Le(10u)), SizeIs(Le(10u))));
    344 
    345  EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
    346 }
    347 
    348 TEST(RtpPacketizerAv1TestEven, EvenDistribution) {
    349  auto kFrame = BuildAv1Frame({
    350      Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1206, 0)),
    351      Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1476, 0)),
    352      Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1431, 0)),
    353  });
    354  EXPECT_THAT(Packetize(kFrame, {}), ElementsAre(SizeIs(1032), SizeIs(1032),
    355                                                 SizeIs(1032), SizeIs(1028)));
    356 }
    357 
    358 }  // namespace
    359 }  // namespace webrtc