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