Add ability to configure video codecs at peer level (PC level framework)

Bug: b/192821182
Change-Id: Ic1b55028102fbd331f0fb6a3a8c758c311267cbc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/226220
Reviewed-by: Andrey Logvin <landrey@webrtc.org>
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34477}
diff --git a/api/test/peerconnection_quality_test_fixture.h b/api/test/peerconnection_quality_test_fixture.h
index 8717e8f..20d9c74 100644
--- a/api/test/peerconnection_quality_test_fixture.h
+++ b/api/test/peerconnection_quality_test_fixture.h
@@ -268,6 +268,27 @@
     absl::optional<std::string> sync_group;
   };
 
+  struct VideoCodecConfig {
+    explicit VideoCodecConfig(std::string name)
+        : name(std::move(name)), required_params() {}
+    VideoCodecConfig(std::string name,
+                     std::map<std::string, std::string> required_params)
+        : name(std::move(name)), required_params(std::move(required_params)) {}
+    // Next two fields are used to specify concrete video codec, that should be
+    // used in the test. Video code will be negotiated in SDP during offer/
+    // answer exchange.
+    // Video codec name. You can find valid names in
+    // media/base/media_constants.h
+    std::string name = cricket::kVp8CodecName;
+    // Map of parameters, that have to be specified on SDP codec. Each parameter
+    // is described by key and value. Codec parameters will match the specified
+    // map if and only if for each key from |required_params| there will be
+    // a parameter with name equal to this key and parameter value will be equal
+    // to the value from |required_params| for this key.
+    // If empty then only name will be used to match the codec.
+    std::map<std::string, std::string> required_params;
+  };
+
   // This class is used to fully configure one peer inside the call.
   class PeerConfigurer {
    public:
@@ -343,6 +364,14 @@
     // applied to all summed RTP streams for this peer.
     virtual PeerConfigurer* SetBitrateSettings(
         BitrateSettings bitrate_settings) = 0;
+    // Set the list of video codecs used by the peer during the test. These
+    // codecs will be negotiated in SDP during offer/answer exchange. The order
+    // of these codecs during negotiation will be the same as in |video_codecs|.
+    // Codecs have to be available in codecs list provided by peer connection to
+    // be negotiated. If some of specified codecs won't be found, the test will
+    // crash.
+    virtual PeerConfigurer* SetVideoCodecs(
+        std::vector<VideoCodecConfig> video_codecs) = 0;
   };
 
   // Contains configuration for echo emulator.
@@ -352,27 +381,6 @@
     TimeDelta echo_delay = TimeDelta::Millis(50);
   };
 
-  struct VideoCodecConfig {
-    explicit VideoCodecConfig(std::string name)
-        : name(std::move(name)), required_params() {}
-    VideoCodecConfig(std::string name,
-                     std::map<std::string, std::string> required_params)
-        : name(std::move(name)), required_params(std::move(required_params)) {}
-    // Next two fields are used to specify concrete video codec, that should be
-    // used in the test. Video code will be negotiated in SDP during offer/
-    // answer exchange.
-    // Video codec name. You can find valid names in
-    // media/base/media_constants.h
-    std::string name = cricket::kVp8CodecName;
-    // Map of parameters, that have to be specified on SDP codec. Each parameter
-    // is described by key and value. Codec parameters will match the specified
-    // map if and only if for each key from |required_params| there will be
-    // a parameter with name equal to this key and parameter value will be equal
-    // to the value from |required_params| for this key.
-    // If empty then only name will be used to match the codec.
-    std::map<std::string, std::string> required_params;
-  };
-
   // Contains parameters, that describe how long framework should run quality
   // test.
   struct RunParams {
@@ -383,6 +391,11 @@
     // it will be shut downed.
     TimeDelta run_duration;
 
+    // DEPRECATED: Instead of setting the codecs in RunParams (which apply to
+    //             all the participants in the call, please set them with
+    //             PeerConfigurer, this will allow more flexibility and let
+    //             different Peers support different codecs.
+    //
     // List of video codecs to use during the test. These codecs will be
     // negotiated in SDP during offer/answer exchange. The order of these codecs
     // during negotiation will be the same as in |video_codecs|. Codecs have
diff --git a/test/pc/e2e/peer_configurer.cc b/test/pc/e2e/peer_configurer.cc
index 18570c2..caf29eb 100644
--- a/test/pc/e2e/peer_configurer.cc
+++ b/test/pc/e2e/peer_configurer.cc
@@ -90,11 +90,22 @@
           *p->name + "_auto_audio_stream_label_");
       audio_stream_names_provider.MaybeSetName(&p->audio_config->stream_label);
     }
-  }
 
-  if (run_params->video_codecs.empty()) {
-    run_params->video_codecs.push_back(
-        VideoCodecConfig(cricket::kVp8CodecName));
+    if (p->video_codecs.empty()) {
+      // TODO(mbonadei): Remove the usage of RunParams to set codecs, this is
+      // only needed for backwards compatibility.
+      if (!run_params->video_codecs.empty()) {
+        p->video_codecs = run_params->video_codecs;
+      } else {
+        p->video_codecs.push_back(
+            PeerConnectionE2EQualityTestFixture::VideoCodecConfig(
+                cricket::kVp8CodecName));
+      }
+    } else {
+      RTC_CHECK(run_params->video_codecs.empty())
+          << "Setting video_codecs in both PeerConfigurer and RunParams is not "
+             "supported.";
+    }
   }
 }
 
@@ -102,7 +113,6 @@
     const RunParams& run_params,
     const std::vector<std::unique_ptr<PeerConfigurerImpl>>& peers) {
   RTC_CHECK_GT(run_params.video_encoder_bitrate_multiplier, 0.0);
-  RTC_CHECK_GE(run_params.video_codecs.size(), 1);
 
   std::set<std::string> peer_names;
   std::set<std::string> video_labels;
@@ -113,6 +123,8 @@
 
   for (size_t i = 0; i < peers.size(); ++i) {
     Params* p = peers[i]->params();
+    // Each peer should at least support 1 video codec.
+    RTC_CHECK_GE(p->video_codecs.size(), 1);
 
     {
       RTC_CHECK(p->name);
@@ -160,14 +172,14 @@
           RTC_CHECK_LT(*video_config.simulcast_config->target_spatial_index,
                        video_config.simulcast_config->simulcast_streams_count);
         }
-        RTC_CHECK_EQ(run_params.video_codecs.size(), 1)
+        RTC_CHECK_EQ(p->video_codecs.size(), 1)
             << "Only 1 video codec is supported when simulcast is enabled in "
             << "at least 1 video config";
         RTC_CHECK(!video_config.max_encode_bitrate_bps)
             << "Setting max encode bitrate is not implemented for simulcast.";
         RTC_CHECK(!video_config.min_encode_bitrate_bps)
             << "Setting min encode bitrate is not implemented for simulcast.";
-        if (run_params.video_codecs[0].name == cricket::kVp8CodecName &&
+        if (p->video_codecs[0].name == cricket::kVp8CodecName &&
             !video_config.simulcast_config->encoding_params.empty()) {
           RTC_CHECK_EQ(video_config.simulcast_config->simulcast_streams_count,
                        video_config.simulcast_config->encoding_params.size())
diff --git a/test/pc/e2e/peer_configurer.h b/test/pc/e2e/peer_configurer.h
index 422d3d7..bacfb7a 100644
--- a/test/pc/e2e/peer_configurer.h
+++ b/test/pc/e2e/peer_configurer.h
@@ -168,6 +168,12 @@
     params_->bitrate_settings = bitrate_settings;
     return this;
   }
+  PeerConfigurer* SetVideoCodecs(
+      std::vector<PeerConnectionE2EQualityTestFixture::VideoCodecConfig>
+          video_codecs) override {
+    params_->video_codecs = std::move(video_codecs);
+    return this;
+  }
 
   PeerConfigurer* SetIceTransportFactory(
       std::unique_ptr<IceTransportFactory> factory) override {
diff --git a/test/pc/e2e/peer_connection_quality_test.cc b/test/pc/e2e/peer_connection_quality_test.cc
index 38a9ebf..6fbfd37 100644
--- a/test/pc/e2e/peer_connection_quality_test.cc
+++ b/test/pc/e2e/peer_connection_quality_test.cc
@@ -444,8 +444,9 @@
     RtpTransceiverInit transceiver_params;
     if (video_config.simulcast_config) {
       transceiver_params.direction = RtpTransceiverDirection::kSendOnly;
-      // Because simulcast enabled |run_params.video_codecs| has only 1 element.
-      if (run_params.video_codecs[0].name == cricket::kVp8CodecName) {
+      // Because simulcast enabled |alice_->params()->video_codecs| has only 1
+      // element.
+      if (alice_->params()->video_codecs[0].name == cricket::kVp8CodecName) {
         // For Vp8 simulcast we need to add as many RtpEncodingParameters to the
         // track as many simulcast streams requested. If they specified in
         // |video_config.simulcast_config| it should be copied from there.
@@ -508,14 +509,14 @@
     const RunParams& run_params) {
   std::vector<RtpCodecCapability> with_rtx_video_capabilities =
       FilterVideoCodecCapabilities(
-          run_params.video_codecs, true, run_params.use_ulp_fec,
+          peer->params()->video_codecs, true, run_params.use_ulp_fec,
           run_params.use_flex_fec,
           peer->pc_factory()
               ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
               .codecs);
   std::vector<RtpCodecCapability> without_rtx_video_capabilities =
       FilterVideoCodecCapabilities(
-          run_params.video_codecs, false, run_params.use_ulp_fec,
+          peer->params()->video_codecs, false, run_params.use_ulp_fec,
           run_params.use_flex_fec,
           peer->pc_factory()
               ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
@@ -552,8 +553,7 @@
            video_config.simulcast_config->simulcast_streams_count});
     }
   }
-  PatchingParams patching_params(run_params.video_codecs,
-                                 run_params.use_conference_mode,
+  PatchingParams patching_params(run_params.use_conference_mode,
                                  stream_label_to_simulcast_streams_count);
   return std::make_unique<SignalingInterceptor>(patching_params);
 }
@@ -594,8 +594,8 @@
   RTC_CHECK(offer);
   offer->ToString(&log_output);
   RTC_LOG(INFO) << "Original offer: " << log_output;
-  LocalAndRemoteSdp patch_result =
-      signaling_interceptor->PatchOffer(std::move(offer));
+  LocalAndRemoteSdp patch_result = signaling_interceptor->PatchOffer(
+      std::move(offer), alice_->params()->video_codecs[0]);
   patch_result.local_sdp->ToString(&log_output);
   RTC_LOG(INFO) << "Offer to set as local description: " << log_output;
   patch_result.remote_sdp->ToString(&log_output);
@@ -611,7 +611,8 @@
   RTC_CHECK(answer);
   answer->ToString(&log_output);
   RTC_LOG(INFO) << "Original answer: " << log_output;
-  patch_result = signaling_interceptor->PatchAnswer(std::move(answer));
+  patch_result = signaling_interceptor->PatchAnswer(
+      std::move(answer), bob_->params()->video_codecs[0]);
   patch_result.local_sdp->ToString(&log_output);
   RTC_LOG(INFO) << "Answer to set as local description: " << log_output;
   patch_result.remote_sdp->ToString(&log_output);
diff --git a/test/pc/e2e/peer_connection_quality_test_params.h b/test/pc/e2e/peer_connection_quality_test_params.h
index e1c0232..31938f7 100644
--- a/test/pc/e2e/peer_connection_quality_test_params.h
+++ b/test/pc/e2e/peer_connection_quality_test_params.h
@@ -116,6 +116,8 @@
 
   PeerConnectionInterface::RTCConfiguration rtc_configuration;
   BitrateSettings bitrate_settings;
+  std::vector<PeerConnectionE2EQualityTestFixture::VideoCodecConfig>
+      video_codecs;
 };
 
 }  // namespace webrtc_pc_e2e
diff --git a/test/pc/e2e/sdp/sdp_changer.cc b/test/pc/e2e/sdp/sdp_changer.cc
index b46aea1..aa067f0 100644
--- a/test/pc/e2e/sdp/sdp_changer.cc
+++ b/test/pc/e2e/sdp/sdp_changer.cc
@@ -166,14 +166,15 @@
 }
 
 LocalAndRemoteSdp SignalingInterceptor::PatchOffer(
-    std::unique_ptr<SessionDescriptionInterface> offer) {
+    std::unique_ptr<SessionDescriptionInterface> offer,
+    const PeerConnectionE2EQualityTestFixture::VideoCodecConfig& first_codec) {
   for (auto& content : offer->description()->contents()) {
     context_.mids_order.push_back(content.mid());
     cricket::MediaContentDescription* media_desc = content.media_description();
     if (media_desc->type() != cricket::MediaType::MEDIA_TYPE_VIDEO) {
       continue;
     }
-    if (content.media_description()->streams().size() == 0) {
+    if (content.media_description()->streams().empty()) {
       // It means that this media section describes receive only media section
       // in SDP.
       RTC_CHECK_EQ(content.media_description()->direction(),
@@ -183,13 +184,13 @@
     media_desc->set_conference_mode(params_.use_conference_mode);
   }
 
-  if (params_.stream_label_to_simulcast_streams_count.size() > 0) {
+  if (!params_.stream_label_to_simulcast_streams_count.empty()) {
     // Because simulcast enabled |params_.video_codecs| has only 1 element.
-    if (params_.video_codecs[0].name == cricket::kVp8CodecName) {
+    if (first_codec.name == cricket::kVp8CodecName) {
       return PatchVp8Offer(std::move(offer));
     }
 
-    if (params_.video_codecs[0].name == cricket::kVp9CodecName) {
+    if (first_codec.name == cricket::kVp9CodecName) {
       return PatchVp9Offer(std::move(offer));
     }
   }
@@ -362,7 +363,8 @@
 }
 
 LocalAndRemoteSdp SignalingInterceptor::PatchAnswer(
-    std::unique_ptr<SessionDescriptionInterface> answer) {
+    std::unique_ptr<SessionDescriptionInterface> answer,
+    const PeerConnectionE2EQualityTestFixture::VideoCodecConfig& first_codec) {
   for (auto& content : answer->description()->contents()) {
     cricket::MediaContentDescription* media_desc = content.media_description();
     if (media_desc->type() != cricket::MediaType::MEDIA_TYPE_VIDEO) {
@@ -375,13 +377,13 @@
     media_desc->set_conference_mode(params_.use_conference_mode);
   }
 
-  if (params_.stream_label_to_simulcast_streams_count.size() > 0) {
+  if (!params_.stream_label_to_simulcast_streams_count.empty()) {
     // Because simulcast enabled |params_.video_codecs| has only 1 element.
-    if (params_.video_codecs[0].name == cricket::kVp8CodecName) {
+    if (first_codec.name == cricket::kVp8CodecName) {
       return PatchVp8Answer(std::move(answer));
     }
 
-    if (params_.video_codecs[0].name == cricket::kVp9CodecName) {
+    if (first_codec.name == cricket::kVp9CodecName) {
       return PatchVp9Answer(std::move(answer));
     }
   }
@@ -534,7 +536,7 @@
       // This is candidate for simulcast section, so it should be transformed
       // into candidates for replicated sections. The sdpMLineIndex is set to
       // -1 and ignored if the rid is present.
-      for (auto rid : simulcast_info_it->second->rids) {
+      for (const std::string& rid : simulcast_info_it->second->rids) {
         out.push_back(CreateIceCandidate(rid, -1, candidate->candidate()));
       }
     } else {
@@ -560,7 +562,7 @@
       // section.
       out.push_back(CreateIceCandidate(simulcast_info_it->second->mid, 0,
                                        candidate->candidate()));
-    } else if (context_.simulcast_infos_by_rid.size()) {
+    } else if (!context_.simulcast_infos_by_rid.empty()) {
       // When using simulcast and bundle, put everything on the first m-line.
       out.push_back(CreateIceCandidate("", 0, candidate->candidate()));
     } else {
diff --git a/test/pc/e2e/sdp/sdp_changer.h b/test/pc/e2e/sdp/sdp_changer.h
index 11e3d42..943d332 100644
--- a/test/pc/e2e/sdp/sdp_changer.h
+++ b/test/pc/e2e/sdp/sdp_changer.h
@@ -61,17 +61,12 @@
 
 struct PatchingParams {
   PatchingParams(
-      std::vector<PeerConnectionE2EQualityTestFixture::VideoCodecConfig>
-          video_codecs,
       bool use_conference_mode,
       std::map<std::string, int> stream_label_to_simulcast_streams_count)
-      : video_codecs(std::move(video_codecs)),
-        use_conference_mode(use_conference_mode),
+      : use_conference_mode(use_conference_mode),
         stream_label_to_simulcast_streams_count(
             stream_label_to_simulcast_streams_count) {}
 
-  std::vector<PeerConnectionE2EQualityTestFixture::VideoCodecConfig>
-      video_codecs;
   bool use_conference_mode;
   std::map<std::string, int> stream_label_to_simulcast_streams_count;
 };
@@ -81,9 +76,11 @@
   explicit SignalingInterceptor(PatchingParams params) : params_(params) {}
 
   LocalAndRemoteSdp PatchOffer(
-      std::unique_ptr<SessionDescriptionInterface> offer);
+      std::unique_ptr<SessionDescriptionInterface> offer,
+      const PeerConnectionE2EQualityTestFixture::VideoCodecConfig& first_codec);
   LocalAndRemoteSdp PatchAnswer(
-      std::unique_ptr<SessionDescriptionInterface> offer);
+      std::unique_ptr<SessionDescriptionInterface> answer,
+      const PeerConnectionE2EQualityTestFixture::VideoCodecConfig& first_codec);
 
   std::vector<std::unique_ptr<IceCandidateInterface>> PatchOffererIceCandidates(
       rtc::ArrayView<const IceCandidateInterface* const> candidates);
@@ -132,9 +129,9 @@
   LocalAndRemoteSdp PatchVp9Offer(
       std::unique_ptr<SessionDescriptionInterface> offer);
   LocalAndRemoteSdp PatchVp8Answer(
-      std::unique_ptr<SessionDescriptionInterface> offer);
+      std::unique_ptr<SessionDescriptionInterface> answer);
   LocalAndRemoteSdp PatchVp9Answer(
-      std::unique_ptr<SessionDescriptionInterface> offer);
+      std::unique_ptr<SessionDescriptionInterface> answer);
 
   void FillSimulcastContext(SessionDescriptionInterface* offer);
   std::unique_ptr<cricket::SessionDescription> RestoreMediaSectionsOrder(