mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-15 14:50:39 +01:00

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}
196 lines
8.2 KiB
C++
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
|