Add plumbing for video NACK to be coupled between channels.

Bug: webrtc:13931, webrtc:14920
Change-Id: I451869e295e099a1d08c0c80e481decd53149f1b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/294382
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39373}
diff --git a/media/base/fake_media_engine.h b/media/base/fake_media_engine.h
index 1d8f383..ac55fd1 100644
--- a/media/base/fake_media_engine.h
+++ b/media/base/fake_media_engine.h
@@ -513,6 +513,18 @@
   void RequestRecvKeyFrame(uint32_t ssrc) override;
   void GenerateSendKeyFrame(uint32_t ssrc,
                             const std::vector<std::string>& rids) override;
+  webrtc::RtcpMode SendCodecRtcpMode() const override {
+    return webrtc::RtcpMode::kCompound;
+  }
+  bool SendCodecHasLntf() const override { return false; }
+  bool SendCodecHasNack() const override { return false; }
+  absl::optional<int> SendCodecRtxTime() const override {
+    return absl::nullopt;
+  }
+  void SetReceiverFeedbackParameters(bool lntf_enabled,
+                                     bool nack_enabled,
+                                     webrtc::RtcpMode rtcp_mode,
+                                     absl::optional<int> rtx_time) override {}
 
  private:
   bool SetRecvCodecs(const std::vector<VideoCodec>& codecs);
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index 6572579..571d661 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -959,6 +959,11 @@
   virtual void SetVideoCodecSwitchingEnabled(bool enabled) = 0;
   virtual bool GetStats(VideoMediaSendInfo* stats) = 0;
   virtual void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) = 0;
+  // Information queries to support SetReceiverFeedbackParameters
+  virtual webrtc::RtcpMode SendCodecRtcpMode() const = 0;
+  virtual bool SendCodecHasLntf() const = 0;
+  virtual bool SendCodecHasNack() const = 0;
+  virtual absl::optional<int> SendCodecRtxTime() const = 0;
 };
 
 class VideoMediaReceiveChannelInterface : public MediaReceiveChannelInterface {
@@ -988,6 +993,10 @@
   // Clear recordable encoded frame callback for `ssrc`
   virtual void ClearRecordableEncodedFrameCallback(uint32_t ssrc) = 0;
   virtual bool GetStats(VideoMediaReceiveInfo* stats) = 0;
+  virtual void SetReceiverFeedbackParameters(bool lntf_enabled,
+                                             bool nack_enabled,
+                                             webrtc::RtcpMode rtcp_mode,
+                                             absl::optional<int> rtx_time) = 0;
 };
 
 // Info about data received in DataMediaChannel.  For use in
diff --git a/media/base/media_channel_impl.h b/media/base/media_channel_impl.h
index e371166..96a9bca 100644
--- a/media/base/media_channel_impl.h
+++ b/media/base/media_channel_impl.h
@@ -652,6 +652,15 @@
   void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override {
     return impl_->FillBitrateInfo(bwe_info);
   }
+  // Information queries to support SetReceiverFeedbackParameters
+  webrtc::RtcpMode SendCodecRtcpMode() const override {
+    return impl()->SendCodecRtcpMode();
+  }
+  bool SendCodecHasLntf() const override { return impl()->SendCodecHasLntf(); }
+  bool SendCodecHasNack() const override { return impl()->SendCodecHasNack(); }
+  absl::optional<int> SendCodecRtxTime() const override {
+    return impl()->SendCodecRtxTime();
+  }
 
   MediaChannel* ImplForTesting() override { return impl_; }
 
@@ -775,6 +784,13 @@
   bool GetStats(VideoMediaReceiveInfo* info) override {
     return impl_->GetReceiveStats(info);
   }
+  void SetReceiverFeedbackParameters(bool lntf_enabled,
+                                     bool nack_enabled,
+                                     webrtc::RtcpMode rtcp_mode,
+                                     absl::optional<int> rtx_time) override {
+    impl()->SetReceiverFeedbackParameters(lntf_enabled, nack_enabled, rtcp_mode,
+                                          rtx_time);
+  }
   MediaChannel* ImplForTesting() override { return impl_; }
 
  private:
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index edd6c38..976dba3 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -981,14 +981,13 @@
   for (auto& kv : send_streams_) {
     kv.second->SetSendParameters(changed_params);
   }
-  if (changed_params.send_codec || changed_params.rtcp_mode) {
-    // Update receive feedback parameters from new codec or RTCP mode.
-    RTC_LOG(LS_INFO)
-        << "SetFeedbackParameters on all the receive streams because the send "
-           "codec or RTCP mode has changed.";
-    for (auto& kv : receive_streams_) {
-      RTC_DCHECK(kv.second != nullptr);
-      kv.second->SetFeedbackParameters(
+  if (role() == MediaChannel::Role::kBoth) {
+    if (changed_params.send_codec || changed_params.rtcp_mode) {
+      // Update receive feedback parameters from new codec or RTCP mode.
+      RTC_LOG(LS_INFO) << "SetFeedbackParameters on all the receive streams "
+                          "because the send "
+                          "codec or RTCP mode has changed.";
+      SetReceiverFeedbackParameters(
           HasLntf(send_codec_->codec), HasNack(send_codec_->codec),
           send_params_.rtcp.reduced_size ? webrtc::RtcpMode::kReducedSize
                                          : webrtc::RtcpMode::kCompound,
@@ -998,6 +997,23 @@
   return true;
 }
 
+void WebRtcVideoChannel::SetReceiverFeedbackParameters(
+    bool lntf_enabled,
+    bool nack_enabled,
+    webrtc::RtcpMode rtcp_mode,
+    absl::optional<int> rtx_time) {
+  RTC_DCHECK_RUN_ON(&thread_checker_);
+
+  RTC_DCHECK(role() == MediaChannel::Role::kReceive ||
+             role() == MediaChannel::Role::kBoth);
+  // Update receive feedback parameters from new codec or RTCP mode.
+  for (auto& kv : receive_streams_) {
+    RTC_DCHECK(kv.second != nullptr);
+    kv.second->SetFeedbackParameters(lntf_enabled, nack_enabled, rtcp_mode,
+                                     rtx_time);
+  }
+}
+
 webrtc::RtpParameters WebRtcVideoChannel::GetRtpSendParameters(
     uint32_t ssrc) const {
   RTC_DCHECK_RUN_ON(&thread_checker_);
diff --git a/media/engine/webrtc_video_engine.h b/media/engine/webrtc_video_engine.h
index 8a14ea4..1b9ca3a 100644
--- a/media/engine/webrtc_video_engine.h
+++ b/media/engine/webrtc_video_engine.h
@@ -231,6 +231,39 @@
       rtc::scoped_refptr<webrtc::FrameTransformerInterface> frame_transformer)
       override;
 
+  // Information queries to support SetReceiverFeedbackParameters
+  webrtc::RtcpMode SendCodecRtcpMode() const override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    return send_params_.rtcp.reduced_size ? webrtc::RtcpMode::kReducedSize
+                                          : webrtc::RtcpMode::kCompound;
+  }
+
+  bool SendCodecHasLntf() const override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    if (!send_codec_) {
+      return false;
+    }
+    return HasLntf(send_codec_->codec);
+  }
+  bool SendCodecHasNack() const override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    if (!send_codec_) {
+      return false;
+    }
+    return HasNack(send_codec_->codec);
+  }
+  absl::optional<int> SendCodecRtxTime() const override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    if (!send_codec_) {
+      return absl::nullopt;
+    }
+    return send_codec_->rtx_time;
+  }
+  void SetReceiverFeedbackParameters(bool lntf_enabled,
+                                     bool nack_enabled,
+                                     webrtc::RtcpMode rtcp_mode,
+                                     absl::optional<int> rtx_time) override;
+
  private:
   class WebRtcVideoReceiveStream;
 
diff --git a/pc/channel.cc b/pc/channel.cc
index 6c457fc..dd94b7e 100644
--- a/pc/channel.cc
+++ b/pc/channel.cc
@@ -1064,6 +1064,12 @@
           mid().c_str());
       return false;
     }
+    // adjust receive streams based on send codec
+    media_receive_channel()->SetReceiverFeedbackParameters(
+        media_send_channel()->SendCodecHasLntf(),
+        media_send_channel()->SendCodecHasNack(),
+        media_send_channel()->SendCodecRtcpMode(),
+        media_send_channel()->SendCodecRtxTime());
     last_send_params_ = send_params;
   }
 
@@ -1131,6 +1137,12 @@
         mid().c_str());
     return false;
   }
+  // adjust receive streams based on send codec
+  media_receive_channel()->SetReceiverFeedbackParameters(
+      media_send_channel()->SendCodecHasLntf(),
+      media_send_channel()->SendCodecHasNack(),
+      media_send_channel()->SendCodecRtcpMode(),
+      media_send_channel()->SendCodecRtxTime());
   last_send_params_ = send_params;
 
   if (needs_recv_params_update) {