Enable VP8 configuration via scalability mode

Bug: webrtc:13959
Change-Id: I16054506ca4086767323443fb9b1e623224e234d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/258791
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36884}
diff --git a/modules/video_coding/video_codec_initializer.cc b/modules/video_coding/video_codec_initializer.cc
index 7ecacb2..03f7ffe 100644
--- a/modules/video_coding/video_codec_initializer.cc
+++ b/modules/video_coding/video_codec_initializer.cc
@@ -21,8 +21,10 @@
 #include "api/video/video_bitrate_allocation.h"
 #include "api/video_codecs/video_encoder.h"
 #include "modules/video_coding/codecs/av1/av1_svc_config.h"
+#include "modules/video_coding/codecs/vp8/vp8_scalability.h"
 #include "modules/video_coding/codecs/vp9/svc_config.h"
 #include "modules/video_coding/include/video_coding_defines.h"
+#include "modules/video_coding/svc/scalability_mode_util.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/experiments/min_video_bitrate_experiment.h"
 #include "rtc_base/logging.h"
@@ -114,8 +116,14 @@
     sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
     sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
     sim_stream->qpMax = streams[i].max_qp;
+
+    int num_temporal_layers =
+        streams[i].scalability_mode.has_value()
+            ? ScalabilityModeToNumTemporalLayers(*streams[i].scalability_mode)
+            : streams[i].num_temporal_layers.value_or(1);
+
     sim_stream->numberOfTemporalLayers =
-        static_cast<unsigned char>(streams[i].num_temporal_layers.value_or(1));
+        static_cast<unsigned char>(num_temporal_layers);
     sim_stream->active = streams[i].active;
 
     video_codec.width =
@@ -130,9 +138,16 @@
                                  static_cast<unsigned int>(streams[i].max_qp));
     max_framerate = std::max(max_framerate, streams[i].max_framerate);
 
+    // TODO(bugs.webrtc.org/11607): Since scalability mode is a top-level
+    // setting on VideoCodec, setting it makes sense only if it is the same for
+    // all simulcast streams.
     if (streams[0].scalability_mode != streams[i].scalability_mode) {
-      RTC_LOG(LS_WARNING) << "Inconsistent scalability modes configured.";
       scalability_mode.reset();
+      // For VP8, top-level scalability mode doesn't matter, since configuration
+      // is based on the per-simulcast stream configuration of temporal layers.
+      if (video_codec.codecType != kVideoCodecVP8) {
+        RTC_LOG(LS_WARNING) << "Inconsistent scalability modes configured.";
+      }
     }
   }
 
@@ -167,9 +182,26 @@
         *video_codec.VP8() = VideoEncoder::GetDefaultVp8Settings();
       }
 
-      video_codec.VP8()->numberOfTemporalLayers = static_cast<unsigned char>(
-          streams.back().num_temporal_layers.value_or(
-              video_codec.VP8()->numberOfTemporalLayers));
+      // Validate specified scalability modes. If some layer has an unsupported
+      // mode, store it as the top-level scalability mode, which will make
+      // InitEncode fail with an appropriate error.
+      for (const auto& stream : streams) {
+        if (stream.scalability_mode.has_value() &&
+            !VP8SupportsScalabilityMode(*stream.scalability_mode)) {
+          RTC_LOG(LS_WARNING)
+              << "Invalid scalability mode for VP8: "
+              << ScalabilityModeToString(*stream.scalability_mode);
+          video_codec.SetScalabilityMode(*stream.scalability_mode);
+          break;
+        }
+      }
+      video_codec.VP8()->numberOfTemporalLayers =
+          streams.back().scalability_mode.has_value()
+              ? ScalabilityModeToNumTemporalLayers(
+                    *streams.back().scalability_mode)
+              : streams.back().num_temporal_layers.value_or(
+                    video_codec.VP8()->numberOfTemporalLayers);
+
       RTC_DCHECK_GE(video_codec.VP8()->numberOfTemporalLayers, 1);
       RTC_DCHECK_LE(video_codec.VP8()->numberOfTemporalLayers,
                     kMaxTemporalStreams);