Split VCMCodecDataBase into VCMEncoderDataBase and VCMDecoderDataBase.

Intended to ease further refactoring, cleanup and deletion in this code.

Bug: webrtc:8830
Change-Id: Ib862b073e93b67b4f8eedbbf40ad3a8354a566a2
Reviewed-on: https://webrtc-review.googlesource.com/55562
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22120}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 329427e..1b7b511 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -13,14 +13,16 @@
   deps = []
 
   sources = [
-    "codec_database.cc",
-    "codec_database.h",
     "codec_timer.cc",
     "codec_timer.h",
+    "decoder_database.cc",
+    "decoder_database.h",
     "decoding_state.cc",
     "decoding_state.h",
     "encoded_frame.cc",
     "encoded_frame.h",
+    "encoder_database.cc",
+    "encoder_database.h",
     "fec_controller_default.cc",
     "fec_controller_default.h",
     "fec_rate_table.h",
diff --git a/modules/video_coding/codec_database.cc b/modules/video_coding/codec_database.cc
deleted file mode 100644
index 975c360..0000000
--- a/modules/video_coding/codec_database.cc
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- *  Copyright (c) 2012 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.
- */
-
-#include "modules/video_coding/codec_database.h"
-
-#if defined(USE_BUILTIN_SW_CODECS)
-#include "modules/video_coding/codecs/h264/include/h264.h"
-#include "modules/video_coding/codecs/i420/include/i420.h"  // nogncheck
-#include "modules/video_coding/codecs/vp8/include/vp8.h"    // nogncheck
-#include "modules/video_coding/codecs/vp9/include/vp9.h"    // nogncheck
-#endif
-
-#include "modules/video_coding/internal_defines.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-
-namespace {
-const size_t kDefaultPayloadSize = 1440;
-}
-
-namespace webrtc {
-
-#if defined(USE_BUILTIN_SW_CODECS)
-// Create an internal Decoder given a codec type
-static std::unique_ptr<VCMGenericDecoder> CreateDecoder(VideoCodecType type) {
-  switch (type) {
-    case kVideoCodecVP8:
-      return std::unique_ptr<VCMGenericDecoder>(
-          new VCMGenericDecoder(VP8Decoder::Create()));
-    case kVideoCodecVP9:
-      return std::unique_ptr<VCMGenericDecoder>(
-          new VCMGenericDecoder(VP9Decoder::Create()));
-    case kVideoCodecI420:
-      return std::unique_ptr<VCMGenericDecoder>(
-          new VCMGenericDecoder(new I420Decoder()));
-    case kVideoCodecH264:
-      if (H264Decoder::IsSupported()) {
-        return std::unique_ptr<VCMGenericDecoder>(
-            new VCMGenericDecoder(H264Decoder::Create()));
-      }
-      break;
-    default:
-      break;
-  }
-  RTC_LOG(LS_WARNING) << "No internal decoder of this type exists.";
-  return std::unique_ptr<VCMGenericDecoder>();
-}
-#endif
-
-VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings,
-                                     int number_of_cores,
-                                     bool require_key_frame)
-    : settings(settings),
-      number_of_cores(number_of_cores),
-      require_key_frame(require_key_frame) {
-  RTC_DCHECK_GE(number_of_cores, 0);
-}
-
-VCMExtDecoderMapItem::VCMExtDecoderMapItem(
-    VideoDecoder* external_decoder_instance,
-    uint8_t payload_type)
-    : payload_type(payload_type),
-      external_decoder_instance(external_decoder_instance) {}
-
-VCMCodecDataBase::VCMCodecDataBase(
-    VCMEncodedFrameCallback* encoded_frame_callback)
-    : number_of_cores_(0),
-      max_payload_size_(kDefaultPayloadSize),
-      periodic_key_frames_(false),
-      pending_encoder_reset_(true),
-      send_codec_(),
-      receive_codec_(),
-      encoder_payload_type_(0),
-      external_encoder_(nullptr),
-      internal_source_(false),
-      encoded_frame_callback_(encoded_frame_callback),
-      dec_map_(),
-      dec_external_map_() {}
-
-VCMCodecDataBase::~VCMCodecDataBase() {
-  DeleteEncoder();
-  ptr_decoder_.reset();
-  for (auto& kv : dec_map_)
-    delete kv.second;
-  for (auto& kv : dec_external_map_)
-    delete kv.second;
-}
-
-// Assuming only one registered encoder - since only one used, no need for more.
-bool VCMCodecDataBase::SetSendCodec(const VideoCodec* send_codec,
-                                    int number_of_cores,
-                                    size_t max_payload_size) {
-  RTC_DCHECK(send_codec);
-  if (max_payload_size == 0) {
-    max_payload_size = kDefaultPayloadSize;
-  }
-  RTC_DCHECK_GE(number_of_cores, 1);
-  RTC_DCHECK_GE(send_codec->plType, 1);
-  // Make sure the start bit rate is sane...
-  RTC_DCHECK_LE(send_codec->startBitrate, 1000000);
-  RTC_DCHECK(send_codec->codecType != kVideoCodecUnknown);
-  bool reset_required = pending_encoder_reset_;
-  if (number_of_cores_ != number_of_cores) {
-    number_of_cores_ = number_of_cores;
-    reset_required = true;
-  }
-  if (max_payload_size_ != max_payload_size) {
-    max_payload_size_ = max_payload_size;
-    reset_required = true;
-  }
-
-  VideoCodec new_send_codec;
-  memcpy(&new_send_codec, send_codec, sizeof(new_send_codec));
-
-  if (new_send_codec.maxBitrate == 0) {
-    // max is one bit per pixel
-    new_send_codec.maxBitrate = (static_cast<int>(send_codec->height) *
-                                 static_cast<int>(send_codec->width) *
-                                 static_cast<int>(send_codec->maxFramerate)) /
-                                1000;
-    if (send_codec->startBitrate > new_send_codec.maxBitrate) {
-      // But if the user tries to set a higher start bit rate we will
-      // increase the max accordingly.
-      new_send_codec.maxBitrate = send_codec->startBitrate;
-    }
-  }
-
-  if (new_send_codec.startBitrate > new_send_codec.maxBitrate)
-    new_send_codec.startBitrate = new_send_codec.maxBitrate;
-
-  if (!reset_required) {
-    reset_required = RequiresEncoderReset(new_send_codec);
-  }
-
-  memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_));
-
-  if (!reset_required) {
-    return true;
-  }
-
-  // If encoder exists, will destroy it and create new one.
-  DeleteEncoder();
-  RTC_DCHECK_EQ(encoder_payload_type_, send_codec_.plType)
-      << "Encoder not registered for payload type " << send_codec_.plType;
-  ptr_encoder_.reset(new VCMGenericEncoder(
-      external_encoder_, encoded_frame_callback_, internal_source_));
-  encoded_frame_callback_->SetInternalSource(internal_source_);
-  if (ptr_encoder_->InitEncode(&send_codec_, number_of_cores_,
-                               max_payload_size_) < 0) {
-    RTC_LOG(LS_ERROR) << "Failed to initialize video encoder.";
-    DeleteEncoder();
-    return false;
-  }
-
-  // Intentionally don't check return value since the encoder registration
-  // shouldn't fail because the codec doesn't support changing the periodic key
-  // frame setting.
-  ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_);
-
-  pending_encoder_reset_ = false;
-
-  return true;
-}
-
-bool VCMCodecDataBase::DeregisterExternalEncoder(uint8_t payload_type,
-                                                 bool* was_send_codec) {
-  RTC_DCHECK(was_send_codec);
-  *was_send_codec = false;
-  if (encoder_payload_type_ != payload_type) {
-    return false;
-  }
-  if (send_codec_.plType == payload_type) {
-    // De-register as send codec if needed.
-    DeleteEncoder();
-    memset(&send_codec_, 0, sizeof(VideoCodec));
-    *was_send_codec = true;
-  }
-  encoder_payload_type_ = 0;
-  external_encoder_ = nullptr;
-  internal_source_ = false;
-  return true;
-}
-
-void VCMCodecDataBase::RegisterExternalEncoder(VideoEncoder* external_encoder,
-                                               uint8_t payload_type,
-                                               bool internal_source) {
-  // Since only one encoder can be used at a given time, only one external
-  // encoder can be registered/used.
-  external_encoder_ = external_encoder;
-  encoder_payload_type_ = payload_type;
-  internal_source_ = internal_source;
-  pending_encoder_reset_ = true;
-}
-
-bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) {
-  if (!ptr_encoder_)
-    return true;
-
-  // Does not check startBitrate or maxFramerate
-  if (new_send_codec.codecType != send_codec_.codecType ||
-      strcmp(new_send_codec.plName, send_codec_.plName) != 0 ||
-      new_send_codec.plType != send_codec_.plType ||
-      new_send_codec.width != send_codec_.width ||
-      new_send_codec.height != send_codec_.height ||
-      new_send_codec.maxBitrate != send_codec_.maxBitrate ||
-      new_send_codec.minBitrate != send_codec_.minBitrate ||
-      new_send_codec.qpMax != send_codec_.qpMax ||
-      new_send_codec.numberOfSimulcastStreams !=
-          send_codec_.numberOfSimulcastStreams ||
-      new_send_codec.mode != send_codec_.mode) {
-    return true;
-  }
-
-  switch (new_send_codec.codecType) {
-    case kVideoCodecVP8:
-      if (memcmp(&new_send_codec.VP8(), send_codec_.VP8(),
-                 sizeof(new_send_codec.VP8())) != 0) {
-        return true;
-      }
-      break;
-    case kVideoCodecVP9:
-      if (memcmp(&new_send_codec.VP9(), send_codec_.VP9(),
-                 sizeof(new_send_codec.VP9())) != 0) {
-        return true;
-      }
-      break;
-    case kVideoCodecH264:
-      if (memcmp(&new_send_codec.H264(), send_codec_.H264(),
-                 sizeof(new_send_codec.H264())) != 0) {
-        return true;
-      }
-      break;
-    case kVideoCodecGeneric:
-      break;
-    // Known codecs without payload-specifics
-    case kVideoCodecI420:
-    case kVideoCodecRED:
-    case kVideoCodecULPFEC:
-    case kVideoCodecFlexfec:
-    case kVideoCodecMultiplex:
-      break;
-    // Unknown codec type, reset just to be sure.
-    case kVideoCodecUnknown:
-      return true;
-  }
-
-  if (new_send_codec.numberOfSimulcastStreams > 0) {
-    for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
-         ++i) {
-      if (memcmp(&new_send_codec.simulcastStream[i],
-                 &send_codec_.simulcastStream[i],
-                 sizeof(new_send_codec.simulcastStream[i])) != 0) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-VCMGenericEncoder* VCMCodecDataBase::GetEncoder() {
-  return ptr_encoder_.get();
-}
-
-bool VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) {
-  periodic_key_frames_ = enable;
-  if (ptr_encoder_) {
-    return (ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_) == 0);
-  }
-  return true;
-}
-
-bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
-  ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type);
-  if (it == dec_external_map_.end()) {
-    // Not found
-    return false;
-  }
-  // We can't use payload_type to check if the decoder is currently in use,
-  // because payload type may be out of date (e.g. before we decode the first
-  // frame after RegisterReceiveCodec)
-  if (ptr_decoder_ &&
-      ptr_decoder_->IsSameDecoder((*it).second->external_decoder_instance)) {
-    // Release it if it was registered and in use.
-    ptr_decoder_.reset();
-  }
-  DeregisterReceiveCodec(payload_type);
-  delete it->second;
-  dec_external_map_.erase(it);
-  return true;
-}
-
-// Add the external encoder object to the list of external decoders.
-// Won't be registered as a receive codec until RegisterReceiveCodec is called.
-void VCMCodecDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder,
-                                               uint8_t payload_type) {
-  // Check if payload value already exists, if so  - erase old and insert new.
-  VCMExtDecoderMapItem* ext_decoder =
-      new VCMExtDecoderMapItem(external_decoder, payload_type);
-  DeregisterExternalDecoder(payload_type);
-  dec_external_map_[payload_type] = ext_decoder;
-}
-
-bool VCMCodecDataBase::DecoderRegistered() const {
-  return !dec_map_.empty();
-}
-
-bool VCMCodecDataBase::RegisterReceiveCodec(const VideoCodec* receive_codec,
-                                            int number_of_cores,
-                                            bool require_key_frame) {
-  if (number_of_cores < 0) {
-    return false;
-  }
-  // Check if payload value already exists, if so  - erase old and insert new.
-  DeregisterReceiveCodec(receive_codec->plType);
-  if (receive_codec->codecType == kVideoCodecUnknown) {
-    return false;
-  }
-  VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
-  dec_map_[receive_codec->plType] = new VCMDecoderMapItem(
-      new_receive_codec, number_of_cores, require_key_frame);
-  return true;
-}
-
-bool VCMCodecDataBase::DeregisterReceiveCodec(uint8_t payload_type) {
-  DecoderMap::iterator it = dec_map_.find(payload_type);
-  if (it == dec_map_.end()) {
-    return false;
-  }
-  delete it->second;
-  dec_map_.erase(it);
-  if (receive_codec_.plType == payload_type) {
-    // This codec is currently in use.
-    memset(&receive_codec_, 0, sizeof(VideoCodec));
-  }
-  return true;
-}
-
-VCMGenericDecoder* VCMCodecDataBase::GetDecoder(
-    const VCMEncodedFrame& frame,
-    VCMDecodedFrameCallback* decoded_frame_callback) {
-  RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
-  uint8_t payload_type = frame.PayloadType();
-  if (payload_type == receive_codec_.plType || payload_type == 0) {
-    return ptr_decoder_.get();
-  }
-  // Check for exisitng decoder, if exists - delete.
-  if (ptr_decoder_) {
-    ptr_decoder_.reset();
-    memset(&receive_codec_, 0, sizeof(VideoCodec));
-  }
-  ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
-  if (!ptr_decoder_) {
-    return nullptr;
-  }
-  VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
-  callback->OnIncomingPayloadType(receive_codec_.plType);
-  if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
-      0) {
-    ptr_decoder_.reset();
-    memset(&receive_codec_, 0, sizeof(VideoCodec));
-    return nullptr;
-  }
-  return ptr_decoder_.get();
-}
-
-VCMGenericDecoder* VCMCodecDataBase::GetCurrentDecoder() {
-  return ptr_decoder_.get();
-}
-
-bool VCMCodecDataBase::PrefersLateDecoding() const {
-  return ptr_decoder_ ? ptr_decoder_->PrefersLateDecoding() : true;
-}
-
-bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const {
-  return send_codec_.width == width && send_codec_.height == height;
-}
-
-std::unique_ptr<VCMGenericDecoder> VCMCodecDataBase::CreateAndInitDecoder(
-    const VCMEncodedFrame& frame,
-    VideoCodec* new_codec) const {
-  uint8_t payload_type = frame.PayloadType();
-  RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
-                   << static_cast<int>(payload_type) << "'.";
-  RTC_DCHECK(new_codec);
-  const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
-  if (!decoder_item) {
-    RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
-                      << static_cast<int>(payload_type);
-    return nullptr;
-  }
-  std::unique_ptr<VCMGenericDecoder> ptr_decoder;
-  const VCMExtDecoderMapItem* external_dec_item =
-      FindExternalDecoderItem(payload_type);
-  if (external_dec_item) {
-    // External codec.
-    ptr_decoder.reset(new VCMGenericDecoder(
-        external_dec_item->external_decoder_instance, true));
-  } else {
-#if !defined(USE_BUILTIN_SW_CODECS)
-    RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
-#else
-    // Create decoder.
-    ptr_decoder = CreateDecoder(decoder_item->settings->codecType);
-#endif
-  }
-  if (!ptr_decoder)
-    return nullptr;
-
-  // Copy over input resolutions to prevent codec reinitialization due to
-  // the first frame being of a different resolution than the database values.
-  // This is best effort, since there's no guarantee that width/height have been
-  // parsed yet (and may be zero).
-  if (frame.EncodedImage()._encodedWidth > 0 &&
-      frame.EncodedImage()._encodedHeight > 0) {
-    decoder_item->settings->width = frame.EncodedImage()._encodedWidth;
-    decoder_item->settings->height = frame.EncodedImage()._encodedHeight;
-  }
-  if (ptr_decoder->InitDecode(decoder_item->settings.get(),
-                              decoder_item->number_of_cores) < 0) {
-    return nullptr;
-  }
-  memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
-  return ptr_decoder;
-}
-
-void VCMCodecDataBase::DeleteEncoder() {
-  if (!ptr_encoder_)
-    return;
-  ptr_encoder_->Release();
-  ptr_encoder_.reset();
-}
-
-const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem(
-    uint8_t payload_type) const {
-  DecoderMap::const_iterator it = dec_map_.find(payload_type);
-  if (it != dec_map_.end()) {
-    return (*it).second;
-  }
-  return nullptr;
-}
-
-const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem(
-    uint8_t payload_type) const {
-  ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
-  if (it != dec_external_map_.end()) {
-    return (*it).second;
-  }
-  return nullptr;
-}
-}  // namespace webrtc
diff --git a/modules/video_coding/codec_database.h b/modules/video_coding/codec_database.h
deleted file mode 100644
index 80b32b3..0000000
--- a/modules/video_coding/codec_database.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *  Copyright (c) 2012 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 MODULES_VIDEO_CODING_CODEC_DATABASE_H_
-#define MODULES_VIDEO_CODING_CODEC_DATABASE_H_
-
-#include <map>
-#include <memory>
-
-#include "modules/video_coding/include/video_codec_interface.h"
-#include "modules/video_coding/include/video_coding.h"
-#include "modules/video_coding/generic_decoder.h"
-#include "modules/video_coding/generic_encoder.h"
-#include "typedefs.h"  // NOLINT(build/include)
-
-namespace webrtc {
-
-struct VCMDecoderMapItem {
- public:
-  VCMDecoderMapItem(VideoCodec* settings,
-                    int number_of_cores,
-                    bool require_key_frame);
-
-  std::unique_ptr<VideoCodec> settings;
-  int number_of_cores;
-  bool require_key_frame;
-};
-
-struct VCMExtDecoderMapItem {
- public:
-  VCMExtDecoderMapItem(VideoDecoder* external_decoder_instance,
-                       uint8_t payload_type);
-
-  uint8_t payload_type;
-  VideoDecoder* external_decoder_instance;
-};
-
-class VCMCodecDataBase {
- public:
-  explicit VCMCodecDataBase(VCMEncodedFrameCallback* encoded_frame_callback);
-  ~VCMCodecDataBase();
-
-  // Sets the sender side codec and initiates the desired codec given the
-  // VideoCodec struct.
-  // Returns true if the codec was successfully registered, false otherwise.
-  bool SetSendCodec(const VideoCodec* send_codec,
-                    int number_of_cores,
-                    size_t max_payload_size);
-
-  // Registers and initializes an external encoder object.
-  // |internal_source| should be set to true if the codec has an internal
-  // video source and doesn't need the user to provide it with frames via
-  // the Encode() method.
-  void RegisterExternalEncoder(VideoEncoder* external_encoder,
-                               uint8_t payload_type,
-                               bool internal_source);
-
-  // Deregisters an external encoder. Returns true if the encoder was
-  // found and deregistered, false otherwise. |was_send_codec| is set to true
-  // if the external encoder was the send codec before being deregistered.
-  bool DeregisterExternalEncoder(uint8_t payload_type, bool* was_send_codec);
-
-  VCMGenericEncoder* GetEncoder();
-
-  bool SetPeriodicKeyFrames(bool enable);
-
-  // Deregisters an external decoder object specified by |payload_type|.
-  bool DeregisterExternalDecoder(uint8_t payload_type);
-
-  // Registers an external decoder object to the payload type |payload_type|.
-  void RegisterExternalDecoder(VideoDecoder* external_decoder,
-                               uint8_t payload_type);
-
-  bool DecoderRegistered() const;
-
-  bool RegisterReceiveCodec(const VideoCodec* receive_codec,
-                            int number_of_cores,
-                            bool require_key_frame);
-
-  bool DeregisterReceiveCodec(uint8_t payload_type);
-
-  // Returns a decoder specified by |payload_type|. The decoded frame callback
-  // of the encoder is set to |decoded_frame_callback|. If no such decoder
-  // already exists an instance will be created and initialized.
-  // NULL is returned if no encoder with the specified payload type was found
-  // and the function failed to create one.
-  VCMGenericDecoder* GetDecoder(
-      const VCMEncodedFrame& frame,
-      VCMDecodedFrameCallback* decoded_frame_callback);
-
-  // Returns the current decoder (i.e. the same value as was last returned from
-  // GetDecoder();
-  VCMGenericDecoder* GetCurrentDecoder();
-
-  // Returns true if the currently active decoder prefer to decode frames late.
-  // That means that frames must be decoded near the render times stamp.
-  bool PrefersLateDecoding() const;
-
-  bool MatchesCurrentResolution(int width, int height) const;
-
- private:
-  typedef std::map<uint8_t, VCMDecoderMapItem*> DecoderMap;
-  typedef std::map<uint8_t, VCMExtDecoderMapItem*> ExternalDecoderMap;
-
-  std::unique_ptr<VCMGenericDecoder> CreateAndInitDecoder(
-      const VCMEncodedFrame& frame,
-      VideoCodec* new_codec) const;
-
-  // Determines whether a new codec has to be created or not.
-  // Checks every setting apart from maxFramerate and startBitrate.
-  bool RequiresEncoderReset(const VideoCodec& send_codec);
-
-  void DeleteEncoder();
-
-  const VCMDecoderMapItem* FindDecoderItem(uint8_t payload_type) const;
-
-  const VCMExtDecoderMapItem* FindExternalDecoderItem(
-      uint8_t payload_type) const;
-
-  int number_of_cores_;
-  size_t max_payload_size_;
-  bool periodic_key_frames_;
-  bool pending_encoder_reset_;
-  VideoCodec send_codec_;
-  VideoCodec receive_codec_;
-  uint8_t encoder_payload_type_;
-  VideoEncoder* external_encoder_;
-  bool internal_source_;
-  VCMEncodedFrameCallback* const encoded_frame_callback_;
-  std::unique_ptr<VCMGenericEncoder> ptr_encoder_;
-  std::unique_ptr<VCMGenericDecoder> ptr_decoder_;
-  DecoderMap dec_map_;
-  ExternalDecoderMap dec_external_map_;
-};  // VCMCodecDataBase
-
-}  // namespace webrtc
-
-#endif  // MODULES_VIDEO_CODING_CODEC_DATABASE_H_
diff --git a/modules/video_coding/decoder_database.cc b/modules/video_coding/decoder_database.cc
new file mode 100644
index 0000000..87609b8
--- /dev/null
+++ b/modules/video_coding/decoder_database.cc
@@ -0,0 +1,244 @@
+/*
+ *  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.
+ */
+
+#include "modules/video_coding/decoder_database.h"
+#if defined(USE_BUILTIN_SW_CODECS)
+#include "modules/video_coding/codecs/h264/include/h264.h"
+#include "modules/video_coding/codecs/i420/include/i420.h"  // nogncheck
+#include "modules/video_coding/codecs/vp8/include/vp8.h"    // nogncheck
+#include "modules/video_coding/codecs/vp9/include/vp9.h"    // nogncheck
+#endif
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+#if defined(USE_BUILTIN_SW_CODECS)
+// Create an internal Decoder given a codec type
+static std::unique_ptr<VCMGenericDecoder> CreateDecoder(VideoCodecType type) {
+  switch (type) {
+    case kVideoCodecVP8:
+      return std::unique_ptr<VCMGenericDecoder>(
+          new VCMGenericDecoder(VP8Decoder::Create()));
+    case kVideoCodecVP9:
+      return std::unique_ptr<VCMGenericDecoder>(
+          new VCMGenericDecoder(VP9Decoder::Create()));
+    case kVideoCodecI420:
+      return std::unique_ptr<VCMGenericDecoder>(
+          new VCMGenericDecoder(new I420Decoder()));
+    case kVideoCodecH264:
+      if (H264Decoder::IsSupported()) {
+        return std::unique_ptr<VCMGenericDecoder>(
+            new VCMGenericDecoder(H264Decoder::Create()));
+      }
+      break;
+    default:
+      break;
+  }
+  RTC_LOG(LS_WARNING) << "No internal decoder of this type exists.";
+  return std::unique_ptr<VCMGenericDecoder>();
+}
+#endif
+
+VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings,
+                                     int number_of_cores,
+                                     bool require_key_frame)
+    : settings(settings),
+      number_of_cores(number_of_cores),
+      require_key_frame(require_key_frame) {
+  RTC_DCHECK_GE(number_of_cores, 0);
+}
+
+VCMExtDecoderMapItem::VCMExtDecoderMapItem(
+    VideoDecoder* external_decoder_instance,
+    uint8_t payload_type)
+    : payload_type(payload_type),
+      external_decoder_instance(external_decoder_instance) {}
+
+VCMDecoderDataBase::VCMDecoderDataBase()
+    : receive_codec_(), dec_map_(), dec_external_map_() {}
+
+VCMDecoderDataBase::~VCMDecoderDataBase() {
+  ptr_decoder_.reset();
+  for (auto& kv : dec_map_)
+    delete kv.second;
+  for (auto& kv : dec_external_map_)
+    delete kv.second;
+}
+
+bool VCMDecoderDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
+  ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type);
+  if (it == dec_external_map_.end()) {
+    // Not found
+    return false;
+  }
+  // We can't use payload_type to check if the decoder is currently in use,
+  // because payload type may be out of date (e.g. before we decode the first
+  // frame after RegisterReceiveCodec)
+  if (ptr_decoder_ &&
+      ptr_decoder_->IsSameDecoder((*it).second->external_decoder_instance)) {
+    // Release it if it was registered and in use.
+    ptr_decoder_.reset();
+  }
+  DeregisterReceiveCodec(payload_type);
+  delete it->second;
+  dec_external_map_.erase(it);
+  return true;
+}
+
+// Add the external encoder object to the list of external decoders.
+// Won't be registered as a receive codec until RegisterReceiveCodec is called.
+void VCMDecoderDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder,
+                                                 uint8_t payload_type) {
+  // Check if payload value already exists, if so  - erase old and insert new.
+  VCMExtDecoderMapItem* ext_decoder =
+      new VCMExtDecoderMapItem(external_decoder, payload_type);
+  DeregisterExternalDecoder(payload_type);
+  dec_external_map_[payload_type] = ext_decoder;
+}
+
+bool VCMDecoderDataBase::DecoderRegistered() const {
+  return !dec_map_.empty();
+}
+
+bool VCMDecoderDataBase::RegisterReceiveCodec(const VideoCodec* receive_codec,
+                                              int number_of_cores,
+                                              bool require_key_frame) {
+  if (number_of_cores < 0) {
+    return false;
+  }
+  // Check if payload value already exists, if so  - erase old and insert new.
+  DeregisterReceiveCodec(receive_codec->plType);
+  if (receive_codec->codecType == kVideoCodecUnknown) {
+    return false;
+  }
+  VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
+  dec_map_[receive_codec->plType] = new VCMDecoderMapItem(
+      new_receive_codec, number_of_cores, require_key_frame);
+  return true;
+}
+
+bool VCMDecoderDataBase::DeregisterReceiveCodec(uint8_t payload_type) {
+  DecoderMap::iterator it = dec_map_.find(payload_type);
+  if (it == dec_map_.end()) {
+    return false;
+  }
+  delete it->second;
+  dec_map_.erase(it);
+  if (receive_codec_.plType == payload_type) {
+    // This codec is currently in use.
+    memset(&receive_codec_, 0, sizeof(VideoCodec));
+  }
+  return true;
+}
+
+VCMGenericDecoder* VCMDecoderDataBase::GetDecoder(
+    const VCMEncodedFrame& frame,
+    VCMDecodedFrameCallback* decoded_frame_callback) {
+  RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
+  uint8_t payload_type = frame.PayloadType();
+  if (payload_type == receive_codec_.plType || payload_type == 0) {
+    return ptr_decoder_.get();
+  }
+  // Check for exisitng decoder, if exists - delete.
+  if (ptr_decoder_) {
+    ptr_decoder_.reset();
+    memset(&receive_codec_, 0, sizeof(VideoCodec));
+  }
+  ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
+  if (!ptr_decoder_) {
+    return nullptr;
+  }
+  VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
+  callback->OnIncomingPayloadType(receive_codec_.plType);
+  if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
+      0) {
+    ptr_decoder_.reset();
+    memset(&receive_codec_, 0, sizeof(VideoCodec));
+    return nullptr;
+  }
+  return ptr_decoder_.get();
+}
+
+VCMGenericDecoder* VCMDecoderDataBase::GetCurrentDecoder() {
+  return ptr_decoder_.get();
+}
+
+bool VCMDecoderDataBase::PrefersLateDecoding() const {
+  return ptr_decoder_ ? ptr_decoder_->PrefersLateDecoding() : true;
+}
+
+std::unique_ptr<VCMGenericDecoder> VCMDecoderDataBase::CreateAndInitDecoder(
+    const VCMEncodedFrame& frame,
+    VideoCodec* new_codec) const {
+  uint8_t payload_type = frame.PayloadType();
+  RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
+                   << static_cast<int>(payload_type) << "'.";
+  RTC_DCHECK(new_codec);
+  const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
+  if (!decoder_item) {
+    RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
+                      << static_cast<int>(payload_type);
+    return nullptr;
+  }
+  std::unique_ptr<VCMGenericDecoder> ptr_decoder;
+  const VCMExtDecoderMapItem* external_dec_item =
+      FindExternalDecoderItem(payload_type);
+  if (external_dec_item) {
+    // External codec.
+    ptr_decoder.reset(new VCMGenericDecoder(
+        external_dec_item->external_decoder_instance, true));
+  } else {
+#if !defined(USE_BUILTIN_SW_CODECS)
+    RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
+#else
+    // Create decoder.
+    ptr_decoder = CreateDecoder(decoder_item->settings->codecType);
+#endif
+  }
+  if (!ptr_decoder)
+    return nullptr;
+
+  // Copy over input resolutions to prevent codec reinitialization due to
+  // the first frame being of a different resolution than the database values.
+  // This is best effort, since there's no guarantee that width/height have been
+  // parsed yet (and may be zero).
+  if (frame.EncodedImage()._encodedWidth > 0 &&
+      frame.EncodedImage()._encodedHeight > 0) {
+    decoder_item->settings->width = frame.EncodedImage()._encodedWidth;
+    decoder_item->settings->height = frame.EncodedImage()._encodedHeight;
+  }
+  if (ptr_decoder->InitDecode(decoder_item->settings.get(),
+                              decoder_item->number_of_cores) < 0) {
+    return nullptr;
+  }
+  memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
+  return ptr_decoder;
+}
+
+const VCMDecoderMapItem* VCMDecoderDataBase::FindDecoderItem(
+    uint8_t payload_type) const {
+  DecoderMap::const_iterator it = dec_map_.find(payload_type);
+  if (it != dec_map_.end()) {
+    return (*it).second;
+  }
+  return nullptr;
+}
+
+const VCMExtDecoderMapItem* VCMDecoderDataBase::FindExternalDecoderItem(
+    uint8_t payload_type) const {
+  ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
+  if (it != dec_external_map_.end()) {
+    return (*it).second;
+  }
+  return nullptr;
+}
+
+}  // namespace webrtc
diff --git a/modules/video_coding/decoder_database.h b/modules/video_coding/decoder_database.h
new file mode 100644
index 0000000..8c03edb
--- /dev/null
+++ b/modules/video_coding/decoder_database.h
@@ -0,0 +1,96 @@
+/*
+ *  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 MODULES_VIDEO_CODING_DECODER_DATABASE_H_
+#define MODULES_VIDEO_CODING_DECODER_DATABASE_H_
+
+#include <map>
+#include <memory>
+
+#include "modules/video_coding/generic_decoder.h"
+
+namespace webrtc {
+
+struct VCMDecoderMapItem {
+ public:
+  VCMDecoderMapItem(VideoCodec* settings,
+                    int number_of_cores,
+                    bool require_key_frame);
+
+  std::unique_ptr<VideoCodec> settings;
+  int number_of_cores;
+  bool require_key_frame;
+};
+
+struct VCMExtDecoderMapItem {
+ public:
+  VCMExtDecoderMapItem(VideoDecoder* external_decoder_instance,
+                       uint8_t payload_type);
+
+  uint8_t payload_type;
+  VideoDecoder* external_decoder_instance;
+};
+
+class VCMDecoderDataBase {
+ public:
+  VCMDecoderDataBase();
+  ~VCMDecoderDataBase();
+
+  bool DeregisterExternalDecoder(uint8_t payload_type);
+  void RegisterExternalDecoder(VideoDecoder* external_decoder,
+                               uint8_t payload_type);
+
+  bool DecoderRegistered() const;
+
+  bool RegisterReceiveCodec(const VideoCodec* receive_codec,
+                            int number_of_cores,
+                            bool require_key_frame);
+
+  bool DeregisterReceiveCodec(uint8_t payload_type);
+
+  // Returns a decoder specified by |payload_type|. The decoded frame callback
+  // of the encoder is set to |decoded_frame_callback|. If no such decoder
+  // already exists an instance will be created and initialized.
+  // NULL is returned if no encoder with the specified payload type was found
+  // and the function failed to create one.
+  VCMGenericDecoder* GetDecoder(
+      const VCMEncodedFrame& frame,
+      VCMDecodedFrameCallback* decoded_frame_callback);
+
+  // Returns the current decoder (i.e. the same value as was last returned from
+  // GetDecoder();
+  VCMGenericDecoder* GetCurrentDecoder();
+
+  // Returns true if the currently active decoder prefer to decode frames late.
+  // That means that frames must be decoded near the render times stamp.
+  bool PrefersLateDecoding() const;
+
+ private:
+  typedef std::map<uint8_t, VCMDecoderMapItem*> DecoderMap;
+  typedef std::map<uint8_t, VCMExtDecoderMapItem*> ExternalDecoderMap;
+
+  std::unique_ptr<VCMGenericDecoder> CreateAndInitDecoder(
+      const VCMEncodedFrame& frame,
+      VideoCodec* new_codec) const;
+
+  const VCMDecoderMapItem* FindDecoderItem(uint8_t payload_type) const;
+
+  const VCMExtDecoderMapItem* FindExternalDecoderItem(
+      uint8_t payload_type) const;
+
+  VideoCodec receive_codec_;
+  std::unique_ptr<VCMGenericDecoder> ptr_decoder_;
+  DecoderMap dec_map_;
+  ExternalDecoderMap dec_external_map_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_VIDEO_CODING_DECODER_DATABASE_H_
diff --git a/modules/video_coding/encoder_database.cc b/modules/video_coding/encoder_database.cc
new file mode 100644
index 0000000..60e640a
--- /dev/null
+++ b/modules/video_coding/encoder_database.cc
@@ -0,0 +1,233 @@
+/*
+ *  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.
+ */
+
+#include "modules/video_coding/encoder_database.h"
+
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+namespace {
+const size_t kDefaultPayloadSize = 1440;
+}
+
+VCMEncoderDataBase::VCMEncoderDataBase(
+    VCMEncodedFrameCallback* encoded_frame_callback)
+    : number_of_cores_(0),
+      max_payload_size_(kDefaultPayloadSize),
+      periodic_key_frames_(false),
+      pending_encoder_reset_(true),
+      send_codec_(),
+      encoder_payload_type_(0),
+      external_encoder_(nullptr),
+      internal_source_(false),
+      encoded_frame_callback_(encoded_frame_callback) {}
+
+VCMEncoderDataBase::~VCMEncoderDataBase() {
+  DeleteEncoder();
+}
+
+// Assuming only one registered encoder - since only one used, no need for more.
+bool VCMEncoderDataBase::SetSendCodec(const VideoCodec* send_codec,
+                                      int number_of_cores,
+                                      size_t max_payload_size) {
+  RTC_DCHECK(send_codec);
+  if (max_payload_size == 0) {
+    max_payload_size = kDefaultPayloadSize;
+  }
+  RTC_DCHECK_GE(number_of_cores, 1);
+  RTC_DCHECK_GE(send_codec->plType, 1);
+  // Make sure the start bit rate is sane...
+  RTC_DCHECK_LE(send_codec->startBitrate, 1000000);
+  RTC_DCHECK(send_codec->codecType != kVideoCodecUnknown);
+  bool reset_required = pending_encoder_reset_;
+  if (number_of_cores_ != number_of_cores) {
+    number_of_cores_ = number_of_cores;
+    reset_required = true;
+  }
+  if (max_payload_size_ != max_payload_size) {
+    max_payload_size_ = max_payload_size;
+    reset_required = true;
+  }
+
+  VideoCodec new_send_codec;
+  memcpy(&new_send_codec, send_codec, sizeof(new_send_codec));
+
+  if (new_send_codec.maxBitrate == 0) {
+    // max is one bit per pixel
+    new_send_codec.maxBitrate = (static_cast<int>(send_codec->height) *
+                                 static_cast<int>(send_codec->width) *
+                                 static_cast<int>(send_codec->maxFramerate)) /
+                                1000;
+    if (send_codec->startBitrate > new_send_codec.maxBitrate) {
+      // But if the user tries to set a higher start bit rate we will
+      // increase the max accordingly.
+      new_send_codec.maxBitrate = send_codec->startBitrate;
+    }
+  }
+
+  if (new_send_codec.startBitrate > new_send_codec.maxBitrate)
+    new_send_codec.startBitrate = new_send_codec.maxBitrate;
+
+  if (!reset_required) {
+    reset_required = RequiresEncoderReset(new_send_codec);
+  }
+
+  memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_));
+
+  if (!reset_required) {
+    return true;
+  }
+
+  // If encoder exists, will destroy it and create new one.
+  DeleteEncoder();
+  RTC_DCHECK_EQ(encoder_payload_type_, send_codec_.plType)
+      << "Encoder not registered for payload type " << send_codec_.plType;
+  ptr_encoder_.reset(new VCMGenericEncoder(
+      external_encoder_, encoded_frame_callback_, internal_source_));
+  encoded_frame_callback_->SetInternalSource(internal_source_);
+  if (ptr_encoder_->InitEncode(&send_codec_, number_of_cores_,
+                               max_payload_size_) < 0) {
+    RTC_LOG(LS_ERROR) << "Failed to initialize video encoder.";
+    DeleteEncoder();
+    return false;
+  }
+
+  // Intentionally don't check return value since the encoder registration
+  // shouldn't fail because the codec doesn't support changing the periodic key
+  // frame setting.
+  ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_);
+
+  pending_encoder_reset_ = false;
+
+  return true;
+}
+
+bool VCMEncoderDataBase::DeregisterExternalEncoder(uint8_t payload_type,
+                                                   bool* was_send_codec) {
+  RTC_DCHECK(was_send_codec);
+  *was_send_codec = false;
+  if (encoder_payload_type_ != payload_type) {
+    return false;
+  }
+  if (send_codec_.plType == payload_type) {
+    // De-register as send codec if needed.
+    DeleteEncoder();
+    memset(&send_codec_, 0, sizeof(VideoCodec));
+    *was_send_codec = true;
+  }
+  encoder_payload_type_ = 0;
+  external_encoder_ = nullptr;
+  internal_source_ = false;
+  return true;
+}
+
+void VCMEncoderDataBase::RegisterExternalEncoder(VideoEncoder* external_encoder,
+                                                 uint8_t payload_type,
+                                                 bool internal_source) {
+  // Since only one encoder can be used at a given time, only one external
+  // encoder can be registered/used.
+  external_encoder_ = external_encoder;
+  encoder_payload_type_ = payload_type;
+  internal_source_ = internal_source;
+  pending_encoder_reset_ = true;
+}
+
+bool VCMEncoderDataBase::RequiresEncoderReset(
+    const VideoCodec& new_send_codec) {
+  if (!ptr_encoder_)
+    return true;
+
+  // Does not check startBitrate or maxFramerate
+  if (new_send_codec.codecType != send_codec_.codecType ||
+      strcmp(new_send_codec.plName, send_codec_.plName) != 0 ||
+      new_send_codec.plType != send_codec_.plType ||
+      new_send_codec.width != send_codec_.width ||
+      new_send_codec.height != send_codec_.height ||
+      new_send_codec.maxBitrate != send_codec_.maxBitrate ||
+      new_send_codec.minBitrate != send_codec_.minBitrate ||
+      new_send_codec.qpMax != send_codec_.qpMax ||
+      new_send_codec.numberOfSimulcastStreams !=
+          send_codec_.numberOfSimulcastStreams ||
+      new_send_codec.mode != send_codec_.mode) {
+    return true;
+  }
+
+  switch (new_send_codec.codecType) {
+    case kVideoCodecVP8:
+      if (memcmp(&new_send_codec.VP8(), send_codec_.VP8(),
+                 sizeof(new_send_codec.VP8())) != 0) {
+        return true;
+      }
+      break;
+    case kVideoCodecVP9:
+      if (memcmp(&new_send_codec.VP9(), send_codec_.VP9(),
+                 sizeof(new_send_codec.VP9())) != 0) {
+        return true;
+      }
+      break;
+    case kVideoCodecH264:
+      if (memcmp(&new_send_codec.H264(), send_codec_.H264(),
+                 sizeof(new_send_codec.H264())) != 0) {
+        return true;
+      }
+      break;
+    case kVideoCodecGeneric:
+      break;
+    // Known codecs without payload-specifics
+    case kVideoCodecI420:
+    case kVideoCodecRED:
+    case kVideoCodecULPFEC:
+    case kVideoCodecFlexfec:
+    case kVideoCodecMultiplex:
+      break;
+    // Unknown codec type, reset just to be sure.
+    case kVideoCodecUnknown:
+      return true;
+  }
+
+  if (new_send_codec.numberOfSimulcastStreams > 0) {
+    for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
+         ++i) {
+      if (memcmp(&new_send_codec.simulcastStream[i],
+                 &send_codec_.simulcastStream[i],
+                 sizeof(new_send_codec.simulcastStream[i])) != 0) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+VCMGenericEncoder* VCMEncoderDataBase::GetEncoder() {
+  return ptr_encoder_.get();
+}
+
+bool VCMEncoderDataBase::SetPeriodicKeyFrames(bool enable) {
+  periodic_key_frames_ = enable;
+  if (ptr_encoder_) {
+    return (ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_) == 0);
+  }
+  return true;
+}
+
+void VCMEncoderDataBase::DeleteEncoder() {
+  if (!ptr_encoder_)
+    return;
+  ptr_encoder_->Release();
+  ptr_encoder_.reset();
+}
+
+bool VCMEncoderDataBase::MatchesCurrentResolution(int width, int height) const {
+  return send_codec_.width == width && send_codec_.height == height;
+}
+
+}  // namespace webrtc
diff --git a/modules/video_coding/encoder_database.h b/modules/video_coding/encoder_database.h
new file mode 100644
index 0000000..34734ad
--- /dev/null
+++ b/modules/video_coding/encoder_database.h
@@ -0,0 +1,79 @@
+/*
+ *  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 MODULES_VIDEO_CODING_ENCODER_DATABASE_H_
+#define MODULES_VIDEO_CODING_ENCODER_DATABASE_H_
+
+#include <memory>
+
+#include "modules/video_coding/generic_encoder.h"
+
+namespace webrtc {
+
+class VCMEncoderDataBase {
+ public:
+  explicit VCMEncoderDataBase(VCMEncodedFrameCallback* encoded_frame_callback);
+  ~VCMEncoderDataBase();
+
+  // Sets the sender side codec and initiates the desired codec given the
+  // VideoCodec struct.
+  // Returns true if the codec was successfully registered, false otherwise.
+  bool SetSendCodec(const VideoCodec* send_codec,
+                    int number_of_cores,
+                    size_t max_payload_size);
+
+  // Registers and initializes an external encoder object.
+  // |internal_source| should be set to true if the codec has an internal
+  // video source and doesn't need the user to provide it with frames via
+  // the Encode() method.
+  void RegisterExternalEncoder(VideoEncoder* external_encoder,
+                               uint8_t payload_type,
+                               bool internal_source);
+
+  // Deregisters an external encoder. Returns true if the encoder was
+  // found and deregistered, false otherwise. |was_send_codec| is set to true
+  // if the external encoder was the send codec before being deregistered.
+  bool DeregisterExternalEncoder(uint8_t payload_type, bool* was_send_codec);
+
+  VCMGenericEncoder* GetEncoder();
+
+  bool SetPeriodicKeyFrames(bool enable);
+
+  // Deregisters an external decoder object specified by |payload_type|.
+  bool DeregisterExternalDecoder(uint8_t payload_type);
+
+  // Registers an external decoder object to the payload type |payload_type|.
+  void RegisterExternalDecoder(VideoDecoder* external_decoder,
+                               uint8_t payload_type);
+
+  bool MatchesCurrentResolution(int width, int height) const;
+
+ private:
+  // Determines whether a new codec has to be created or not.
+  // Checks every setting apart from maxFramerate and startBitrate.
+  bool RequiresEncoderReset(const VideoCodec& send_codec);
+
+  void DeleteEncoder();
+
+  int number_of_cores_;
+  size_t max_payload_size_;
+  bool periodic_key_frames_;
+  bool pending_encoder_reset_;
+  VideoCodec send_codec_;
+  uint8_t encoder_payload_type_;
+  VideoEncoder* external_encoder_;
+  bool internal_source_;
+  VCMEncodedFrameCallback* const encoded_frame_callback_;
+  std::unique_ptr<VCMGenericEncoder> ptr_encoder_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_VIDEO_CODING_ENCODER_DATABASE_H_
diff --git a/modules/video_coding/video_coding_impl.h b/modules/video_coding/video_coding_impl.h
index be9c09f..8a442c8 100644
--- a/modules/video_coding/video_coding_impl.h
+++ b/modules/video_coding/video_coding_impl.h
@@ -18,7 +18,8 @@
 #include <vector>
 
 #include "common_video/include/frame_callback.h"
-#include "modules/video_coding/codec_database.h"
+#include "modules/video_coding/decoder_database.h"
+#include "modules/video_coding/encoder_database.h"
 #include "modules/video_coding/frame_buffer.h"
 #include "modules/video_coding/generic_decoder.h"
 #include "modules/video_coding/generic_encoder.h"
@@ -121,7 +122,7 @@
   media_optimization::MediaOptimization _mediaOpt;
   VCMEncodedFrameCallback _encodedFrameCallback RTC_GUARDED_BY(encoder_crit_);
   EncodedImageCallback* const post_encode_callback_;
-  VCMCodecDataBase _codecDataBase RTC_GUARDED_BY(encoder_crit_);
+  VCMEncoderDataBase _codecDataBase RTC_GUARDED_BY(encoder_crit_);
   bool frame_dropper_enabled_ RTC_GUARDED_BY(encoder_crit_);
 
   // Must be accessed on the construction thread of VideoSender.
@@ -214,7 +215,7 @@
   bool drop_frames_until_keyframe_ RTC_GUARDED_BY(process_crit_);
   size_t max_nack_list_size_ RTC_GUARDED_BY(process_crit_);
 
-  VCMCodecDataBase _codecDataBase RTC_GUARDED_BY(receive_crit_);
+  VCMDecoderDataBase _codecDataBase RTC_GUARDED_BY(receive_crit_);
   EncodedImageCallback* pre_decode_image_callback_;
 
   VCMProcessTimer _receiveStatsTimer;
diff --git a/modules/video_coding/video_receiver.cc b/modules/video_coding/video_receiver.cc
index 112edda..038c523 100644
--- a/modules/video_coding/video_receiver.cc
+++ b/modules/video_coding/video_receiver.cc
@@ -44,7 +44,7 @@
       _scheduleKeyRequest(false),
       drop_frames_until_keyframe_(false),
       max_nack_list_size_(0),
-      _codecDataBase(nullptr),
+      _codecDataBase(),
       pre_decode_image_callback_(pre_decode_image_callback),
       _receiveStatsTimer(1000, clock_),
       _retransmissionTimer(10, clock_),