tor-browser

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

rtp_video_frame_h265_assembler_unittests.cc (5433B)


      1 /*
      2 *  Copyright (c) 2024 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 <cstdint>
     12 #include <iterator>
     13 #include <memory>
     14 #include <optional>
     15 #include <utility>
     16 #include <vector>
     17 
     18 #include "api/array_view.h"
     19 #include "api/video/encoded_frame.h"
     20 #include "api/video/rtp_video_frame_assembler.h"
     21 #include "api/video/video_codec_type.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_received.h"
     25 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
     26 #include "modules/rtp_rtcp/source/rtp_video_header.h"
     27 #include "rtc_base/checks.h"
     28 #include "test/gmock.h"
     29 #include "test/gtest.h"
     30 
     31 namespace webrtc {
     32 namespace {
     33 
     34 using ::testing::ElementsAreArray;
     35 using ::testing::Eq;
     36 using ::testing::IsEmpty;
     37 using ::testing::SizeIs;
     38 using ::testing::UnorderedElementsAre;
     39 using PayloadFormat = RtpVideoFrameAssembler::PayloadFormat;
     40 
     41 class PacketBuilder {
     42 public:
     43  explicit PacketBuilder(PayloadFormat format)
     44      : format_(format), packet_to_send_(&extension_manager_) {}
     45 
     46  PacketBuilder& WithSeqNum(uint16_t seq_num) {
     47    seq_num_ = seq_num;
     48    return *this;
     49  }
     50 
     51  PacketBuilder& WithPayload(ArrayView<const uint8_t> payload) {
     52    payload_.assign(payload.begin(), payload.end());
     53    return *this;
     54  }
     55 
     56  PacketBuilder& WithVideoHeader(const RTPVideoHeader& video_header) {
     57    video_header_ = video_header;
     58    return *this;
     59  }
     60 
     61  template <typename T, typename... Args>
     62  PacketBuilder& WithExtension(int id, const Args&... args) {
     63    extension_manager_.Register<T>(id);
     64    packet_to_send_.IdentifyExtensions(extension_manager_);
     65    packet_to_send_.SetExtension<T>(std::forward<const Args>(args)...);
     66    return *this;
     67  }
     68 
     69  RtpPacketReceived Build() {
     70    auto packetizer =
     71        RtpPacketizer::Create(GetVideoCodecType(), payload_, {}, video_header_);
     72    packetizer->NextPacket(&packet_to_send_);
     73    packet_to_send_.SetSequenceNumber(seq_num_);
     74 
     75    RtpPacketReceived received(&extension_manager_);
     76    received.Parse(packet_to_send_.Buffer());
     77    return received;
     78  }
     79 
     80 private:
     81  std::optional<VideoCodecType> GetVideoCodecType() {
     82    switch (format_) {
     83      case PayloadFormat::kH265: {
     84        return kVideoCodecH265;
     85      }
     86      default:
     87        RTC_DCHECK_NOTREACHED();
     88        return std::nullopt;
     89    }
     90  }
     91 
     92  const RtpVideoFrameAssembler::PayloadFormat format_;
     93  uint16_t seq_num_ = 0;
     94  std::vector<uint8_t> payload_;
     95  RTPVideoHeader video_header_;
     96  RtpPacketReceived::ExtensionManager extension_manager_;
     97  RtpPacketToSend packet_to_send_;
     98 };
     99 
    100 void AppendFrames(RtpVideoFrameAssembler::FrameVector&& from,
    101                  RtpVideoFrameAssembler::FrameVector& to) {
    102  to.insert(to.end(), std::make_move_iterator(from.begin()),
    103            std::make_move_iterator(from.end()));
    104 }
    105 
    106 ArrayView<int64_t> References(const std::unique_ptr<EncodedFrame>& frame) {
    107  return MakeArrayView(frame->references, frame->num_references);
    108 }
    109 
    110 ArrayView<const uint8_t> Payload(const std::unique_ptr<EncodedFrame>& frame) {
    111  return *frame->GetEncodedData();
    112 }
    113 
    114 TEST(RtpVideoFrameH265Assembler, H265Packetization) {
    115  RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kH265);
    116  RtpVideoFrameAssembler::FrameVector frames;
    117 
    118  // Key and delta frames generated on linux with ffmpeg command:
    119  // `ffmpeg -i /dev/video0 -r 30 -c:v libx265 -s 1280x720 camera.h265`,
    120  // truncated for test.
    121  // IDR_N_LP(key) frame with start code included.
    122  uint8_t kIdrPayload[] = {0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0xaf,
    123                           0x08, 0x4a, 0x31, 0x11, 0x15, 0xe5, 0xc0};
    124  // TRAIL_R(delta) frame with start code included.
    125  uint8_t kDeltaPayload[] = {0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0xd0,
    126                             0x09, 0x7e, 0x10, 0xc6, 0x1c, 0x8c, 0x17};
    127 
    128  RTPVideoHeader video_header;
    129  video_header.frame_type = VideoFrameType::kVideoFrameKey;
    130  RtpVideoFrameAssembler::FrameVector idr_frames =
    131      assembler.InsertPacket(PacketBuilder(PayloadFormat::kH265)
    132                                 .WithPayload(kIdrPayload)
    133                                 .WithVideoHeader(video_header)
    134                                 .WithSeqNum(10)
    135                                 .Build());
    136  AppendFrames(std::move(idr_frames), frames);
    137 
    138  RtpVideoFrameAssembler::FrameVector delta_frames =
    139      assembler.InsertPacket(PacketBuilder(PayloadFormat::kH265)
    140                                 .WithPayload(kDeltaPayload)
    141                                 .WithSeqNum(11)
    142                                 .Build());
    143  AppendFrames(std::move(delta_frames), frames);
    144  ASSERT_THAT(frames, SizeIs(2));
    145 
    146  auto first_frame = frames[0].ExtractFrame();
    147  EXPECT_THAT(first_frame->Id(), Eq(10));
    148  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kIdrPayload));
    149  EXPECT_THAT(References(first_frame), IsEmpty());
    150 
    151  auto second_frame = frames[1].ExtractFrame();
    152  EXPECT_THAT(second_frame->Id(), Eq(11));
    153  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kDeltaPayload));
    154  EXPECT_THAT(References(second_frame), UnorderedElementsAre(10));
    155 }
    156 
    157 }  // namespace
    158 }  // namespace webrtc