2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/video_coding/main/source/codec_database.h"
15 #include "webrtc/engine_configurations.h"
16 #ifdef VIDEOCODEC_I420
17 #include "webrtc/modules/video_coding/codecs/i420/main/interface/i420.h"
20 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
23 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
25 #include "webrtc/modules/video_coding/main/source/internal_defines.h"
26 #include "webrtc/system_wrappers/interface/logging.h"
30 VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() {
31 VideoCodecVP8 vp8_settings;
32 memset(&vp8_settings, 0, sizeof(vp8_settings));
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;
45 VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() {
46 VideoCodecVP9 vp9_settings;
47 memset(&vp9_settings, 0, sizeof(vp9_settings));
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;
59 VideoCodecH264 VideoEncoder::GetDefaultH264Settings() {
60 VideoCodecH264 h264_settings;
61 memset(&h264_settings, 0, sizeof(h264_settings));
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;
74 VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings,
76 bool require_key_frame)
78 number_of_cores(number_of_cores),
79 require_key_frame(require_key_frame) {
80 assert(number_of_cores >= 0);
83 VCMExtDecoderMapItem::VCMExtDecoderMapItem(
84 VideoDecoder* external_decoder_instance,
86 bool internal_render_timing)
87 : payload_type(payload_type),
88 external_decoder_instance(external_decoder_instance),
89 internal_render_timing(internal_render_timing) {
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),
100 external_payload_type_(0),
101 external_encoder_(NULL),
102 internal_source_(false),
105 current_dec_is_external_(false),
107 dec_external_map_() {}
109 VCMCodecDataBase::~VCMCodecDataBase() {
114 int VCMCodecDataBase::NumberOfCodecs() {
115 return VCM_NUM_VIDEO_CODECS_AVAILABLE;
118 bool VCMCodecDataBase::Codec(int list_id,
119 VideoCodec* settings) {
123 if (list_id >= VCM_NUM_VIDEO_CODECS_AVAILABLE) {
126 memset(settings, 0, sizeof(VideoCodec));
128 #ifdef VIDEOCODEC_VP8
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();
146 #ifdef VIDEOCODEC_VP9
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();
164 #ifdef VIDEOCODEC_H264
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();
182 #ifdef VIDEOCODEC_I420
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;
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);
214 if (codec_type == settings->codecType) {
221 void VCMCodecDataBase::ResetSender() {
223 periodic_key_frames_ = false;
226 // Assuming only one registered encoder - since only one used, no need for more.
227 bool VCMCodecDataBase::SetSendCodec(
228 const VideoCodec* send_codec,
230 int max_payload_size,
231 VCMEncodedFrameCallback* encoded_frame_callback) {
235 if (max_payload_size <= 0) {
236 max_payload_size = kDefaultPayloadSize;
238 if (number_of_cores <= 0) {
241 if (send_codec->plType <= 0) {
244 // Make sure the start bit rate is sane...
245 if (send_codec->startBitrate > 1000000) {
248 if (send_codec->codecType == kVideoCodecUnknown) {
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;
256 if (max_payload_size_ != max_payload_size) {
257 max_payload_size_ = max_payload_size;
258 reset_required = true;
261 VideoCodec new_send_codec;
262 memcpy(&new_send_codec, send_codec, sizeof(new_send_codec));
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;
276 if (!reset_required) {
277 reset_required = RequiresEncoderReset(new_send_codec);
280 memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_));
282 if (!reset_required) {
283 encoded_frame_callback->SetPayloadType(send_codec->plType);
284 if (ptr_encoder_->RegisterEncodeCallback(encoded_frame_callback) < 0) {
290 // If encoder exists, will destroy it and create new one.
292 if (send_codec->plType == external_payload_type_) {
294 ptr_encoder_ = new VCMGenericEncoder(*external_encoder_, internal_source_);
295 current_enc_is_external_ = true;
297 ptr_encoder_ = CreateEncoder(send_codec->codecType);
298 current_enc_is_external_ = false;
303 encoded_frame_callback->SetPayloadType(send_codec->plType);
304 if (ptr_encoder_->InitEncode(send_codec,
306 max_payload_size_) < 0) {
309 } else if (ptr_encoder_->RegisterEncodeCallback(encoded_frame_callback) < 0) {
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
317 ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_);
319 pending_encoder_reset_ = false;
324 bool VCMCodecDataBase::SendCodec(VideoCodec* current_send_codec) const {
328 memcpy(current_send_codec, &send_codec_, sizeof(VideoCodec));
332 VideoCodecType VCMCodecDataBase::SendCodec() const {
334 return kVideoCodecUnknown;
336 return send_codec_.codecType;
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) {
346 if (send_codec_.plType == payload_type) {
347 // De-register as send codec if needed.
349 memset(&send_codec_, 0, sizeof(VideoCodec));
350 current_enc_is_external_ = false;
351 *was_send_codec = true;
353 external_payload_type_ = 0;
354 external_encoder_ = NULL;
355 internal_source_ = false;
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;
371 bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) {
372 if (ptr_encoder_ == NULL) {
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) {
392 switch (new_send_codec.codecType) {
394 if (memcmp(&new_send_codec.codecSpecific.VP8,
395 &send_codec_.codecSpecific.VP8,
396 sizeof(new_send_codec.codecSpecific.VP8)) != 0) {
401 if (memcmp(&new_send_codec.codecSpecific.VP9,
402 &send_codec_.codecSpecific.VP9,
403 sizeof(new_send_codec.codecSpecific.VP9)) != 0) {
407 case kVideoCodecH264:
408 if (memcmp(&new_send_codec.codecSpecific.H264,
409 &send_codec_.codecSpecific.H264,
410 sizeof(new_send_codec.codecSpecific.H264)) != 0) {
414 case kVideoCodecGeneric:
416 // Known codecs without payload-specifics
417 case kVideoCodecI420:
419 case kVideoCodecULPFEC:
421 // Unknown codec type, reset just to be sure.
422 case kVideoCodecUnknown:
426 if (new_send_codec.numberOfSimulcastStreams > 0) {
427 for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
429 if (memcmp(&new_send_codec.simulcastStream[i],
430 &send_codec_.simulcastStream[i],
431 sizeof(new_send_codec.simulcastStream[i])) !=
440 VCMGenericEncoder* VCMCodecDataBase::GetEncoder() {
444 bool VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) {
445 periodic_key_frames_ = enable;
447 return (ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_) == 0);
452 void VCMCodecDataBase::ResetReceiver() {
453 ReleaseDecoder(ptr_decoder_);
455 memset(&receive_codec_, 0, sizeof(VideoCodec));
456 while (!dec_map_.empty()) {
457 DecoderMap::iterator it = dec_map_.begin();
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);
466 current_dec_is_external_ = false;
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()) {
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_);
484 DeregisterReceiveCodec(payload_type);
486 dec_external_map_.erase(it);
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);
502 DeregisterExternalDecoder(payload_type);
503 dec_external_map_[payload_type] = ext_decoder;
507 bool VCMCodecDataBase::DecoderRegistered() const {
508 return !dec_map_.empty();
511 bool VCMCodecDataBase::RegisterReceiveCodec(
512 const VideoCodec* receive_codec,
514 bool require_key_frame) {
515 if (number_of_cores < 0) {
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) {
523 VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
524 dec_map_[receive_codec->plType] = new VCMDecoderMapItem(new_receive_codec,
530 bool VCMCodecDataBase::DeregisterReceiveCodec(
531 uint8_t payload_type) {
532 DecoderMap::iterator it = dec_map_.find(payload_type);
533 if (it == dec_map_.end()) {
536 VCMDecoderMapItem* dec_item = (*it).second;
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;
547 bool VCMCodecDataBase::ReceiveCodec(VideoCodec* current_receive_codec) const {
548 assert(current_receive_codec);
552 memcpy(current_receive_codec, &receive_codec_, sizeof(VideoCodec));
556 VideoCodecType VCMCodecDataBase::ReceiveCodec() const {
558 return kVideoCodecUnknown;
560 return receive_codec_.codecType;
563 VCMGenericDecoder* VCMCodecDataBase::GetDecoder(
564 uint8_t payload_type, VCMDecodedFrameCallback* decoded_frame_callback) {
565 if (payload_type == receive_codec_.plType || payload_type == 0) {
568 // Check for exisitng decoder, if exists - delete.
570 ReleaseDecoder(ptr_decoder_);
572 memset(&receive_codec_, 0, sizeof(VideoCodec));
574 ptr_decoder_ = CreateAndInitDecoder(payload_type, &receive_codec_,
575 ¤t_dec_is_external_);
579 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
580 if (callback) callback->IncomingCodecChanged(receive_codec_);
581 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback)
583 ReleaseDecoder(ptr_decoder_);
585 memset(&receive_codec_, 0, sizeof(VideoCodec));
591 VCMGenericDecoder* VCMCodecDataBase::CreateDecoderCopy() const {
595 VideoDecoder* decoder_copy = ptr_decoder_->_decoder.Copy();
599 return new VCMGenericDecoder(*decoder_copy, ptr_decoder_->External());
602 void VCMCodecDataBase::ReleaseDecoder(VCMGenericDecoder* decoder) const {
604 assert(&decoder->_decoder);
606 if (!decoder->External()) {
607 delete &decoder->_decoder;
613 void VCMCodecDataBase::CopyDecoder(const VCMGenericDecoder& decoder) {
614 VideoDecoder* decoder_copy = decoder._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)) {
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;
632 return render_timing;
635 VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder(
636 uint8_t payload_type,
637 VideoCodec* new_codec,
638 bool* external) const {
641 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
643 LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
647 VCMGenericDecoder* ptr_decoder = NULL;
648 const VCMExtDecoderMapItem* external_dec_item = FindExternalDecoderItem(
650 if (external_dec_item) {
652 ptr_decoder = new VCMGenericDecoder(
653 *external_dec_item->external_decoder_instance, true);
657 ptr_decoder = CreateDecoder(decoder_item->settings->codecType);
664 if (ptr_decoder->InitDecode(decoder_item->settings.get(),
665 decoder_item->number_of_cores) < 0) {
666 ReleaseDecoder(ptr_decoder);
669 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
673 VCMGenericEncoder* VCMCodecDataBase::CreateEncoder(
674 const VideoCodecType type) const {
676 #ifdef VIDEOCODEC_VP8
678 return new VCMGenericEncoder(*(VP8Encoder::Create()));
680 #ifdef VIDEOCODEC_VP9
682 return new VCMGenericEncoder(*(VP9Encoder::Create()));
684 #ifdef VIDEOCODEC_I420
685 case kVideoCodecI420:
686 return new VCMGenericEncoder(*(new I420Encoder));
689 LOG(LS_WARNING) << "No internal encoder of this type exists.";
694 void VCMCodecDataBase::DeleteEncoder() {
696 ptr_encoder_->Release();
697 if (!current_enc_is_external_) {
698 delete &ptr_encoder_->_encoder;
705 VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const {
707 #ifdef VIDEOCODEC_VP8
709 return new VCMGenericDecoder(*(VP8Decoder::Create()));
711 #ifdef VIDEOCODEC_VP9
713 return new VCMGenericDecoder(*(VP9Decoder::Create()));
715 #ifdef VIDEOCODEC_I420
716 case kVideoCodecI420:
717 return new VCMGenericDecoder(*(new I420Decoder));
720 LOG(LS_WARNING) << "No internal decoder of this type exists.";
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()) {
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()) {
742 } // namespace webrtc