Update the red_payload_type without recreating video receive streams.
A follow-up change will combine the setters for ulpfec and red payload
types, since they're entwined.
Bug: webrtc:11993
Change-Id: Ifea7fe9f4ebc7ac88a62db6cd6748f4d3c20db4c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/271482
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37785}
diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h
index 79edf9d..82ad8cf 100644
--- a/call/video_receive_stream.h
+++ b/call/video_receive_stream.h
@@ -305,6 +305,8 @@
virtual void SetUlpfecPayloadType(int ulpfec_payload_type) = 0;
+ virtual void SetRedPayloadType(int red_payload_type) = 0;
+
virtual void SetRtcpXr(Config::Rtp::RtcpXr rtcp_xr) = 0;
protected:
diff --git a/media/engine/fake_webrtc_call.h b/media/engine/fake_webrtc_call.h
index f34bb5b..26be780 100644
--- a/media/engine/fake_webrtc_call.h
+++ b/media/engine/fake_webrtc_call.h
@@ -302,6 +302,10 @@
config_.rtp.ulpfec_payload_type = ulpfec_payload_type;
}
+ void SetRedPayloadType(int red_payload_type) override {
+ config_.rtp.red_payload_type = red_payload_type;
+ }
+
void SetRtcpXr(Config::Rtp::RtcpXr rtcp_xr) override {
config_.rtp.rtcp_xr = rtcp_xr;
}
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index b02fa4d..774368c 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -2973,16 +2973,18 @@
raw_payload_types, decoders);
const auto& codec = recv_codecs.front();
- if (config_.rtp.ulpfec_payload_type != codec.ulpfec.ulpfec_payload_type) {
- config_.rtp.ulpfec_payload_type = codec.ulpfec.ulpfec_payload_type;
- stream_->SetUlpfecPayloadType(config_.rtp.ulpfec_payload_type);
- }
-
- bool recreate_needed = false;
if (config_.rtp.red_payload_type != codec.ulpfec.red_payload_type) {
config_.rtp.red_payload_type = codec.ulpfec.red_payload_type;
- recreate_needed = true;
+ stream_->SetRedPayloadType(codec.ulpfec.red_payload_type);
+ }
+
+ // Check and optionally set `ulpfec_payload_type` _after_ checking the
+ // `red_payload_type` due to encapsulation. See RtpVideoStreamReceiver2
+ // for more details.
+ if (config_.rtp.ulpfec_payload_type != codec.ulpfec.ulpfec_payload_type) {
+ config_.rtp.ulpfec_payload_type = codec.ulpfec.ulpfec_payload_type;
+ stream_->SetUlpfecPayloadType(config_.rtp.ulpfec_payload_type);
}
const bool has_lntf = HasLntf(codec.codec);
@@ -3020,6 +3022,8 @@
codec.ulpfec.red_payload_type;
}
+ bool recreate_needed = false;
+
if (config_.rtp.rtx_associated_payload_types !=
rtx_associated_payload_types) {
rtx_associated_payload_types.swap(config_.rtp.rtx_associated_payload_types);
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
index 2b765d9..9809ddf 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
@@ -266,6 +266,7 @@
config->rtp.extensions,
this,
clock_)),
+ red_payload_type_(config_.rtp.red_payload_type),
packet_sink_(config->rtp.packet_sink_),
receiving_(false),
last_packet_log_ms_(-1),
@@ -667,7 +668,7 @@
RtpPacketReceived packet;
if (!packet.Parse(rtp_packet, rtp_packet_length))
return;
- if (packet.PayloadType() == config_.rtp.red_payload_type) {
+ if (packet.PayloadType() == red_payload_type_) {
RTC_LOG(LS_WARNING) << "Discarding recovered packet with RED encapsulation";
return;
}
@@ -1005,7 +1006,28 @@
void RtpVideoStreamReceiver2::set_ulpfec_payload_type(int payload_type) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
ulpfec_receiver_ = MaybeConstructUlpfecReceiver(
- config_.rtp.remote_ssrc, config_.rtp.red_payload_type, payload_type,
+ config_.rtp.remote_ssrc, red_payload_type_, payload_type,
+ config_.rtp.extensions, this, clock_);
+}
+
+int RtpVideoStreamReceiver2::red_payload_type() const {
+ RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ return red_payload_type_;
+}
+
+void RtpVideoStreamReceiver2::set_red_payload_type(int payload_type) {
+ RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ RTC_DCHECK_GE(payload_type, -1);
+ RTC_DCHECK_LE(payload_type, 0x7f);
+ // TODO(tommi, brandtr): It would be less error prone to require both
+ // red and ulpfec payload ids to be set at the same time.
+
+ // Stash away the currently configured ulpfec payload id to carry over to the
+ // potentially new `ulpfec_receiver_` instance.
+ int ulpfec_type = ulpfec_payload_type();
+ red_payload_type_ = payload_type;
+ ulpfec_receiver_ = MaybeConstructUlpfecReceiver(
+ config_.rtp.remote_ssrc, red_payload_type_, ulpfec_type,
config_.rtp.extensions, this, clock_);
}
@@ -1043,7 +1065,7 @@
NotifyReceiverOfEmptyPacket(packet.SequenceNumber());
return;
}
- if (packet.PayloadType() == config_.rtp.red_payload_type) {
+ if (packet.PayloadType() == red_payload_type_) {
ParseAndHandleEncapsulatingHeader(packet);
return;
}
@@ -1066,7 +1088,7 @@
void RtpVideoStreamReceiver2::ParseAndHandleEncapsulatingHeader(
const RtpPacketReceived& packet) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
- RTC_DCHECK_EQ(packet.PayloadType(), config_.rtp.red_payload_type);
+ RTC_DCHECK_EQ(packet.PayloadType(), red_payload_type_);
if (!ulpfec_receiver_ || packet.payload_size() == 0U)
return;
diff --git a/video/rtp_video_stream_receiver2.h b/video/rtp_video_stream_receiver2.h
index ab84007..8d54d5c 100644
--- a/video/rtp_video_stream_receiver2.h
+++ b/video/rtp_video_stream_receiver2.h
@@ -203,6 +203,9 @@
int ulpfec_payload_type() const;
void set_ulpfec_payload_type(int payload_type);
+ int red_payload_type() const;
+ void set_red_payload_type(int payload_type);
+
absl::optional<int64_t> LastReceivedPacketMs() const;
absl::optional<int64_t> LastReceivedKeyframePacketMs() const;
@@ -327,6 +330,7 @@
ReceiveStatistics* const rtp_receive_statistics_;
std::unique_ptr<UlpfecReceiver> ulpfec_receiver_
RTC_GUARDED_BY(packet_sequence_checker_);
+ int red_payload_type_ RTC_GUARDED_BY(packet_sequence_checker_);
RTC_NO_UNIQUE_ADDRESS SequenceChecker worker_task_checker_;
// TODO(bugs.webrtc.org/11993): This checker conceptually represents
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index 1b8c519..5da6ea9 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -556,6 +556,11 @@
rtp_video_stream_receiver_.set_ulpfec_payload_type(payload_type);
}
+void VideoReceiveStream2::SetRedPayloadType(int payload_type) {
+ RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ rtp_video_stream_receiver_.set_red_payload_type(payload_type);
+}
+
void VideoReceiveStream2::SetRtcpXr(Config::Rtp::RtcpXr rtcp_xr) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
rtp_video_stream_receiver_.SetReferenceTimeReport(
diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h
index 01cbf73..907a7d4 100644
--- a/video/video_receive_stream2.h
+++ b/video/video_receive_stream2.h
@@ -152,6 +152,7 @@
void SetLossNotificationEnabled(bool enabled) override;
void SetNackHistory(TimeDelta history) override;
void SetUlpfecPayloadType(int payload_type) override;
+ void SetRedPayloadType(int payload_type) override;
void SetRtcpXr(Config::Rtp::RtcpXr rtcp_xr) override;
webrtc::VideoReceiveStreamInterface::Stats GetStats() const override;