AV1 OBU test helper.

Bug: none
Change-Id: I942319122f823e18e500c049274527b00e6feba6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/223061
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34363}
This commit is contained in:
philipel 2021-06-23 13:52:06 +02:00 committed by WebRTC LUCI CQ
parent 28e582d55a
commit 4e513346ec
4 changed files with 188 additions and 124 deletions

View File

@ -439,6 +439,14 @@ rtc_library("mock_rtp_rtcp") {
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("rtp_packetizer_av1_test_helper") {
testonly = true
sources = [
"source/rtp_packetizer_av1_test_helper.cc",
"source/rtp_packetizer_av1_test_helper.h",
]
}
if (rtc_include_tests) {
if (!build_with_chromium) {
rtc_executable("test_packet_masks_metrics") {
@ -558,6 +566,7 @@ if (rtc_include_tests) {
":fec_test_helper",
":mock_rtp_rtcp",
":rtcp_transceiver",
":rtp_packetizer_av1_test_helper",
":rtp_rtcp",
":rtp_rtcp_format",
":rtp_rtcp_legacy",

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021 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_packetizer_av1_test_helper.h"
#include <stdint.h>
#include <initializer_list>
#include <vector>
namespace webrtc {
Av1Obu::Av1Obu(uint8_t obu_type) : header_(obu_type | kAv1ObuSizePresentBit) {}
Av1Obu& Av1Obu::WithExtension(uint8_t extension) {
extension_ = extension;
header_ |= kAv1ObuExtensionPresentBit;
return *this;
}
Av1Obu& Av1Obu::WithoutSize() {
header_ &= ~kAv1ObuSizePresentBit;
return *this;
}
Av1Obu& Av1Obu::WithPayload(std::vector<uint8_t> payload) {
payload_ = std::move(payload);
return *this;
}
std::vector<uint8_t> BuildAv1Frame(std::initializer_list<Av1Obu> obus) {
std::vector<uint8_t> raw;
for (const Av1Obu& obu : obus) {
raw.push_back(obu.header_);
if (obu.header_ & kAv1ObuExtensionPresentBit) {
raw.push_back(obu.extension_);
}
if (obu.header_ & kAv1ObuSizePresentBit) {
// write size in leb128 format.
size_t payload_size = obu.payload_.size();
while (payload_size >= 0x80) {
raw.push_back(0x80 | (payload_size & 0x7F));
payload_size >>= 7;
}
raw.push_back(payload_size);
}
raw.insert(raw.end(), obu.payload_.begin(), obu.payload_.end());
}
return raw;
}
} // namespace webrtc

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_PACKETIZER_AV1_TEST_HELPER_H_
#define MODULES_RTP_RTCP_SOURCE_RTP_PACKETIZER_AV1_TEST_HELPER_H_
#include <stdint.h>
#include <initializer_list>
#include <utility>
#include <vector>
namespace webrtc {
// All obu types offset by 3 to take correct position in the obu_header.
constexpr uint8_t kAv1ObuTypeSequenceHeader = 1 << 3;
constexpr uint8_t kAv1ObuTypeTemporalDelimiter = 2 << 3;
constexpr uint8_t kAv1ObuTypeFrameHeader = 3 << 3;
constexpr uint8_t kAv1ObuTypeTileGroup = 4 << 3;
constexpr uint8_t kAv1ObuTypeMetadata = 5 << 3;
constexpr uint8_t kAv1ObuTypeFrame = 6 << 3;
constexpr uint8_t kAv1ObuTypeTileList = 8 << 3;
constexpr uint8_t kAv1ObuExtensionPresentBit = 0b0'0000'100;
constexpr uint8_t kAv1ObuSizePresentBit = 0b0'0000'010;
constexpr uint8_t kAv1ObuExtensionS1T1 = 0b001'01'000;
class Av1Obu {
public:
explicit Av1Obu(uint8_t obu_type);
Av1Obu& WithExtension(uint8_t extension);
Av1Obu& WithoutSize();
Av1Obu& WithPayload(std::vector<uint8_t> payload);
private:
friend std::vector<uint8_t> BuildAv1Frame(std::initializer_list<Av1Obu> obus);
uint8_t header_;
uint8_t extension_ = 0;
std::vector<uint8_t> payload_;
};
std::vector<uint8_t> BuildAv1Frame(std::initializer_list<Av1Obu> obus);
} // namespace webrtc
#endif // MODULES_RTP_RTCP_SOURCE_RTP_PACKETIZER_AV1_TEST_HELPER_H_

View File

@ -21,6 +21,7 @@
#include "api/scoped_refptr.h"
#include "api/video/encoded_image.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "modules/rtp_rtcp/source/rtp_packetizer_av1_test_helper.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
#include "test/gmock.h"
#include "test/gtest.h"
@ -35,17 +36,6 @@ using ::testing::Le;
using ::testing::SizeIs;
constexpr uint8_t kNewCodedVideoSequenceBit = 0b00'00'1000;
// All obu types offset by 3 to take correct position in the obu_header.
constexpr uint8_t kObuTypeSequenceHeader = 1 << 3;
constexpr uint8_t kObuTypeTemporalDelimiter = 2 << 3;
constexpr uint8_t kObuTypeFrameHeader = 3 << 3;
constexpr uint8_t kObuTypeTileGroup = 4 << 3;
constexpr uint8_t kObuTypeMetadata = 5 << 3;
constexpr uint8_t kObuTypeFrame = 6 << 3;
constexpr uint8_t kObuTypeTileList = 8 << 3;
constexpr uint8_t kObuExtensionPresentBit = 0b0'0000'100;
constexpr uint8_t kObuSizePresentBit = 0b0'0000'010;
constexpr uint8_t kObuExtensionS1T1 = 0b001'01'000;
// Wrapper around rtp_packet to make it look like container of payload bytes.
struct RtpPayload {
@ -109,135 +99,90 @@ Av1Frame ReassembleFrame(rtc::ArrayView<const RtpPayload> rtp_payloads) {
return Av1Frame(VideoRtpDepacketizerAv1().AssembleFrame(payloads));
}
class Obu {
public:
explicit Obu(uint8_t obu_type) : header_(obu_type | kObuSizePresentBit) {
EXPECT_EQ(obu_type & 0b0'1111'000, obu_type);
}
Obu& WithExtension(uint8_t extension) {
extension_ = extension;
header_ |= kObuExtensionPresentBit;
return *this;
}
Obu& WithoutSize() {
header_ &= ~kObuSizePresentBit;
return *this;
}
Obu& WithPayload(std::vector<uint8_t> payload) {
payload_ = std::move(payload);
return *this;
}
private:
friend std::vector<uint8_t> BuildAv1Frame(std::initializer_list<Obu> obus);
uint8_t header_;
uint8_t extension_ = 0;
std::vector<uint8_t> payload_;
};
std::vector<uint8_t> BuildAv1Frame(std::initializer_list<Obu> obus) {
std::vector<uint8_t> raw;
for (const Obu& obu : obus) {
raw.push_back(obu.header_);
if (obu.header_ & kObuExtensionPresentBit) {
raw.push_back(obu.extension_);
}
if (obu.header_ & kObuSizePresentBit) {
// write size in leb128 format.
size_t payload_size = obu.payload_.size();
while (payload_size >= 0x80) {
raw.push_back(0x80 | (payload_size & 0x7F));
payload_size >>= 7;
}
raw.push_back(payload_size);
}
raw.insert(raw.end(), obu.payload_.begin(), obu.payload_.end());
}
return raw;
}
TEST(RtpPacketizerAv1Test, PacketizeOneObuWithoutSizeAndExtension) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeFrame).WithoutSize().WithPayload({1, 2, 3, 4, 5, 6, 7})});
auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
.WithoutSize()
.WithPayload({1, 2, 3, 4, 5, 6, 7})});
EXPECT_THAT(Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'01'0000, // aggregation header
kObuTypeFrame, 1, 2, 3, 4, 5, 6, 7)));
kAv1ObuTypeFrame, 1, 2, 3, 4, 5, 6, 7)));
}
TEST(RtpPacketizerAv1Test, PacketizeOneObuWithoutSizeWithExtension) {
auto kFrame = BuildAv1Frame({Obu(kObuTypeFrame)
auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
.WithoutSize()
.WithExtension(kObuExtensionS1T1)
.WithExtension(kAv1ObuExtensionS1T1)
.WithPayload({2, 3, 4, 5, 6, 7})});
EXPECT_THAT(Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'01'0000, // aggregation header
kObuTypeFrame | kObuExtensionPresentBit,
kObuExtensionS1T1, 2, 3, 4, 5, 6, 7)));
EXPECT_THAT(
Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'01'0000, // aggregation header
kAv1ObuTypeFrame | kAv1ObuExtensionPresentBit,
kAv1ObuExtensionS1T1, 2, 3, 4, 5, 6, 7)));
}
TEST(RtpPacketizerAv1Test, RemovesObuSizeFieldWithoutExtension) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeFrame).WithPayload({11, 12, 13, 14, 15, 16, 17})});
{Av1Obu(kAv1ObuTypeFrame).WithPayload({11, 12, 13, 14, 15, 16, 17})});
EXPECT_THAT(
Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'01'0000, // aggregation header
kObuTypeFrame, 11, 12, 13, 14, 15, 16, 17)));
kAv1ObuTypeFrame, 11, 12, 13, 14, 15, 16, 17)));
}
TEST(RtpPacketizerAv1Test, RemovesObuSizeFieldWithExtension) {
auto kFrame = BuildAv1Frame({Obu(kObuTypeFrame)
.WithExtension(kObuExtensionS1T1)
auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
.WithExtension(kAv1ObuExtensionS1T1)
.WithPayload({1, 2, 3, 4, 5, 6, 7})});
EXPECT_THAT(Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'01'0000, // aggregation header
kObuTypeFrame | kObuExtensionPresentBit,
kObuExtensionS1T1, 1, 2, 3, 4, 5, 6, 7)));
EXPECT_THAT(
Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'01'0000, // aggregation header
kAv1ObuTypeFrame | kAv1ObuExtensionPresentBit,
kAv1ObuExtensionS1T1, 1, 2, 3, 4, 5, 6, 7)));
}
TEST(RtpPacketizerAv1Test, OmitsSizeForLastObuWhenThreeObusFitsIntoThePacket) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
Obu(kObuTypeMetadata).WithPayload({11, 12, 13, 14}),
Obu(kObuTypeFrame).WithPayload({21, 22, 23, 24, 25, 26})});
EXPECT_THAT(
Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'11'0000, // aggregation header
7, kObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6, //
5, kObuTypeMetadata, 11, 12, 13, 14, //
kObuTypeFrame, 21, 22, 23, 24, 25, 26)));
{Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
Av1Obu(kAv1ObuTypeMetadata).WithPayload({11, 12, 13, 14}),
Av1Obu(kAv1ObuTypeFrame).WithPayload({21, 22, 23, 24, 25, 26})});
EXPECT_THAT(Packetize(kFrame, {}),
ElementsAre(ElementsAre(
0b00'11'0000, // aggregation header
7, kAv1ObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6, //
5, kAv1ObuTypeMetadata, 11, 12, 13, 14, //
kAv1ObuTypeFrame, 21, 22, 23, 24, 25, 26)));
}
TEST(RtpPacketizerAv1Test, UseSizeForAllObusWhenFourObusFitsIntoThePacket) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
Obu(kObuTypeMetadata).WithPayload({11, 12, 13, 14}),
Obu(kObuTypeFrameHeader).WithPayload({21, 22, 23}),
Obu(kObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});
EXPECT_THAT(
Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'00'0000, // aggregation header
7, kObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6, //
5, kObuTypeMetadata, 11, 12, 13, 14, //
4, kObuTypeFrameHeader, 21, 22, 23, //
7, kObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
{Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6}),
Av1Obu(kAv1ObuTypeMetadata).WithPayload({11, 12, 13, 14}),
Av1Obu(kAv1ObuTypeFrameHeader).WithPayload({21, 22, 23}),
Av1Obu(kAv1ObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});
EXPECT_THAT(Packetize(kFrame, {}),
ElementsAre(ElementsAre(
0b00'00'0000, // aggregation header
7, kAv1ObuTypeSequenceHeader, 1, 2, 3, 4, 5, 6, //
5, kAv1ObuTypeMetadata, 11, 12, 13, 14, //
4, kAv1ObuTypeFrameHeader, 21, 22, 23, //
7, kAv1ObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
}
TEST(RtpPacketizerAv1Test, DiscardsTemporalDelimiterAndTileListObu) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeTemporalDelimiter), Obu(kObuTypeMetadata),
Obu(kObuTypeTileList).WithPayload({1, 2, 3, 4, 5, 6}),
Obu(kObuTypeFrameHeader).WithPayload({21, 22, 23}),
Obu(kObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});
{Av1Obu(kAv1ObuTypeTemporalDelimiter), Av1Obu(kAv1ObuTypeMetadata),
Av1Obu(kAv1ObuTypeTileList).WithPayload({1, 2, 3, 4, 5, 6}),
Av1Obu(kAv1ObuTypeFrameHeader).WithPayload({21, 22, 23}),
Av1Obu(kAv1ObuTypeTileGroup).WithPayload({31, 32, 33, 34, 35, 36})});
EXPECT_THAT(
Packetize(kFrame, {}),
ElementsAre(ElementsAre(0b00'11'0000, // aggregation header
1,
kObuTypeMetadata, //
4, kObuTypeFrameHeader, 21, 22,
kAv1ObuTypeMetadata, //
4, kAv1ObuTypeFrameHeader, 21, 22,
23, //
kObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
kAv1ObuTypeTileGroup, 31, 32, 33, 34, 35, 36)));
}
TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPacketForceSplitObuHeader) {
@ -246,17 +191,17 @@ TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPacketForceSplitObuHeader) {
const uint8_t kExpectPayload1[6] = {
0b01'10'0000, // aggregation_header
3,
kObuTypeFrameHeader | kObuExtensionPresentBit,
kObuExtensionS1T1,
kAv1ObuTypeFrameHeader | kAv1ObuExtensionPresentBit,
kAv1ObuExtensionS1T1,
21, //
kObuTypeTileGroup | kObuExtensionPresentBit};
kAv1ObuTypeTileGroup | kAv1ObuExtensionPresentBit};
const uint8_t kExpectPayload2[6] = {0b10'01'0000, // aggregation_header
kObuExtensionS1T1, 11, 12, 13, 14};
auto kFrame = BuildAv1Frame({Obu(kObuTypeFrameHeader)
.WithExtension(kObuExtensionS1T1)
kAv1ObuExtensionS1T1, 11, 12, 13, 14};
auto kFrame = BuildAv1Frame({Av1Obu(kAv1ObuTypeFrameHeader)
.WithExtension(kAv1ObuExtensionS1T1)
.WithPayload({21}),
Obu(kObuTypeTileGroup)
.WithExtension(kObuExtensionS1T1)
Av1Obu(kAv1ObuTypeTileGroup)
.WithExtension(kAv1ObuExtensionS1T1)
.WithPayload({11, 12, 13, 14})});
RtpPacketizer::PayloadSizeLimits limits;
@ -269,7 +214,7 @@ TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPacketForceSplitObuHeader) {
TEST(RtpPacketizerAv1Test,
SetsNbitAtTheFirstPacketOfAKeyFrameWithSequenceHeader) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
{Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 6;
auto packets = Packetize(kFrame, limits, VideoFrameType::kVideoFrameKey);
@ -280,8 +225,8 @@ TEST(RtpPacketizerAv1Test,
TEST(RtpPacketizerAv1Test,
DoesntSetNbitAtThePacketsOfAKeyFrameWithoutSequenceHeader) {
auto kFrame =
BuildAv1Frame({Obu(kObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7})});
auto kFrame = BuildAv1Frame(
{Av1Obu(kAv1ObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7})});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 6;
auto packets = Packetize(kFrame, limits, VideoFrameType::kVideoFrameKey);
@ -293,7 +238,7 @@ TEST(RtpPacketizerAv1Test,
TEST(RtpPacketizerAv1Test, DoesntSetNbitAtThePacketsOfADeltaFrame) {
// Even when that delta frame starts with a (redundant) sequence header.
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
{Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3, 4, 5, 6, 7})});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 6;
auto packets = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta);
@ -308,8 +253,9 @@ TEST(RtpPacketizerAv1Test, DoesntSetNbitAtThePacketsOfADeltaFrame) {
// RtpDepacketizer always inserts obu_size fields in the output, use frame where
// each obu has obu_size fields for more streight forward validation.
TEST(RtpPacketizerAv1Test, SplitSingleObuIntoTwoPackets) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeFrame).WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});
auto kFrame =
BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
.WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 8;
@ -322,7 +268,7 @@ TEST(RtpPacketizerAv1Test, SplitSingleObuIntoTwoPackets) {
TEST(RtpPacketizerAv1Test, SplitSingleObuIntoManyPackets) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeFrame).WithPayload(std::vector<uint8_t>(1200, 27))});
{Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(1200, 27))});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 100;
@ -336,7 +282,7 @@ TEST(RtpPacketizerAv1Test, SplitSingleObuIntoManyPackets) {
TEST(RtpPacketizerAv1Test, SetMarkerBitForLastPacketInEndOfPictureFrame) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
{Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 100;
@ -350,7 +296,7 @@ TEST(RtpPacketizerAv1Test, SetMarkerBitForLastPacketInEndOfPictureFrame) {
TEST(RtpPacketizerAv1Test, DoesntSetMarkerBitForPacketsNotInEndOfPictureFrame) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
{Av1Obu(kAv1ObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 100;
@ -366,8 +312,8 @@ TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPackets) {
// 2nd OBU is too large to fit into one packet, so its head would be in the
// same packet as the 1st OBU.
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeSequenceHeader).WithPayload({11, 12}),
Obu(kObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7, 8, 9})});
{Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({11, 12}),
Av1Obu(kAv1ObuTypeFrame).WithPayload({1, 2, 3, 4, 5, 6, 7, 8, 9})});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 8;
@ -380,8 +326,9 @@ TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPackets) {
TEST(RtpPacketizerAv1Test,
SplitSingleObuIntoTwoPacketsBecauseOfSinglePacketLimit) {
auto kFrame = BuildAv1Frame(
{Obu(kObuTypeFrame).WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});
auto kFrame =
BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame)
.WithPayload({11, 12, 13, 14, 15, 16, 17, 18, 19})});
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 10;
limits.single_packet_reduction_len = 8;