Use DD encoder/decoder in RTC event log encoder/parser.

Bug: webrtc:14801
Change-Id: I7013c42765e81d147bf8284f8c29666e67fdb91f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/296765
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39929}
This commit is contained in:
philipel 2023-04-21 16:40:04 +02:00 committed by WebRTC LUCI CQ
parent 94e5817759
commit d1e5dedffe
11 changed files with 191 additions and 25 deletions

View file

@ -625,6 +625,8 @@ if (rtc_enable_protobuf) {
"../rtc_base:rtc_base_tests_utils",
"../rtc_base:timeutils",
"../system_wrappers",
"../system_wrappers:field_trial",
"../test:field_trial",
"../test:fileutils",
"../test:test_support",
"../test/logging:log_writer",

View file

@ -13,6 +13,7 @@
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/network_state_predictor.h"
#include "logging/rtc_event_log/dependency_descriptor_encoder_decoder.h"
#include "logging/rtc_event_log/encoder/blob_encoding.h"
#include "logging/rtc_event_log/encoder/delta_encoding.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
@ -56,6 +57,7 @@
#include "modules/rtp_rtcp/source/rtcp_packet/rtpfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet.h"
#include "rtc_base/checks.h"
@ -147,6 +149,8 @@ bool ConvertToProtoFormat(const std::vector<RtpExtension>& extensions,
proto_config->set_transport_sequence_number_id(extension.id);
} else if (extension.uri == RtpExtension::kVideoRotationUri) {
proto_config->set_video_rotation_id(extension.id);
} else if (extension.uri == RtpExtension::kDependencyDescriptorUri) {
proto_config->set_dependency_descriptor_id(extension.id);
} else {
++unknown_extensions;
}
@ -457,6 +461,29 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
}
}
{
// TODO(webrtc:14975) Remove this kill switch after DD in RTC event log has
// been rolled out.
if (!webrtc::field_trial::IsDisabled(
"WebRTC-RtcEventLogEncodeDependencyDescriptor")) {
std::vector<rtc::ArrayView<const uint8_t>> raw_dds(batch.size());
bool has_dd = false;
for (size_t i = 0; i < batch.size(); ++i) {
raw_dds[i] =
batch[i]
->template GetRawExtension<RtpDependencyDescriptorExtension>();
has_dd |= !raw_dds[i].empty();
}
if (has_dd) {
if (auto dd_encoded =
RtcEventLogDependencyDescriptorEncoderDecoder::Encode(
raw_dds)) {
*proto_batch->mutable_dependency_descriptor() = *dd_encoded;
}
}
}
}
if (batch.size() == 1) {
return;
}

View file

@ -40,6 +40,7 @@
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "rtc_base/fake_clock.h"
#include "rtc_base/random.h"
#include "test/field_trial.h"
#include "test/gtest.h"
namespace webrtc {
@ -1291,6 +1292,20 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketOutgoing) {
TestRtpPackets<RtcEventRtpPacketOutgoing, LoggedRtpPacketOutgoing>();
}
TEST_P(RtcEventLogEncoderTest,
RtcEventRtpPacketIncomingNoDependencyDescriptor) {
test::ScopedFieldTrials no_dd(
"WebRTC-RtcEventLogEncodeDependencyDescriptor/Disabled/");
TestRtpPackets<RtcEventRtpPacketIncoming, LoggedRtpPacketIncoming>();
}
TEST_P(RtcEventLogEncoderTest,
RtcEventRtpPacketOutgoingNoDependencyDescriptor) {
test::ScopedFieldTrials no_dd(
"WebRTC-RtcEventLogEncodeDependencyDescriptor/Disabled/");
TestRtpPackets<RtcEventRtpPacketOutgoing, LoggedRtpPacketOutgoing>();
}
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
uint32_t ssrc = prng_.Rand<uint32_t>();

View file

@ -47,6 +47,8 @@ struct LoggedRtpPacket {
Timestamp timestamp;
// TODO(terelius): This allocates space for 15 CSRCs even if none are used.
RTPHeader header;
// RTPHeader::extension is a mess, save DD wire format instead.
std::vector<uint8_t> dependency_descriptor_wire_format;
size_t header_length;
size_t total_length;
};

View file

@ -57,6 +57,10 @@ class RtcEventRtpPacketIncoming final : public RtcEvent {
return packet_.GetExtension<ExtensionTrait>(std::forward<Args>(args)...);
}
template <typename ExtensionTrait>
rtc::ArrayView<const uint8_t> GetRawExtension() const {
return packet_.GetRawExtension<ExtensionTrait>();
}
template <typename ExtensionTrait>
bool HasExtension() const {
return packet_.HasExtension<ExtensionTrait>();
}

View file

@ -58,6 +58,10 @@ class RtcEventRtpPacketOutgoing final : public RtcEvent {
return packet_.GetExtension<ExtensionTrait>(std::forward<Args>(args)...);
}
template <typename ExtensionTrait>
rtc::ArrayView<const uint8_t> GetRawExtension() const {
return packet_.GetRawExtension<ExtensionTrait>();
}
template <typename ExtensionTrait>
bool HasExtension() const {
return packet_.HasExtension<ExtensionTrait>();
}

View file

@ -453,6 +453,7 @@ message RtpHeaderExtensionConfig {
optional int32 transport_sequence_number_id = 3;
optional int32 video_rotation_id = 4;
optional int32 audio_level_id = 5;
optional int32 dependency_descriptor_id = 6;
// TODO(terelius): Add other header extensions like playout delay?
}

View file

@ -25,6 +25,7 @@
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
#include "logging/rtc_event_log/dependency_descriptor_encoder_decoder.h"
#include "logging/rtc_event_log/encoder/blob_encoding.h"
#include "logging/rtc_event_log/encoder/delta_encoding.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
@ -35,6 +36,7 @@
#include "modules/rtp_rtcp/include/rtp_cvo.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/checks.h"
@ -297,6 +299,22 @@ ParsedRtcEventLog::ParseStatus StoreRtpPackets(
RTC_PARSE_CHECK_OR_RETURN(proto.has_header_size());
RTC_PARSE_CHECK_OR_RETURN(proto.has_padding_size());
const size_t number_of_deltas =
proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
const size_t total_packets = number_of_deltas + 1;
std::vector<std::vector<uint8_t>> dependency_descriptor_wire_format(
total_packets);
if (proto.has_dependency_descriptor()) {
auto status_or_decoded =
RtcEventLogDependencyDescriptorEncoderDecoder::Decode(
proto.dependency_descriptor(), total_packets);
if (!status_or_decoded.ok()) {
return status_or_decoded.status();
}
dependency_descriptor_wire_format = status_or_decoded.value();
}
// Base event
{
RTPHeader header;
@ -342,13 +360,16 @@ ParsedRtcEventLog::ParseStatus StoreRtpPackets(
} else {
RTC_PARSE_CHECK_OR_RETURN(!proto.has_voice_activity());
}
(*rtp_packets_map)[header.ssrc].emplace_back(
LoggedType logged_packet(
Timestamp::Millis(proto.timestamp_ms()), header, proto.header_size(),
proto.payload_size() + header.headerLength + header.paddingLength);
if (!dependency_descriptor_wire_format[0].empty()) {
logged_packet.rtp.dependency_descriptor_wire_format =
dependency_descriptor_wire_format[0];
}
(*rtp_packets_map)[header.ssrc].push_back(std::move(logged_packet));
}
const size_t number_of_deltas =
proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
if (number_of_deltas == 0) {
return ParsedRtcEventLog::ParseStatus::Success();
}
@ -544,10 +565,15 @@ ParsedRtcEventLog::ParseStatus StoreRtpPackets(
RTC_PARSE_CHECK_OR_RETURN(voice_activity_values.size() <= i ||
!voice_activity_values[i].has_value());
}
(*rtp_packets_map)[header.ssrc].emplace_back(
Timestamp::Millis(timestamp_ms), header, header.headerLength,
payload_size_values[i].value() + header.headerLength +
header.paddingLength);
LoggedType logged_packet(Timestamp::Millis(timestamp_ms), header,
header.headerLength,
payload_size_values[i].value() +
header.headerLength + header.paddingLength);
if (!dependency_descriptor_wire_format[i + 1].empty()) {
logged_packet.rtp.dependency_descriptor_wire_format =
dependency_descriptor_wire_format[i + 1];
}
(*rtp_packets_map)[header.ssrc].push_back(std::move(logged_packet));
}
return ParsedRtcEventLog::ParseStatus::Success();
}
@ -888,6 +914,11 @@ std::vector<RtpExtension> GetRuntimeRtpHeaderExtensionConfig(
rtp_extensions.emplace_back(RtpExtension::kVideoRotationUri,
proto_header_extensions.video_rotation_id());
}
if (proto_header_extensions.has_dependency_descriptor_id()) {
rtp_extensions.emplace_back(
RtpExtension::kDependencyDescriptorUri,
proto_header_extensions.dependency_descriptor_id());
}
return rtp_extensions;
}
// End of conversion functions.
@ -972,8 +1003,9 @@ ParsedRtcEventLog::GetDefaultHeaderExtensionMap() {
constexpr int kPlayoutDelayDefaultId = 6;
constexpr int kVideoContentTypeDefaultId = 7;
constexpr int kVideoTimingDefaultId = 8;
constexpr int kDependencyDescriptorDefaultId = 9;
webrtc::RtpHeaderExtensionMap default_map;
webrtc::RtpHeaderExtensionMap default_map(/*extmap_allow_mixed=*/true);
default_map.Register<AudioLevel>(kAudioLevelDefaultId);
default_map.Register<TransmissionOffset>(kTimestampOffsetDefaultId);
default_map.Register<AbsoluteSendTime>(kAbsSendTimeDefaultId);
@ -983,6 +1015,8 @@ ParsedRtcEventLog::GetDefaultHeaderExtensionMap() {
default_map.Register<PlayoutDelayLimits>(kPlayoutDelayDefaultId);
default_map.Register<VideoContentTypeExtension>(kVideoContentTypeDefaultId);
default_map.Register<VideoTimingExtension>(kVideoTimingDefaultId);
default_map.Register<RtpDependencyDescriptorExtension>(
kDependencyDescriptorDefaultId);
return default_map;
}

View file

@ -45,6 +45,7 @@
#include "logging/rtc_event_log/rtc_event_log_unittest_helper.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "rtc_base/checks.h"
#include "rtc_base/fake_clock.h"
@ -228,7 +229,9 @@ void RtcEventLogSession::WriteAudioRecvConfigs(size_t audio_recv_streams,
do {
ssrc = prng_.Rand<uint32_t>();
} while (SsrcUsed(ssrc, incoming_extensions_));
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap(
/*configure_all=*/false,
/*excluded_extensions=*/{RtpDependencyDescriptorExtension::kId});
incoming_extensions_.emplace_back(ssrc, extensions);
auto event = gen_.NewAudioReceiveStreamConfig(ssrc, extensions);
event_log->Log(event->Copy());
@ -245,7 +248,9 @@ void RtcEventLogSession::WriteAudioSendConfigs(size_t audio_send_streams,
do {
ssrc = prng_.Rand<uint32_t>();
} while (SsrcUsed(ssrc, outgoing_extensions_));
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap(
/*configure_all=*/false,
/*excluded_extensions=*/{RtpDependencyDescriptorExtension::kId});
outgoing_extensions_.emplace_back(ssrc, extensions);
auto event = gen_.NewAudioSendStreamConfig(ssrc, extensions);
event_log->Log(event->Copy());
@ -263,6 +268,10 @@ void RtcEventLogSession::WriteVideoRecvConfigs(size_t video_recv_streams,
RtpHeaderExtensionMap all_extensions =
ParsedRtcEventLog::GetDefaultHeaderExtensionMap();
if (std::get<2>(GetParam()) == RtcEventLog::EncodingType::Legacy) {
all_extensions.Deregister(RtpDependencyDescriptorExtension::Uri());
}
clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
uint32_t ssrc = prng_.Rand<uint32_t>();
incoming_extensions_.emplace_back(ssrc, all_extensions);
@ -274,7 +283,12 @@ void RtcEventLogSession::WriteVideoRecvConfigs(size_t video_recv_streams,
do {
ssrc = prng_.Rand<uint32_t>();
} while (SsrcUsed(ssrc, incoming_extensions_));
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::vector<RTPExtensionType> excluded_extensions;
if (std::get<2>(GetParam()) == RtcEventLog::EncodingType::Legacy) {
excluded_extensions.push_back(RtpDependencyDescriptorExtension::kId);
}
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap(
/*configure_all=*/false, excluded_extensions);
incoming_extensions_.emplace_back(ssrc, extensions);
auto new_event = gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
event_log->Log(new_event->Copy());
@ -292,6 +306,10 @@ void RtcEventLogSession::WriteVideoSendConfigs(size_t video_send_streams,
RtpHeaderExtensionMap all_extensions =
ParsedRtcEventLog::GetDefaultHeaderExtensionMap();
if (std::get<2>(GetParam()) == RtcEventLog::EncodingType::Legacy) {
all_extensions.Deregister(RtpDependencyDescriptorExtension::Uri());
}
clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
uint32_t ssrc = prng_.Rand<uint32_t>();
outgoing_extensions_.emplace_back(ssrc, all_extensions);
@ -303,7 +321,12 @@ void RtcEventLogSession::WriteVideoSendConfigs(size_t video_send_streams,
do {
ssrc = prng_.Rand<uint32_t>();
} while (SsrcUsed(ssrc, outgoing_extensions_));
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::vector<RTPExtensionType> excluded_extensions;
if (std::get<2>(GetParam()) == RtcEventLog::EncodingType::Legacy) {
excluded_extensions.push_back(RtpDependencyDescriptorExtension::kId);
}
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap(
/*configure_all=*/false, excluded_extensions);
outgoing_extensions_.emplace_back(ssrc, extensions);
auto event = gen_.NewVideoSendStreamConfig(ssrc, extensions);
event_log->Log(event->Copy());

View file

@ -35,12 +35,14 @@
#include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
#include "modules/rtp_rtcp/source/rtcp_packet/rrtr.h"
#include "modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h"
#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.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_packet_to_send.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/time_utils.h"
#include "system_wrappers/include/field_trial.h"
#include "system_wrappers/include/ntp_time.h"
#include "test/gtest.h"
@ -58,8 +60,8 @@ struct ExtensionPair {
constexpr int kMaxCsrcs = 3;
// Maximum serialized size of a header extension, including 1 byte ID.
constexpr int kMaxExtensionSizeBytes = 4;
constexpr int kMaxNumExtensions = 5;
constexpr int kMaxExtensionSizeBytes = 10;
constexpr int kMaxNumExtensions = 6;
constexpr ExtensionPair kExtensions[kMaxNumExtensions] = {
{RTPExtensionType::kRtpExtensionTransmissionTimeOffset,
@ -70,7 +72,9 @@ constexpr ExtensionPair kExtensions[kMaxNumExtensions] = {
RtpExtension::kTransportSequenceNumberUri},
{RTPExtensionType::kRtpExtensionAudioLevel, RtpExtension::kAudioLevelUri},
{RTPExtensionType::kRtpExtensionVideoRotation,
RtpExtension::kVideoRotationUri}};
RtpExtension::kVideoRotationUri},
{RTPExtensionType::kRtpExtensionDependencyDescriptor,
RtpExtension::kDependencyDescriptorUri}};
template <typename T>
void ShuffleInPlace(Random* prng, rtc::ArrayView<T> array) {
@ -614,6 +618,15 @@ void EventGenerator::RandomizeRtpPacket(
rtp_packet->SetExtension<TransportSequenceNumber>(prng_.Rand<uint16_t>());
}
if (extension_map.IsRegistered(RtpDependencyDescriptorExtension::kId) &&
(all_configured_exts || prng_.Rand<bool>())) {
std::vector<uint8_t> raw_data(3 + prng_.Rand(6));
for (uint8_t& d : raw_data) {
d = prng_.Rand<uint8_t>();
}
rtp_packet->SetRawExtension<RtpDependencyDescriptorExtension>(raw_data);
}
RTC_CHECK_LE(rtp_packet->headers_size() + payload_size, IP_PACKET_SIZE);
uint8_t* payload = rtp_packet->AllocatePayload(payload_size);
@ -675,8 +688,7 @@ std::unique_ptr<RtcEventRtpPacketOutgoing> EventGenerator::NewRtpPacketOutgoing(
1 - padding_size -
kMaxHeaderSize));
RtpPacketToSend rtp_packet(&extension_map,
kMaxHeaderSize + payload_size + padding_size);
RtpPacketToSend rtp_packet(&extension_map);
RandomizeRtpPacket(payload_size, padding_size, ssrc, extension_map,
&rtp_packet, all_configured_exts);
@ -686,28 +698,41 @@ std::unique_ptr<RtcEventRtpPacketOutgoing> EventGenerator::NewRtpPacketOutgoing(
}
RtpHeaderExtensionMap EventGenerator::NewRtpHeaderExtensionMap(
bool configure_all) {
bool configure_all,
const std::vector<RTPExtensionType>& excluded_extensions) {
RtpHeaderExtensionMap extension_map;
std::vector<int> id(RtpExtension::kOneByteHeaderExtensionMaxId -
RtpExtension::kMinId + 1);
std::iota(id.begin(), id.end(), RtpExtension::kMinId);
ShuffleInPlace(&prng_, rtc::ArrayView<int>(id));
if (configure_all || prng_.Rand<bool>()) {
auto not_excluded = [&](RTPExtensionType type) -> bool {
return !absl::c_linear_search(excluded_extensions, type);
};
if (not_excluded(AudioLevel::kId) && (configure_all || prng_.Rand<bool>())) {
extension_map.Register<AudioLevel>(id[0]);
}
if (configure_all || prng_.Rand<bool>()) {
if (not_excluded(TransmissionOffset::kId) &&
(configure_all || prng_.Rand<bool>())) {
extension_map.Register<TransmissionOffset>(id[1]);
}
if (configure_all || prng_.Rand<bool>()) {
if (not_excluded(AbsoluteSendTime::kId) &&
(configure_all || prng_.Rand<bool>())) {
extension_map.Register<AbsoluteSendTime>(id[2]);
}
if (configure_all || prng_.Rand<bool>()) {
if (not_excluded(VideoOrientation::kId) &&
(configure_all || prng_.Rand<bool>())) {
extension_map.Register<VideoOrientation>(id[3]);
}
if (configure_all || prng_.Rand<bool>()) {
if (not_excluded(TransportSequenceNumber::kId) &&
(configure_all || prng_.Rand<bool>())) {
extension_map.Register<TransportSequenceNumber>(id[4]);
}
if (not_excluded(RtpDependencyDescriptorExtension::kId) &&
(configure_all || prng_.Rand<bool>())) {
extension_map.Register<RtpDependencyDescriptorExtension>(id[5]);
}
return extension_map;
}
@ -1006,6 +1031,27 @@ void VerifyLoggedRtpHeader(const Event& original_header,
}
}
template <typename Event>
void VerifyLoggedDependencyDescriptor(const Event& packet,
const std::vector<uint8_t>& logged_dd) {
if (webrtc::field_trial::IsDisabled(
"WebRTC-RtcEventLogEncodeDependencyDescriptor")) {
EXPECT_TRUE(logged_dd.empty());
} else {
rtc::ArrayView<const uint8_t> original =
packet.template GetRawExtension<RtpDependencyDescriptorExtension>();
EXPECT_EQ(logged_dd.size(), original.size());
bool dd_is_same = true;
for (size_t i = 0; i < logged_dd.size(); ++i) {
dd_is_same = logged_dd[i] == original[i];
if (!dd_is_same) {
break;
}
}
EXPECT_TRUE(dd_is_same);
}
}
void EventVerifier::VerifyLoggedRouteChangeEvent(
const RtcEventRouteChange& original_event,
const LoggedRouteChangeEvent& logged_event) const {
@ -1039,6 +1085,8 @@ void EventVerifier::VerifyLoggedRtpPacketIncoming(
logged_event.rtp.header.paddingLength);
VerifyLoggedRtpHeader(original_event, logged_event.rtp.header);
VerifyLoggedDependencyDescriptor(
original_event, logged_event.rtp.dependency_descriptor_wire_format);
}
void EventVerifier::VerifyLoggedRtpPacketOutgoing(
@ -1059,6 +1107,8 @@ void EventVerifier::VerifyLoggedRtpPacketOutgoing(
// someone has a strong reason to keep it, it'll be removed.
VerifyLoggedRtpHeader(original_event, logged_event.rtp.header);
VerifyLoggedDependencyDescriptor(
original_event, logged_event.rtp.dependency_descriptor_wire_format);
}
void EventVerifier::VerifyLoggedGenericPacketSent(

View file

@ -15,6 +15,7 @@
#include <stdint.h>
#include <memory>
#include <vector>
#include "logging/rtc_event_log/events/rtc_event_alr_state.h"
#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
@ -124,8 +125,11 @@ class EventGenerator {
bool all_configured_exts = true);
// `configure_all` determines whether all supported extensions are configured,
// or a random subset.
RtpHeaderExtensionMap NewRtpHeaderExtensionMap(bool configure_all = false);
// or a random subset. Extensions in `excluded_extensions` will always be
// excluded.
RtpHeaderExtensionMap NewRtpHeaderExtensionMap(
bool configure_all = false,
const std::vector<RTPExtensionType>& excluded_extensions = {});
std::unique_ptr<RtcEventAudioReceiveStreamConfig> NewAudioReceiveStreamConfig(
uint32_t ssrc,