Allow to set av1 scalability mode after encoder is constructed

Bug: webrtc:11404
Change-Id: I70b4115c8afdc4f32fd876d31d54b7d95d0a7e1b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188582
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32437}
diff --git a/api/video_codecs/video_codec.h b/api/video_codecs/video_codec.h
index 48e72ed..e1a8d06 100644
--- a/api/video_codecs/video_codec.h
+++ b/api/video_codecs/video_codec.h
@@ -16,6 +16,7 @@
 
 #include <string>
 
+#include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 #include "api/video/video_bitrate_allocation.h"
 #include "api/video/video_codec_type.h"
@@ -101,6 +102,14 @@
  public:
   VideoCodec();
 
+  // Scalability mode as described in
+  // https://www.w3.org/TR/webrtc-svc/#scalabilitymodes*
+  // or value 'NONE' to indicate no scalability.
+  absl::string_view ScalabilityMode() const { return scalability_mode_; }
+  void SetScalabilityMode(absl::string_view scalability_mode) {
+    scalability_mode_ = std::string(scalability_mode);
+  }
+
   // Public variables. TODO(hta): Make them private with accessors.
   VideoCodecType codecType;
 
@@ -166,6 +175,7 @@
   // TODO(hta): Consider replacing the union with a pointer type.
   // This will allow removing the VideoCodec* types from this file.
   VideoCodecUnion codec_specific_;
+  std::string scalability_mode_;
 };
 
 }  // namespace webrtc
diff --git a/media/engine/simulcast_encoder_adapter.cc b/media/engine/simulcast_encoder_adapter.cc
index 961de15..36163c8 100644
--- a/media/engine/simulcast_encoder_adapter.cc
+++ b/media/engine/simulcast_encoder_adapter.cc
@@ -156,8 +156,6 @@
   // The adapter is typically created on the worker thread, but operated on
   // the encoder task queue.
   encoder_queue_.Detach();
-
-  memset(&codec_, 0, sizeof(webrtc::VideoCodec));
 }
 
 SimulcastEncoderAdapter::~SimulcastEncoderAdapter() {
diff --git a/modules/video_coding/codecs/av1/BUILD.gn b/modules/video_coding/codecs/av1/BUILD.gn
index b88bdef..27b22a0 100644
--- a/modules/video_coding/codecs/av1/BUILD.gn
+++ b/modules/video_coding/codecs/av1/BUILD.gn
@@ -40,6 +40,7 @@
   public = [ "libaom_av1_encoder.h" ]
   deps = [
     "../../../../api/video_codecs:video_codecs_api",
+    "../../svc:scalability_structures",
     "../../svc:scalable_video_controller",
   ]
   absl_deps = [
diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
index 435761b..6216b9b 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
@@ -27,6 +27,7 @@
 #include "api/video_codecs/video_encoder.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "modules/video_coding/include/video_error_codes.h"
+#include "modules/video_coding/svc/create_scalability_structure.h"
 #include "modules/video_coding/svc/scalable_video_controller.h"
 #include "modules/video_coding/svc/scalable_video_controller_no_layering.h"
 #include "rtc_base/checks.h"
@@ -93,7 +94,7 @@
   void SetSvcRefFrameConfig(
       const ScalableVideoController::LayerFrameConfig& layer_frame);
 
-  const std::unique_ptr<ScalableVideoController> svc_controller_;
+  std::unique_ptr<ScalableVideoController> svc_controller_;
   bool inited_;
   absl::optional<aom_svc_params_t> svc_params_;
   VideoCodec encoder_settings_;
@@ -164,6 +165,21 @@
                            "LibaomAv1Encoder.";
     return result;
   }
+  if (encoder_settings_.numberOfSimulcastStreams > 1) {
+    RTC_LOG(LS_WARNING) << "Simulcast is not implemented by LibaomAv1Encoder.";
+    return result;
+  }
+  absl::string_view scalability_mode = encoder_settings_.ScalabilityMode();
+  // When scalability_mode is not set, keep using svc_controller_ created
+  // at construction of the encoder.
+  if (!scalability_mode.empty()) {
+    svc_controller_ = CreateScalabilityStructure(scalability_mode);
+  }
+  if (svc_controller_ == nullptr) {
+    RTC_LOG(LS_WARNING) << "Failed to set scalability mode "
+                        << scalability_mode;
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
 
   if (!SetSvcParams(svc_controller_->StreamConfig())) {
     return WEBRTC_VIDEO_CODEC_ERROR;
diff --git a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
index dd3d163..78725ab 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
@@ -179,14 +179,13 @@
 class LibaomAv1SvcTest : public ::testing::TestWithParam<SvcTestParam> {};
 
 TEST_P(LibaomAv1SvcTest, EncodeAndDecodeAllDecodeTargets) {
-  std::unique_ptr<ScalableVideoController> svc_controller =
-      CreateScalabilityStructure(GetParam().name);
-  size_t num_decode_targets =
-      svc_controller->DependencyStructure().num_decode_targets;
+  size_t num_decode_targets = CreateScalabilityStructure(GetParam().name)
+                                  ->DependencyStructure()
+                                  .num_decode_targets;
 
-  std::unique_ptr<VideoEncoder> encoder =
-      CreateLibaomAv1Encoder(std::move(svc_controller));
+  std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
   VideoCodec codec_settings = DefaultCodecSettings();
+  codec_settings.SetScalabilityMode(GetParam().name);
   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
             WEBRTC_VIDEO_CODEC_OK);
   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
diff --git a/modules/video_coding/decoder_database.cc b/modules/video_coding/decoder_database.cc
index 32be39b..a7a4b8f 100644
--- a/modules/video_coding/decoder_database.cc
+++ b/modules/video_coding/decoder_database.cc
@@ -96,7 +96,7 @@
   dec_map_.erase(it);
   if (payload_type == current_payload_type_) {
     // This codec is currently in use.
-    memset(&receive_codec_, 0, sizeof(VideoCodec));
+    receive_codec_ = {};
     current_payload_type_ = 0;
   }
   return true;
@@ -113,7 +113,7 @@
   // If decoder exists - delete.
   if (ptr_decoder_) {
     ptr_decoder_.reset();
-    memset(&receive_codec_, 0, sizeof(VideoCodec));
+    receive_codec_ = {};
     current_payload_type_ = 0;
   }
   ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
@@ -126,7 +126,7 @@
   if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
       0) {
     ptr_decoder_.reset();
-    memset(&receive_codec_, 0, sizeof(VideoCodec));
+    receive_codec_ = {};
     current_payload_type_ = 0;
     return nullptr;
   }
@@ -178,7 +178,7 @@
     RTC_LOG(LS_ERROR) << "Failed to initialize decoder. Error code: " << err;
     return nullptr;
   }
-  memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
+  *new_codec = *decoder_item->settings.get();
   return ptr_decoder;
 }
 
diff --git a/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc b/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
index 69c14ff..259524f 100644
--- a/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
+++ b/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
@@ -54,7 +54,6 @@
 class SimulcastRateAllocatorTest : public ::testing::TestWithParam<bool> {
  public:
   SimulcastRateAllocatorTest() {
-    memset(&codec_, 0, sizeof(VideoCodec));
     codec_.codecType = kVideoCodecVP8;
     codec_.minBitrate = kMinBitrateKbps;
     codec_.maxBitrate = kLegacyScreenshareMaxBitrateKbps;
diff --git a/modules/video_coding/utility/simulcast_test_fixture_impl.cc b/modules/video_coding/utility/simulcast_test_fixture_impl.cc
index 981454e..e262d0f 100644
--- a/modules/video_coding/utility/simulcast_test_fixture_impl.cc
+++ b/modules/video_coding/utility/simulcast_test_fixture_impl.cc
@@ -213,7 +213,7 @@
     VideoCodecType codec_type,
     bool reverse_layer_order) {
   RTC_CHECK(settings);
-  memset(settings, 0, sizeof(VideoCodec));
+  *settings = {};
   settings->codecType = codec_type;
   settings->startBitrate = 300;
   settings->minBitrate = 30;
diff --git a/test/video_codec_settings.h b/test/video_codec_settings.h
index 8e56535..82c82cd 100644
--- a/test/video_codec_settings.h
+++ b/test/video_codec_settings.h
@@ -25,7 +25,7 @@
 const uint16_t kTestOutlierFrameSizePercent = 250;
 
 static void CodecSettings(VideoCodecType codec_type, VideoCodec* settings) {
-  memset(settings, 0, sizeof(VideoCodec));
+  *settings = {};
 
   settings->width = kTestWidth;
   settings->height = kTestHeight;
diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc
index 02eb903..fbd32e4 100644
--- a/video/video_receive_stream.cc
+++ b/video/video_receive_stream.cc
@@ -115,8 +115,6 @@
 
 VideoCodec CreateDecoderVideoCodec(const VideoReceiveStream::Decoder& decoder) {
   VideoCodec codec;
-  memset(&codec, 0, sizeof(codec));
-
   codec.codecType = PayloadStringToCodecType(decoder.video_format.name);
 
   if (codec.codecType == kVideoCodecVP8) {
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index 21c188f..c2440f8 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -113,8 +113,6 @@
 
 VideoCodec CreateDecoderVideoCodec(const VideoReceiveStream::Decoder& decoder) {
   VideoCodec codec;
-  memset(&codec, 0, sizeof(codec));
-
   codec.codecType = PayloadStringToCodecType(decoder.video_format.name);
 
   if (codec.codecType == kVideoCodecVP8) {