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