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 ¤t_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