Update VideoEncoderSoftwareFallbackWrapper to take VideoEncoder as arg

VideoEncoderSoftwareFallbackWrapper is updated to take a VideoEncoder as
argument instead relying on built-in SW codecs. The purpose is to make
VideoEncoderSoftwareFallbackWrapper more modular and not depend on
built-in SW encoders.

Bug: webrtc:7925
Change-Id: I99896f0751cfb77e01efd29c97d3bd07bdb2c7c0
Reviewed-on: https://webrtc-review.googlesource.com/22320
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Anders Carlsson <andersc@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20671}
diff --git a/media/engine/convert_legacy_video_factory.cc b/media/engine/convert_legacy_video_factory.cc
index d40f869..f3638ee 100644
--- a/media/engine/convert_legacy_video_factory.cc
+++ b/media/engine/convert_legacy_video_factory.cc
@@ -27,6 +27,7 @@
 #include "media/engine/webrtcvideodecoderfactory.h"
 #include "media/engine/webrtcvideoencoderfactory.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/ptr_util.h"
 
 namespace cricket {
 
@@ -95,44 +96,39 @@
   std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
       const webrtc::SdpVideoFormat& format) {
     const VideoCodec codec(format);
+
+    // Try creating internal encoder.
+    std::unique_ptr<webrtc::VideoEncoder> internal_encoder;
+    if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(),
+                          codec)) {
+      internal_encoder =
+          CodecNamesEq(format.name.c_str(), kVp8CodecName)
+              ? rtc::MakeUnique<webrtc::VP8EncoderSimulcastProxy>(
+                    internal_encoder_factory_.get())
+              : std::unique_ptr<webrtc::VideoEncoder>(
+                    internal_encoder_factory_->CreateVideoEncoder(codec));
+    }
+
     // Try creating external encoder.
+    std::unique_ptr<webrtc::VideoEncoder> external_encoder;
     if (external_encoder_factory_ != nullptr &&
         FindMatchingCodec(external_encoder_factory_->supported_codecs(),
                           codec)) {
-      std::unique_ptr<webrtc::VideoEncoder> external_encoder;
-      if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) {
-        // If it's a codec type we can simulcast, create a wrapped encoder.
-        external_encoder = std::unique_ptr<webrtc::VideoEncoder>(
-            new webrtc::SimulcastEncoderAdapter(
-                external_encoder_factory_.get()));
-      } else {
-        external_encoder =
-            CreateScopedVideoEncoder(external_encoder_factory_.get(), codec);
-      }
-      if (external_encoder) {
-        return std::unique_ptr<webrtc::VideoEncoder>(
-            new webrtc::VideoEncoderSoftwareFallbackWrapper(
-                codec, std::move(external_encoder)));
-      }
+      external_encoder = CodecNamesEq(format.name.c_str(), kVp8CodecName)
+                             ? rtc::MakeUnique<webrtc::SimulcastEncoderAdapter>(
+                                   external_encoder_factory_.get())
+                             : CreateScopedVideoEncoder(
+                                   external_encoder_factory_.get(), codec);
     }
 
-    // Try creating internal encoder.
-    if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(),
-                          codec)) {
-      if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) {
-        return std::unique_ptr<webrtc::VideoEncoder>(
-            new webrtc::VP8EncoderSimulcastProxy(
-                internal_encoder_factory_.get()));
-      } else {
-        return std::unique_ptr<webrtc::VideoEncoder>(
-            internal_encoder_factory_->CreateVideoEncoder(codec));
-      }
+    if (internal_encoder && external_encoder) {
+      // Both internal SW encoder and external HW encoder available - create
+      // fallback encoder.
+      return rtc::MakeUnique<webrtc::VideoEncoderSoftwareFallbackWrapper>(
+          std::move(internal_encoder), std::move(external_encoder));
     }
-
-    // This shouldn't happen, we should not be trying to create something we
-    // don't support.
-    RTC_NOTREACHED();
-    return nullptr;
+    return external_encoder ? std::move(external_encoder)
+                            : std::move(internal_encoder);
   }
 
   std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const {
diff --git a/media/engine/videoencodersoftwarefallbackwrapper.cc b/media/engine/videoencodersoftwarefallbackwrapper.cc
index 5e57c55..69254f5 100644
--- a/media/engine/videoencodersoftwarefallbackwrapper.cc
+++ b/media/engine/videoencodersoftwarefallbackwrapper.cc
@@ -25,11 +25,8 @@
 const char kVp8ForceFallbackEncoderFieldTrial[] =
     "WebRTC-VP8-Forced-Fallback-Encoder-v2";
 
-bool EnableForcedFallback(const cricket::VideoCodec& codec) {
-  if (!webrtc::field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial))
-    return false;
-
-  return (PayloadStringToCodecType(codec.name) == kVideoCodecVP8);
+bool EnableForcedFallback() {
+  return field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial);
 }
 
 bool IsForcedFallbackPossible(const VideoCodec& codec_settings) {
@@ -68,8 +65,8 @@
 }  // namespace
 
 VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
-    const cricket::VideoCodec& codec,
-    std::unique_ptr<webrtc::VideoEncoder> encoder)
+    std::unique_ptr<webrtc::VideoEncoder> sw_encoder,
+    std::unique_ptr<webrtc::VideoEncoder> hw_encoder)
     : number_of_cores_(0),
       max_payload_size_(0),
       rates_set_(false),
@@ -77,10 +74,11 @@
       channel_parameters_set_(false),
       packet_loss_(0),
       rtt_(0),
-      codec_(codec),
-      encoder_(std::move(encoder)),
+      use_fallback_encoder_(false),
+      encoder_(std::move(hw_encoder)),
+      fallback_encoder_(std::move(sw_encoder)),
       callback_(nullptr),
-      forced_fallback_possible_(EnableForcedFallback(codec)) {
+      forced_fallback_possible_(EnableForcedFallback()) {
   if (forced_fallback_possible_) {
     GetForcedFallbackParamsFromFieldTrialGroup(
         &forced_fallback_.min_pixels_, &forced_fallback_.max_pixels_,
@@ -91,20 +89,13 @@
 
 bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() {
   RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding.";
-  MaybeModifyCodecForFallback();
-  cricket::InternalEncoderFactory internal_factory;
-  if (!FindMatchingCodec(internal_factory.supported_codecs(), codec_)) {
-    RTC_LOG(LS_WARNING)
-        << "Encoder requesting fallback to codec not supported in software.";
-    return false;
-  }
-  fallback_encoder_.reset(internal_factory.CreateVideoEncoder(codec_));
-  if (fallback_encoder_->InitEncode(&codec_settings_, number_of_cores_,
-                                    max_payload_size_) !=
-      WEBRTC_VIDEO_CODEC_OK) {
+
+  const int ret = fallback_encoder_->InitEncode(
+      &codec_settings_, number_of_cores_, max_payload_size_);
+  use_fallback_encoder_ = (ret == WEBRTC_VIDEO_CODEC_OK);
+  if (!use_fallback_encoder_) {
     RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback.";
     fallback_encoder_->Release();
-    fallback_encoder_.reset();
     return false;
   }
   // Replay callback, rates, and channel parameters.
@@ -148,13 +139,13 @@
 
   int32_t ret =
       encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size);
-  if (ret == WEBRTC_VIDEO_CODEC_OK || codec_.name.empty()) {
-    if (fallback_encoder_) {
+  if (ret == WEBRTC_VIDEO_CODEC_OK) {
+    if (use_fallback_encoder_) {
       RTC_LOG(LS_WARNING)
           << "InitEncode OK, no longer using the software fallback encoder.";
       fallback_encoder_->Release();
+      use_fallback_encoder_ = false;
     }
-    fallback_encoder_.reset();
     if (callback_)
       encoder_->RegisterEncodeCompleteCallback(callback_);
     return ret;
@@ -171,25 +162,21 @@
     EncodedImageCallback* callback) {
   callback_ = callback;
   int32_t ret = encoder_->RegisterEncodeCompleteCallback(callback);
-  if (fallback_encoder_)
+  if (use_fallback_encoder_)
     return fallback_encoder_->RegisterEncodeCompleteCallback(callback);
   return ret;
 }
 
 int32_t VideoEncoderSoftwareFallbackWrapper::Release() {
-  // If the fallback_encoder_ is non-null, it means it was created via
-  // InitFallbackEncoder which has Release()d encoder_, so we should only ever
-  // need to Release() whichever one is active.
-  if (fallback_encoder_)
-    return fallback_encoder_->Release();
-  return encoder_->Release();
+  return use_fallback_encoder_ ? fallback_encoder_->Release()
+                               : encoder_->Release();
 }
 
 int32_t VideoEncoderSoftwareFallbackWrapper::Encode(
     const VideoFrame& frame,
     const CodecSpecificInfo* codec_specific_info,
     const std::vector<FrameType>* frame_types) {
-  if (fallback_encoder_)
+  if (use_fallback_encoder_)
     return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
   int32_t ret = encoder_->Encode(frame, codec_specific_info, frame_types);
   // If requested, try a software fallback.
@@ -215,7 +202,7 @@
   packet_loss_ = packet_loss;
   rtt_ = rtt;
   int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt);
-  if (fallback_encoder_)
+  if (use_fallback_encoder_)
     return fallback_encoder_->SetChannelParameters(packet_loss, rtt);
   return ret;
 }
@@ -227,15 +214,14 @@
   bitrate_allocation_ = bitrate_allocation;
   framerate_ = framerate;
   int32_t ret = encoder_->SetRateAllocation(bitrate_allocation_, framerate);
-  if (fallback_encoder_)
+  if (use_fallback_encoder_)
     return fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate);
   return ret;
 }
 
 bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const {
-  if (fallback_encoder_)
-    return fallback_encoder_->SupportsNativeHandle();
-  return encoder_->SupportsNativeHandle();
+  return use_fallback_encoder_ ? fallback_encoder_->SupportsNativeHandle()
+                               : encoder_->SupportsNativeHandle();
 }
 
 VideoEncoder::ScalingSettings
@@ -258,19 +244,18 @@
   return encoder_->GetScalingSettings();
 }
 
-const char *VideoEncoderSoftwareFallbackWrapper::ImplementationName() const {
-  if (fallback_encoder_)
-    return fallback_encoder_->ImplementationName();
-  return encoder_->ImplementationName();
+const char* VideoEncoderSoftwareFallbackWrapper::ImplementationName() const {
+  return use_fallback_encoder_ ? fallback_encoder_->ImplementationName()
+                               : encoder_->ImplementationName();
 }
 
 bool VideoEncoderSoftwareFallbackWrapper::IsForcedFallbackActive() const {
-  return (forced_fallback_possible_ && fallback_encoder_ &&
+  return (forced_fallback_possible_ && use_fallback_encoder_ &&
           forced_fallback_.active_);
 }
 
 bool VideoEncoderSoftwareFallbackWrapper::TryInitForcedFallbackEncoder() {
-  if (!forced_fallback_possible_ || fallback_encoder_) {
+  if (!forced_fallback_possible_ || use_fallback_encoder_) {
     return false;
   }
   // Fallback not active.
@@ -313,20 +298,11 @@
   if (!IsForcedFallbackPossible(codec_settings_)) {
     if (IsForcedFallbackActive()) {
       fallback_encoder_->Release();
-      fallback_encoder_.reset();
+      use_fallback_encoder_ = false;
     }
     RTC_LOG(LS_INFO) << "Disable forced_fallback_possible_ due to settings.";
     forced_fallback_possible_ = false;
   }
 }
 
-void VideoEncoderSoftwareFallbackWrapper::MaybeModifyCodecForFallback() {
-  // We have a specific case for H264 ConstrainedBaseline because that is the
-  // only supported profile in Sw fallback.
-  if (!cricket::CodecNamesEq(codec_.name.c_str(), cricket::kH264CodecName))
-    return;
-  codec_.SetParam(cricket::kH264FmtpProfileLevelId,
-                  cricket::kH264ProfileLevelConstrainedBaseline);
-}
-
 }  // namespace webrtc
diff --git a/media/engine/videoencodersoftwarefallbackwrapper.h b/media/engine/videoencodersoftwarefallbackwrapper.h
index 6322982..a9a349c 100644
--- a/media/engine/videoencodersoftwarefallbackwrapper.h
+++ b/media/engine/videoencodersoftwarefallbackwrapper.h
@@ -26,8 +26,8 @@
 class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder {
  public:
   VideoEncoderSoftwareFallbackWrapper(
-      const cricket::VideoCodec& codec,
-      std::unique_ptr<webrtc::VideoEncoder> encoder);
+      std::unique_ptr<webrtc::VideoEncoder> sw_encoder,
+      std::unique_ptr<webrtc::VideoEncoder> hw_encoder);
 
   int32_t InitEncode(const VideoCodec* codec_settings,
                      int32_t number_of_cores,
@@ -87,10 +87,10 @@
   uint32_t packet_loss_;
   int64_t rtt_;
 
-  cricket::VideoCodec codec_;
-  std::unique_ptr<webrtc::VideoEncoder> encoder_;
+  bool use_fallback_encoder_;
+  const std::unique_ptr<webrtc::VideoEncoder> encoder_;
 
-  std::unique_ptr<webrtc::VideoEncoder> fallback_encoder_;
+  const std::unique_ptr<webrtc::VideoEncoder> fallback_encoder_;
   EncodedImageCallback* callback_;
 
   bool forced_fallback_possible_;
diff --git a/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc b/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc
index 1ec325d..e39b02f 100644
--- a/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc
+++ b/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc
@@ -13,6 +13,7 @@
 #include <utility>
 
 #include "api/video/i420_buffer.h"
+#include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "modules/video_coding/codecs/vp8/simulcast_rate_allocator.h"
 #include "modules/video_coding/codecs/vp8/temporal_layers.h"
 #include "modules/video_coding/include/video_codec_interface.h"
@@ -42,7 +43,7 @@
       const std::string& field_trials)
       : override_field_trials_(field_trials),
         fake_encoder_(new CountingFakeEncoder()),
-        fallback_wrapper_(cricket::VideoCodec("VP8"),
+        fallback_wrapper_(std::unique_ptr<VideoEncoder>(VP8Encoder::Create()),
                           std::unique_ptr<VideoEncoder>(fake_encoder_)) {}
 
   class CountingFakeEncoder : public VideoEncoder {
diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
index 34ec2a1..dc77605 100644
--- a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
+++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
@@ -382,7 +382,9 @@
 
   if (config_.sw_fallback_encoder) {
     encoder_ = rtc::MakeUnique<VideoEncoderSoftwareFallbackWrapper>(
-        codec, std::move(encoder_));
+        std::unique_ptr<VideoEncoder>(
+            cricket::InternalEncoderFactory().CreateVideoEncoder(codec)),
+        std::move(encoder_));
   }
   if (config_.sw_fallback_decoder) {
     decoder_ = rtc::MakeUnique<VideoDecoderSoftwareFallbackWrapper>(