Adds RTPSenderVideo::Config struct with red/ulpfec config
This CL moves the various parameters in the the RTPSenderVideo ctor into
a struct, and adds the red/ulpfec payload types to it.
Once the downstream usage of SetUlpfecConfig() is gone, we can make
those members const and avoid locking in SendVideo().
Bug: webrtc:10809
Change-Id: I9a96ab5b2a4eb2997ebf4a3a3e3cd2eb5715fd79
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/155365
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29384}
diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc
index c8196b6..ca6132f 100644
--- a/call/rtp_video_sender.cc
+++ b/call/rtp_video_sender.cc
@@ -55,6 +55,68 @@
using webrtc_internal_rtp_video_sender::RtpStreamSender;
+bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
+ const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
+ if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
+ return true;
+ }
+ if (codecType == kVideoCodecGeneric &&
+ field_trial::IsEnabled("WebRTC-GenericPictureId")) {
+ return true;
+ }
+ return false;
+}
+
+bool ShouldDisableRedAndUlpfec(bool flexfec_enabled,
+ const RtpConfig& rtp_config) {
+ // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
+ const bool nack_enabled = rtp_config.nack.rtp_history_ms > 0;
+
+ // Shorthands.
+ auto IsRedEnabled = [&]() { return rtp_config.ulpfec.red_payload_type >= 0; };
+ auto IsUlpfecEnabled = [&]() {
+ return rtp_config.ulpfec.ulpfec_payload_type >= 0;
+ };
+
+ bool should_disable_red_and_ulpfec = false;
+
+ if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
+ RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
+ should_disable_red_and_ulpfec = true;
+ }
+
+ // If enabled, FlexFEC takes priority over RED+ULPFEC.
+ if (flexfec_enabled) {
+ if (IsUlpfecEnabled()) {
+ RTC_LOG(LS_INFO)
+ << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
+ }
+ should_disable_red_and_ulpfec = true;
+ }
+
+ // Payload types without picture ID cannot determine that a stream is complete
+ // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
+ // is a waste of bandwidth since FEC packets still have to be transmitted.
+ // Note that this is not the case with FlexFEC.
+ if (nack_enabled && IsUlpfecEnabled() &&
+ !PayloadTypeSupportsSkippingFecPackets(rtp_config.payload_name)) {
+ RTC_LOG(LS_WARNING)
+ << "Transmitting payload type without picture ID using "
+ "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
+ "also have to be retransmitted. Disabling ULPFEC.";
+ should_disable_red_and_ulpfec = true;
+ }
+
+ // Verify payload types.
+ if (IsUlpfecEnabled() ^ IsRedEnabled()) {
+ RTC_LOG(LS_WARNING)
+ << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
+ should_disable_red_and_ulpfec = true;
+ }
+
+ return should_disable_red_and_ulpfec;
+}
+
std::vector<RtpStreamSender> CreateRtpStreamSenders(
Clock* clock,
const RtpConfig& rtp_config,
@@ -129,31 +191,38 @@
rtp_rtcp->SetSendingStatus(false);
rtp_rtcp->SetSendingMediaStatus(false);
rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
+ // Set NACK.
+ rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
- auto sender_video = std::make_unique<RTPSenderVideo>(
- configuration.clock, rtp_rtcp->RtpSender(),
- configuration.flexfec_sender, playout_delay_oracle.get(),
- frame_encryptor, crypto_options.sframe.require_frame_encryption,
- rtp_config.lntf.enabled, /*enable_retransmit_all_layers*/ false,
- FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trial_config;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = configuration.clock;
+ video_config.rtp_sender = rtp_rtcp->RtpSender();
+ video_config.flexfec_sender = configuration.flexfec_sender;
+ video_config.playout_delay_oracle = playout_delay_oracle.get();
+ video_config.frame_encryptor = frame_encryptor;
+ video_config.require_frame_encryption =
+ crypto_options.sframe.require_frame_encryption;
+ video_config.need_rtp_packet_infos = rtp_config.lntf.enabled;
+ video_config.enable_retransmit_all_layers = false;
+ video_config.field_trials = &field_trial_config;
+ const bool should_disable_red_and_ulpfec =
+ ShouldDisableRedAndUlpfec(enable_flexfec, rtp_config);
+ if (rtp_config.ulpfec.red_payload_type != -1 &&
+ !should_disable_red_and_ulpfec) {
+ video_config.red_payload_type = rtp_config.ulpfec.red_payload_type;
+ }
+ if (rtp_config.ulpfec.ulpfec_payload_type != -1 &&
+ !should_disable_red_and_ulpfec) {
+ video_config.ulpfec_payload_type = rtp_config.ulpfec.ulpfec_payload_type;
+ }
+ auto sender_video = std::make_unique<RTPSenderVideo>(video_config);
rtp_streams.emplace_back(std::move(playout_delay_oracle),
std::move(rtp_rtcp), std::move(sender_video));
}
return rtp_streams;
}
-bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
- const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
- if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
- return true;
- }
- if (codecType == kVideoCodecGeneric &&
- field_trial::IsEnabled("WebRTC-GenericPictureId")) {
- return true;
- }
- return false;
-}
-
// TODO(brandtr): Update this function when we support multistream protection.
std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
Clock* clock,
@@ -316,7 +385,6 @@
}
}
- ConfigureProtection();
ConfigureSsrcs();
ConfigureRids();
@@ -497,65 +565,6 @@
}
}
-void RtpVideoSender::ConfigureProtection() {
- // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
- const bool flexfec_enabled = (flexfec_sender_ != nullptr);
-
- // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
- const bool nack_enabled = rtp_config_.nack.rtp_history_ms > 0;
- int red_payload_type = rtp_config_.ulpfec.red_payload_type;
- int ulpfec_payload_type = rtp_config_.ulpfec.ulpfec_payload_type;
-
- // Shorthands.
- auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
- auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
- auto DisableRedAndUlpfec = [&]() {
- red_payload_type = -1;
- ulpfec_payload_type = -1;
- };
-
- if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
- RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
- DisableRedAndUlpfec();
- }
-
- // If enabled, FlexFEC takes priority over RED+ULPFEC.
- if (flexfec_enabled) {
- if (IsUlpfecEnabled()) {
- RTC_LOG(LS_INFO)
- << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
- }
- DisableRedAndUlpfec();
- }
-
- // Payload types without picture ID cannot determine that a stream is complete
- // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
- // is a waste of bandwidth since FEC packets still have to be transmitted.
- // Note that this is not the case with FlexFEC.
- if (nack_enabled && IsUlpfecEnabled() &&
- !PayloadTypeSupportsSkippingFecPackets(rtp_config_.payload_name)) {
- RTC_LOG(LS_WARNING)
- << "Transmitting payload type without picture ID using "
- "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
- "also have to be retransmitted. Disabling ULPFEC.";
- DisableRedAndUlpfec();
- }
-
- // Verify payload types.
- if (IsUlpfecEnabled() ^ IsRedEnabled()) {
- RTC_LOG(LS_WARNING)
- << "Only RED or only ULPFEC enabled, but not both. Disabling both.";
- DisableRedAndUlpfec();
- }
-
- for (const RtpStreamSender& stream : rtp_streams_) {
- // Set NACK.
- stream.rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
- // Set RED/ULPFEC information.
- stream.sender_video->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
- }
-}
-
bool RtpVideoSender::FecEnabled() const {
const bool flexfec_enabled = (flexfec_sender_ != nullptr);
const bool ulpfec_enabled =
diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
index aa30005..62d5f98 100644
--- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -136,10 +136,13 @@
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
configuration.local_media_ssrc = kTestSsrc;
rtp_rtcp_module_ = RtpRtcp::Create(configuration);
- rtp_sender_video_ = std::make_unique<RTPSenderVideo>(
- &fake_clock, rtp_rtcp_module_->RtpSender(), nullptr,
- &playout_delay_oracle_, nullptr, false, false, false,
- FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock;
+ video_config.rtp_sender = rtp_rtcp_module_->RtpSender();
+ video_config.playout_delay_oracle = &playout_delay_oracle_;
+ video_config.field_trials = &field_trials;
+ rtp_sender_video_ = std::make_unique<RTPSenderVideo>(video_config);
rtp_rtcp_module_->SetRTCPStatus(RtcpMode::kCompound);
rtp_rtcp_module_->SetStorePacketsStatus(true, 600);
EXPECT_EQ(0, rtp_rtcp_module_->SetSendingStatus(true));
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 705e53c..34944bc 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -178,9 +178,13 @@
sender_.impl_->SetSequenceNumber(kSequenceNumber);
sender_.impl_->SetStorePacketsStatus(true, 100);
- sender_video_ = std::make_unique<RTPSenderVideo>(
- &clock_, sender_.impl_->RtpSender(), nullptr, &playout_delay_oracle_,
- nullptr, false, false, false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &clock_;
+ video_config.rtp_sender = sender_.impl_->RtpSender();
+ video_config.playout_delay_oracle = &playout_delay_oracle_;
+ video_config.field_trials = &field_trials;
+ sender_video_ = std::make_unique<RTPSenderVideo>(video_config);
memset(&codec_, 0, sizeof(VideoCodec));
codec_.plType = 100;
diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index 1138591..90b92b3 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -588,9 +588,13 @@
rtp_sender_ = std::make_unique<RTPSender>(config);
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
- &playout_delay_oracle, nullptr, false, false,
- false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
const uint8_t kPayloadType = 127;
const absl::optional<VideoCodecType> kCodecType =
@@ -1078,9 +1082,13 @@
const uint8_t kPayloadType = 127;
const VideoCodecType kCodecType = VideoCodecType::kVideoCodecGeneric;
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
- &playout_delay_oracle, nullptr, false, false,
- false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
uint8_t payload[] = {47, 11, 32, 93, 89};
// Send keyframe
@@ -1118,9 +1126,13 @@
const uint8_t payload[] = {11, 22, 33, 44, 55};
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
- &playout_delay_oracle, nullptr, false, false,
- false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
// Send a frame.
RTPVideoHeader video_header;
@@ -1160,9 +1172,14 @@
rtp_sender_->SetStorePacketsStatus(true, 10);
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(
- &fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle,
- nullptr, false, false, false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.flexfec_sender = &flexfec_sender;
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
// Parameters selected to generate a single FEC packet per media packet.
FecProtectionParams params;
@@ -1248,9 +1265,14 @@
rtp_sender_->SetStorePacketsStatus(true, 10);
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(
- &fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle,
- nullptr, false, false, false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.flexfec_sender = &flexfec_sender;
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
// Need extension to be registered for timing frames to be sent.
ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
@@ -1376,9 +1398,14 @@
rtp_sender_->SetSequenceNumber(kSeqNum);
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(
- &fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle,
- nullptr, false, false, false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.flexfec_sender = &flexfec_sender;
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
// Parameters selected to generate a single FEC packet per media packet.
FecProtectionParams params;
@@ -1643,9 +1670,14 @@
rtp_sender_->SetSequenceNumber(kSeqNum);
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(
- &fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle,
- nullptr, false, false, false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.flexfec_sender = &flexfec_sender;
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
// Parameters selected to generate a single FEC packet per media packet.
FecProtectionParams params;
params.fec_rate = 15;
@@ -1715,9 +1747,13 @@
rtp_sender_ = std::make_unique<RTPSender>(config);
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
- &playout_delay_oracle, nullptr, false, false,
- false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
const VideoCodecType kCodecType = VideoCodecType::kVideoCodecGeneric;
const uint8_t kPayloadType = 127;
@@ -1766,45 +1802,50 @@
rtp_sender_.reset();
}
+class StreamDataTestCallback : public StreamDataCountersCallback {
+ public:
+ StreamDataTestCallback()
+ : StreamDataCountersCallback(), ssrc_(0), counters_() {}
+ ~StreamDataTestCallback() override = default;
+
+ void DataCountersUpdated(const StreamDataCounters& counters,
+ uint32_t ssrc) override {
+ ssrc_ = ssrc;
+ counters_ = counters;
+ }
+
+ uint32_t ssrc_;
+ StreamDataCounters counters_;
+
+ void MatchPacketCounter(const RtpPacketCounter& expected,
+ const RtpPacketCounter& actual) {
+ EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
+ EXPECT_EQ(expected.header_bytes, actual.header_bytes);
+ EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
+ EXPECT_EQ(expected.packets, actual.packets);
+ }
+
+ void Matches(uint32_t ssrc, const StreamDataCounters& counters) {
+ EXPECT_EQ(ssrc, ssrc_);
+ MatchPacketCounter(counters.transmitted, counters_.transmitted);
+ MatchPacketCounter(counters.retransmitted, counters_.retransmitted);
+ EXPECT_EQ(counters.fec.packets, counters_.fec.packets);
+ }
+};
+
TEST_P(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) {
- class TestCallback : public StreamDataCountersCallback {
- public:
- TestCallback() : StreamDataCountersCallback(), ssrc_(0), counters_() {}
- ~TestCallback() override = default;
+ StreamDataTestCallback callback;
- void DataCountersUpdated(const StreamDataCounters& counters,
- uint32_t ssrc) override {
- ssrc_ = ssrc;
- counters_ = counters;
- }
-
- uint32_t ssrc_;
- StreamDataCounters counters_;
-
- void MatchPacketCounter(const RtpPacketCounter& expected,
- const RtpPacketCounter& actual) {
- EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
- EXPECT_EQ(expected.header_bytes, actual.header_bytes);
- EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
- EXPECT_EQ(expected.packets, actual.packets);
- }
-
- void Matches(uint32_t ssrc, const StreamDataCounters& counters) {
- EXPECT_EQ(ssrc, ssrc_);
- MatchPacketCounter(counters.transmitted, counters_.transmitted);
- MatchPacketCounter(counters.retransmitted, counters_.retransmitted);
- EXPECT_EQ(counters.fec.packets, counters_.fec.packets);
- }
- } callback;
-
- const uint8_t kRedPayloadType = 96;
- const uint8_t kUlpfecPayloadType = 97;
const uint8_t kPayloadType = 127;
const VideoCodecType kCodecType = VideoCodecType::kVideoCodecGeneric;
PlayoutDelayOracle playout_delay_oracle;
- RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
- &playout_delay_oracle, nullptr, false, false,
- false, FieldTrialBasedConfig());
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ RTPSenderVideo rtp_sender_video(video_config);
uint8_t payload[] = {47, 11, 32, 93, 89};
rtp_sender_->SetStorePacketsStatus(true, 1);
uint32_t ssrc = rtp_sender_->SSRC();
@@ -1849,8 +1890,36 @@
expected.transmitted.packets = 3;
callback.Matches(ssrc, expected);
+ rtp_sender_->RegisterRtpStatisticsCallback(nullptr);
+}
+
+TEST_P(RtpSenderTestWithoutPacer, StreamDataCountersCallbacksUlpfec) {
+ StreamDataTestCallback callback;
+
+ const uint8_t kRedPayloadType = 96;
+ const uint8_t kUlpfecPayloadType = 97;
+ const uint8_t kPayloadType = 127;
+ const VideoCodecType kCodecType = VideoCodecType::kVideoCodecGeneric;
+ PlayoutDelayOracle playout_delay_oracle;
+ FieldTrialBasedConfig field_trials;
+ RTPSenderVideo::Config video_config;
+ video_config.clock = &fake_clock_;
+ video_config.rtp_sender = rtp_sender_.get();
+ video_config.playout_delay_oracle = &playout_delay_oracle;
+ video_config.field_trials = &field_trials;
+ video_config.red_payload_type = kRedPayloadType;
+ video_config.ulpfec_payload_type = kUlpfecPayloadType;
+ RTPSenderVideo rtp_sender_video(video_config);
+ uint8_t payload[] = {47, 11, 32, 93, 89};
+ rtp_sender_->SetStorePacketsStatus(true, 1);
+ uint32_t ssrc = rtp_sender_->SSRC();
+
+ rtp_sender_->RegisterRtpStatisticsCallback(&callback);
+
+ RTPVideoHeader video_header;
+ StreamDataCounters expected;
+
// Send ULPFEC.
- rtp_sender_video.SetUlpfecConfig(kRedPayloadType, kUlpfecPayloadType);
FecProtectionParams fec_params;
fec_params.fec_mask_type = kFecMaskRandom;
fec_params.fec_rate = 1;
@@ -1860,9 +1929,9 @@
VideoFrameType::kVideoFrameDelta, kPayloadType, kCodecType, 1234, 4321,
payload, sizeof(payload), nullptr, &video_header,
kDefaultExpectedRetransmissionTimeMs));
- expected.transmitted.payload_bytes = 40;
- expected.transmitted.header_bytes = 60;
- expected.transmitted.packets = 5;
+ expected.transmitted.payload_bytes = 28;
+ expected.transmitted.header_bytes = 24;
+ expected.transmitted.packets = 2;
expected.fec.packets = 1;
callback.Matches(ssrc, expected);
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index 6a6ef97..fc40a97 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -205,34 +205,50 @@
bool need_rtp_packet_infos,
bool enable_retransmit_all_layers,
const WebRtcKeyValueConfig& field_trials)
- : rtp_sender_(rtp_sender),
- clock_(clock),
+ : RTPSenderVideo([&] {
+ Config config;
+ config.clock = clock;
+ config.rtp_sender = rtp_sender;
+ config.flexfec_sender = flexfec_sender;
+ config.playout_delay_oracle = playout_delay_oracle;
+ config.frame_encryptor = frame_encryptor;
+ config.require_frame_encryption = require_frame_encryption;
+ config.need_rtp_packet_infos = need_rtp_packet_infos;
+ config.enable_retransmit_all_layers = enable_retransmit_all_layers;
+ config.field_trials = &field_trials;
+ return config;
+ }()) {}
+
+RTPSenderVideo::RTPSenderVideo(const Config& config)
+ : rtp_sender_(config.rtp_sender),
+ clock_(config.clock),
retransmission_settings_(
- enable_retransmit_all_layers
+ config.enable_retransmit_all_layers
? kRetransmitAllLayers
: (kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers)),
last_rotation_(kVideoRotation_0),
transmit_color_space_next_frame_(false),
- playout_delay_oracle_(playout_delay_oracle),
- rtp_sequence_number_map_(need_rtp_packet_infos
+ playout_delay_oracle_(config.playout_delay_oracle),
+ rtp_sequence_number_map_(config.need_rtp_packet_infos
? std::make_unique<RtpSequenceNumberMap>(
kRtpSequenceNumberMapMaxEntries)
: nullptr),
- red_payload_type_(-1),
- ulpfec_payload_type_(-1),
- flexfec_sender_(flexfec_sender),
+ red_payload_type_(config.red_payload_type),
+ ulpfec_payload_type_(config.ulpfec_payload_type),
+ flexfec_sender_(config.flexfec_sender),
delta_fec_params_{0, 1, kFecMaskRandom},
key_fec_params_{0, 1, kFecMaskRandom},
fec_bitrate_(1000, RateStatistics::kBpsScale),
video_bitrate_(1000, RateStatistics::kBpsScale),
packetization_overhead_bitrate_(1000, RateStatistics::kBpsScale),
- frame_encryptor_(frame_encryptor),
- require_frame_encryption_(require_frame_encryption),
+ frame_encryptor_(config.frame_encryptor),
+ require_frame_encryption_(config.require_frame_encryption),
generic_descriptor_auth_experiment_(
- field_trials.Lookup("WebRTC-GenericDescriptorAuth").find("Enabled") ==
- 0),
+ config.field_trials->Lookup("WebRTC-GenericDescriptorAuth")
+ .find("Enabled") == 0),
exclude_transport_sequence_number_from_fec_experiment_(
- field_trials.Lookup(kExcludeTransportSequenceNumberFromFecFieldTrial)
+ config.field_trials
+ ->Lookup(kExcludeTransportSequenceNumberFromFecFieldTrial)
.find("Enabled") == 0) {
RTC_DCHECK(playout_delay_oracle_);
}
@@ -273,7 +289,7 @@
{
// Only protect while creating RED and FEC packets, not when sending.
rtc::CritScope cs(&crit_);
- red_packet->SetPayloadType(red_payload_type_);
+ red_packet->SetPayloadType(*red_payload_type_);
if (ulpfec_enabled()) {
if (protect_media_packet) {
if (exclude_transport_sequence_number_from_fec_experiment_) {
@@ -302,7 +318,8 @@
uint16_t first_fec_sequence_number =
rtp_sender_->AllocateSequenceNumber(num_fec_packets);
fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed(
- red_payload_type_, ulpfec_payload_type_, first_fec_sequence_number);
+ *red_payload_type_, *ulpfec_payload_type_,
+ first_fec_sequence_number);
RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
}
}
@@ -399,8 +416,12 @@
RTC_DCHECK_LE(ulpfec_payload_type, 127);
rtc::CritScope cs(&crit_);
- red_payload_type_ = red_payload_type;
- ulpfec_payload_type_ = ulpfec_payload_type;
+ if (red_payload_type != -1) {
+ red_payload_type_ = red_payload_type;
+ }
+ if (ulpfec_payload_type != -1) {
+ ulpfec_payload_type_ = ulpfec_payload_type;
+ }
// Must not enable ULPFEC without RED.
RTC_DCHECK(!(red_enabled() ^ ulpfec_enabled()));
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.h b/modules/rtp_rtcp/source/rtp_sender_video.h
index 9ef9576..1b956fd 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -56,6 +56,29 @@
public:
static constexpr int64_t kTLRateWindowSizeMs = 2500;
+ struct Config {
+ Config() = default;
+ Config(const Config&) = delete;
+ Config(Config&&) = default;
+
+ // All members of this struct, with the exception of |field_trials|, are
+ // expected to outlive the RTPSenderVideo object they are passed to.
+ Clock* clock = nullptr;
+ RTPSender* rtp_sender = nullptr;
+ FlexfecSender* flexfec_sender = nullptr;
+ PlayoutDelayOracle* playout_delay_oracle = nullptr;
+ FrameEncryptorInterface* frame_encryptor = nullptr;
+ bool require_frame_encryption = false;
+ bool need_rtp_packet_infos = false;
+ bool enable_retransmit_all_layers = false;
+ absl::optional<int> red_payload_type;
+ absl::optional<int> ulpfec_payload_type;
+ const WebRtcKeyValueConfig* field_trials = nullptr;
+ };
+
+ explicit RTPSenderVideo(const Config& config);
+
+ // TODO(bugs.webrtc.org/10809): Remove when downstream usage is gone.
RTPSenderVideo(Clock* clock,
RTPSender* rtpSender,
FlexfecSender* flexfec_sender,
@@ -100,6 +123,7 @@
// corresponding feature is turned off. Note that we DO NOT support enabling
// ULPFEC without enabling RED, and RED is only ever used when ULPFEC is
// enabled.
+ // TODO(bugs.webrtc.org/10809): Remove when downstream usage is gone.
void SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type);
// FlexFEC/ULPFEC.
@@ -162,11 +186,11 @@
size_t unpacketized_payload_size);
bool red_enabled() const RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_) {
- return red_payload_type_ >= 0;
+ return red_payload_type_.has_value();
}
bool ulpfec_enabled() const RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_) {
- return ulpfec_payload_type_ >= 0;
+ return ulpfec_payload_type_.has_value();
}
bool flexfec_enabled() const { return flexfec_sender_ != nullptr; }
@@ -209,8 +233,8 @@
RTC_PT_GUARDED_BY(crit_);
// RED/ULPFEC.
- int red_payload_type_ RTC_GUARDED_BY(crit_);
- int ulpfec_payload_type_ RTC_GUARDED_BY(crit_);
+ absl::optional<int> red_payload_type_ RTC_GUARDED_BY(crit_);
+ absl::optional<int> ulpfec_payload_type_ RTC_GUARDED_BY(crit_);
UlpfecGenerator ulpfec_generator_ RTC_GUARDED_BY(crit_);
// FlexFEC.
diff --git a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
index 4bd80d3..856d239 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
@@ -99,15 +99,15 @@
RTPSender* rtp_sender,
FlexfecSender* flexfec_sender,
const WebRtcKeyValueConfig& field_trials)
- : RTPSenderVideo(clock,
- rtp_sender,
- flexfec_sender,
- &playout_delay_oracle_,
- nullptr,
- false,
- false,
- false,
- field_trials) {}
+ : RTPSenderVideo([&] {
+ Config config;
+ config.clock = clock;
+ config.rtp_sender = rtp_sender;
+ config.flexfec_sender = flexfec_sender;
+ config.playout_delay_oracle = &playout_delay_oracle_;
+ config.field_trials = &field_trials;
+ return config;
+ }()) {}
~TestRtpSenderVideo() override {}
bool AllowRetransmission(const RTPVideoHeader& header,