WebRtcVideoEngine: Encapsulate logic for unifying internal and external video codecs

This CL encapsulates the logic for unifying the internal and external
video encoders into a helper class. The purpose is to prepare for
introducing a new video encoder factory interface that inherently
represents all encoders (i.e. both internal and external). A helper
interface EncoderFactoryAdapter is introduced that both the old
WebRtcVideoEncoderFactory and the new factory interface can implement
and serves as common point to leave the rest of the code unchanged.

BUG=webrtc:7925

Review-Url: https://codereview.webrtc.org/3006713002
Cr-Original-Commit-Position: refs/heads/master@{#19600}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: a35df4260f2e51f35e94fa74d1e840f73b597369
diff --git a/media/engine/webrtcvideoengine.cc b/media/engine/webrtcvideoengine.cc
index 274b801..0305444 100644
--- a/media/engine/webrtcvideoengine.cc
+++ b/media/engine/webrtcvideoengine.cc
@@ -42,7 +42,68 @@
 using DegradationPreference = webrtc::VideoSendStream::DegradationPreference;
 
 namespace cricket {
+// This class represents all encoders, i.e. both internal and external. It
+// serves as a temporary adapter between WebRtcVideoEncoderFactory* and the new
+// factory interface that is being developed.
+// TODO(magjed): Remove once WebRtcVideoEncoderFactory* is deprecated and
+// webrtc:7925 is fixed.
+class EncoderFactoryAdapter {
+ public:
+  struct AllocatedEncoder {
+    AllocatedEncoder() = default;
+    AllocatedEncoder(std::unique_ptr<webrtc::VideoEncoder> encoder,
+                     bool is_hardware_accelerated,
+                     bool has_internal_source);
+
+    std::unique_ptr<webrtc::VideoEncoder> encoder;
+    bool is_hardware_accelerated;
+    bool has_internal_source;
+  };
+
+  virtual ~EncoderFactoryAdapter() {}
+
+  virtual AllocatedEncoder CreateVideoEncoder(
+      const VideoCodec& codec,
+      bool is_conference_mode_screenshare) const = 0;
+
+  virtual std::vector<VideoCodec> GetSupportedCodecs() const = 0;
+
+  virtual std::unique_ptr<EncoderFactoryAdapter> clone() const = 0;
+};
+
 namespace {
+
+// Wraps cricket::WebRtcVideoEncoderFactory* into common EncoderFactoryAdapter
+// interface.
+// TODO(magjed): Add wrapper class for future webrtc::VideoEncoderFactory
+// interface, https://bugs.chromium.org/p/webrtc/issues/detail?id=7925.
+class CricketEncoderFactoryAdapter : public EncoderFactoryAdapter {
+ public:
+  explicit CricketEncoderFactoryAdapter(
+      WebRtcVideoEncoderFactory* external_encoder_factory)
+      : internal_encoder_factory_(new InternalEncoderFactory()),
+        external_encoder_factory_(external_encoder_factory) {}
+
+ private:
+  explicit CricketEncoderFactoryAdapter(
+      const CricketEncoderFactoryAdapter& other)
+      : CricketEncoderFactoryAdapter(other.external_encoder_factory_) {}
+
+  AllocatedEncoder CreateVideoEncoder(
+      const VideoCodec& codec,
+      bool is_conference_mode_screenshare) const override;
+
+  std::vector<VideoCodec> GetSupportedCodecs() const override;
+
+  std::unique_ptr<EncoderFactoryAdapter> clone() const override {
+    return std::unique_ptr<EncoderFactoryAdapter>(
+        new CricketEncoderFactoryAdapter(*this));
+  }
+
+  const std::unique_ptr<WebRtcVideoEncoderFactory> internal_encoder_factory_;
+  WebRtcVideoEncoderFactory* const external_encoder_factory_;
+};
+
 // If this field trial is enabled, we will enable sending FlexFEC and disable
 // sending ULPFEC whenever the former has been negotiated in the SDPs.
 bool IsFlexfecFieldTrialEnabled() {
@@ -206,9 +267,6 @@
 // Minimum time interval for logging stats.
 static const int64_t kStatsLogIntervalMs = 10000;
 
-static std::vector<VideoCodec> GetSupportedCodecs(
-    const WebRtcVideoEncoderFactory* external_encoder_factory);
-
 rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings>
 WebRtcVideoChannel::WebRtcVideoSendStream::ConfigureVideoEncoderSettings(
     const VideoCodec& codec) {
@@ -310,7 +368,8 @@
 WebRtcVideoEngine::WebRtcVideoEngine()
     : initialized_(false),
       external_decoder_factory_(NULL),
-      external_encoder_factory_(NULL) {
+      encoder_factory_(new CricketEncoderFactoryAdapter(
+          nullptr /* external_encoder_factory */)) {
   LOG(LS_INFO) << "WebRtcVideoEngine::WebRtcVideoEngine()";
 }
 
@@ -329,13 +388,12 @@
     const VideoOptions& options) {
   RTC_DCHECK(initialized_);
   LOG(LS_INFO) << "CreateChannel. Options: " << options.ToString();
-  return new WebRtcVideoChannel(call, config, options,
-                                external_encoder_factory_,
+  return new WebRtcVideoChannel(call, config, options, *encoder_factory_,
                                 external_decoder_factory_);
 }
 
 std::vector<VideoCodec> WebRtcVideoEngine::codecs() const {
-  return GetSupportedCodecs(external_encoder_factory_);
+  return encoder_factory_->GetSupportedCodecs();
 }
 
 RtpCapabilities WebRtcVideoEngine::GetCapabilities() const {
@@ -373,7 +431,7 @@
 void WebRtcVideoEngine::SetExternalEncoderFactory(
     WebRtcVideoEncoderFactory* encoder_factory) {
   RTC_DCHECK(!initialized_);
-  external_encoder_factory_ = encoder_factory;
+  encoder_factory_.reset(new CricketEncoderFactoryAdapter(encoder_factory));
 }
 
 // This is a helper function for AppendVideoCodecs below. It will return the
@@ -439,8 +497,8 @@
   }
 }
 
-static std::vector<VideoCodec> GetSupportedCodecs(
-    const WebRtcVideoEncoderFactory* external_encoder_factory) {
+std::vector<VideoCodec> CricketEncoderFactoryAdapter::GetSupportedCodecs()
+    const {
   const std::vector<VideoCodec> internal_codecs =
       InternalEncoderFactory().supported_codecs();
   LOG(LS_INFO) << "Internally supported codecs: "
@@ -449,9 +507,9 @@
   std::vector<VideoCodec> unified_codecs;
   AppendVideoCodecs(internal_codecs, &unified_codecs);
 
-  if (external_encoder_factory != nullptr) {
+  if (external_encoder_factory_ != nullptr) {
     const std::vector<VideoCodec>& external_codecs =
-        external_encoder_factory->supported_codecs();
+        external_encoder_factory_->supported_codecs();
     AppendVideoCodecs(external_codecs, &unified_codecs);
     LOG(LS_INFO) << "Codecs supported by the external encoder factory: "
                  << CodecVectorToString(external_codecs);
@@ -464,13 +522,13 @@
     webrtc::Call* call,
     const MediaConfig& config,
     const VideoOptions& options,
-    WebRtcVideoEncoderFactory* external_encoder_factory,
+    const EncoderFactoryAdapter& encoder_factory,
     WebRtcVideoDecoderFactory* external_decoder_factory)
     : VideoMediaChannel(config),
       call_(call),
       unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
       video_config_(config.video),
-      external_encoder_factory_(external_encoder_factory),
+      encoder_factory_(encoder_factory.clone()),
       external_decoder_factory_(external_decoder_factory),
       default_send_options_(options),
       last_stats_log_ms_(-1) {
@@ -478,7 +536,7 @@
 
   rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
   sending_ = false;
-  recv_codecs_ = MapCodecs(GetSupportedCodecs(external_encoder_factory));
+  recv_codecs_ = MapCodecs(encoder_factory_->GetSupportedCodecs());
   recv_flexfec_payload_type_ = recv_codecs_.front().flexfec_payload_type;
 }
 
@@ -493,7 +551,7 @@
 WebRtcVideoChannel::SelectSendVideoCodec(
     const std::vector<VideoCodecSettings>& remote_mapped_codecs) const {
   const std::vector<VideoCodec> local_supported_codecs =
-      GetSupportedCodecs(external_encoder_factory_);
+      encoder_factory_->GetSupportedCodecs();
   // Select the first remote codec that is supported locally.
   for (const VideoCodecSettings& remote_mapped_codec : remote_mapped_codecs) {
     // For H264, we will limit the encode level to the remote offered level
@@ -805,7 +863,7 @@
 
   // Verify that every mapped codec is supported locally.
   const std::vector<VideoCodec> local_supported_codecs =
-      GetSupportedCodecs(external_encoder_factory_);
+      encoder_factory_->GetSupportedCodecs();
   for (const VideoCodecSettings& mapped_codec : mapped_codecs) {
     if (!FindMatchingCodec(local_supported_codecs, mapped_codec.codec)) {
       LOG(LS_ERROR) << "SetRecvParameters called with unsupported video codec: "
@@ -976,8 +1034,8 @@
   config.periodic_alr_bandwidth_probing =
       video_config_.periodic_alr_bandwidth_probing;
   WebRtcVideoSendStream* stream = new WebRtcVideoSendStream(
-      call_, sp, std::move(config), default_send_options_,
-      external_encoder_factory_, video_config_.enable_cpu_overuse_detection,
+      call_, sp, std::move(config), default_send_options_, *encoder_factory_,
+      video_config_.enable_cpu_overuse_detection,
       bitrate_config_.max_bitrate_bps, send_codec_, send_rtp_extensions_,
       send_params_);
 
@@ -1413,27 +1471,20 @@
       conference_mode(false),
       codec_settings(codec_settings) {}
 
-WebRtcVideoChannel::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder(
+EncoderFactoryAdapter::AllocatedEncoder::AllocatedEncoder(
     std::unique_ptr<webrtc::VideoEncoder> encoder,
-    bool is_external,
-    const cricket::VideoCodec& codec,
+    bool is_hardware_accelerated,
     bool has_internal_source)
-    : encoder_(std::move(encoder)),
-      is_external_(is_external),
-      codec_(codec),
-      has_internal_source_(has_internal_source) {}
-
-void WebRtcVideoChannel::WebRtcVideoSendStream::AllocatedEncoder::Reset() {
-  encoder_.reset();
-  codec_ = cricket::VideoCodec();
-}
+    : encoder(std::move(encoder)),
+      is_hardware_accelerated(is_hardware_accelerated),
+      has_internal_source(has_internal_source) {}
 
 WebRtcVideoChannel::WebRtcVideoSendStream::WebRtcVideoSendStream(
     webrtc::Call* call,
     const StreamParams& sp,
     webrtc::VideoSendStream::Config config,
     const VideoOptions& options,
-    WebRtcVideoEncoderFactory* external_encoder_factory,
+    const EncoderFactoryAdapter& encoder_factory,
     bool enable_cpu_overuse_detection,
     int max_bitrate_bps,
     const rtc::Optional<VideoCodecSettings>& codec_settings,
@@ -1447,8 +1498,7 @@
       call_(call),
       enable_cpu_overuse_detection_(enable_cpu_overuse_detection),
       source_(nullptr),
-      external_encoder_factory_(external_encoder_factory),
-      internal_encoder_factory_(new InternalEncoderFactory()),
+      encoder_factory_(encoder_factory.clone()),
       stream_(nullptr),
       encoder_sink_(nullptr),
       parameters_(std::move(config), options, max_bitrate_bps, codec_settings),
@@ -1510,7 +1560,7 @@
     call_->DestroyVideoSendStream(stream_);
   }
   // Release |allocated_encoder_|.
-  allocated_encoder_.Reset();
+  allocated_encoder_.reset();
 }
 
 bool WebRtcVideoChannel::WebRtcVideoSendStream::SetVideoSend(
@@ -1581,11 +1631,10 @@
   return ssrcs_;
 }
 
-WebRtcVideoChannel::WebRtcVideoSendStream::AllocatedEncoder
-WebRtcVideoChannel::WebRtcVideoSendStream::CreateVideoEncoder(
-    const VideoCodec& codec) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
-
+EncoderFactoryAdapter::AllocatedEncoder
+CricketEncoderFactoryAdapter::CreateVideoEncoder(
+    const VideoCodec& codec,
+    bool is_conference_mode_screenshare) const {
   // Try creating external encoder.
   if (external_encoder_factory_ != nullptr &&
       FindMatchingCodec(external_encoder_factory_->supported_codecs(), codec)) {
@@ -1607,7 +1656,7 @@
       const bool has_internal_source =
           external_encoder_factory_->EncoderTypeHasInternalSource(codec_type);
       return AllocatedEncoder(std::move(internal_encoder),
-                              true /* is_external */, codec,
+                              true /* is_hardware_accelerated */,
                               has_internal_source);
     }
   }
@@ -1616,9 +1665,7 @@
   std::unique_ptr<webrtc::VideoEncoder> internal_encoder;
   if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(), codec)) {
     if (CodecNamesEq(codec.name.c_str(), kVp8CodecName) &&
-        parameters_.encoder_config.content_type ==
-            webrtc::VideoEncoderConfig::ContentType::kScreen &&
-        parameters_.conference_mode && UseSimulcastScreenshare()) {
+        is_conference_mode_screenshare && UseSimulcastScreenshare()) {
       // TODO(sprang): Remove this adapter once libvpx supports simulcast with
       // same-resolution substreams.
       internal_encoder = std::unique_ptr<webrtc::VideoEncoder>(
@@ -1628,7 +1675,7 @@
           internal_encoder_factory_->CreateVideoEncoder(codec));
     }
     return AllocatedEncoder(std::move(internal_encoder),
-                            false /* is_external */, codec,
+                            false /* is_hardware_accelerated */,
                             false /* has_internal_source */);
   }
 
@@ -1648,20 +1695,28 @@
   // Do not re-create encoders of the same type. We can't overwrite
   // |allocated_encoder_| immediately, because we need to release it after the
   // RecreateWebRtcStream() call.
-  AllocatedEncoder new_encoder;
-  if (force_encoder_allocation || !allocated_encoder_.encoder() ||
-      allocated_encoder_.codec() != codec_settings.codec) {
-    new_encoder = CreateVideoEncoder(codec_settings.codec);
+  std::unique_ptr<webrtc::VideoEncoder> new_encoder;
+  if (force_encoder_allocation || !allocated_encoder_ ||
+      allocated_codec_ != codec_settings.codec) {
+    const bool is_conference_mode_screenshare =
+        parameters_.encoder_config.content_type ==
+            webrtc::VideoEncoderConfig::ContentType::kScreen &&
+        parameters_.conference_mode;
+    EncoderFactoryAdapter::AllocatedEncoder new_allocated_encoder =
+        encoder_factory_->CreateVideoEncoder(codec_settings.codec,
+                                             is_conference_mode_screenshare);
+    new_encoder = std::unique_ptr<webrtc::VideoEncoder>(
+        std::move(new_allocated_encoder.encoder));
+    parameters_.config.encoder_settings.encoder = new_encoder.get();
+    parameters_.config.encoder_settings.full_overuse_time =
+        new_allocated_encoder.is_hardware_accelerated;
+    parameters_.config.encoder_settings.internal_source =
+        new_allocated_encoder.has_internal_source;
   } else {
     new_encoder = std::move(allocated_encoder_);
   }
-  parameters_.config.encoder_settings.encoder = new_encoder.encoder();
-  parameters_.config.encoder_settings.full_overuse_time =
-      new_encoder.IsExternal();
   parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
   parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
-  parameters_.config.encoder_settings.internal_source =
-      new_encoder.HasInternalSource();
   parameters_.config.rtp.ulpfec = codec_settings.ulpfec;
   parameters_.config.rtp.flexfec.payload_type =
       codec_settings.flexfec_payload_type;
@@ -1686,6 +1741,7 @@
   LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec.";
   RecreateWebRtcStream();
   allocated_encoder_ = std::move(new_encoder);
+  allocated_codec_ = codec_settings.codec;
 }
 
 void WebRtcVideoChannel::WebRtcVideoSendStream::SetSendParameters(
diff --git a/media/engine/webrtcvideoengine.h b/media/engine/webrtcvideoengine.h
index deb13b1..3224d00 100644
--- a/media/engine/webrtcvideoengine.h
+++ b/media/engine/webrtcvideoengine.h
@@ -47,6 +47,7 @@
 
 namespace cricket {
 
+class EncoderFactoryAdapter;
 class VideoCapturer;
 class VideoProcessor;
 class VideoRenderer;
@@ -121,7 +122,7 @@
   bool initialized_;
 
   WebRtcVideoDecoderFactory* external_decoder_factory_;
-  WebRtcVideoEncoderFactory* external_encoder_factory_;
+  std::unique_ptr<EncoderFactoryAdapter> encoder_factory_;
 };
 
 class WebRtcVideoChannel : public VideoMediaChannel, public webrtc::Transport {
@@ -129,7 +130,7 @@
   WebRtcVideoChannel(webrtc::Call* call,
                      const MediaConfig& config,
                      const VideoOptions& options,
-                     WebRtcVideoEncoderFactory* external_encoder_factory,
+                     const EncoderFactoryAdapter& encoder_factory,
                      WebRtcVideoDecoderFactory* external_decoder_factory);
   ~WebRtcVideoChannel() override;
 
@@ -258,7 +259,7 @@
         const StreamParams& sp,
         webrtc::VideoSendStream::Config config,
         const VideoOptions& options,
-        WebRtcVideoEncoderFactory* external_encoder_factory,
+        const EncoderFactoryAdapter& encoder_factory,
         bool enable_cpu_overuse_detection,
         int max_bitrate_bps,
         const rtc::Optional<VideoCodecSettings>& codec_settings,
@@ -310,42 +311,8 @@
       webrtc::VideoEncoderConfig encoder_config;
     };
 
-    class AllocatedEncoder {
-     public:
-      AllocatedEncoder() = default;
-      AllocatedEncoder(AllocatedEncoder&&) = default;
-      AllocatedEncoder& operator=(AllocatedEncoder&&) = default;
-
-      AllocatedEncoder(std::unique_ptr<webrtc::VideoEncoder> encoder,
-                       bool is_external,
-                       const cricket::VideoCodec& codec,
-                       bool has_internal_source);
-
-      // Returns a raw pointer to the allocated encoder. This object still has
-      // ownership of the encoder and is responsible for deleting it.
-      webrtc::VideoEncoder* encoder() { return encoder_.get(); }
-
-      // Returns true if the encoder is external.
-      bool IsExternal() { return is_external_; }
-
-      cricket::VideoCodec codec() { return codec_; }
-
-      bool HasInternalSource() { return has_internal_source_; }
-
-      // Release the encoders this object manages.
-      void Reset();
-
-     private:
-      std::unique_ptr<webrtc::VideoEncoder> encoder_;
-      bool is_external_;
-      cricket::VideoCodec codec_;
-      bool has_internal_source_;
-    };
-
     rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings>
     ConfigureVideoEncoderSettings(const VideoCodec& codec);
-    // Creates and returns a new AllocatedEncoder of the specified codec type.
-    AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec);
     void SetCodec(const VideoCodecSettings& codec,
                   bool force_encoder_allocation);
     void RecreateWebRtcStream();
@@ -370,9 +337,7 @@
     const bool enable_cpu_overuse_detection_;
     rtc::VideoSourceInterface<webrtc::VideoFrame>* source_
         ACCESS_ON(&thread_checker_);
-    WebRtcVideoEncoderFactory* const external_encoder_factory_
-        ACCESS_ON(&thread_checker_);
-    const std::unique_ptr<WebRtcVideoEncoderFactory> internal_encoder_factory_
+    std::unique_ptr<EncoderFactoryAdapter> encoder_factory_
         ACCESS_ON(&thread_checker_);
 
     webrtc::VideoSendStream* stream_ ACCESS_ON(&thread_checker_);
@@ -388,7 +353,9 @@
     // TODO(skvlad): Combine parameters_ and rtp_parameters_ once we have only
     // one stream per MediaChannel.
     webrtc::RtpParameters rtp_parameters_ ACCESS_ON(&thread_checker_);
-    AllocatedEncoder allocated_encoder_ ACCESS_ON(&thread_checker_);
+    std::unique_ptr<webrtc::VideoEncoder> allocated_encoder_
+        ACCESS_ON(&thread_checker_);
+    VideoCodec allocated_codec_ ACCESS_ON(&thread_checker_);
 
     bool sending_ ACCESS_ON(&thread_checker_);
   };
@@ -529,7 +496,7 @@
   rtc::Optional<VideoCodecSettings> send_codec_;
   rtc::Optional<std::vector<webrtc::RtpExtension>> send_rtp_extensions_;
 
-  WebRtcVideoEncoderFactory* const external_encoder_factory_;
+  std::unique_ptr<EncoderFactoryAdapter> encoder_factory_;
   WebRtcVideoDecoderFactory* const external_decoder_factory_;
   std::vector<VideoCodecSettings> recv_codecs_;
   std::vector<webrtc::RtpExtension> recv_rtp_extensions_;