• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetDefaultVp8Settings()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 
GetDefaultH264Settings()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 
VCMDecoderMapItem(VideoCodec * settings,int number_of_cores,bool require_key_frame)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 
VCMExtDecoderMapItem(VideoDecoder * external_decoder_instance,uint8_t payload_type,bool internal_render_timing)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 
VCMCodecDataBase()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 
~VCMCodecDataBase()92 VCMCodecDataBase::~VCMCodecDataBase() {
93   ResetSender();
94   ResetReceiver();
95 }
96 
NumberOfCodecs()97 int VCMCodecDataBase::NumberOfCodecs() {
98   return VCM_NUM_VIDEO_CODECS_AVAILABLE;
99 }
100 
Codec(int list_id,VideoCodec * settings)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 
Codec(VideoCodecType codec_type,VideoCodec * settings)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 
ResetSender()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.
SetSendCodec(const VideoCodec * send_codec,int number_of_cores,int max_payload_size,VCMEncodedFrameCallback * encoded_frame_callback)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 
SendCodec(VideoCodec * current_send_codec) const289 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 
SendCodec() const297 VideoCodecType VCMCodecDataBase::SendCodec() const {
298   if (!ptr_encoder_) {
299     return kVideoCodecUnknown;
300   }
301   return send_codec_.codecType;
302 }
303 
DeregisterExternalEncoder(uint8_t payload_type,bool * was_send_codec)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 
RegisterExternalEncoder(VideoEncoder * external_encoder,uint8_t payload_type,bool internal_source)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 
RequiresEncoderReset(const VideoCodec & new_send_codec)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 
GetEncoder()398 VCMGenericEncoder* VCMCodecDataBase::GetEncoder() {
399   return ptr_encoder_;
400 }
401 
SetPeriodicKeyFrames(bool enable)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 
ResetReceiver()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 
DeregisterExternalDecoder(uint8_t payload_type)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.
RegisterExternalDecoder(VideoDecoder * external_decoder,uint8_t payload_type,bool internal_render_timing)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 
DecoderRegistered() const465 bool VCMCodecDataBase::DecoderRegistered() const {
466   return !dec_map_.empty();
467 }
468 
RegisterReceiveCodec(const VideoCodec * receive_codec,int number_of_cores,bool require_key_frame)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 
DeregisterReceiveCodec(uint8_t payload_type)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 
ReceiveCodec(VideoCodec * current_receive_codec) const505 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 
ReceiveCodec() const514 VideoCodecType VCMCodecDataBase::ReceiveCodec() const {
515   if (!ptr_decoder_) {
516     return kVideoCodecUnknown;
517   }
518   return receive_codec_.codecType;
519 }
520 
GetDecoder(uint8_t payload_type,VCMDecodedFrameCallback * decoded_frame_callback)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 
CreateDecoderCopy() const549 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 
ReleaseDecoder(VCMGenericDecoder * decoder) const560 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 
CopyDecoder(const VCMGenericDecoder & decoder)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 
SupportsRenderScheduling() const583 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 
CreateAndInitDecoder(uint8_t payload_type,VideoCodec * new_codec,bool * external) const593 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 
CreateEncoder(const VideoCodecType type) const631 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 
DeleteEncoder()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 
CreateDecoder(VideoCodecType type) const659 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 
FindDecoderItem(uint8_t payload_type) const675 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 
FindExternalDecoderItem(uint8_t payload_type) const684 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