Revert "Replace VideoDecoder with VideoDecoderFactory in VideoReceiveStream config."

This reverts commit 529d0d9795b81dbed5e4231f15d3752a5fc0df32.

Reason for revert: Seems to break perf tests, likely some breakage in video_quality_tests decoder configuration.

Original change's description:
> Replace VideoDecoder with VideoDecoderFactory in VideoReceiveStream config.
> 
> Preparation for deleting EnableFrameRecordning, and also a step
> towards landing of the new VideoStreamDecoder.
> 
> Bug: webrtc:9106
> Change-Id: I50964ee458b08a702ec69b82a62e4995c57cee82
> Reviewed-on: https://webrtc-review.googlesource.com/97660
> Commit-Queue: Niels Moller <nisse@webrtc.org>
> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
> Reviewed-by: Anders Carlsson <andersc@webrtc.org>
> Reviewed-by: Sebastian Jansson <srte@webrtc.org>
> Reviewed-by: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#24861}

TBR=brandtr@webrtc.org,nisse@webrtc.org,andersc@webrtc.org,sprang@webrtc.org,philipel@webrtc.org,srte@webrtc.org

Change-Id: Id34e4a3452a7dbc06167a4df5bb4c2825ebd7bd0
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:9106
Reviewed-on: https://webrtc-review.googlesource.com/102421
Reviewed-by: Niels Moller <nisse@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24866}
diff --git a/call/bitrate_estimator_tests.cc b/call/bitrate_estimator_tests.cc
index 766e38c..af0e4c9 100644
--- a/call/bitrate_estimator_tests.cc
+++ b/call/bitrate_estimator_tests.cc
@@ -170,8 +170,7 @@
           is_sending_receiving_(false),
           send_stream_(nullptr),
           frame_generator_capturer_(),
-          decoder_factory_(
-              []() { return absl::make_unique<test::FakeDecoder>(); }) {
+          fake_decoder_() {
       test_->GetVideoSendConfig()->rtp.ssrcs[0]++;
       send_stream_ = test_->sender_call_->CreateVideoSendStream(
           test_->GetVideoSendConfig()->Copy(),
@@ -186,7 +185,7 @@
       frame_generator_capturer_->Start();
 
       VideoReceiveStream::Decoder decoder;
-      decoder.decoder_factory = &decoder_factory_;
+      decoder.decoder = &fake_decoder_;
       decoder.payload_type = test_->GetVideoSendConfig()->rtp.payload_type;
       decoder.video_format =
           SdpVideoFormat(test_->GetVideoSendConfig()->rtp.payload_name);
@@ -230,8 +229,7 @@
     VideoSendStream* send_stream_;
     VideoReceiveStream* video_receive_stream_;
     std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
-
-    test::FunctionVideoDecoderFactory decoder_factory_;
+    test::FakeDecoder fake_decoder_;
   };
 
   LogObserver receiver_log_;
diff --git a/call/call_perf_tests.cc b/call/call_perf_tests.cc
index 05c39fe..b8b4601 100644
--- a/call/call_perf_tests.cc
+++ b/call/call_perf_tests.cc
@@ -33,6 +33,7 @@
 #include "test/call_test.h"
 #include "test/direct_transport.h"
 #include "test/drifting_clock.h"
+#include "test/encoder_proxy_factory.h"
 #include "test/encoder_settings.h"
 #include "test/fake_encoder.h"
 #include "test/field_trial.h"
@@ -43,7 +44,6 @@
 #include "test/single_threaded_task_queue.h"
 #include "test/testsupport/fileutils.h"
 #include "test/testsupport/perf_test.h"
-#include "test/video_encoder_proxy_factory.h"
 #include "video/transport_adapter.h"
 
 using webrtc::test::DriftingClock;
@@ -807,7 +807,7 @@
     uint32_t last_set_bitrate_kbps_;
     VideoSendStream* send_stream_;
     test::FrameGeneratorCapturer* frame_generator_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
     VideoEncoderConfig encoder_config_;
   } test;
 
diff --git a/call/video_receive_stream.cc b/call/video_receive_stream.cc
index 672abd8..c4cdd49 100644
--- a/call/video_receive_stream.cc
+++ b/call/video_receive_stream.cc
@@ -20,8 +20,9 @@
 std::string VideoReceiveStream::Decoder::ToString() const {
   char buf[1024];
   rtc::SimpleStringBuilder ss(buf);
-  ss << "{payload_type: " << payload_type;
-  ss << ", payload_name: " << video_format.name;
+  ss << "{decoder: " << (decoder ? "(VideoDecoder)" : "nullptr");
+  ss << ", payload_type: " << payload_type;
+  ss << ", name: " << video_format.name;
   ss << ", codec_params: {";
   for (const auto& it : video_format.parameters)
     ss << it.first << ": " << it.second;
diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h
index d299cd8..b5c1649 100644
--- a/call/video_receive_stream.h
+++ b/call/video_receive_stream.h
@@ -33,7 +33,7 @@
 namespace webrtc {
 
 class RtpPacketSinkInterface;
-class VideoDecoderFactory;
+class VideoDecoder;
 
 class VideoReceiveStream {
  public:
@@ -45,10 +45,8 @@
     ~Decoder();
     std::string ToString() const;
 
-    // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection).
-    // TODO(nisse): Move one level out, to VideoReceiveStream::Config, and later
-    // to the configuration of VideoStreamDecoder.
-    VideoDecoderFactory* decoder_factory = nullptr;
+    // The actual decoder instance.
+    VideoDecoder* decoder = nullptr;
     SdpVideoFormat video_format;
 
     // Received RTP packets with this payload type will be sent to this decoder
@@ -212,10 +210,6 @@
     // Target delay in milliseconds. A positive value indicates this stream is
     // used for streaming instead of a real-time call.
     int target_delay_ms = 0;
-
-    // TODO(nisse): Used with VideoDecoderFactory::LegacyCreateVideoDecoder.
-    // Delete when that method is retired.
-    std::string stream_id;
   };
 
   // Starts stream activity.
diff --git a/media/engine/webrtcvideoengine.cc b/media/engine/webrtcvideoengine.cc
index 73585a8..501f5de 100644
--- a/media/engine/webrtcvideoengine.cc
+++ b/media/engine/webrtcvideoengine.cc
@@ -16,11 +16,14 @@
 #include <string>
 #include <utility>
 
+#include "api/video/i420_buffer.h"
 #include "api/video_codecs/sdp_video_format.h"
+#include "api/video_codecs/video_decoder.h"
 #include "api/video_codecs/video_decoder_factory.h"
 #include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_factory.h"
 #include "call/call.h"
+#include "common_video/h264/profile_level_id.h"
 #include "media/engine/constants.h"
 #if defined(USE_BUILTIN_SW_CODECS)
 #include "media/engine/convert_legacy_video_factory.h"  // nogncheck
@@ -28,6 +31,7 @@
 #include "media/engine/simulcast.h"
 #include "media/engine/webrtcmediaengine.h"
 #include "media/engine/webrtcvoiceengine.h"
+#include "modules/video_coding/include/video_error_codes.h"
 #include "rtc_base/copyonwritebuffer.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/string_builder.h"
@@ -40,6 +44,36 @@
 
 namespace {
 
+// Video decoder class to be used for unknown codecs. Doesn't support decoding
+// but logs messages to LS_ERROR.
+class NullVideoDecoder : public webrtc::VideoDecoder {
+ public:
+  int32_t InitDecode(const webrtc::VideoCodec* codec_settings,
+                     int32_t number_of_cores) override {
+    RTC_LOG(LS_ERROR) << "Can't initialize NullVideoDecoder.";
+    return WEBRTC_VIDEO_CODEC_OK;
+  }
+
+  int32_t Decode(const webrtc::EncodedImage& input_image,
+                 bool missing_frames,
+                 const webrtc::CodecSpecificInfo* codec_specific_info,
+                 int64_t render_time_ms) override {
+    RTC_LOG(LS_ERROR) << "The NullVideoDecoder doesn't support decoding.";
+    return WEBRTC_VIDEO_CODEC_OK;
+  }
+
+  int32_t RegisterDecodeCompleteCallback(
+      webrtc::DecodedImageCallback* callback) override {
+    RTC_LOG(LS_ERROR)
+        << "Can't register decode complete callback on NullVideoDecoder.";
+    return WEBRTC_VIDEO_CODEC_OK;
+  }
+
+  int32_t Release() override { return WEBRTC_VIDEO_CODEC_OK; }
+
+  const char* ImplementationName() const override { return "NullVideoDecoder"; }
+};
+
 // 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() {
@@ -2160,10 +2194,12 @@
       first_frame_timestamp_(-1),
       estimated_remote_start_ntp_time_ms_(0) {
   config_.renderer = this;
-  ConfigureCodecs(recv_codecs);
+  DecoderMap old_decoders;
+  ConfigureCodecs(recv_codecs, &old_decoders);
   ConfigureFlexfecCodec(flexfec_config.payload_type);
   MaybeRecreateWebRtcFlexfecStream();
   RecreateWebRtcVideoStream();
+  RTC_DCHECK(old_decoders.empty());
 }
 
 WebRtcVideoChannel::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
@@ -2172,6 +2208,7 @@
     call_->DestroyFlexfecReceiveStream(flexfec_stream_);
   }
   call_->DestroyVideoReceiveStream(stream_);
+  allocated_decoders_.clear();
 }
 
 const std::vector<uint32_t>&
@@ -2210,23 +2247,58 @@
 }
 
 void WebRtcVideoChannel::WebRtcVideoReceiveStream::ConfigureCodecs(
-    const std::vector<VideoCodecSettings>& recv_codecs) {
+    const std::vector<VideoCodecSettings>& recv_codecs,
+    DecoderMap* old_decoders) {
   RTC_DCHECK(!recv_codecs.empty());
+  *old_decoders = std::move(allocated_decoders_);
   config_.decoders.clear();
   config_.rtp.rtx_associated_payload_types.clear();
   for (const auto& recv_codec : recv_codecs) {
     webrtc::SdpVideoFormat video_format(recv_codec.codec.name,
                                         recv_codec.codec.params);
+    std::unique_ptr<webrtc::VideoDecoder> new_decoder;
+
+    if (allocated_decoders_.count(video_format) > 0) {
+      RTC_LOG(LS_WARNING)
+          << "VideoReceiveStream configured with duplicate codecs: "
+          << video_format.name;
+      continue;
+    }
+
+    auto it = old_decoders->find(video_format);
+    if (it != old_decoders->end()) {
+      new_decoder = std::move(it->second);
+      old_decoders->erase(it);
+    }
+
+    if (!new_decoder && decoder_factory_) {
+      new_decoder = decoder_factory_->LegacyCreateVideoDecoder(
+          webrtc::SdpVideoFormat(recv_codec.codec.name,
+                                 recv_codec.codec.params),
+          stream_params_.id);
+    }
+
+    // If we still have no valid decoder, we have to create a "Null" decoder
+    // that ignores all calls. The reason we can get into this state is that
+    // the old decoder factory interface doesn't have a way to query supported
+    // codecs.
+    if (!new_decoder)
+      new_decoder.reset(new NullVideoDecoder());
 
     webrtc::VideoReceiveStream::Decoder decoder;
-    decoder.decoder_factory = decoder_factory_;
-    decoder.video_format = video_format;
+    decoder.decoder = new_decoder.get();
     decoder.payload_type = recv_codec.codec.id;
     decoder.video_format =
         webrtc::SdpVideoFormat(recv_codec.codec.name, recv_codec.codec.params);
     config_.decoders.push_back(decoder);
     config_.rtp.rtx_associated_payload_types[recv_codec.rtx_payload_type] =
         recv_codec.codec.id;
+
+    const bool did_insert =
+        allocated_decoders_
+            .insert(std::make_pair(video_format, std::move(new_decoder)))
+            .second;
+    RTC_CHECK(did_insert);
   }
 
   const auto& codec = recv_codecs.front();
@@ -2306,8 +2378,9 @@
     const ChangedRecvParameters& params) {
   bool video_needs_recreation = false;
   bool flexfec_needs_recreation = false;
+  DecoderMap old_decoders;
   if (params.codec_settings) {
-    ConfigureCodecs(*params.codec_settings);
+    ConfigureCodecs(*params.codec_settings, &old_decoders);
     video_needs_recreation = true;
   }
   if (params.rtp_header_extensions) {
@@ -2340,7 +2413,6 @@
   }
   webrtc::VideoReceiveStream::Config config = config_.Copy();
   config.rtp.protected_by_flexfec = (flexfec_stream_ != nullptr);
-  config.stream_id = stream_params_.id;
   stream_ = call_->CreateVideoReceiveStream(std::move(config));
   MaybeAssociateFlexfecWithVideo();
   stream_->Start();
diff --git a/media/engine/webrtcvideoengine.h b/media/engine/webrtcvideoengine.h
index 40c39af..d949d78 100644
--- a/media/engine/webrtcvideoengine.h
+++ b/media/engine/webrtcvideoengine.h
@@ -37,7 +37,9 @@
 #include "rtc_base/thread_checker.h"
 
 namespace webrtc {
+class VideoDecoder;
 class VideoDecoderFactory;
+class VideoEncoder;
 class VideoEncoderFactory;
 struct MediaConfig;
 }  // namespace webrtc
@@ -378,13 +380,26 @@
     VideoReceiverInfo GetVideoReceiverInfo(bool log_stats);
 
    private:
+    struct SdpVideoFormatCompare {
+      bool operator()(const webrtc::SdpVideoFormat& lhs,
+                      const webrtc::SdpVideoFormat& rhs) const {
+        return std::tie(lhs.name, lhs.parameters) <
+               std::tie(rhs.name, rhs.parameters);
+      }
+    };
+    typedef std::map<webrtc::SdpVideoFormat,
+                     std::unique_ptr<webrtc::VideoDecoder>,
+                     SdpVideoFormatCompare>
+        DecoderMap;
+
     void RecreateWebRtcVideoStream();
     void MaybeRecreateWebRtcFlexfecStream();
 
     void MaybeAssociateFlexfecWithVideo();
     void MaybeDissociateFlexfecFromVideo();
 
-    void ConfigureCodecs(const std::vector<VideoCodecSettings>& recv_codecs);
+    void ConfigureCodecs(const std::vector<VideoCodecSettings>& recv_codecs,
+                         DecoderMap* old_codecs);
     void ConfigureFlexfecCodec(int flexfec_payload_type);
 
     std::string GetCodecNameFromPayloadType(int payload_type);
@@ -392,7 +407,7 @@
     absl::optional<uint32_t> GetFirstPrimarySsrc() const;
 
     webrtc::Call* const call_;
-    const StreamParams stream_params_;
+    StreamParams stream_params_;
 
     // Both |stream_| and |flexfec_stream_| are managed by |this|. They are
     // destroyed by calling call_->DestroyVideoReceiveStream and
@@ -403,7 +418,8 @@
     webrtc::FlexfecReceiveStream::Config flexfec_config_;
     webrtc::FlexfecReceiveStream* flexfec_stream_;
 
-    webrtc::VideoDecoderFactory* const decoder_factory_;
+    webrtc::VideoDecoderFactory* decoder_factory_;
+    DecoderMap allocated_decoders_;
 
     rtc::CriticalSection sink_lock_;
     rtc::VideoSinkInterface<webrtc::VideoFrame>* sink_
diff --git a/test/BUILD.gn b/test/BUILD.gn
index ec9e880..26f929b 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -542,6 +542,7 @@
     "constants.h",
     "drifting_clock.cc",
     "drifting_clock.h",
+    "encoder_proxy_factory.h",
     "encoder_settings.cc",
     "encoder_settings.h",
     "fake_videorenderer.h",
@@ -556,8 +557,6 @@
     "rtp_rtcp_observer.h",
     "statistics.cc",
     "statistics.h",
-    "video_decoder_proxy_factory.h",
-    "video_encoder_proxy_factory.h",
     "win/run_loop_win.cc",
   ]
   if (!is_win) {
diff --git a/test/call_test.cc b/test/call_test.cc
index 1b1d356..89ac329 100644
--- a/test/call_test.cc
+++ b/test/call_test.cc
@@ -52,7 +52,6 @@
         fake_encoder->SetMaxBitrate(fake_encoder_max_bitrate_);
         return fake_encoder;
       }),
-      fake_decoder_factory_([]() { return absl::make_unique<FakeDecoder>(); }),
       num_video_streams_(1),
       num_audio_streams_(0),
       num_flexfec_streams_(0),
@@ -367,10 +366,11 @@
     if (!decode_sub_stream || i == *decode_sub_stream) {
       decoder = test::CreateMatchingDecoder(video_send_config);
     } else {
+      decoder.decoder = new test::FakeDecoder();
       decoder.payload_type = video_send_config.rtp.payload_type;
       decoder.video_format = SdpVideoFormat(video_send_config.rtp.payload_name);
     }
-    decoder.decoder_factory = &fake_decoder_factory_;
+    allocated_decoders_.emplace_back(decoder.decoder);
     video_recv_config.decoders.push_back(decoder);
     receive_configs->emplace_back(std::move(video_recv_config));
   }
@@ -433,6 +433,7 @@
 
 void CallTest::CreateMatchingReceiveConfigs(Transport* rtcp_send_transport) {
   video_receive_configs_.clear();
+  allocated_decoders_.clear();
   for (VideoSendStream::Config& video_send_config : video_send_configs_) {
     CreateMatchingVideoReceiveConfigs(video_send_config, rtcp_send_transport);
   }
@@ -634,6 +635,7 @@
     receiver_call_->DestroyFlexfecReceiveStream(flexfec_recv_stream);
 
   video_receive_streams_.clear();
+  allocated_decoders_.clear();
 }
 
 void CallTest::DestroyVideoSendStreams() {
diff --git a/test/call_test.h b/test/call_test.h
index 0b2058b..eb96cfd 100644
--- a/test/call_test.h
+++ b/test/call_test.h
@@ -22,7 +22,6 @@
 #include "test/fake_videorenderer.h"
 #include "test/fake_vp8_encoder.h"
 #include "test/frame_generator_capturer.h"
-#include "test/function_video_decoder_factory.h"
 #include "test/function_video_encoder_factory.h"
 #include "test/rtp_rtcp_observer.h"
 #include "test/single_threaded_task_queue.h"
@@ -202,7 +201,7 @@
 
   test::FunctionVideoEncoderFactory fake_encoder_factory_;
   int fake_encoder_max_bitrate_ = -1;
-  test::FunctionVideoDecoderFactory fake_decoder_factory_;
+  std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders_;
   // Number of simulcast substreams.
   size_t num_video_streams_;
   size_t num_audio_streams_;
diff --git a/test/video_encoder_proxy_factory.h b/test/encoder_proxy_factory.h
similarity index 92%
rename from test/video_encoder_proxy_factory.h
rename to test/encoder_proxy_factory.h
index e7289c0..8672a46 100644
--- a/test/video_encoder_proxy_factory.h
+++ b/test/encoder_proxy_factory.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef TEST_VIDEO_ENCODER_PROXY_FACTORY_H_
-#define TEST_VIDEO_ENCODER_PROXY_FACTORY_H_
+#ifndef TEST_ENCODER_PROXY_FACTORY_H_
+#define TEST_ENCODER_PROXY_FACTORY_H_
 
 #include <memory>
 #include <vector>
@@ -24,9 +24,9 @@
 // An encoder factory with a single underlying VideoEncoder object,
 // intended for test purposes. Each call to CreateVideoEncoder returns
 // a proxy for the same encoder, typically an instance of FakeEncoder.
-class VideoEncoderProxyFactory final : public VideoEncoderFactory {
+class EncoderProxyFactory final : public VideoEncoderFactory {
  public:
-  explicit VideoEncoderProxyFactory(VideoEncoder* encoder) : encoder_(encoder) {
+  explicit EncoderProxyFactory(VideoEncoder* encoder) : encoder_(encoder) {
     codec_info_.is_hardware_accelerated = false;
     codec_info_.has_internal_source = false;
   }
@@ -100,4 +100,4 @@
 }  // namespace test
 }  // namespace webrtc
 
-#endif  // TEST_VIDEO_ENCODER_PROXY_FACTORY_H_
+#endif  // TEST_ENCODER_PROXY_FACTORY_H_
diff --git a/test/encoder_settings.cc b/test/encoder_settings.cc
index 945559b..1013433 100644
--- a/test/encoder_settings.cc
+++ b/test/encoder_settings.cc
@@ -12,7 +12,13 @@
 #include <algorithm>
 #include <string>
 
+#include "media/engine/internaldecoderfactory.h"
+#include "modules/video_coding/codecs/h264/include/h264.h"
+#include "modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h"
+#include "modules/video_coding/codecs/vp8/include/vp8.h"
+#include "modules/video_coding/codecs/vp9/include/vp9.h"
 #include "rtc_base/refcountedobject.h"
+#include "test/fake_decoder.h"
 
 namespace webrtc {
 namespace test {
@@ -122,6 +128,18 @@
   VideoReceiveStream::Decoder decoder;
   decoder.payload_type = payload_type;
   decoder.video_format = SdpVideoFormat(payload_name);
+  if (payload_name == "H264") {
+    decoder.decoder = H264Decoder::Create().release();
+  } else if (payload_name == "VP8") {
+    decoder.decoder = VP8Decoder::Create().release();
+  } else if (payload_name == "VP9") {
+    decoder.decoder = VP9Decoder::Create().release();
+  } else if (payload_name == "multiplex") {
+    decoder.decoder = new MultiplexDecoderAdapter(
+        new InternalDecoderFactory(), SdpVideoFormat(cricket::kVp9CodecName));
+  } else {
+    decoder.decoder = new FakeDecoder();
+  }
   return decoder;
 }
 
diff --git a/test/video_decoder_proxy_factory.h b/test/video_decoder_proxy_factory.h
deleted file mode 100644
index 250750c..0000000
--- a/test/video_decoder_proxy_factory.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef TEST_VIDEO_DECODER_PROXY_FACTORY_H_
-#define TEST_VIDEO_DECODER_PROXY_FACTORY_H_
-
-#include <memory>
-#include <vector>
-
-#include "absl/memory/memory.h"
-#include "api/video_codecs/video_decoder.h"
-#include "api/video_codecs/video_decoder_factory.h"
-
-namespace webrtc {
-namespace test {
-
-// An decoder factory with a single underlying VideoDecoder object, intended for
-// test purposes. Each call to CreateVideoDecoder returns a proxy for the same
-// decoder, typically an instance of FakeDecoder or MockEncoder.
-class VideoDecoderProxyFactory final : public VideoDecoderFactory {
- public:
-  explicit VideoDecoderProxyFactory(VideoDecoder* decoder)
-      : decoder_(decoder) {}
-
-  // Unused by tests.
-  std::vector<SdpVideoFormat> GetSupportedFormats() const override {
-    RTC_NOTREACHED();
-    return {};
-  }
-
-  std::unique_ptr<VideoDecoder> CreateVideoDecoder(
-      const SdpVideoFormat& format) override {
-    return absl::make_unique<DecoderProxy>(decoder_);
-  }
-
- private:
-  // Wrapper class, since CreateVideoDecoder needs to surrender
-  // ownership to the object it returns.
-  class DecoderProxy final : public VideoDecoder {
-   public:
-    explicit DecoderProxy(VideoDecoder* decoder) : decoder_(decoder) {}
-
-   private:
-    int32_t Decode(const EncodedImage& input_image,
-                   bool missing_frames,
-                   const CodecSpecificInfo* codec_specific_info,
-                   int64_t render_time_ms) override {
-      return decoder_->Decode(input_image, missing_frames, codec_specific_info,
-                              render_time_ms);
-    }
-    int32_t InitDecode(const VideoCodec* config,
-                       int32_t number_of_cores) override {
-      return decoder_->InitDecode(config, number_of_cores);
-    }
-    int32_t RegisterDecodeCompleteCallback(
-        DecodedImageCallback* callback) override {
-      return decoder_->RegisterDecodeCompleteCallback(callback);
-    }
-    int32_t Release() override { return decoder_->Release(); }
-    bool PrefersLateDecoding() const { return decoder_->PrefersLateDecoding(); }
-    const char* ImplementationName() const override {
-      return decoder_->ImplementationName();
-    }
-
-    VideoDecoder* const decoder_;
-  };
-
-  VideoDecoder* const decoder_;
-};
-
-}  // namespace test
-}  // namespace webrtc
-
-#endif  // TEST_VIDEO_DECODER_PROXY_FACTORY_H_
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 624d278..cecdd38 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -364,7 +364,6 @@
       "../call:call_interfaces",
       "../common_video",
       "../logging:rtc_event_log_api",
-      "../media:rtc_internal_video_codecs",
       "../modules/rtp_rtcp",
       "../rtc_base:checks",
       "../rtc_base:rtc_base_approved",
diff --git a/video/end_to_end_tests/bandwidth_tests.cc b/video/end_to_end_tests/bandwidth_tests.cc
index ab5e568..5ab24fa 100644
--- a/video/end_to_end_tests/bandwidth_tests.cc
+++ b/video/end_to_end_tests/bandwidth_tests.cc
@@ -15,12 +15,12 @@
 #include "rtc_base/rate_limiter.h"
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
+#include "test/encoder_proxy_factory.h"
 #include "test/fake_encoder.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
 #include "test/rtp_rtcp_observer.h"
-#include "test/video_encoder_proxy_factory.h"
 
 namespace webrtc {
 
@@ -344,7 +344,7 @@
     test::SingleThreadedTaskQueueForTesting* const task_queue_;
     rtc::CriticalSection crit_;
     VideoSendStream* send_stream_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
     uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_);
   } test(&task_queue_);
 
diff --git a/video/end_to_end_tests/codec_tests.cc b/video/end_to_end_tests/codec_tests.cc
index fad3ac7..5c52555 100644
--- a/video/end_to_end_tests/codec_tests.cc
+++ b/video/end_to_end_tests/codec_tests.cc
@@ -39,7 +39,7 @@
                 VideoRotation rotation_to_test,
                 const std::string& payload_name,
                 VideoEncoderFactory* encoder_factory,
-                VideoDecoderFactory* decoder_factory)
+                std::unique_ptr<webrtc::VideoDecoder> decoder)
       : EndToEndTest(4 * CodecEndToEndTest::kDefaultTimeoutMs),
         // TODO(hta): This timeout (120 seconds) is excessive.
         // https://bugs.webrtc.org/6830
@@ -47,7 +47,7 @@
         expected_rotation_(rotation_to_test),
         payload_name_(payload_name),
         encoder_factory_(encoder_factory),
-        decoder_factory_(decoder_factory),
+        decoder_(std::move(decoder)),
         frame_counter_(0) {}
 
   void PerformTest() override {
@@ -70,7 +70,7 @@
         send_config->rtp.payload_type;
     (*receive_configs)[0].decoders[0].video_format =
         SdpVideoFormat(send_config->rtp.payload_name);
-    (*receive_configs)[0].decoders[0].decoder_factory = decoder_factory_;
+    (*receive_configs)[0].decoders[0].decoder = decoder_.get();
   }
 
   void OnFrame(const VideoFrame& video_frame) override {
@@ -89,7 +89,7 @@
   VideoRotation expected_rotation_;
   std::string payload_name_;
   VideoEncoderFactory* encoder_factory_;
-  VideoDecoderFactory* decoder_factory_;
+  std::unique_ptr<webrtc::VideoDecoder> decoder_;
   int frame_counter_;
 };
 
@@ -101,20 +101,16 @@
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP8) {
   test::FunctionVideoEncoderFactory encoder_factory(
       []() { return VP8Encoder::Create(); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return VP8Decoder::Create(); });
   CodecObserver test(5, kVideoRotation_0, "VP8", &encoder_factory,
-                     &decoder_factory);
+                     VP8Decoder::Create());
   RunBaseTest(&test);
 }
 
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP8Rotation90) {
   test::FunctionVideoEncoderFactory encoder_factory(
       []() { return VP8Encoder::Create(); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return VP8Decoder::Create(); });
   CodecObserver test(5, kVideoRotation_90, "VP8", &encoder_factory,
-                     &decoder_factory);
+                     VP8Decoder::Create());
   RunBaseTest(&test);
 }
 
@@ -122,58 +118,47 @@
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP9) {
   test::FunctionVideoEncoderFactory encoder_factory(
       []() { return VP9Encoder::Create(); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return VP9Decoder::Create(); });
   CodecObserver test(500, kVideoRotation_0, "VP9", &encoder_factory,
-                     &decoder_factory);
+                     VP9Decoder::Create());
   RunBaseTest(&test);
 }
 
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP9VideoRotation90) {
   test::FunctionVideoEncoderFactory encoder_factory(
       []() { return VP9Encoder::Create(); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return VP9Decoder::Create(); });
   CodecObserver test(5, kVideoRotation_90, "VP9", &encoder_factory,
-                     &decoder_factory);
+                     VP9Decoder::Create());
   RunBaseTest(&test);
 }
 
 // Mutiplex tests are using VP9 as the underlying implementation.
 TEST_P(CodecEndToEndTest, SendsAndReceivesMultiplex) {
   InternalEncoderFactory internal_encoder_factory;
-  InternalDecoderFactory internal_decoder_factory;
+  InternalDecoderFactory decoder_factory;
   test::FunctionVideoEncoderFactory encoder_factory(
       [&internal_encoder_factory]() {
         return absl::make_unique<MultiplexEncoderAdapter>(
             &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
       });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      [&internal_decoder_factory]() {
-        return absl::make_unique<MultiplexDecoderAdapter>(
-            &internal_decoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
-      });
-
-  CodecObserver test(5, kVideoRotation_0, "multiplex", &encoder_factory,
-                     &decoder_factory);
+  CodecObserver test(
+      5, kVideoRotation_0, "multiplex", &encoder_factory,
+      absl::make_unique<MultiplexDecoderAdapter>(
+          &decoder_factory, SdpVideoFormat(cricket::kVp9CodecName)));
   RunBaseTest(&test);
 }
 
 TEST_P(CodecEndToEndTest, SendsAndReceivesMultiplexVideoRotation90) {
   InternalEncoderFactory internal_encoder_factory;
-  InternalDecoderFactory internal_decoder_factory;
+  InternalDecoderFactory decoder_factory;
   test::FunctionVideoEncoderFactory encoder_factory(
       [&internal_encoder_factory]() {
         return absl::make_unique<MultiplexEncoderAdapter>(
             &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
       });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      [&internal_decoder_factory]() {
-        return absl::make_unique<MultiplexDecoderAdapter>(
-            &internal_decoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
-      });
-  CodecObserver test(5, kVideoRotation_90, "multiplex", &encoder_factory,
-                     &decoder_factory);
+  CodecObserver test(
+      5, kVideoRotation_90, "multiplex", &encoder_factory,
+      absl::make_unique<MultiplexDecoderAdapter>(
+          &decoder_factory, SdpVideoFormat(cricket::kVp9CodecName)));
   RunBaseTest(&test);
 }
 
@@ -198,20 +183,16 @@
 TEST_P(EndToEndTestH264, SendsAndReceivesH264) {
   test::FunctionVideoEncoderFactory encoder_factory(
       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return H264Decoder::Create(); });
   CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
-                     &decoder_factory);
+                     H264Decoder::Create());
   RunBaseTest(&test);
 }
 
 TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) {
   test::FunctionVideoEncoderFactory encoder_factory(
       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return H264Decoder::Create(); });
   CodecObserver test(5, kVideoRotation_90, "H264", &encoder_factory,
-                     &decoder_factory);
+                     H264Decoder::Create());
   RunBaseTest(&test);
 }
 
@@ -220,10 +201,8 @@
   codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
   test::FunctionVideoEncoderFactory encoder_factory(
       [codec]() { return H264Encoder::Create(codec); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return H264Decoder::Create(); });
   CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
-                     &decoder_factory);
+                     H264Decoder::Create());
   RunBaseTest(&test);
 }
 
@@ -232,10 +211,8 @@
   codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
   test::FunctionVideoEncoderFactory encoder_factory(
       [codec]() { return H264Encoder::Create(codec); });
-  test::FunctionVideoDecoderFactory decoder_factory(
-      []() { return H264Decoder::Create(); });
   CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
-                     &decoder_factory);
+                     H264Decoder::Create());
   RunBaseTest(&test);
 }
 #endif  // defined(WEBRTC_USE_H264)
diff --git a/video/end_to_end_tests/fec_tests.cc b/video/end_to_end_tests/fec_tests.cc
index 0300d12..000f6d7 100644
--- a/video/end_to_end_tests/fec_tests.cc
+++ b/video/end_to_end_tests/fec_tests.cc
@@ -11,7 +11,6 @@
 #include "api/test/simulated_network.h"
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
-#include "media/engine/internaldecoderfactory.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "test/call_test.h"
@@ -99,7 +98,7 @@
       encoder_config->codec_type = kVideoCodecVP8;
       VideoReceiveStream::Decoder decoder =
           test::CreateMatchingDecoder(*send_config);
-      decoder.decoder_factory = &decoder_factory_;
+      decoder_.reset(decoder.decoder);
       (*receive_configs)[0].decoders.clear();
       (*receive_configs)[0].decoders.push_back(decoder);
 
@@ -120,7 +119,7 @@
     rtc::CriticalSection crit_;
     std::unique_ptr<VideoEncoder> encoder_;
     test::FunctionVideoEncoderFactory encoder_factory_;
-    InternalDecoderFactory decoder_factory_;
+    std::unique_ptr<VideoDecoder> decoder_;
     std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
     // Several packets can have the same timestamp.
     std::multiset<uint32_t> dropped_timestamps_ RTC_GUARDED_BY(crit_);
@@ -330,7 +329,8 @@
           ulpfec_sequence_number_(0),
           has_last_sequence_number_(false),
           last_sequence_number_(0),
-          encoder_factory_([]() { return VP8Encoder::Create(); }) {}
+          encoder_factory_([]() { return VP8Encoder::Create(); }),
+          decoder_(VP8Decoder::Create()) {}
 
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
@@ -461,7 +461,7 @@
           send_config->rtp.payload_type;
       (*receive_configs)[0].decoders[0].video_format =
           SdpVideoFormat(send_config->rtp.payload_name);
-      (*receive_configs)[0].decoders[0].decoder_factory = &decoder_factory_;
+      (*receive_configs)[0].decoders[0].decoder = decoder_.get();
     }
 
     void PerformTest() override {
@@ -482,8 +482,9 @@
     uint16_t ulpfec_sequence_number_ RTC_GUARDED_BY(&crit_);
     bool has_last_sequence_number_;
     uint16_t last_sequence_number_;
+    std::unique_ptr<webrtc::VideoEncoder> encoder_;
     test::FunctionVideoEncoderFactory encoder_factory_;
-    InternalDecoderFactory decoder_factory_;
+    std::unique_ptr<webrtc::VideoDecoder> decoder_;
   } test;
 
   RunBaseTest(&test);
diff --git a/video/end_to_end_tests/log_tests.cc b/video/end_to_end_tests/log_tests.cc
index 77466b6..aa62383 100644
--- a/video/end_to_end_tests/log_tests.cc
+++ b/video/end_to_end_tests/log_tests.cc
@@ -8,7 +8,6 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "media/engine/internaldecoderfactory.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "rtc_base/file.h"
 #include "test/call_test.h"
@@ -67,6 +66,8 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
+      decoder_ = VP8Decoder::Create();
+
       send_config->post_encode_callback = this;
       send_config->rtp.payload_name = "VP8";
       send_config->encoder_settings.encoder_factory = &encoder_factory_;
@@ -77,7 +78,7 @@
           send_config->rtp.payload_type;
       (*receive_configs)[0].decoders[0].video_format =
           SdpVideoFormat(send_config->rtp.payload_name);
-      (*receive_configs)[0].decoders[0].decoder_factory = &decoder_factory_;
+      (*receive_configs)[0].decoders[0].decoder = decoder_.get();
     }
 
     void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
@@ -96,7 +97,7 @@
    private:
     LogEndToEndTest* const fixture_;
     test::FunctionVideoEncoderFactory encoder_factory_;
-    InternalDecoderFactory decoder_factory_;
+    std::unique_ptr<VideoDecoder> decoder_;
     rtc::CriticalSection crit_;
     int recorded_frames_ RTC_GUARDED_BY(crit_);
   } test(this);
diff --git a/video/end_to_end_tests/multi_codec_receive_tests.cc b/video/end_to_end_tests/multi_codec_receive_tests.cc
index e13bc35..7399ef8 100644
--- a/video/end_to_end_tests/multi_codec_receive_tests.cc
+++ b/video/end_to_end_tests/multi_codec_receive_tests.cc
@@ -180,7 +180,6 @@
   struct CodecConfig {
     std::string payload_name;
     VideoEncoderFactory* encoder_factory;
-    VideoDecoderFactory* decoder_factory;
     size_t num_temporal_layers;
   };
 
@@ -198,16 +197,18 @@
 
 void MultiCodecReceiveTest::ConfigureDecoders(
     const std::vector<CodecConfig>& configs) {
-  video_receive_configs_[0].decoders.clear();
   // Placing the payload names in a std::set retains the unique names only.
   std::set<std::string> unique_payload_names;
   for (const auto& config : configs)
-    if (unique_payload_names.insert(config.payload_name).second) {
-      VideoReceiveStream::Decoder decoder = test::CreateMatchingDecoder(
-          PayloadNameToPayloadType(config.payload_name), config.payload_name);
-      decoder.decoder_factory = config.decoder_factory;
+    unique_payload_names.insert(config.payload_name);
 
-      video_receive_configs_[0].decoders.push_back(decoder);
+  video_receive_configs_[0].decoders.clear();
+  for (const auto& payload_name : unique_payload_names) {
+    VideoReceiveStream::Decoder decoder = test::CreateMatchingDecoder(
+        PayloadNameToPayloadType(payload_name), payload_name);
+    allocated_decoders_.push_back(
+        std::unique_ptr<VideoDecoder>(decoder.decoder));
+    video_receive_configs_[0].decoders.push_back(decoder);
   }
 }
 
@@ -269,13 +270,9 @@
       []() { return VP8Encoder::Create(); });
   test::FunctionVideoEncoderFactory vp9_encoder_factory(
       []() { return VP9Encoder::Create(); });
-  test::FunctionVideoDecoderFactory vp8_decoder_factory(
-      []() { return VP8Decoder::Create(); });
-  test::FunctionVideoDecoderFactory vp9_decoder_factory(
-      []() { return VP9Decoder::Create(); });
-  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
-                     {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1},
-                     {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1}});
+  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, 1},
+                     {"VP9", &vp9_encoder_factory, 1},
+                     {"VP8", &vp8_encoder_factory, 1}});
 }
 
 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9WithTl) {
@@ -283,13 +280,9 @@
       []() { return VP8Encoder::Create(); });
   test::FunctionVideoEncoderFactory vp9_encoder_factory(
       []() { return VP9Encoder::Create(); });
-  test::FunctionVideoDecoderFactory vp8_decoder_factory(
-      []() { return VP8Decoder::Create(); });
-  test::FunctionVideoDecoderFactory vp9_decoder_factory(
-      []() { return VP9Decoder::Create(); });
-  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 2},
-                     {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 2},
-                     {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 2}});
+  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, 2},
+                     {"VP9", &vp9_encoder_factory, 2},
+                     {"VP8", &vp8_encoder_factory, 2}});
 }
 
 #if defined(WEBRTC_USE_H264)
@@ -298,13 +291,9 @@
       []() { return VP8Encoder::Create(); });
   test::FunctionVideoEncoderFactory h264_encoder_factory(
       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
-  test::FunctionVideoDecoderFactory vp8_decoder_factory(
-      []() { return VP8Decoder::Create(); });
-  test::FunctionVideoDecoderFactory h264_decoder_factory(
-      []() { return H264Decoder::Create(); });
-  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
-                     {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
-                     {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1}});
+  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, 1},
+                     {"H264", &h264_encoder_factory, 1},
+                     {"VP8", &vp8_encoder_factory, 1}});
 }
 
 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8H264WithTl) {
@@ -312,13 +301,9 @@
       []() { return VP8Encoder::Create(); });
   test::FunctionVideoEncoderFactory h264_encoder_factory(
       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
-  test::FunctionVideoDecoderFactory vp8_decoder_factory(
-      []() { return VP8Decoder::Create(); });
-  test::FunctionVideoDecoderFactory h264_decoder_factory(
-      []() { return H264Decoder::Create(); });
-  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3},
-                     {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
-                     {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3}});
+  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, 3},
+                     {"H264", &h264_encoder_factory, 1},
+                     {"VP8", &vp8_encoder_factory, 3}});
 }
 
 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9H264) {
@@ -328,16 +313,10 @@
       []() { return VP9Encoder::Create(); });
   test::FunctionVideoEncoderFactory h264_encoder_factory(
       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
-  test::FunctionVideoDecoderFactory vp8_decoder_factory(
-      []() { return VP8Decoder::Create(); });
-  test::FunctionVideoDecoderFactory vp9_decoder_factory(
-      []() { return VP9Decoder::Create(); });
-  test::FunctionVideoDecoderFactory h264_decoder_factory(
-      []() { return H264Decoder::Create(); });
-  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
-                     {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1},
-                     {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
-                     {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1}});
+  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, 1},
+                     {"VP9", &vp9_encoder_factory, 1},
+                     {"H264", &h264_encoder_factory, 1},
+                     {"VP9", &vp9_encoder_factory, 1}});
 }
 
 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9H264WithTl) {
@@ -347,16 +326,10 @@
       []() { return VP9Encoder::Create(); });
   test::FunctionVideoEncoderFactory h264_encoder_factory(
       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
-  test::FunctionVideoDecoderFactory vp8_decoder_factory(
-      []() { return VP8Decoder::Create(); });
-  test::FunctionVideoDecoderFactory vp9_decoder_factory(
-      []() { return VP9Decoder::Create(); });
-  test::FunctionVideoDecoderFactory h264_decoder_factory(
-      []() { return H264Decoder::Create(); });
-  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3},
-                     {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 2},
-                     {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
-                     {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 3}});
+  RunTestWithCodecs({{"VP8", &vp8_encoder_factory, 3},
+                     {"VP9", &vp9_encoder_factory, 2},
+                     {"H264", &h264_encoder_factory, 1},
+                     {"VP9", &vp9_encoder_factory, 3}});
 }
 #endif  // defined(WEBRTC_USE_H264)
 
diff --git a/video/end_to_end_tests/multi_stream_tester.cc b/video/end_to_end_tests/multi_stream_tester.cc
index 7d66976..c4f99e6 100644
--- a/video/end_to_end_tests/multi_stream_tester.cc
+++ b/video/end_to_end_tests/multi_stream_tester.cc
@@ -18,7 +18,6 @@
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
 #include "logging/rtc_event_log/rtc_event_log.h"
-#include "media/engine/internaldecoderfactory.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "test/call_test.h"
 #include "test/encoder_settings.h"
@@ -52,9 +51,9 @@
   VideoSendStream* send_streams[kNumStreams];
   VideoReceiveStream* receive_streams[kNumStreams];
   test::FrameGeneratorCapturer* frame_generators[kNumStreams];
+  std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
   test::FunctionVideoEncoderFactory encoder_factory(
       []() { return VP8Encoder::Create(); });
-  InternalDecoderFactory decoder_factory;
 
   task_queue_->SendTask([&]() {
     sender_call = absl::WrapUnique(Call::Create(config));
@@ -92,7 +91,8 @@
       receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
       VideoReceiveStream::Decoder decoder =
           test::CreateMatchingDecoder(send_config);
-      decoder.decoder_factory = &decoder_factory;
+      allocated_decoders.push_back(
+          std::unique_ptr<VideoDecoder>(decoder.decoder));
       receive_config.decoders.push_back(decoder);
 
       UpdateReceiveConfig(i, &receive_config);
diff --git a/video/end_to_end_tests/network_state_tests.cc b/video/end_to_end_tests/network_state_tests.cc
index 937777f..59c2b51 100644
--- a/video/end_to_end_tests/network_state_tests.cc
+++ b/video/end_to_end_tests/network_state_tests.cc
@@ -13,9 +13,9 @@
 #include "call/simulated_network.h"
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
+#include "test/encoder_proxy_factory.h"
 #include "test/fake_encoder.h"
 #include "test/gtest.h"
-#include "test/video_encoder_proxy_factory.h"
 
 namespace webrtc {
 namespace {
@@ -82,7 +82,7 @@
     MediaType network_to_bring_up,
     VideoEncoder* encoder,
     Transport* transport) {
-  test::VideoEncoderProxyFactory encoder_factory(encoder);
+  test::EncoderProxyFactory encoder_factory(encoder);
 
   task_queue_.SendTask([this, network_to_bring_up, &encoder_factory,
                         transport]() {
@@ -341,7 +341,7 @@
     rtc::Event packet_event_;
     Call* sender_call_;
     Call* receiver_call_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
     NetworkState sender_state_ RTC_GUARDED_BY(test_crit_);
     int sender_rtp_ RTC_GUARDED_BY(test_crit_);
     int sender_padding_ RTC_GUARDED_BY(test_crit_);
diff --git a/video/replay.cc b/video/replay.cc
index 10aec6f..a5eafae 100644
--- a/video/replay.cc
+++ b/video/replay.cc
@@ -19,7 +19,6 @@
 #include "call/call.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "logging/rtc_event_log/rtc_event_log.h"
-#include "media/engine/internaldecoderfactory.h"
 #include "modules/rtp_rtcp/include/rtp_header_parser.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/file.h"
@@ -32,7 +31,6 @@
 #include "test/call_test.h"
 #include "test/encoder_settings.h"
 #include "test/fake_decoder.h"
-#include "test/function_video_decoder_factory.h"
 #include "test/gtest.h"
 #include "test/null_transport.h"
 #include "test/rtp_file_reader.h"
@@ -332,7 +330,6 @@
     test::NullTransport transport;
     std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>> sinks;
     std::vector<VideoReceiveStream*> receive_streams;
-    std::unique_ptr<VideoDecoderFactory> decoder_factory;
   };
 
   // Loads multiple configurations from the provided configuration file.
@@ -353,7 +350,6 @@
       return nullptr;
     }
 
-    stream_state->decoder_factory = absl::make_unique<InternalDecoderFactory>();
     size_t config_count = 0;
     for (const auto& json : json_configs) {
       // Create the configuration and parse the JSON into the config.
@@ -361,9 +357,9 @@
           &(stream_state->transport), json);
       // Instantiate the underlying decoder.
       for (auto& decoder : receive_config.decoders) {
-        decoder = test::CreateMatchingDecoder(decoder.payload_type,
-                                              decoder.video_format.name);
-        decoder.decoder_factory = stream_state->decoder_factory.get();
+        decoder.decoder = test::CreateMatchingDecoder(decoder.payload_type,
+                                                      decoder.video_format.name)
+                              .decoder;
       }
       // Create a window for this config.
       std::stringstream window_title;
@@ -421,19 +417,13 @@
     VideoReceiveStream::Decoder decoder;
     decoder =
         test::CreateMatchingDecoder(flags::MediaPayloadType(), flags::Codec());
-    if (flags::DecoderBitstreamFilename().empty()) {
-      stream_state->decoder_factory =
-          absl::make_unique<InternalDecoderFactory>();
-    } else {
+    if (!flags::DecoderBitstreamFilename().empty()) {
       // Replace decoder with file writer if we're writing the bitstream to a
       // file instead.
-      stream_state->decoder_factory =
-          absl::make_unique<test::FunctionVideoDecoderFactory>([]() {
-            return absl::make_unique<DecoderBitstreamFileWriter>(
-                flags::DecoderBitstreamFilename().c_str());
-          });
+      delete decoder.decoder;
+      decoder.decoder = new DecoderBitstreamFileWriter(
+          flags::DecoderBitstreamFilename().c_str());
     }
-    decoder.decoder_factory = stream_state->decoder_factory.get();
     receive_config.decoders.push_back(decoder);
 
     stream_state->receive_streams.emplace_back(
diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc
index 838825e..cd4c5f7 100644
--- a/video/video_quality_test.cc
+++ b/video/video_quality_test.cc
@@ -495,6 +495,7 @@
   video_receive_configs_.clear();
   video_send_configs_.clear();
   video_encoder_configs_.clear();
+  allocated_decoders_.clear();
   bool decode_all_receive_streams = true;
   size_t num_video_substreams = params_.ss[0].streams.size();
   RTC_CHECK(num_video_streams_ > 0);
diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc
index 186ce4b..7facf85 100644
--- a/video/video_receive_stream.cc
+++ b/video/video_receive_stream.cc
@@ -18,7 +18,6 @@
 
 #include "absl/memory/memory.h"
 #include "absl/types/optional.h"
-#include "api/video_codecs/video_decoder_factory.h"
 #include "call/rtp_stream_receiver_controller_interface.h"
 #include "call/rtx_receive_stream.h"
 #include "common_types.h"  // NOLINT(build/include)
@@ -76,37 +75,6 @@
 
   return codec;
 }
-
-// Video decoder class to be used for unknown codecs. Doesn't support decoding
-// but logs messages to LS_ERROR.
-class NullVideoDecoder : public webrtc::VideoDecoder {
- public:
-  int32_t InitDecode(const webrtc::VideoCodec* codec_settings,
-                     int32_t number_of_cores) override {
-    RTC_LOG(LS_ERROR) << "Can't initialize NullVideoDecoder.";
-    return WEBRTC_VIDEO_CODEC_OK;
-  }
-
-  int32_t Decode(const webrtc::EncodedImage& input_image,
-                 bool missing_frames,
-                 const webrtc::CodecSpecificInfo* codec_specific_info,
-                 int64_t render_time_ms) override {
-    RTC_LOG(LS_ERROR) << "The NullVideoDecoder doesn't support decoding.";
-    return WEBRTC_VIDEO_CODEC_OK;
-  }
-
-  int32_t RegisterDecodeCompleteCallback(
-      webrtc::DecodedImageCallback* callback) override {
-    RTC_LOG(LS_ERROR)
-        << "Can't register decode complete callback on NullVideoDecoder.";
-    return WEBRTC_VIDEO_CODEC_OK;
-  }
-
-  int32_t Release() override { return WEBRTC_VIDEO_CODEC_OK; }
-
-  const char* ImplementationName() const override { return "NullVideoDecoder"; }
-};
-
 }  // namespace
 
 namespace internal {
@@ -153,7 +121,7 @@
   RTC_DCHECK(!config_.decoders.empty());
   std::set<int> decoder_payload_types;
   for (const Decoder& decoder : config_.decoders) {
-    RTC_CHECK(decoder.decoder_factory);
+    RTC_CHECK(decoder.decoder);
     RTC_CHECK(decoder_payload_types.find(decoder.payload_type) ==
               decoder_payload_types.end())
         << "Duplicate payload type (" << decoder.payload_type
@@ -235,19 +203,7 @@
   RTC_DCHECK(renderer != nullptr);
 
   for (const Decoder& decoder : config_.decoders) {
-    std::unique_ptr<VideoDecoder> video_decoder =
-        decoder.decoder_factory->LegacyCreateVideoDecoder(decoder.video_format,
-                                                          config_.stream_id);
-    // If we still have no valid decoder, we have to create a "Null" decoder
-    // that ignores all calls. The reason we can get into this state is that the
-    // old decoder factory interface doesn't have a way to query supported
-    // codecs.
-    if (!video_decoder) {
-      video_decoder = absl::make_unique<NullVideoDecoder>();
-    }
-    video_decoders_.push_back(std::move(video_decoder));
-
-    video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(),
+    video_receiver_.RegisterExternalDecoder(decoder.decoder,
                                             decoder.payload_type);
     VideoCodec codec = CreateDecoderVideoCodec(decoder);
     rtp_video_stream_receiver_.AddReceiveCodec(codec,
diff --git a/video/video_receive_stream.h b/video/video_receive_stream.h
index fb0ee3b..76ee2ed 100644
--- a/video/video_receive_stream.h
+++ b/video/video_receive_stream.h
@@ -143,10 +143,6 @@
   std::unique_ptr<VideoStreamDecoder> video_stream_decoder_;
   RtpStreamsSynchronizer rtp_stream_sync_;
 
-  // TODO(nisse, philipel): Creation and ownership of video encoders should be
-  // moved to the new VideoStreamDecoder.
-  std::vector<std::unique_ptr<VideoDecoder>> video_decoders_;
-
   rtc::CriticalSection ivf_writer_lock_;
   std::unique_ptr<IvfFileWriter> ivf_writer_ RTC_GUARDED_BY(ivf_writer_lock_);
 
diff --git a/video/video_receive_stream_unittest.cc b/video/video_receive_stream_unittest.cc
index e4ba69b..4b433d2 100644
--- a/video/video_receive_stream_unittest.cc
+++ b/video/video_receive_stream_unittest.cc
@@ -23,7 +23,6 @@
 #include "rtc_base/event.h"
 #include "system_wrappers/include/clock.h"
 #include "test/field_trial.h"
-#include "test/video_decoder_proxy_factory.h"
 #include "video/call_stats.h"
 #include "video/video_receive_stream.h"
 
@@ -66,9 +65,7 @@
   VideoReceiveStreamTest()
       : process_thread_(ProcessThread::Create("TestThread")),
         config_(&mock_transport_),
-        call_stats_(Clock::GetRealTimeClock(), process_thread_.get()),
-        h264_decoder_factory_(&mock_h264_video_decoder_),
-        null_decoder_factory_(&mock_null_video_decoder_) {}
+        call_stats_(Clock::GetRealTimeClock(), process_thread_.get()) {}
 
   void SetUp() {
     constexpr int kDefaultNumCpuCores = 2;
@@ -80,12 +77,12 @@
     h264_decoder.video_format = SdpVideoFormat("H264");
     h264_decoder.video_format.parameters.insert(
         {"sprop-parameter-sets", "Z0IACpZTBYmI,aMljiA=="});
-    h264_decoder.decoder_factory = &h264_decoder_factory_;
+    h264_decoder.decoder = &mock_h264_video_decoder_;
     config_.decoders.push_back(h264_decoder);
     VideoReceiveStream::Decoder null_decoder;
     null_decoder.payload_type = 98;
     null_decoder.video_format = SdpVideoFormat("null");
-    null_decoder.decoder_factory = &null_decoder_factory_;
+    null_decoder.decoder = &mock_null_video_decoder_;
     config_.decoders.push_back(null_decoder);
 
     video_receive_stream_.reset(new webrtc::internal::VideoReceiveStream(
@@ -99,8 +96,6 @@
   CallStats call_stats_;
   MockVideoDecoder mock_h264_video_decoder_;
   MockVideoDecoder mock_null_video_decoder_;
-  test::VideoDecoderProxyFactory h264_decoder_factory_;
-  test::VideoDecoderProxyFactory null_decoder_factory_;
   cricket::FakeVideoRenderer fake_renderer_;
   MockTransport mock_transport_;
   PacketRouter packet_router_;
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index a4d5e19..c015f56 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -36,6 +36,7 @@
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
 #include "test/configurable_frame_size_encoder.h"
+#include "test/encoder_proxy_factory.h"
 #include "test/fake_encoder.h"
 #include "test/fake_texture_frame.h"
 #include "test/field_trial.h"
@@ -47,7 +48,6 @@
 #include "test/null_transport.h"
 #include "test/rtcp_packet_parser.h"
 #include "test/testsupport/perf_test.h"
-#include "test/video_encoder_proxy_factory.h"
 
 #include "call/video_send_stream.h"
 #include "video/send_statistics_proxy.h"
@@ -1173,7 +1173,7 @@
 
     std::unique_ptr<internal::TransportAdapter> transport_adapter_;
     test::ConfigurableFrameSizeEncoder encoder_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
 
     const size_t max_packet_size_;
     const size_t stop_size_;
@@ -1961,7 +1961,7 @@
 
   test::NullTransport transport;
   EncoderObserver encoder;
-  test::VideoEncoderProxyFactory encoder_factory(&encoder);
+  test::EncoderProxyFactory encoder_factory(&encoder);
 
   task_queue_.SendTask([this, &transport, &encoder_factory]() {
     CreateSenderCall();
@@ -2039,7 +2039,7 @@
       bitrate_config);
 
   StartBitrateObserver encoder;
-  test::VideoEncoderProxyFactory encoder_factory(&encoder);
+  test::EncoderProxyFactory encoder_factory(&encoder);
   // Since this test does not use a capturer, set |internal_source| = true.
   // Encoder configuration is otherwise updated on the next video frame.
   encoder_factory.SetHasInternalSource(true);
@@ -2124,7 +2124,7 @@
 TEST_P(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) {
   test::NullTransport transport;
   StartStopBitrateObserver encoder;
-  test::VideoEncoderProxyFactory encoder_factory(&encoder);
+  test::EncoderProxyFactory encoder_factory(&encoder);
   encoder_factory.SetHasInternalSource(true);
   test::FrameForwarder forwarder;
 
@@ -2167,7 +2167,7 @@
 TEST_P(VideoSendStreamTest, VideoSendStreamUpdateActiveSimulcastLayers) {
   test::NullTransport transport;
   StartStopBitrateObserver encoder;
-  test::VideoEncoderProxyFactory encoder_factory(&encoder);
+  test::EncoderProxyFactory encoder_factory(&encoder);
   encoder_factory.SetHasInternalSource(true);
   test::FrameForwarder forwarder;
 
@@ -2441,7 +2441,7 @@
     bool callback_registered_ RTC_GUARDED_BY(crit_);
     size_t num_releases_ RTC_GUARDED_BY(crit_);
     bool released_ RTC_GUARDED_BY(crit_);
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
     VideoEncoderConfig encoder_config_;
   } test_encoder(&task_queue_);
 
@@ -2512,7 +2512,7 @@
     rtc::Event init_encode_event_;
     size_t num_initializations_;
     VideoSendStream* stream_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
     VideoEncoderConfig encoder_config_;
   } test;
 
@@ -2622,7 +2622,7 @@
   rtc::Event init_encode_event_;
   size_t num_initializations_;
   VideoSendStream* stream_;
-  test::VideoEncoderProxyFactory encoder_factory_;
+  test::EncoderProxyFactory encoder_factory_;
   VideoEncoderConfig encoder_config_;
 };
 
@@ -2840,7 +2840,7 @@
       EXPECT_TRUE(Wait())
           << "Timed out while waiting for the encoder to be initialized.";
     }
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
   } test;
 
   RunBaseTest(&test);
@@ -3020,7 +3020,7 @@
     int num_initializations_;
     webrtc::Call* call_;
     webrtc::VideoSendStream* send_stream_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
     webrtc::VideoEncoderConfig encoder_config_;
   } test(&task_queue_);
 
@@ -3109,7 +3109,7 @@
     }
 
     VideoSendStream* send_stream_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
   } test;
 
   RunBaseTest(&test);
@@ -3741,7 +3741,7 @@
 
    private:
     test::SingleThreadedTaskQueueForTesting* const task_queue_;
-    test::VideoEncoderProxyFactory encoder_factory_;
+    test::EncoderProxyFactory encoder_factory_;
     Call* call_;
     rtc::CriticalSection crit_;
     uint32_t max_bitrate_bps_ RTC_GUARDED_BY(&crit_);
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index bcccbca..b97d2cf 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -22,13 +22,13 @@
 #include "rtc_base/refcountedobject.h"
 #include "system_wrappers/include/metrics_default.h"
 #include "system_wrappers/include/sleep.h"
+#include "test/encoder_proxy_factory.h"
 #include "test/encoder_settings.h"
 #include "test/fake_encoder.h"
 #include "test/field_trial.h"
 #include "test/frame_generator.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
-#include "test/video_encoder_proxy_factory.h"
 #include "video/send_statistics_proxy.h"
 #include "video/video_stream_encoder.h"
 
@@ -691,7 +691,7 @@
   int codec_height_;
   int max_framerate_;
   TestEncoder fake_encoder_;
-  test::VideoEncoderProxyFactory encoder_factory_;
+  test::EncoderProxyFactory encoder_factory_;
   std::unique_ptr<MockableSendStatisticsProxy> stats_proxy_;
   TestSink sink_;
   AdaptingFrameForwarder video_source_;