Allow ulpfec payload type reconfig without recreating receive streams. Bug: none Change-Id: I1c5dad7811dd93552c185145e5a1488a8e9bb863 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/271000 Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37771}
diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h index 451203b..f4ed0a9 100644 --- a/call/video_receive_stream.h +++ b/call/video_receive_stream.h
@@ -303,6 +303,8 @@ // Must be called on the packet delivery thread. virtual void SetNackHistory(TimeDelta history) = 0; + virtual void SetUlpfecPayloadType(int ulpfec_payload_type) = 0; + protected: virtual ~VideoReceiveStreamInterface() {} };
diff --git a/media/engine/fake_webrtc_call.h b/media/engine/fake_webrtc_call.h index c807d31..b076fd9 100644 --- a/media/engine/fake_webrtc_call.h +++ b/media/engine/fake_webrtc_call.h
@@ -23,6 +23,7 @@ #include <map> #include <memory> #include <string> +#include <utility> #include <vector> #include "absl/strings/string_view.h" @@ -297,6 +298,10 @@ config_.rtp.nack.rtp_history_ms = history.ms(); } + void SetUlpfecPayloadType(int ulpfec_payload_type) override { + config_.rtp.ulpfec_payload_type = ulpfec_payload_type; + } + void Start() override; void Stop() override;
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index c562abe..c39bf67 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc
@@ -2972,14 +2972,14 @@ ExtractCodecInformation(recv_codecs, rtx_associated_payload_types, raw_payload_types, decoders); - bool recreate_needed = false; - 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; - recreate_needed = true; + 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;
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc index 536d16f..9aa5f0a 100644 --- a/video/rtp_video_stream_receiver2.cc +++ b/video/rtp_video_stream_receiver2.cc
@@ -124,22 +124,25 @@ } std::unique_ptr<UlpfecReceiver> MaybeConstructUlpfecReceiver( - const VideoReceiveStreamInterface::Config::Rtp& rtp, + uint32_t remote_ssrc, + int red_payload_type, + int ulpfec_payload_type, + rtc::ArrayView<const RtpExtension> extensions, RecoveredPacketReceiver* callback, Clock* clock) { - RTC_DCHECK_GE(rtp.ulpfec_payload_type, -1); - if (rtp.red_payload_type == -1) + RTC_DCHECK_GE(red_payload_type, -1); + RTC_DCHECK_GE(ulpfec_payload_type, -1); + if (red_payload_type == -1) return nullptr; // TODO(tommi, brandtr): Consider including this check too once // `UlpfecReceiver` has been updated to not consider both red and ulpfec // payload ids. - // if (rtp.ulpfec_payload_type == -1) + // if (ulpfec_payload_type == -1) // return nullptr; - return std::make_unique<UlpfecReceiver>(rtp.remote_ssrc, - rtp.ulpfec_payload_type, callback, - rtp.extensions, clock); + return std::make_unique<UlpfecReceiver>(remote_ssrc, ulpfec_payload_type, + callback, extensions, clock); } static const int kPacketLogIntervalMs = 10000; @@ -256,7 +259,13 @@ forced_playout_delay_max_ms_("max_ms", absl::nullopt), forced_playout_delay_min_ms_("min_ms", absl::nullopt), rtp_receive_statistics_(rtp_receive_statistics), - ulpfec_receiver_(MaybeConstructUlpfecReceiver(config->rtp, this, clock)), + ulpfec_receiver_( + MaybeConstructUlpfecReceiver(config->rtp.remote_ssrc, + config->rtp.red_payload_type, + config->rtp.ulpfec_payload_type, + config->rtp.extensions, + this, + clock_)), packet_sink_(config->rtp.packet_sink_), receiving_(false), last_packet_log_ms_(-1), @@ -983,6 +992,18 @@ history.ms() > 0 ? kMaxPacketAgeToNack : kDefaultMaxReorderingThreshold); } +int RtpVideoStreamReceiver2::ulpfec_payload_type() const { + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); + return ulpfec_receiver_ ? ulpfec_receiver_->ulpfec_payload_type() : -1; +} + +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.extensions, this, clock_); +} + absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedPacketMs() const { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); if (last_received_rtp_system_time_) { @@ -1040,16 +1061,18 @@ void RtpVideoStreamReceiver2::ParseAndHandleEncapsulatingHeader( const RtpPacketReceived& packet) { RTC_DCHECK_RUN_ON(&packet_sequence_checker_); - if (packet.PayloadType() == config_.rtp.red_payload_type && - packet.payload_size() > 0) { - if (packet.payload()[0] == config_.rtp.ulpfec_payload_type) { - // Notify video_receiver about received FEC packets to avoid NACKing these - // packets. - NotifyReceiverOfEmptyPacket(packet.SequenceNumber()); - } - if (ulpfec_receiver_ && ulpfec_receiver_->AddReceivedRedPacket(packet)) { - ulpfec_receiver_->ProcessReceivedFec(); - } + RTC_DCHECK_EQ(packet.PayloadType(), config_.rtp.red_payload_type); + + if (!ulpfec_receiver_ || packet.payload_size() == 0U) + return; + + if (packet.payload()[0] == ulpfec_receiver_->ulpfec_payload_type()) { + // Notify video_receiver about received FEC packets to avoid NACKing these + // packets. + NotifyReceiverOfEmptyPacket(packet.SequenceNumber()); + } + if (ulpfec_receiver_->AddReceivedRedPacket(packet)) { + ulpfec_receiver_->ProcessReceivedFec(); } }
diff --git a/video/rtp_video_stream_receiver2.h b/video/rtp_video_stream_receiver2.h index c341536..4fa216c 100644 --- a/video/rtp_video_stream_receiver2.h +++ b/video/rtp_video_stream_receiver2.h
@@ -198,6 +198,9 @@ void SetNackHistory(TimeDelta history); + int ulpfec_payload_type() const; + void set_ulpfec_payload_type(int payload_type); + absl::optional<int64_t> LastReceivedPacketMs() const; absl::optional<int64_t> LastReceivedKeyframePacketMs() const; @@ -320,7 +323,8 @@ FieldTrialOptional<int> forced_playout_delay_max_ms_; FieldTrialOptional<int> forced_playout_delay_min_ms_; ReceiveStatistics* const rtp_receive_statistics_; - std::unique_ptr<UlpfecReceiver> ulpfec_receiver_; + std::unique_ptr<UlpfecReceiver> ulpfec_receiver_ + 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 413c45a..5015c2d 100644 --- a/video/video_receive_stream2.cc +++ b/video/video_receive_stream2.cc
@@ -349,7 +349,8 @@ } const bool protected_by_fec = - config_.rtp.protected_by_flexfec || config_.rtp.ulpfec_payload_type != -1; + config_.rtp.protected_by_flexfec || + rtp_video_stream_receiver_.ulpfec_payload_type() != -1; if (config_.rtp.nack.rtp_history_ms > 0 && protected_by_fec) { frame_buffer_->SetProtectionMode(kProtectionNackFEC); @@ -530,7 +531,8 @@ const_cast<int&>(config_.rtp.nack.rtp_history_ms) = history.ms(); const bool protected_by_fec = - config_.rtp.protected_by_flexfec || config_.rtp.ulpfec_payload_type != -1; + config_.rtp.protected_by_flexfec || + rtp_video_stream_receiver_.ulpfec_payload_type() != -1; frame_buffer_->SetProtectionMode(history.ms() > 0 && protected_by_fec ? kProtectionNackFEC @@ -549,6 +551,11 @@ frame_buffer_->SetMaxWaits(max_wait_for_keyframe, max_wait_for_frame); } +void VideoReceiveStream2::SetUlpfecPayloadType(int payload_type) { + RTC_DCHECK_RUN_ON(&packet_sequence_checker_); + rtp_video_stream_receiver_.set_ulpfec_payload_type(payload_type); +} + void VideoReceiveStream2::CreateAndRegisterExternalDecoder( const Decoder& decoder) { TRACE_EVENT0("webrtc",
diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h index 39ed2c3..fccec05 100644 --- a/video/video_receive_stream2.h +++ b/video/video_receive_stream2.h
@@ -11,6 +11,7 @@ #ifndef VIDEO_VIDEO_RECEIVE_STREAM2_H_ #define VIDEO_VIDEO_RECEIVE_STREAM2_H_ +#include <map> #include <memory> #include <string> #include <vector> @@ -150,6 +151,7 @@ void SetFlexFecProtection(RtpPacketSinkInterface* flexfec_sink) override; void SetLossNotificationEnabled(bool enabled) override; void SetNackHistory(TimeDelta history) override; + void SetUlpfecPayloadType(int payload_type) override; webrtc::VideoReceiveStreamInterface::Stats GetStats() const override;