webrtc/modules/rtp_rtcp/source/rtp_depacketizer_av1_unittest.cc
Danil Chapovalov ccf12c6e97 Reland "Add AV1 RtpDepacketizer class"
This is a reland of 49470c2ac4
Tentative reland to rule-out bot flakiness.

Original change's description:
> Add AV1 RtpDepacketizer class
>
> Implement Parse function that extracts is_first_packet_in_frame,
> is_last_packet_in_frame, and frame_type fields.
>
> Bug: webrtc:11042
> Change-Id: I9360ea52ef274281b5c5e4c31955100b92155bfe
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159180
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Reviewed-by: Sam Zackrisson <saza@webrtc.org>
> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#29814}

TBR=saza@webrtc.org,philipel@webrtc.org

Bug: webrtc:11042
Change-Id: Ibd672ce685bcab86960500740465539ed70fcdf4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159941
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29819}
2019-11-18 15:23:08 +00:00

196 lines
8.2 KiB
C++

/*
* 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_depacketizer_av1.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
// Signals number of the OBU (fragments) in the packet.
constexpr uint8_t kObuCountAny = 0b0000'0000;
constexpr uint8_t kObuCountOne = 0b0001'0000;
constexpr uint8_t kObuCountTwo = 0b0010'0000;
constexpr uint8_t kObuHeaderSequenceHeader = 0b0'0001'000;
constexpr uint8_t kObuHeaderTemporalDelimiter = 0b0'0010'000;
constexpr uint8_t kObuHeaderFrame = 0b0'0110'000;
TEST(RtpDepacketizerAv1Test, ParsePassFullRtpPayloadAsCodecPayload) {
const uint8_t packet[] = {(uint8_t{1} << 7) | kObuCountOne, 1, 2, 3, 4};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_EQ(parsed.payload_length, sizeof(packet));
EXPECT_TRUE(parsed.payload == packet);
}
TEST(RtpDepacketizerAv1Test, 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.
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_FALSE(parsed.video.is_first_packet_in_frame);
}
TEST(RtpDepacketizerAv1Test, ParseTreatsNoContinuationFlagAsBeginningOfFrame) {
const uint8_t packet[] = {(uint8_t{0} << 7) | kObuCountOne, kObuHeaderFrame};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.is_first_packet_in_frame);
}
TEST(RtpDepacketizerAv1Test, ParseTreatsWillContinueFlagAsNotEndOfFrame) {
const uint8_t packet[] = {(uint8_t{1} << 6) | kObuCountOne, kObuHeaderFrame};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_FALSE(parsed.video.is_last_packet_in_frame);
}
TEST(RtpDepacketizerAv1Test, ParseTreatsNoWillContinueFlagAsEndOfFrame) {
const uint8_t packet[] = {(uint8_t{0} << 6) | kObuCountOne, kObuHeaderFrame};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.is_last_packet_in_frame);
}
TEST(RtpDepacketizerAv1Test, ParseTreatsStartOfSequenceHeaderAsKeyFrame) {
const uint8_t packet[] = {kObuCountOne, kObuHeaderSequenceHeader};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.is_first_packet_in_frame);
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameKey);
}
TEST(RtpDepacketizerAv1Test, ParseTreatsNotStartOfFrameAsDeltaFrame) {
const uint8_t packet[] = {
(uint8_t{1} << 7) | kObuCountOne,
// Byte that look like start of sequence header, but since it is not start
// of an OBU, it is actually not a start of sequence header.
kObuHeaderSequenceHeader};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_FALSE(parsed.video.is_first_packet_in_frame);
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameDelta);
}
TEST(RtpDepacketizerAv1Test,
ParseTreatsStartOfFrameWithoutSequenceHeaderAsDeltaFrame) {
const uint8_t packet[] = {kObuCountOne, kObuHeaderFrame};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.is_first_packet_in_frame);
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameDelta);
}
TEST(RtpDepacketizerAv1Test, ParseFindsSequenceHeaderBehindFragmentSize1) {
const uint8_t packet[] = {kObuCountAny,
1, // size of the next fragment
kObuHeaderSequenceHeader};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameKey);
}
TEST(RtpDepacketizerAv1Test, ParseFindsSequenceHeaderBehindFragmentSize2) {
const uint8_t packet[] = {kObuCountTwo,
2, // size of the next fragment
kObuHeaderSequenceHeader,
42, // SH payload.
kObuHeaderFrame};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameKey);
}
TEST(RtpDepacketizerAv1Test,
ParseFindsSequenceHeaderBehindMultiByteFragmentSize) {
const uint8_t packet[] = {kObuCountTwo,
0b1000'0101, // leb128 encoded value of 5
0b1000'0000, // using 3 bytes
0b0000'0000, // to encode the value.
kObuHeaderSequenceHeader,
8, // 4 bytes of SH payload.
0,
0,
0,
kObuHeaderFrame};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameKey);
}
TEST(RtpDepacketizerAv1Test, ParseFindsSequenceHeaderBehindTemporalDelimiter) {
const uint8_t packet[] = {kObuCountTwo,
1, // size of the next fragment
kObuHeaderTemporalDelimiter,
kObuHeaderSequenceHeader,
8, // 4 bytes of SH payload.
0,
0,
0};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameKey);
}
TEST(RtpDepacketizerAv1Test,
ParseFindsSequenceHeaderBehindTemporalDelimiterAndSize) {
const uint8_t packet[] = {kObuCountAny,
1, // size of the next fragment
kObuHeaderTemporalDelimiter,
5, // size of the next fragment
kObuHeaderSequenceHeader,
8, // 4 bytes of SH payload.
0,
0,
0,
1, // size of the next fragment
kObuHeaderFrame};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameKey);
}
TEST(RtpDepacketizerAv1Test, ParseSkipsEmptyFragments) {
static_assert(kObuHeaderSequenceHeader == 8, "");
const uint8_t packet[] = {kObuCountAny,
0, // size of the next fragment
8, // size of the next fragment that look like SH
kObuHeaderFrame,
1,
2,
3,
4,
5,
6,
7};
RtpDepacketizerAv1 depacketizer;
RtpDepacketizer::ParsedPayload parsed;
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
EXPECT_TRUE(parsed.video.frame_type == VideoFrameType::kVideoFrameDelta);
}
} // namespace
} // namespace webrtc