summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_av1_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_av1_unittest.cc392
1 files changed, 392 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_av1_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_av1_unittest.cc
new file mode 100644
index 0000000000..e9ad1a1b8e
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/video_rtp_depacketizer_av1_unittest.cc
@@ -0,0 +1,392 @@
+/*
+ * 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/video_rtp_depacketizer_av1.h"
+
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::ElementsAre;
+
+// Signals number of the OBU (fragments) in the packet.
+constexpr uint8_t kObuCountOne = 0b00'01'0000;
+
+constexpr uint8_t kObuHeaderSequenceHeader = 0b0'0001'000;
+constexpr uint8_t kObuHeaderFrame = 0b0'0110'000;
+
+constexpr uint8_t kObuHeaderHasSize = 0b0'0000'010;
+
+TEST(VideoRtpDepacketizerAv1Test, ParsePassFullRtpPayloadAsCodecPayload) {
+ const uint8_t packet[] = {(uint8_t{1} << 7) | kObuCountOne, 1, 2, 3, 4};
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+ VideoRtpDepacketizerAv1 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_TRUE(parsed);
+ EXPECT_EQ(parsed->video_payload.size(), sizeof(packet));
+ EXPECT_TRUE(parsed->video_payload.cdata() == rtp_payload.cdata());
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ ParseTreatsContinuationFlagAsNotBeginningOfFrame) {
+ const uint8_t packet[] = {
+ (uint8_t{1} << 7) | kObuCountOne,
+ kObuHeaderFrame}; // Value doesn't matter since it is a
+ // continuation of the OBU from previous packet.
+ VideoRtpDepacketizerAv1 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->video_header.is_first_packet_in_frame);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ ParseTreatsNoContinuationFlagAsBeginningOfFrame) {
+ const uint8_t packet[] = {(uint8_t{0} << 7) | kObuCountOne, kObuHeaderFrame};
+ VideoRtpDepacketizerAv1 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
+ ASSERT_TRUE(parsed);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+}
+
+TEST(VideoRtpDepacketizerAv1Test, ParseTreatsWillContinueFlagAsNotEndOfFrame) {
+ const uint8_t packet[] = {(uint8_t{1} << 6) | kObuCountOne, kObuHeaderFrame};
+ rtc::CopyOnWriteBuffer rtp_payload(packet);
+ VideoRtpDepacketizerAv1 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtp_payload);
+ ASSERT_TRUE(parsed);
+ EXPECT_FALSE(parsed->video_header.is_last_packet_in_frame);
+}
+
+TEST(VideoRtpDepacketizerAv1Test, ParseTreatsNoWillContinueFlagAsEndOfFrame) {
+ const uint8_t packet[] = {(uint8_t{0} << 6) | kObuCountOne, kObuHeaderFrame};
+ VideoRtpDepacketizerAv1 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
+ ASSERT_TRUE(parsed);
+ EXPECT_TRUE(parsed->video_header.is_last_packet_in_frame);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ ParseUsesNewCodedVideoSequenceBitAsKeyFrameIndidcator) {
+ const uint8_t packet[] = {(uint8_t{1} << 3) | kObuCountOne,
+ kObuHeaderSequenceHeader};
+ VideoRtpDepacketizerAv1 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
+ ASSERT_TRUE(parsed);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+ EXPECT_TRUE(parsed->video_header.frame_type ==
+ VideoFrameType::kVideoFrameKey);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ ParseUsesUnsetNewCodedVideoSequenceBitAsDeltaFrameIndidcator) {
+ const uint8_t packet[] = {(uint8_t{0} << 3) | kObuCountOne,
+ kObuHeaderSequenceHeader};
+ VideoRtpDepacketizerAv1 depacketizer;
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+ depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
+ ASSERT_TRUE(parsed);
+ EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+ EXPECT_TRUE(parsed->video_header.frame_type ==
+ VideoFrameType::kVideoFrameDelta);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ ParseRejectsPacketWithNewCVSAndContinuationFlagsBothSet) {
+ const uint8_t packet[] = {0b10'00'1000 | kObuCountOne,
+ kObuHeaderSequenceHeader};
+ VideoRtpDepacketizerAv1 depacketizer;
+ ASSERT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(packet)));
+}
+
+TEST(VideoRtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenAbsent) {
+ const uint8_t payload1[] = {0b00'01'0000, // aggregation header
+ 0b0'0110'000, // / Frame
+ 20, 30, 40}; // \ OBU
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ rtc::ArrayView<const uint8_t> frame_view(*frame);
+ EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
+ EXPECT_EQ(frame_view[1], 3);
+}
+
+TEST(VideoRtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenPresent) {
+ const uint8_t payload1[] = {0b00'01'0000, // aggregation header
+ 0b0'0110'010, // / Frame OBU header
+ 3, // obu_size
+ 20,
+ 30,
+ 40}; // \ obu_payload
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ rtc::ArrayView<const uint8_t> frame_view(*frame);
+ EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
+ EXPECT_EQ(frame_view[1], 3);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameSetsOBUPayloadSizeAfterExtensionWhenAbsent) {
+ const uint8_t payload1[] = {0b00'01'0000, // aggregation header
+ 0b0'0110'100, // / Frame
+ 0b010'01'000, // | extension_header
+ 20, 30, 40}; // \ OBU
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ rtc::ArrayView<const uint8_t> frame_view(*frame);
+ EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
+ EXPECT_EQ(frame_view[2], 3);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameSetsOBUPayloadSizeAfterExtensionWhenPresent) {
+ const uint8_t payload1[] = {0b00'01'0000, // aggregation header
+ 0b0'0110'110, // / Frame OBU header
+ 0b010'01'000, // | extension_header
+ 3, // | obu_size
+ 20,
+ 30,
+ 40}; // \ obu_payload
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ rtc::ArrayView<const uint8_t> frame_view(*frame);
+ EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
+ EXPECT_EQ(frame_view[2], 3);
+}
+
+TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithOneObu) {
+ const uint8_t payload1[] = {0b00'01'0000, // aggregation header
+ 0b0'0110'000, // / Frame
+ 20}; // \ OBU
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0110'010, 1, 20));
+}
+
+TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithTwoObus) {
+ const uint8_t payload1[] = {0b00'10'0000, // aggregation header
+ 2, // / Sequence
+ 0b0'0001'000, // | Header
+ 10, // \ OBU
+ 0b0'0110'000, // / Frame
+ 20}; // \ OBU
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0001'010, 1, 10, // Sequence Header OBU
+ 0b0'0110'010, 1, 20)); // Frame OBU
+}
+
+TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithOneObu) {
+ const uint8_t payload1[] = {0b01'01'0000, // aggregation header
+ 0b0'0110'000, 20, 30};
+ const uint8_t payload2[] = {0b10'01'0000, // aggregation header
+ 40};
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0110'010, 3, 20, 30, 40));
+}
+
+TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithTwoObu) {
+ const uint8_t payload1[] = {0b01'10'0000, // aggregation header
+ 2, // / Sequence
+ 0b0'0001'000, // | Header
+ 10, // \ OBU
+ 0b0'0110'000, //
+ 20,
+ 30}; //
+ const uint8_t payload2[] = {0b10'01'0000, // aggregation header
+ 40}; //
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0001'010, 1, 10, // SH
+ 0b0'0110'010, 3, 20, 30, 40)); // Frame
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameFromTwoPacketsWithManyObusSomeWithExtensions) {
+ const uint8_t payload1[] = {0b01'00'0000, // aggregation header
+ 2, // /
+ 0b0'0001'000, // | Sequence Header
+ 10, // \ OBU
+ 2, // /
+ 0b0'0101'000, // | Metadata OBU
+ 20, // \ without extension
+ 4, // /
+ 0b0'0101'100, // | Metadata OBU
+ 0b001'10'000, // | with extension
+ 20, // |
+ 30, // \ metadata payload
+ 5, // /
+ 0b0'0110'100, // | Frame OBU
+ 0b001'10'000, // | with extension
+ 40, // |
+ 50, // |
+ 60}; // |
+ const uint8_t payload2[] = {0b10'01'0000, // aggregation header
+ 70, 80, 90}; // \ tail of the frame OBU
+
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre( // Sequence header OBU
+ 0b0'0001'010, 1, 10,
+ // Metadata OBU without extension
+ 0b0'0101'010, 1, 20,
+ // Metadata OBU with extenion
+ 0b0'0101'110, 0b001'10'000, 2, 20, 30,
+ // Frame OBU with extension
+ 0b0'0110'110, 0b001'10'000, 6, 40, 50, 60, 70, 80, 90));
+}
+
+TEST(VideoRtpDepacketizerAv1Test, AssembleFrameWithOneObuFromManyPackets) {
+ const uint8_t payload1[] = {0b01'01'0000, // aggregation header
+ 0b0'0110'000, 11, 12};
+ const uint8_t payload2[] = {0b11'01'0000, // aggregation header
+ 13, 14};
+ const uint8_t payload3[] = {0b11'01'0000, // aggregation header
+ 15, 16, 17};
+ const uint8_t payload4[] = {0b10'01'0000, // aggregation header
+ 18};
+
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2, payload3,
+ payload4};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0110'010, 8, 11, 12, 13, 14, 15, 16, 17, 18));
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameFromManyPacketsWithSomeObuBorderAligned) {
+ const uint8_t payload1[] = {0b01'10'0000, // aggregation header
+ 3, // size of the 1st fragment
+ 0b0'0011'000, // Frame header OBU
+ 11,
+ 12,
+ 0b0'0100'000, // Tile group OBU
+ 21,
+ 22,
+ 23};
+ const uint8_t payload2[] = {0b10'01'0000, // aggregation header
+ 24, 25, 26, 27};
+ // payload2 ends an OBU, payload3 starts a new one.
+ const uint8_t payload3[] = {0b01'10'0000, // aggregation header
+ 3, // size of the 1st fragment
+ 0b0'0111'000, // Redundant frame header OBU
+ 11,
+ 12,
+ 0b0'0100'000, // Tile group OBU
+ 31,
+ 32};
+ const uint8_t payload4[] = {0b10'01'0000, // aggregation header
+ 33, 34, 35, 36};
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2, payload3,
+ payload4};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0011'010, 2, 11, 12, // Frame header
+ 0b0'0100'010, 7, 21, 22, 23, 24, 25, 26, 27, //
+ 0b0'0111'010, 2, 11, 12, //
+ 0b0'0100'010, 6, 31, 32, 33, 34, 35, 36));
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameFromOnePacketsOneObuPayloadSize127Bytes) {
+ uint8_t payload1[4 + 127];
+ memset(payload1, 0, sizeof(payload1));
+ payload1[0] = 0b00'00'0000; // aggregation header
+ payload1[1] = 0x80; // leb128 encoded size of 128 bytes
+ payload1[2] = 0x01; // in two bytes
+ payload1[3] = 0b0'0110'000; // obu_header with size and extension bits unset.
+ payload1[4 + 42] = 0x42;
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_EQ(frame->size(), 2 + 127u);
+ rtc::ArrayView<const uint8_t> frame_view(*frame);
+ EXPECT_EQ(frame_view[0], 0b0'0110'010); // obu_header with size bit set.
+ EXPECT_EQ(frame_view[1], 127); // obu payload size, 1 byte enough to encode.
+ // Check 'random' byte from the payload is at the same 'random' offset.
+ EXPECT_EQ(frame_view[2 + 42], 0x42);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameFromTwoPacketsOneObuPayloadSize128Bytes) {
+ uint8_t payload1[3 + 32];
+ memset(payload1, 0, sizeof(payload1));
+ payload1[0] = 0b01'00'0000; // aggregation header
+ payload1[1] = 33; // leb128 encoded size of 33 bytes in one byte
+ payload1[2] = 0b0'0110'000; // obu_header with size and extension bits unset.
+ payload1[3 + 10] = 0x10;
+ uint8_t payload2[2 + 96];
+ memset(payload2, 0, sizeof(payload2));
+ payload2[0] = 0b10'00'0000; // aggregation header
+ payload2[1] = 96; // leb128 encoded size of 96 bytes in one byte
+ payload2[2 + 20] = 0x20;
+
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_EQ(frame->size(), 3 + 128u);
+ rtc::ArrayView<const uint8_t> frame_view(*frame);
+ EXPECT_EQ(frame_view[0], 0b0'0110'010); // obu_header with size bit set.
+ EXPECT_EQ(frame_view[1], 0x80); // obu payload size of 128 bytes.
+ EXPECT_EQ(frame_view[2], 0x01); // encoded in two byes
+ // Check two 'random' byte from the payload is at the same 'random' offset.
+ EXPECT_EQ(frame_view[3 + 10], 0x10);
+ EXPECT_EQ(frame_view[3 + 32 + 20], 0x20);
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameFromAlmostEmptyPacketStartingAnOBU) {
+ const uint8_t payload1[] = {0b01'01'0000};
+ const uint8_t payload2[] = {0b10'01'0000, 0b0'0110'000, 10, 20, 30};
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
+
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0110'010, 3, 10, 20, 30));
+}
+
+TEST(VideoRtpDepacketizerAv1Test,
+ AssembleFrameFromAlmostEmptyPacketFinishingAnOBU) {
+ const uint8_t payload1[] = {0b01'01'0000, 0b0'0110'000, 10, 20, 30};
+ const uint8_t payload2[] = {0b10'01'0000};
+ rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
+
+ auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
+ ASSERT_TRUE(frame);
+ EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
+ ElementsAre(0b0'0110'010, 3, 10, 20, 30));
+}
+
+} // namespace
+} // namespace webrtc