Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/video_coding/main/source/codec_database.h"
     12 
     13 #include <assert.h>
     14 
     15 #include "webrtc/engine_configurations.h"
     16 #ifdef VIDEOCODEC_I420
     17 #include "webrtc/modules/video_coding/codecs/i420/main/interface/i420.h"
     18 #endif
     19 #ifdef VIDEOCODEC_VP8
     20 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
     21 #endif
     22 #include "webrtc/modules/video_coding/main/source/internal_defines.h"
     23 #include "webrtc/system_wrappers/interface/logging.h"
     24 
     25 namespace webrtc {
     26 
     27 VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() {
     28   VideoCodecVP8 vp8_settings;
     29   memset(&vp8_settings, 0, sizeof(vp8_settings));
     30 
     31   vp8_settings.resilience = kResilientStream;
     32   vp8_settings.numberOfTemporalLayers = 1;
     33   vp8_settings.denoisingOn = true;
     34   vp8_settings.errorConcealmentOn = false;
     35   vp8_settings.automaticResizeOn = false;
     36   vp8_settings.frameDroppingOn = true;
     37   vp8_settings.keyFrameInterval = 3000;
     38 
     39   return vp8_settings;
     40 }
     41 
     42 VideoCodecH264 VideoEncoder::GetDefaultH264Settings() {
     43   VideoCodecH264 h264_settings;
     44   memset(&h264_settings, 0, sizeof(h264_settings));
     45 
     46   h264_settings.profile = kProfileBase;
     47   h264_settings.frameDroppingOn = true;
     48   h264_settings.keyFrameInterval = 3000;
     49   h264_settings.spsData = NULL;
     50   h264_settings.spsLen = 0;
     51   h264_settings.ppsData = NULL;
     52   h264_settings.ppsLen = 0;
     53 
     54   return h264_settings;
     55 }
     56 
     57 VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings,
     58                                      int number_of_cores,
     59                                      bool require_key_frame)
     60     : settings(settings),
     61       number_of_cores(number_of_cores),
     62       require_key_frame(require_key_frame) {
     63   assert(number_of_cores >= 0);
     64 }
     65 
     66 VCMExtDecoderMapItem::VCMExtDecoderMapItem(
     67     VideoDecoder* external_decoder_instance,
     68     uint8_t payload_type,
     69     bool internal_render_timing)
     70     : payload_type(payload_type),
     71       external_decoder_instance(external_decoder_instance),
     72       internal_render_timing(internal_render_timing) {
     73 }
     74 
     75 VCMCodecDataBase::VCMCodecDataBase()
     76     : number_of_cores_(0),
     77       max_payload_size_(kDefaultPayloadSize),
     78       periodic_key_frames_(false),
     79       pending_encoder_reset_(true),
     80       current_enc_is_external_(false),
     81       send_codec_(),
     82       receive_codec_(),
     83       external_payload_type_(0),
     84       external_encoder_(NULL),
     85       internal_source_(false),
     86       ptr_encoder_(NULL),
     87       ptr_decoder_(NULL),
     88       current_dec_is_external_(false),
     89       dec_map_(),
     90       dec_external_map_() {}
     91 
     92 VCMCodecDataBase::~VCMCodecDataBase() {
     93   ResetSender();
     94   ResetReceiver();
     95 }
     96 
     97 int VCMCodecDataBase::NumberOfCodecs() {
     98   return VCM_NUM_VIDEO_CODECS_AVAILABLE;
     99 }
    100 
    101 bool VCMCodecDataBase::Codec(int list_id,
    102                              VideoCodec* settings) {
    103   if (!settings) {
    104     return false;
    105   }
    106   if (list_id >= VCM_NUM_VIDEO_CODECS_AVAILABLE) {
    107     return false;
    108   }
    109   memset(settings, 0, sizeof(VideoCodec));
    110   switch (list_id) {
    111 #ifdef VIDEOCODEC_VP8
    112     case VCM_VP8_IDX: {
    113       strncpy(settings->plName, "VP8", 4);
    114       settings->codecType = kVideoCodecVP8;
    115       // 96 to 127 dynamic payload types for video codecs.
    116       settings->plType = VCM_VP8_PAYLOAD_TYPE;
    117       settings->startBitrate = 100;
    118       settings->minBitrate = VCM_MIN_BITRATE;
    119       settings->maxBitrate = 0;
    120       settings->maxFramerate = VCM_DEFAULT_FRAME_RATE;
    121       settings->width = VCM_DEFAULT_CODEC_WIDTH;
    122       settings->height = VCM_DEFAULT_CODEC_HEIGHT;
    123       settings->numberOfSimulcastStreams = 0;
    124       settings->qpMax = 56;
    125       settings->codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
    126       return true;
    127     }
    128 #endif
    129 #ifdef VIDEOCODEC_H264
    130     case VCM_H264_IDX: {
    131       strncpy(settings->plName, "H264", 5);
    132       settings->codecType = kVideoCodecH264;
    133       // 96 to 127 dynamic payload types for video codecs.
    134       settings->plType = VCM_H264_PAYLOAD_TYPE;
    135       settings->startBitrate = 100;
    136       settings->minBitrate = VCM_MIN_BITRATE;
    137       settings->maxBitrate = 0;
    138       settings->maxFramerate = VCM_DEFAULT_FRAME_RATE;
    139       settings->width = VCM_DEFAULT_CODEC_WIDTH;
    140       settings->height = VCM_DEFAULT_CODEC_HEIGHT;
    141       settings->numberOfSimulcastStreams = 0;
    142       settings->qpMax = 56;
    143       settings->codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
    144       return true;
    145     }
    146 #endif
    147 #ifdef VIDEOCODEC_I420
    148     case VCM_I420_IDX: {
    149       strncpy(settings->plName, "I420", 5);
    150       settings->codecType = kVideoCodecI420;
    151       // 96 to 127 dynamic payload types for video codecs.
    152       settings->plType = VCM_I420_PAYLOAD_TYPE;
    153       // Bitrate needed for this size and framerate.
    154       settings->startBitrate = 3 * VCM_DEFAULT_CODEC_WIDTH *
    155                                VCM_DEFAULT_CODEC_HEIGHT * 8 *
    156                                VCM_DEFAULT_FRAME_RATE / 1000 / 2;
    157       settings->maxBitrate = settings->startBitrate;
    158       settings->maxFramerate = VCM_DEFAULT_FRAME_RATE;
    159       settings->width = VCM_DEFAULT_CODEC_WIDTH;
    160       settings->height = VCM_DEFAULT_CODEC_HEIGHT;
    161       settings->minBitrate = VCM_MIN_BITRATE;
    162       settings->numberOfSimulcastStreams = 0;
    163       return true;
    164     }
    165 #endif
    166     default: {
    167       return false;
    168     }
    169   }
    170 }
    171 
    172 bool VCMCodecDataBase::Codec(VideoCodecType codec_type,
    173                              VideoCodec* settings) {
    174   for (int i = 0; i < VCMCodecDataBase::NumberOfCodecs(); i++) {
    175     const bool ret = VCMCodecDataBase::Codec(i, settings);
    176     if (!ret) {
    177       return false;
    178     }
    179     if (codec_type == settings->codecType) {
    180       return true;
    181     }
    182   }
    183   return false;
    184 }
    185 
    186 void VCMCodecDataBase::ResetSender() {
    187   DeleteEncoder();
    188   periodic_key_frames_ = false;
    189 }
    190 
    191 // Assuming only one registered encoder - since only one used, no need for more.
    192 bool VCMCodecDataBase::SetSendCodec(
    193     const VideoCodec* send_codec,
    194     int number_of_cores,
    195     int max_payload_size,
    196     VCMEncodedFrameCallback* encoded_frame_callback) {
    197   if (!send_codec) {
    198     return false;
    199   }
    200   if (max_payload_size <= 0) {
    201     max_payload_size = kDefaultPayloadSize;
    202   }
    203   if (number_of_cores <= 0) {
    204     return false;
    205   }
    206   if (send_codec->plType <= 0) {
    207     return false;
    208   }
    209   // Make sure the start bit rate is sane...
    210   if (send_codec->startBitrate > 1000000) {
    211     return false;
    212   }
    213   if (send_codec->codecType == kVideoCodecUnknown) {
    214     return false;
    215   }
    216   bool reset_required = pending_encoder_reset_;
    217   if (number_of_cores_ != number_of_cores) {
    218     number_of_cores_ = number_of_cores;
    219     reset_required = true;
    220   }
    221   if (max_payload_size_ != max_payload_size) {
    222     max_payload_size_ = max_payload_size;
    223     reset_required = true;
    224   }
    225 
    226   VideoCodec new_send_codec;
    227   memcpy(&new_send_codec, send_codec, sizeof(new_send_codec));
    228 
    229   if (new_send_codec.maxBitrate == 0) {
    230     // max is one bit per pixel
    231     new_send_codec.maxBitrate = (static_cast<int>(send_codec->height) *
    232         static_cast<int>(send_codec->width) *
    233         static_cast<int>(send_codec->maxFramerate)) / 1000;
    234     if (send_codec->startBitrate > new_send_codec.maxBitrate) {
    235       // But if the user tries to set a higher start bit rate we will
    236       // increase the max accordingly.
    237       new_send_codec.maxBitrate = send_codec->startBitrate;
    238     }
    239   }
    240 
    241   if (!reset_required) {
    242     reset_required = RequiresEncoderReset(new_send_codec);
    243   }
    244 
    245   memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_));
    246 
    247   if (!reset_required) {
    248     encoded_frame_callback->SetPayloadType(send_codec->plType);
    249     if (ptr_encoder_->RegisterEncodeCallback(encoded_frame_callback) < 0) {
    250       return false;
    251     }
    252     return true;
    253   }
    254 
    255   // If encoder exists, will destroy it and create new one.
    256   DeleteEncoder();
    257   if (send_codec->plType == external_payload_type_) {
    258     // External encoder.
    259     ptr_encoder_ = new VCMGenericEncoder(*external_encoder_, internal_source_);
    260     current_enc_is_external_ = true;
    261   } else {
    262     ptr_encoder_ = CreateEncoder(send_codec->codecType);
    263     current_enc_is_external_ = false;
    264     if (!ptr_encoder_) {
    265       return false;
    266     }
    267   }
    268   encoded_frame_callback->SetPayloadType(send_codec->plType);
    269   if (ptr_encoder_->InitEncode(send_codec,
    270                                number_of_cores_,
    271                                max_payload_size_) < 0) {
    272     DeleteEncoder();
    273     return false;
    274   } else if (ptr_encoder_->RegisterEncodeCallback(encoded_frame_callback) < 0) {
    275     DeleteEncoder();
    276     return false;
    277   }
    278 
    279   // Intentionally don't check return value since the encoder registration
    280   // shouldn't fail because the codec doesn't support changing the periodic key
    281   // frame setting.
    282   ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_);
    283 
    284   pending_encoder_reset_ = false;
    285 
    286   return true;
    287 }
    288 
    289 bool VCMCodecDataBase::SendCodec(VideoCodec* current_send_codec) const {
    290   if (!ptr_encoder_) {
    291     return false;
    292   }
    293   memcpy(current_send_codec, &send_codec_, sizeof(VideoCodec));
    294   return true;
    295 }
    296 
    297 VideoCodecType VCMCodecDataBase::SendCodec() const {
    298   if (!ptr_encoder_) {
    299     return kVideoCodecUnknown;
    300   }
    301   return send_codec_.codecType;
    302 }
    303 
    304 bool VCMCodecDataBase::DeregisterExternalEncoder(
    305     uint8_t payload_type, bool* was_send_codec) {
    306   assert(was_send_codec);
    307   *was_send_codec = false;
    308   if (external_payload_type_ != payload_type) {
    309     return false;
    310   }
    311   if (send_codec_.plType == payload_type) {
    312     // De-register as send codec if needed.
    313     DeleteEncoder();
    314     memset(&send_codec_, 0, sizeof(VideoCodec));
    315     current_enc_is_external_ = false;
    316     *was_send_codec = true;
    317   }
    318   external_payload_type_ = 0;
    319   external_encoder_ = NULL;
    320   internal_source_ = false;
    321   return true;
    322 }
    323 
    324 void VCMCodecDataBase::RegisterExternalEncoder(
    325     VideoEncoder* external_encoder,
    326     uint8_t payload_type,
    327     bool internal_source) {
    328   // Since only one encoder can be used at a given time, only one external
    329   // encoder can be registered/used.
    330   external_encoder_ = external_encoder;
    331   external_payload_type_ = payload_type;
    332   internal_source_ = internal_source;
    333   pending_encoder_reset_ = true;
    334 }
    335 
    336 bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) {
    337   if (ptr_encoder_ == NULL) {
    338     return true;
    339   }
    340 
    341   // Does not check startBitrate or maxFramerate
    342   if (new_send_codec.codecType != send_codec_.codecType ||
    343       strcmp(new_send_codec.plName, send_codec_.plName) != 0 ||
    344       new_send_codec.plType != send_codec_.plType ||
    345       new_send_codec.width != send_codec_.width ||
    346       new_send_codec.height != send_codec_.height ||
    347       new_send_codec.maxBitrate != send_codec_.maxBitrate ||
    348       new_send_codec.minBitrate != send_codec_.minBitrate ||
    349       new_send_codec.qpMax != send_codec_.qpMax ||
    350       new_send_codec.numberOfSimulcastStreams !=
    351           send_codec_.numberOfSimulcastStreams ||
    352       new_send_codec.mode != send_codec_.mode ||
    353       new_send_codec.extra_options != send_codec_.extra_options) {
    354     return true;
    355   }
    356 
    357   switch (new_send_codec.codecType) {
    358     case kVideoCodecVP8:
    359       if (memcmp(&new_send_codec.codecSpecific.VP8,
    360                  &send_codec_.codecSpecific.VP8,
    361                  sizeof(new_send_codec.codecSpecific.VP8)) != 0) {
    362         return true;
    363       }
    364       break;
    365     case kVideoCodecH264:
    366       if (memcmp(&new_send_codec.codecSpecific.H264,
    367                  &send_codec_.codecSpecific.H264,
    368                  sizeof(new_send_codec.codecSpecific.H264)) != 0) {
    369         return true;
    370       }
    371       break;
    372     case kVideoCodecGeneric:
    373       break;
    374     // Known codecs without payload-specifics
    375     case kVideoCodecI420:
    376     case kVideoCodecRED:
    377     case kVideoCodecULPFEC:
    378       break;
    379     // Unknown codec type, reset just to be sure.
    380     case kVideoCodecUnknown:
    381       return true;
    382   }
    383 
    384   if (new_send_codec.numberOfSimulcastStreams > 0) {
    385     for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
    386          ++i) {
    387       if (memcmp(&new_send_codec.simulcastStream[i],
    388                  &send_codec_.simulcastStream[i],
    389                  sizeof(new_send_codec.simulcastStream[i])) !=
    390           0) {
    391         return true;
    392       }
    393     }
    394   }
    395   return false;
    396 }
    397 
    398 VCMGenericEncoder* VCMCodecDataBase::GetEncoder() {
    399   return ptr_encoder_;
    400 }
    401 
    402 bool VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) {
    403   periodic_key_frames_ = enable;
    404   if (ptr_encoder_) {
    405     return (ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_) == 0);
    406   }
    407   return true;
    408 }
    409 
    410 void VCMCodecDataBase::ResetReceiver() {
    411   ReleaseDecoder(ptr_decoder_);
    412   ptr_decoder_ = NULL;
    413   memset(&receive_codec_, 0, sizeof(VideoCodec));
    414   while (!dec_map_.empty()) {
    415     DecoderMap::iterator it = dec_map_.begin();
    416     delete (*it).second;
    417     dec_map_.erase(it);
    418   }
    419   while (!dec_external_map_.empty()) {
    420     ExternalDecoderMap::iterator external_it = dec_external_map_.begin();
    421     delete (*external_it).second;
    422     dec_external_map_.erase(external_it);
    423   }
    424   current_dec_is_external_ = false;
    425 }
    426 
    427 bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
    428   ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type);
    429   if (it == dec_external_map_.end()) {
    430     // Not found
    431     return false;
    432   }
    433   // We can't use payload_type to check if the decoder is currently in use,
    434   // because payload type may be out of date (e.g. before we decode the first
    435   // frame after RegisterReceiveCodec)
    436   if (ptr_decoder_ != NULL &&
    437       &ptr_decoder_->_decoder == (*it).second->external_decoder_instance) {
    438     // Release it if it was registered and in use.
    439     ReleaseDecoder(ptr_decoder_);
    440     ptr_decoder_ = NULL;
    441   }
    442   DeregisterReceiveCodec(payload_type);
    443   delete (*it).second;
    444   dec_external_map_.erase(it);
    445   return true;
    446 }
    447 
    448 // Add the external encoder object to the list of external decoders.
    449 // Won't be registered as a receive codec until RegisterReceiveCodec is called.
    450 bool VCMCodecDataBase::RegisterExternalDecoder(
    451     VideoDecoder* external_decoder,
    452     uint8_t payload_type,
    453     bool internal_render_timing) {
    454   // Check if payload value already exists, if so  - erase old and insert new.
    455   VCMExtDecoderMapItem* ext_decoder = new VCMExtDecoderMapItem(
    456       external_decoder, payload_type, internal_render_timing);
    457   if (!ext_decoder) {
    458     return false;
    459   }
    460   DeregisterExternalDecoder(payload_type);
    461   dec_external_map_[payload_type] = ext_decoder;
    462   return true;
    463 }
    464 
    465 bool VCMCodecDataBase::DecoderRegistered() const {
    466   return !dec_map_.empty();
    467 }
    468 
    469 bool VCMCodecDataBase::RegisterReceiveCodec(
    470     const VideoCodec* receive_codec,
    471     int number_of_cores,
    472     bool require_key_frame) {
    473   if (number_of_cores < 0) {
    474     return false;
    475   }
    476   // Check if payload value already exists, if so  - erase old and insert new.
    477   DeregisterReceiveCodec(receive_codec->plType);
    478   if (receive_codec->codecType == kVideoCodecUnknown) {
    479     return false;
    480   }
    481   VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
    482   dec_map_[receive_codec->plType] = new VCMDecoderMapItem(new_receive_codec,
    483                                                           number_of_cores,
    484                                                           require_key_frame);
    485   return true;
    486 }
    487 
    488 bool VCMCodecDataBase::DeregisterReceiveCodec(
    489     uint8_t payload_type) {
    490   DecoderMap::iterator it = dec_map_.find(payload_type);
    491   if (it == dec_map_.end()) {
    492     return false;
    493   }
    494   VCMDecoderMapItem* dec_item = (*it).second;
    495   delete dec_item;
    496   dec_map_.erase(it);
    497   if (receive_codec_.plType == payload_type) {
    498     // This codec is currently in use.
    499     memset(&receive_codec_, 0, sizeof(VideoCodec));
    500     current_dec_is_external_ = false;
    501   }
    502   return true;
    503 }
    504 
    505 bool VCMCodecDataBase::ReceiveCodec(VideoCodec* current_receive_codec) const {
    506   assert(current_receive_codec);
    507   if (!ptr_decoder_) {
    508     return false;
    509   }
    510   memcpy(current_receive_codec, &receive_codec_, sizeof(VideoCodec));
    511   return true;
    512 }
    513 
    514 VideoCodecType VCMCodecDataBase::ReceiveCodec() const {
    515   if (!ptr_decoder_) {
    516     return kVideoCodecUnknown;
    517   }
    518   return receive_codec_.codecType;
    519 }
    520 
    521 VCMGenericDecoder* VCMCodecDataBase::GetDecoder(
    522     uint8_t payload_type, VCMDecodedFrameCallback* decoded_frame_callback) {
    523   if (payload_type == receive_codec_.plType || payload_type == 0) {
    524     return ptr_decoder_;
    525   }
    526   // Check for exisitng decoder, if exists - delete.
    527   if (ptr_decoder_) {
    528     ReleaseDecoder(ptr_decoder_);
    529     ptr_decoder_ = NULL;
    530     memset(&receive_codec_, 0, sizeof(VideoCodec));
    531   }
    532   ptr_decoder_ = CreateAndInitDecoder(payload_type, &receive_codec_,
    533                                       &current_dec_is_external_);
    534   if (!ptr_decoder_) {
    535     return NULL;
    536   }
    537   VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
    538   if (callback) callback->IncomingCodecChanged(receive_codec_);
    539   if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback)
    540       < 0) {
    541     ReleaseDecoder(ptr_decoder_);
    542     ptr_decoder_ = NULL;
    543     memset(&receive_codec_, 0, sizeof(VideoCodec));
    544     return NULL;
    545   }
    546   return ptr_decoder_;
    547 }
    548 
    549 VCMGenericDecoder* VCMCodecDataBase::CreateDecoderCopy() const {
    550   if (!ptr_decoder_) {
    551     return NULL;
    552   }
    553   VideoDecoder* decoder_copy = ptr_decoder_->_decoder.Copy();
    554   if (!decoder_copy) {
    555     return NULL;
    556   }
    557   return new VCMGenericDecoder(*decoder_copy, ptr_decoder_->External());
    558 }
    559 
    560 void VCMCodecDataBase::ReleaseDecoder(VCMGenericDecoder* decoder) const {
    561   if (decoder) {
    562     assert(&decoder->_decoder);
    563     decoder->Release();
    564     if (!decoder->External()) {
    565       delete &decoder->_decoder;
    566     }
    567     delete decoder;
    568   }
    569 }
    570 
    571 void VCMCodecDataBase::CopyDecoder(const VCMGenericDecoder& decoder) {
    572   VideoDecoder* decoder_copy = decoder._decoder.Copy();
    573   if (decoder_copy) {
    574     VCMDecodedFrameCallback* cb = ptr_decoder_->_callback;
    575     ReleaseDecoder(ptr_decoder_);
    576     ptr_decoder_ = new VCMGenericDecoder(*decoder_copy, decoder.External());
    577     if (cb && ptr_decoder_->RegisterDecodeCompleteCallback(cb)) {
    578       assert(false);
    579     }
    580   }
    581 }
    582 
    583 bool VCMCodecDataBase::SupportsRenderScheduling() const {
    584   bool render_timing = true;
    585   if (current_dec_is_external_) {
    586     const VCMExtDecoderMapItem* ext_item = FindExternalDecoderItem(
    587         receive_codec_.plType);
    588     render_timing = ext_item->internal_render_timing;
    589   }
    590   return render_timing;
    591 }
    592 
    593 VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder(
    594     uint8_t payload_type,
    595     VideoCodec* new_codec,
    596     bool* external) const {
    597   assert(external);
    598   assert(new_codec);
    599   const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
    600   if (!decoder_item) {
    601     LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
    602                   << payload_type;
    603     return NULL;
    604   }
    605   VCMGenericDecoder* ptr_decoder = NULL;
    606   const VCMExtDecoderMapItem* external_dec_item = FindExternalDecoderItem(
    607                                               payload_type);
    608   if (external_dec_item) {
    609     // External codec.
    610     ptr_decoder = new VCMGenericDecoder(
    611         *external_dec_item->external_decoder_instance, true);
    612     *external = true;
    613   } else {
    614     // Create decoder.
    615     ptr_decoder = CreateDecoder(decoder_item->settings->codecType);
    616     *external = false;
    617   }
    618   if (!ptr_decoder) {
    619     return NULL;
    620   }
    621 
    622   if (ptr_decoder->InitDecode(decoder_item->settings.get(),
    623                               decoder_item->number_of_cores) < 0) {
    624     ReleaseDecoder(ptr_decoder);
    625     return NULL;
    626   }
    627   memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
    628   return ptr_decoder;
    629 }
    630 
    631 VCMGenericEncoder* VCMCodecDataBase::CreateEncoder(
    632   const VideoCodecType type) const {
    633   switch (type) {
    634 #ifdef VIDEOCODEC_VP8
    635     case kVideoCodecVP8:
    636       return new VCMGenericEncoder(*(VP8Encoder::Create()));
    637 #endif
    638 #ifdef VIDEOCODEC_I420
    639     case kVideoCodecI420:
    640       return new VCMGenericEncoder(*(new I420Encoder));
    641 #endif
    642     default:
    643       LOG(LS_WARNING) << "No internal encoder of this type exists.";
    644       return NULL;
    645   }
    646 }
    647 
    648 void VCMCodecDataBase::DeleteEncoder() {
    649   if (ptr_encoder_) {
    650     ptr_encoder_->Release();
    651     if (!current_enc_is_external_) {
    652       delete &ptr_encoder_->_encoder;
    653     }
    654     delete ptr_encoder_;
    655     ptr_encoder_ = NULL;
    656   }
    657 }
    658 
    659 VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const {
    660   switch (type) {
    661 #ifdef VIDEOCODEC_VP8
    662     case kVideoCodecVP8:
    663       return new VCMGenericDecoder(*(VP8Decoder::Create()));
    664 #endif
    665 #ifdef VIDEOCODEC_I420
    666     case kVideoCodecI420:
    667       return new VCMGenericDecoder(*(new I420Decoder));
    668 #endif
    669     default:
    670       LOG(LS_WARNING) << "No internal decoder of this type exists.";
    671       return NULL;
    672   }
    673 }
    674 
    675 const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem(
    676     uint8_t payload_type) const {
    677   DecoderMap::const_iterator it = dec_map_.find(payload_type);
    678   if (it != dec_map_.end()) {
    679     return (*it).second;
    680   }
    681   return NULL;
    682 }
    683 
    684 const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem(
    685     uint8_t payload_type) const {
    686   ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
    687   if (it != dec_external_map_.end()) {
    688     return (*it).second;
    689   }
    690   return NULL;
    691 }
    692 }  // namespace webrtc
    693