Change Av1 depacketizer to implement VideoRtpDepacketizer interface
Bug: webrtc:11152 Change-Id: I322115263f60439bee36277157a0acef9bd28e3e Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/165343 Reviewed-by: Sam Zackrisson <saza@webrtc.org> Reviewed-by: Philip Eliasson <philipel@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30260}
This commit is contained in:
parent
f1173f46e5
commit
d06588a758
@ -167,8 +167,6 @@ rtc_library("rtp_rtcp") {
|
||||
"source/rtcp_receiver.h",
|
||||
"source/rtcp_sender.cc",
|
||||
"source/rtcp_sender.h",
|
||||
"source/rtp_depacketizer_av1.cc",
|
||||
"source/rtp_depacketizer_av1.h",
|
||||
"source/rtp_format.cc",
|
||||
"source/rtp_format.h",
|
||||
"source/rtp_format_h264.cc",
|
||||
@ -213,6 +211,8 @@ rtc_library("rtp_rtcp") {
|
||||
"source/ulpfec_receiver_impl.cc",
|
||||
"source/ulpfec_receiver_impl.h",
|
||||
"source/video_rtp_depacketizer.h",
|
||||
"source/video_rtp_depacketizer_av1.cc",
|
||||
"source/video_rtp_depacketizer_av1.h",
|
||||
"source/video_rtp_depacketizer_generic.cc",
|
||||
"source/video_rtp_depacketizer_generic.h",
|
||||
"source/video_rtp_depacketizer_h264.cc",
|
||||
@ -461,7 +461,6 @@ if (rtc_include_tests) {
|
||||
"source/rtcp_sender_unittest.cc",
|
||||
"source/rtcp_transceiver_impl_unittest.cc",
|
||||
"source/rtcp_transceiver_unittest.cc",
|
||||
"source/rtp_depacketizer_av1_unittest.cc",
|
||||
"source/rtp_fec_unittest.cc",
|
||||
"source/rtp_format_h264_unittest.cc",
|
||||
"source/rtp_format_unittest.cc",
|
||||
@ -487,6 +486,7 @@ if (rtc_include_tests) {
|
||||
"source/ulpfec_generator_unittest.cc",
|
||||
"source/ulpfec_header_reader_writer_unittest.cc",
|
||||
"source/ulpfec_receiver_unittest.cc",
|
||||
"source/video_rtp_depacketizer_av1_unittest.cc",
|
||||
"source/video_rtp_depacketizer_generic_unittest.cc",
|
||||
"source/video_rtp_depacketizer_h264_unittest.cc",
|
||||
"source/video_rtp_depacketizer_raw_unittest.cc",
|
||||
|
||||
@ -14,8 +14,8 @@
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_depacketizer_av1.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_generic.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp8.h"
|
||||
@ -60,7 +60,7 @@ std::unique_ptr<VideoRtpDepacketizer> CreateVideoRtpDepacketizer(
|
||||
case kVideoCodecVP9:
|
||||
return std::make_unique<VideoRtpDepacketizerVp9>();
|
||||
case kVideoCodecAV1:
|
||||
return std::make_unique<Legacy<RtpDepacketizerAv1>>();
|
||||
return std::make_unique<VideoRtpDepacketizerAv1>();
|
||||
case kVideoCodecGeneric:
|
||||
case kVideoCodecMultiplex:
|
||||
return std::make_unique<VideoRtpDepacketizerGeneric>();
|
||||
|
||||
@ -20,8 +20,8 @@
|
||||
#include "api/array_view.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/video/encoded_image.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_depacketizer_av1.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
@ -104,7 +104,7 @@ Av1Frame ReassembleFrame(rtc::ArrayView<const RtpPayload> rtp_payloads) {
|
||||
for (size_t i = 0; i < rtp_payloads.size(); ++i) {
|
||||
payloads[i] = rtp_payloads[i];
|
||||
}
|
||||
return Av1Frame(RtpDepacketizerAv1::AssembleFrame(payloads));
|
||||
return Av1Frame(VideoRtpDepacketizerAv1::AssembleFrame(payloads));
|
||||
}
|
||||
|
||||
class Obu {
|
||||
|
||||
@ -8,11 +8,13 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/rtp_rtcp/source/rtp_depacketizer_av1.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "modules/rtp_rtcp/source/rtp_video_header.h"
|
||||
#include "rtc_base/byte_buffer.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -333,7 +335,7 @@ bool CalculateObuSizes(ObuInfo* obu_info) {
|
||||
|
||||
} // namespace
|
||||
|
||||
rtc::scoped_refptr<EncodedImageBuffer> RtpDepacketizerAv1::AssembleFrame(
|
||||
rtc::scoped_refptr<EncodedImageBuffer> VideoRtpDepacketizerAv1::AssembleFrame(
|
||||
rtc::ArrayView<const rtc::ArrayView<const uint8_t>> rtp_payloads) {
|
||||
VectorObuInfo obu_infos = ParseObus(rtp_payloads);
|
||||
if (obu_infos.empty()) {
|
||||
@ -363,42 +365,40 @@ rtc::scoped_refptr<EncodedImageBuffer> RtpDepacketizerAv1::AssembleFrame(
|
||||
return bitstream;
|
||||
}
|
||||
|
||||
bool RtpDepacketizerAv1::Parse(ParsedPayload* parsed_payload,
|
||||
const uint8_t* payload_data,
|
||||
size_t payload_data_length) {
|
||||
RTC_DCHECK(parsed_payload);
|
||||
if (payload_data_length == 0) {
|
||||
absl::optional<VideoRtpDepacketizer::ParsedRtpPayload>
|
||||
VideoRtpDepacketizerAv1::Parse(rtc::CopyOnWriteBuffer rtp_payload) {
|
||||
if (rtp_payload.size() == 0) {
|
||||
RTC_DLOG(LS_ERROR) << "Empty rtp payload.";
|
||||
return false;
|
||||
return absl::nullopt;
|
||||
}
|
||||
uint8_t aggregation_header = payload_data[0];
|
||||
uint8_t aggregation_header = rtp_payload.cdata()[0];
|
||||
if (RtpStartsNewCodedVideoSequence(aggregation_header) &&
|
||||
RtpStartsWithFragment(aggregation_header)) {
|
||||
// new coded video sequence can't start from an OBU fragment.
|
||||
return false;
|
||||
return absl::nullopt;
|
||||
}
|
||||
absl::optional<ParsedRtpPayload> parsed(absl::in_place);
|
||||
|
||||
// To assemble frame, all of the rtp payload is required, including
|
||||
// aggregation header.
|
||||
parsed_payload->payload = payload_data;
|
||||
parsed_payload->payload_length = payload_data_length;
|
||||
parsed->video_payload = std::move(rtp_payload);
|
||||
|
||||
parsed_payload->video.codec = VideoCodecType::kVideoCodecAV1;
|
||||
parsed->video_header.codec = VideoCodecType::kVideoCodecAV1;
|
||||
// These are not accurate since frame may consist of several packet aligned
|
||||
// chunks of obus, but should be good enough for most cases. It might produce
|
||||
// frame that do not map to any real frame, but av1 decoder should be able to
|
||||
// handle it since it promise to handle individual obus rather than full
|
||||
// frames.
|
||||
parsed_payload->video.is_first_packet_in_frame =
|
||||
parsed->video_header.is_first_packet_in_frame =
|
||||
!RtpStartsWithFragment(aggregation_header);
|
||||
parsed_payload->video.is_last_packet_in_frame =
|
||||
parsed->video_header.is_last_packet_in_frame =
|
||||
!RtpEndsWithFragment(aggregation_header);
|
||||
|
||||
parsed_payload->video.frame_type =
|
||||
parsed->video_header.frame_type =
|
||||
RtpStartsNewCodedVideoSequence(aggregation_header)
|
||||
? VideoFrameType::kVideoFrameKey
|
||||
: VideoFrameType::kVideoFrameDelta;
|
||||
return true;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -8,33 +8,34 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_DEPACKETIZER_AV1_H_
|
||||
#define MODULES_RTP_RTCP_SOURCE_RTP_DEPACKETIZER_AV1_H_
|
||||
#ifndef MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_AV1_H_
|
||||
#define MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_AV1_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/video/encoded_image.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_format.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RtpDepacketizerAv1 : public RtpDepacketizer {
|
||||
class VideoRtpDepacketizerAv1 : public VideoRtpDepacketizer {
|
||||
public:
|
||||
RtpDepacketizerAv1() = default;
|
||||
RtpDepacketizerAv1(const RtpDepacketizerAv1&) = delete;
|
||||
RtpDepacketizerAv1& operator=(const RtpDepacketizerAv1&) = delete;
|
||||
~RtpDepacketizerAv1() override = default;
|
||||
VideoRtpDepacketizerAv1() = default;
|
||||
VideoRtpDepacketizerAv1(const VideoRtpDepacketizerAv1&) = delete;
|
||||
VideoRtpDepacketizerAv1& operator=(const VideoRtpDepacketizerAv1&) = delete;
|
||||
~VideoRtpDepacketizerAv1() override = default;
|
||||
|
||||
static rtc::scoped_refptr<EncodedImageBuffer> AssembleFrame(
|
||||
rtc::ArrayView<const rtc::ArrayView<const uint8_t>> rtp_payloads);
|
||||
|
||||
bool Parse(ParsedPayload* parsed_payload,
|
||||
const uint8_t* payload_data,
|
||||
size_t payload_data_length) override;
|
||||
absl::optional<ParsedRtpPayload> Parse(
|
||||
rtc::CopyOnWriteBuffer rtp_payload) override;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_RTP_RTCP_SOURCE_RTP_DEPACKETIZER_AV1_H_
|
||||
#endif // MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_AV1_H_
|
||||
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/rtp_rtcp/source/rtp_depacketizer_av1.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
|
||||
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
@ -26,94 +26,106 @@ constexpr uint8_t kObuHeaderFrame = 0b0'0110'000;
|
||||
|
||||
constexpr uint8_t kObuHeaderHasSize = 0b0'0000'010;
|
||||
|
||||
TEST(RtpDepacketizerAv1Test, ParsePassFullRtpPayloadAsCodecPayload) {
|
||||
TEST(VideoRtpDepacketizerAv1Test, 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);
|
||||
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(RtpDepacketizerAv1Test, ParseTreatsContinuationFlagAsNotBeginningOfFrame) {
|
||||
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.
|
||||
RtpDepacketizerAv1 depacketizer;
|
||||
RtpDepacketizer::ParsedPayload parsed;
|
||||
ASSERT_TRUE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
|
||||
EXPECT_FALSE(parsed.video.is_first_packet_in_frame);
|
||||
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(RtpDepacketizerAv1Test, ParseTreatsNoContinuationFlagAsBeginningOfFrame) {
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
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);
|
||||
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(RtpDepacketizerAv1Test, ParseTreatsWillContinueFlagAsNotEndOfFrame) {
|
||||
TEST(VideoRtpDepacketizerAv1Test, 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);
|
||||
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(RtpDepacketizerAv1Test, ParseTreatsNoWillContinueFlagAsEndOfFrame) {
|
||||
TEST(VideoRtpDepacketizerAv1Test, 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);
|
||||
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(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
ParseUsesNewCodedVideoSequenceBitAsKeyFrameIndidcator) {
|
||||
const uint8_t packet[] = {(uint8_t{1} << 3) | 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);
|
||||
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(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
ParseUsesUnsetNewCodedVideoSequenceBitAsDeltaFrameIndidcator) {
|
||||
const uint8_t packet[] = {(uint8_t{0} << 3) | 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::kVideoFrameDelta);
|
||||
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(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
ParseRejectsPacketWithNewCVSAndContinuationFlagsBothSet) {
|
||||
const uint8_t packet[] = {0b10'00'1000 | kObuCountOne,
|
||||
kObuHeaderSequenceHeader};
|
||||
RtpDepacketizerAv1 depacketizer;
|
||||
RtpDepacketizer::ParsedPayload parsed;
|
||||
EXPECT_FALSE(depacketizer.Parse(&parsed, packet, sizeof(packet)));
|
||||
VideoRtpDepacketizerAv1 depacketizer;
|
||||
ASSERT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(packet)));
|
||||
}
|
||||
|
||||
TEST(RtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenAbsent) {
|
||||
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 = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenPresent) {
|
||||
TEST(VideoRtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenPresent) {
|
||||
const uint8_t payload1[] = {0b00'01'0000, // aggregation header
|
||||
0b0'0110'010, // / Frame OBU header
|
||||
3, // obu_size
|
||||
@ -121,28 +133,28 @@ TEST(RtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenPresent) {
|
||||
30,
|
||||
40}; // \ obu_payload
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test,
|
||||
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 = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
AssembleFrameSetsOBUPayloadSizeAfterExtensionWhenPresent) {
|
||||
const uint8_t payload1[] = {0b00'01'0000, // aggregation header
|
||||
0b0'0110'110, // / Frame OBU header
|
||||
@ -152,25 +164,25 @@ TEST(RtpDepacketizerAv1Test,
|
||||
30,
|
||||
40}; // \ obu_payload
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithOneObu) {
|
||||
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 = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
auto frame = VideoRtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
ASSERT_TRUE(frame);
|
||||
EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
|
||||
ElementsAre(0b0'0110'010, 1, 20));
|
||||
}
|
||||
|
||||
TEST(RtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithTwoObus) {
|
||||
TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithTwoObus) {
|
||||
const uint8_t payload1[] = {0b00'10'0000, // aggregation header
|
||||
2, // / Sequence
|
||||
0b0'0001'000, // | Header
|
||||
@ -178,26 +190,26 @@ TEST(RtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithTwoObus) {
|
||||
0b0'0110'000, // / Frame
|
||||
20}; // \ OBU
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithOneObu) {
|
||||
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 = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithTwoObu) {
|
||||
TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithTwoObu) {
|
||||
const uint8_t payload1[] = {0b01'10'0000, // aggregation header
|
||||
2, // / Sequence
|
||||
0b0'0001'000, // | Header
|
||||
@ -208,14 +220,14 @@ TEST(RtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithTwoObu) {
|
||||
const uint8_t payload2[] = {0b10'01'0000, // aggregation header
|
||||
40}; //
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
AssembleFrameFromTwoPacketsWithManyObusSomeWithExtensions) {
|
||||
const uint8_t payload1[] = {0b01'00'0000, // aggregation header
|
||||
2, // /
|
||||
@ -239,7 +251,7 @@ TEST(RtpDepacketizerAv1Test,
|
||||
70, 80, 90}; // \ tail of the frame OBU
|
||||
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
auto frame = VideoRtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
ASSERT_TRUE(frame);
|
||||
EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
|
||||
ElementsAre( // Sequence header OBU
|
||||
@ -252,7 +264,7 @@ TEST(RtpDepacketizerAv1Test,
|
||||
0b0'0110'110, 0b001'10'000, 6, 40, 50, 60, 70, 80, 90));
|
||||
}
|
||||
|
||||
TEST(RtpDepacketizerAv1Test, AssembleFrameWithOneObuFromManyPackets) {
|
||||
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
|
||||
@ -264,13 +276,13 @@ TEST(RtpDepacketizerAv1Test, AssembleFrameWithOneObuFromManyPackets) {
|
||||
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2, payload3,
|
||||
payload4};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
AssembleFrameFromManyPacketsWithSomeObuBorderAligned) {
|
||||
const uint8_t payload1[] = {0b01'10'0000, // aggregation header
|
||||
3, // size of the 1st fragment
|
||||
@ -296,7 +308,7 @@ TEST(RtpDepacketizerAv1Test,
|
||||
33, 34, 35, 36};
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2, payload3,
|
||||
payload4};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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
|
||||
@ -305,7 +317,7 @@ TEST(RtpDepacketizerAv1Test,
|
||||
0b0'0100'010, 6, 31, 32, 33, 34, 35, 36));
|
||||
}
|
||||
|
||||
TEST(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
AssembleFrameFromOnePacketsOneObuPayloadSize127Bytes) {
|
||||
uint8_t payload1[4 + 127];
|
||||
memset(payload1, 0, sizeof(payload1));
|
||||
@ -315,7 +327,7 @@ TEST(RtpDepacketizerAv1Test,
|
||||
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 = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
auto frame = VideoRtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
ASSERT_TRUE(frame);
|
||||
EXPECT_EQ(frame->size(), 2 + 127u);
|
||||
rtc::ArrayView<const uint8_t> frame_view(*frame);
|
||||
@ -325,7 +337,7 @@ TEST(RtpDepacketizerAv1Test,
|
||||
EXPECT_EQ(frame_view[2 + 42], 0x42);
|
||||
}
|
||||
|
||||
TEST(RtpDepacketizerAv1Test,
|
||||
TEST(VideoRtpDepacketizerAv1Test,
|
||||
AssembleFrameFromTwoPacketsOneObuPayloadSize128Bytes) {
|
||||
uint8_t payload1[3 + 32];
|
||||
memset(payload1, 0, sizeof(payload1));
|
||||
@ -340,7 +352,7 @@ TEST(RtpDepacketizerAv1Test,
|
||||
payload2[2 + 20] = 0x20;
|
||||
|
||||
rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
|
||||
auto frame = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
auto frame = VideoRtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
ASSERT_TRUE(frame);
|
||||
EXPECT_EQ(frame->size(), 3 + 128u);
|
||||
rtc::ArrayView<const uint8_t> frame_view(*frame);
|
||||
@ -352,23 +364,25 @@ TEST(RtpDepacketizerAv1Test,
|
||||
EXPECT_EQ(frame_view[3 + 32 + 20], 0x20);
|
||||
}
|
||||
|
||||
TEST(RtpDepacketizerAv1Test, AssembleFrameFromAlmostEmptyPacketStartingAnOBU) {
|
||||
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 = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
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(RtpDepacketizerAv1Test, AssembleFrameFromAlmostEmptyPacketFinishingAnOBU) {
|
||||
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 = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
auto frame = VideoRtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
ASSERT_TRUE(frame);
|
||||
EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
|
||||
ElementsAre(0b0'0110'010, 3, 10, 20, 30));
|
||||
@ -24,10 +24,10 @@
|
||||
#include "api/video/encoded_frame.h"
|
||||
#include "api/video/video_frame_type.h"
|
||||
#include "common_video/h264/h264_common.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_depacketizer_av1.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_video_header.h"
|
||||
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
|
||||
#include "modules/video_coding/codecs/h264/include/h264_globals.h"
|
||||
#include "modules/video_coding/frame_object.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -441,7 +441,7 @@ std::unique_ptr<RtpFrameObject> PacketBuffer::AssembleFrame(
|
||||
rtc::scoped_refptr<EncodedImageBuffer> bitstream;
|
||||
// TODO(danilchap): Hide codec-specific code paths behind an interface.
|
||||
if (first_packet.codec() == VideoCodecType::kVideoCodecAV1) {
|
||||
bitstream = RtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
bitstream = VideoRtpDepacketizerAv1::AssembleFrame(payloads);
|
||||
if (!bitstream) {
|
||||
// Failed to assemble a frame. Discard and continue.
|
||||
return nullptr;
|
||||
|
||||
@ -562,15 +562,6 @@ webrtc_fuzzer_test("comfort_noise_decoder_fuzzer") {
|
||||
]
|
||||
}
|
||||
|
||||
webrtc_fuzzer_test("rtp_depacketizer_av1_parse_fuzzer") {
|
||||
sources = [
|
||||
"rtp_depacketizer_av1_parse_fuzzer.cc",
|
||||
]
|
||||
deps = [
|
||||
"../../modules/rtp_rtcp",
|
||||
]
|
||||
}
|
||||
|
||||
webrtc_fuzzer_test("rtp_depacketizer_av1_assemble_frame_fuzzer") {
|
||||
sources = [
|
||||
"rtp_depacketizer_av1_assemble_frame_fuzzer.cc",
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* 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 "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@ -34,6 +34,6 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
|
||||
rtp_payloads.push_back(fuzz_input.ReadByteArray(next_size));
|
||||
}
|
||||
// Run code under test.
|
||||
RtpDepacketizerAv1::AssembleFrame(rtp_payloads);
|
||||
VideoRtpDepacketizerAv1::AssembleFrame(rtp_payloads);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
namespace webrtc {
|
||||
void FuzzOneInput(const uint8_t* data, size_t size) {
|
||||
RtpDepacketizerAv1 depacketizer;
|
||||
RtpDepacketizer::ParsedPayload parsed_payload;
|
||||
depacketizer.Parse(&parsed_payload, data, size);
|
||||
}
|
||||
} // namespace webrtc
|
||||
Loading…
x
Reference in New Issue
Block a user