Use simulcast for screenshare only in conference mode

Also, don't crash if InitEncode fails for vp8.

BUG=chromium:705505

Review-Url: https://codereview.webrtc.org/2779163002
Cr-Original-Commit-Position: refs/heads/master@{#17452}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: fe627f30cbd3b4e0665237c7f309973cbf15e30b
diff --git a/media/engine/webrtcvideoengine2.cc b/media/engine/webrtcvideoengine2.cc
index f4b4b6f..8c3f958 100644
--- a/media/engine/webrtcvideoengine2.cc
+++ b/media/engine/webrtcvideoengine2.cc
@@ -1883,7 +1883,8 @@
   // configure a single stream.
   encoder_config.number_of_streams = parameters_.config.rtp.ssrcs.size();
   if (IsCodecBlacklistedForSimulcast(codec.name) ||
-      (is_screencast && !UseSimulcastScreenshare())) {
+      (is_screencast &&
+       (!UseSimulcastScreenshare() || !parameters_.conference_mode))) {
     encoder_config.number_of_streams = 1;
   }
 
@@ -1912,7 +1913,7 @@
 void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() {
   RTC_DCHECK_RUN_ON(&thread_checker_);
   if (!stream_) {
-    // The webrtc::VideoSendStream |stream_|has not yet been created but other
+    // The webrtc::VideoSendStream |stream_| has not yet been created but other
     // parameters has changed.
     return;
   }
diff --git a/media/engine/webrtcvideoengine2_unittest.cc b/media/engine/webrtcvideoengine2_unittest.cc
index 395d6ed..0589610 100644
--- a/media/engine/webrtcvideoengine2_unittest.cc
+++ b/media/engine/webrtcvideoengine2_unittest.cc
@@ -4360,4 +4360,12 @@
                           true);
 }
 
+TEST_F(WebRtcVideoChannel2SimulcastTest,
+       NoSimulcastScreenshareWithoutConference) {
+  webrtc::test::ScopedFieldTrials override_field_trials_(
+      "WebRTC-SimulcastScreenshare/Enabled/");
+  VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 1, true,
+                          false);
+}
+
 }  // namespace cricket
diff --git a/video/vie_encoder.cc b/video/vie_encoder.cc
index 728d37b..9940963 100644
--- a/video/vie_encoder.cc
+++ b/video/vie_encoder.cc
@@ -434,7 +434,7 @@
                      static_cast<uint32_t>(max_data_payload_length_)) == VCM_OK;
   if (!success) {
     LOG(LS_ERROR) << "Failed to configure encoder.";
-    RTC_DCHECK(success);
+    rate_allocator_.reset();
   }
 
   video_sender_.UpdateChannelParemeters(rate_allocator_.get(),
@@ -444,7 +444,9 @@
   if (framerate == 0)
     framerate = codec.maxFramerate;
   stats_proxy_->OnEncoderReconfigured(
-      encoder_config_, rate_allocator_->GetPreferredBitrateBps(framerate));
+      encoder_config_, rate_allocator_.get()
+                           ? rate_allocator_->GetPreferredBitrateBps(framerate)
+                           : codec.maxBitrate);
 
   pending_encoder_reconfiguration_ = false;
 
diff --git a/video/vie_encoder_unittest.cc b/video/vie_encoder_unittest.cc
index eedf771..4c19d58 100644
--- a/video/vie_encoder_unittest.cc
+++ b/video/vie_encoder_unittest.cc
@@ -8,12 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <algorithm>
 #include <limits>
 #include <utility>
 
 #include "webrtc/api/video/i420_buffer.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/media/base/videoadapter.h"
+#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
 #include "webrtc/system_wrappers/include/metrics_default.h"
 #include "webrtc/system_wrappers/include/sleep.h"
@@ -282,6 +284,11 @@
       quality_scaling_ = b;
     }
 
+    void ForceInitEncodeFailure(bool force_failure) {
+      rtc::CritScope lock(&local_crit_sect_);
+      force_init_encode_failed_ = force_failure;
+    }
+
    private:
     int32_t Encode(const VideoFrame& input_image,
                    const CodecSpecificInfo* codec_specific_info,
@@ -307,14 +314,39 @@
       return result;
     }
 
+    int32_t InitEncode(const VideoCodec* config,
+                       int32_t number_of_cores,
+                       size_t max_payload_size) override {
+      int res =
+          FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+      rtc::CritScope lock(&local_crit_sect_);
+      if (config->codecType == kVideoCodecVP8 && config->VP8().tl_factory) {
+        // Simulate setting up temporal layers, in order to validate the life
+        // cycle of these objects.
+        int num_streams = std::max<int>(1, config->numberOfSimulcastStreams);
+        int num_temporal_layers =
+            std::max<int>(1, config->VP8().numberOfTemporalLayers);
+        for (int i = 0; i < num_streams; ++i) {
+          allocated_temporal_layers_.emplace_back(
+              config->VP8().tl_factory->Create(i, num_temporal_layers, 42));
+        }
+      }
+      if (force_init_encode_failed_)
+        return -1;
+      return res;
+    }
+
     rtc::CriticalSection local_crit_sect_;
-    bool block_next_encode_ = false;
+    bool block_next_encode_ GUARDED_BY(local_crit_sect_) = false;
     rtc::Event continue_encode_event_;
-    uint32_t timestamp_ = 0;
-    int64_t ntp_time_ms_ = 0;
-    int last_input_width_ = 0;
-    int last_input_height_ = 0;
-    bool quality_scaling_ = true;
+    uint32_t timestamp_ GUARDED_BY(local_crit_sect_) = 0;
+    int64_t ntp_time_ms_ GUARDED_BY(local_crit_sect_) = 0;
+    int last_input_width_ GUARDED_BY(local_crit_sect_) = 0;
+    int last_input_height_ GUARDED_BY(local_crit_sect_) = 0;
+    bool quality_scaling_ GUARDED_BY(local_crit_sect_) = true;
+    std::vector<std::unique_ptr<TemporalLayers>> allocated_temporal_layers_
+        GUARDED_BY(local_crit_sect_);
+    bool force_init_encode_failed_ GUARDED_BY(local_crit_sect_) = false;
   };
 
   class TestSink : public ViEEncoder::EncoderSink {
@@ -1243,4 +1275,16 @@
 
   vie_encoder_->Stop();
 }
+
+TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) {
+  fake_encoder_.ForceInitEncodeFailure(true);
+  vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
+  ResetEncoder("VP8", 2, 1, true);
+  const int kFrameWidth = 1280;
+  const int kFrameHeight = 720;
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(1, kFrameWidth, kFrameHeight));
+  sink_.ExpectDroppedFrame();
+  vie_encoder_->Stop();
+}
 }  // namespace webrtc