SEA: Only spawn multi-layered encoders if active layers > 1.

With this CL, SimulcastEncoderAdapter no longer configures its encoder
as multi-layered if we only have a single active layer. Instead we
create a single single-layered encoder for that one and only active
layer. When using VP8 SW encoder this means that LibvpxVp8Encoder is
configured to only prepare a single video frame which avoids the cost of
scaling down to layers that we do not send. (A multi-layered
LibvpxVp8Encoder is required to scale even layers we don't encode.)

When profiling this CL I found very small but measurable gains for
representative downscale factors of 20.1 ms of 60 s profile. This is
just 0.0335% CPU so it's not much, but skipping a downscale might be
worth a lot more if we have to map/unmap buffers or do GPU round-trips
in the future (which I have not measured).

When downscaling to factors 4 and 2 due to libyuv having a
"fast-path" for these (i.e. no adaptation active), zero difference was
found for NV12. For I420 there was small regression of 16.1 ms
(0.026% CPU) for this one edge-case. It's possible to work around this,
but considering the tiny changes we're talking about, I really don't
think it's worth the additional complexity. I'll file a bug on libyuv
about scaling factors 2+2 vs 4 and leave it at that.

Bug: webrtc:12603
Change-Id: Id462140c6a829cf6b460baae868e94243f477db3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219683
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34092}
diff --git a/media/engine/simulcast_encoder_adapter.cc b/media/engine/simulcast_encoder_adapter.cc
index bee7b23..3af022a 100644
--- a/media/engine/simulcast_encoder_adapter.cc
+++ b/media/engine/simulcast_encoder_adapter.cc
@@ -344,20 +344,24 @@
 
   // Two distinct scenarios:
   // * Singlecast (total_streams_count == 1) or simulcast with simulcast-capable
-  //   underlaying encoder implementation. SEA operates in bypass mode: original
-  //   settings are passed to the underlaying encoder, frame encode complete
-  //   callback is not intercepted.
+  //   underlaying encoder implementation if active_streams_count > 1. SEA
+  //   operates in bypass mode: original settings are passed to the underlaying
+  //   encoder, frame encode complete callback is not intercepted.
   // * Multi-encoder simulcast or singlecast if layers are deactivated
-  //   (total_streams_count > 1 and active_streams_count >= 1). SEA creates
-  //   N=active_streams_count encoders and configures each to produce a single
-  //   stream.
+  //   (active_streams_count >= 1). SEA creates N=active_streams_count encoders
+  //   and configures each to produce a single stream.
 
+  int active_streams_count = CountActiveStreams(*inst);
+  // If we only have a single active layer it is better to create an encoder
+  // with only one configured layer than creating it with all-but-one disabled
+  // layers because that way we control scaling.
+  bool separate_encoders_needed =
+      !encoder_context->encoder().GetEncoderInfo().supports_simulcast ||
+      active_streams_count == 1;
   // Singlecast or simulcast with simulcast-capable underlaying encoder.
-  if (total_streams_count_ == 1 ||
-      encoder_context->encoder().GetEncoderInfo().supports_simulcast) {
+  if (total_streams_count_ == 1 || !separate_encoders_needed) {
     int ret = encoder_context->encoder().InitEncode(&codec_, settings);
     if (ret >= 0) {
-      int active_streams_count = CountActiveStreams(*inst);
       stream_contexts_.emplace_back(
           /*parent=*/nullptr, std::move(encoder_context),
           /*framerate_controller=*/nullptr, /*stream_idx=*/0, codec_.width,