| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 h264_settings.keyFrameInterval = 3000; | 64 h264_settings.keyFrameInterval = 3000; |
| 65 h264_settings.spsData = nullptr; | 65 h264_settings.spsData = nullptr; |
| 66 h264_settings.spsLen = 0; | 66 h264_settings.spsLen = 0; |
| 67 h264_settings.ppsData = nullptr; | 67 h264_settings.ppsData = nullptr; |
| 68 h264_settings.ppsLen = 0; | 68 h264_settings.ppsLen = 0; |
| 69 h264_settings.profile = H264::kProfileConstrainedBaseline; | 69 h264_settings.profile = H264::kProfileConstrainedBaseline; |
| 70 | 70 |
| 71 return h264_settings; | 71 return h264_settings; |
| 72 } | 72 } |
| 73 | 73 |
| 74 // Create an internal Decoder given a codec type |
| 75 static std::unique_ptr<VCMGenericDecoder> CreateDecoder(VideoCodecType type) { |
| 76 switch (type) { |
| 77 case kVideoCodecVP8: |
| 78 return std::unique_ptr<VCMGenericDecoder>( |
| 79 new VCMGenericDecoder(VP8Decoder::Create())); |
| 80 case kVideoCodecVP9: |
| 81 return std::unique_ptr<VCMGenericDecoder>( |
| 82 new VCMGenericDecoder(VP9Decoder::Create())); |
| 83 case kVideoCodecI420: |
| 84 return std::unique_ptr<VCMGenericDecoder>( |
| 85 new VCMGenericDecoder(new I420Decoder())); |
| 86 case kVideoCodecH264: |
| 87 if (H264Decoder::IsSupported()) { |
| 88 return std::unique_ptr<VCMGenericDecoder>( |
| 89 new VCMGenericDecoder(H264Decoder::Create())); |
| 90 } |
| 91 break; |
| 92 default: |
| 93 break; |
| 94 } |
| 95 LOG(LS_WARNING) << "No internal decoder of this type exists."; |
| 96 return std::unique_ptr<VCMGenericDecoder>(); |
| 97 } |
| 98 |
| 74 VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings, | 99 VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings, |
| 75 int number_of_cores, | 100 int number_of_cores, |
| 76 bool require_key_frame) | 101 bool require_key_frame) |
| 77 : settings(settings), | 102 : settings(settings), |
| 78 number_of_cores(number_of_cores), | 103 number_of_cores(number_of_cores), |
| 79 require_key_frame(require_key_frame) { | 104 require_key_frame(require_key_frame) { |
| 80 RTC_DCHECK_GE(number_of_cores, 0); | 105 RTC_DCHECK_GE(number_of_cores, 0); |
| 81 } | 106 } |
| 82 | 107 |
| 83 VCMExtDecoderMapItem::VCMExtDecoderMapItem( | 108 VCMExtDecoderMapItem::VCMExtDecoderMapItem( |
| 84 VideoDecoder* external_decoder_instance, | 109 VideoDecoder* external_decoder_instance, |
| 85 uint8_t payload_type) | 110 uint8_t payload_type) |
| 86 : payload_type(payload_type), | 111 : payload_type(payload_type), |
| 87 external_decoder_instance(external_decoder_instance) {} | 112 external_decoder_instance(external_decoder_instance) {} |
| 88 | 113 |
| 89 VCMCodecDataBase::VCMCodecDataBase( | 114 VCMCodecDataBase::VCMCodecDataBase( |
| 90 VCMEncodedFrameCallback* encoded_frame_callback) | 115 VCMEncodedFrameCallback* encoded_frame_callback) |
| 91 : number_of_cores_(0), | 116 : number_of_cores_(0), |
| 92 max_payload_size_(kDefaultPayloadSize), | 117 max_payload_size_(kDefaultPayloadSize), |
| 93 periodic_key_frames_(false), | 118 periodic_key_frames_(false), |
| 94 pending_encoder_reset_(true), | 119 pending_encoder_reset_(true), |
| 95 send_codec_(), | 120 send_codec_(), |
| 96 receive_codec_(), | 121 receive_codec_(), |
| 97 encoder_payload_type_(0), | 122 encoder_payload_type_(0), |
| 98 external_encoder_(nullptr), | 123 external_encoder_(nullptr), |
| 99 internal_source_(false), | 124 internal_source_(false), |
| 100 encoded_frame_callback_(encoded_frame_callback), | 125 encoded_frame_callback_(encoded_frame_callback), |
| 101 ptr_decoder_(nullptr), | |
| 102 dec_map_(), | 126 dec_map_(), |
| 103 dec_external_map_() {} | 127 dec_external_map_() {} |
| 104 | 128 |
| 105 VCMCodecDataBase::~VCMCodecDataBase() { | 129 VCMCodecDataBase::~VCMCodecDataBase() { |
| 106 DeleteEncoder(); | 130 DeleteEncoder(); |
| 107 ReleaseDecoder(ptr_decoder_); | 131 ptr_decoder_.reset(); |
| 108 for (auto& kv : dec_map_) | 132 for (auto& kv : dec_map_) |
| 109 delete kv.second; | 133 delete kv.second; |
| 110 for (auto& kv : dec_external_map_) | 134 for (auto& kv : dec_external_map_) |
| 111 delete kv.second; | 135 delete kv.second; |
| 112 } | 136 } |
| 113 | 137 |
| 114 void VCMCodecDataBase::Codec(VideoCodecType codec_type, VideoCodec* settings) { | 138 void VCMCodecDataBase::Codec(VideoCodecType codec_type, VideoCodec* settings) { |
| 115 memset(settings, 0, sizeof(VideoCodec)); | 139 memset(settings, 0, sizeof(VideoCodec)); |
| 116 switch (codec_type) { | 140 switch (codec_type) { |
| 117 case kVideoCodecVP8: | 141 case kVideoCodecVP8: |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 | 408 |
| 385 bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) { | 409 bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) { |
| 386 ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type); | 410 ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type); |
| 387 if (it == dec_external_map_.end()) { | 411 if (it == dec_external_map_.end()) { |
| 388 // Not found | 412 // Not found |
| 389 return false; | 413 return false; |
| 390 } | 414 } |
| 391 // We can't use payload_type to check if the decoder is currently in use, | 415 // We can't use payload_type to check if the decoder is currently in use, |
| 392 // because payload type may be out of date (e.g. before we decode the first | 416 // because payload type may be out of date (e.g. before we decode the first |
| 393 // frame after RegisterReceiveCodec) | 417 // frame after RegisterReceiveCodec) |
| 394 if (ptr_decoder_ != nullptr && | 418 if (ptr_decoder_ && |
| 395 ptr_decoder_->_decoder == (*it).second->external_decoder_instance) { | 419 ptr_decoder_->IsSameDecoder((*it).second->external_decoder_instance)) { |
| 396 // Release it if it was registered and in use. | 420 // Release it if it was registered and in use. |
| 397 ReleaseDecoder(ptr_decoder_); | 421 ptr_decoder_.reset(); |
| 398 ptr_decoder_ = nullptr; | |
| 399 } | 422 } |
| 400 DeregisterReceiveCodec(payload_type); | 423 DeregisterReceiveCodec(payload_type); |
| 401 delete it->second; | 424 delete it->second; |
| 402 dec_external_map_.erase(it); | 425 dec_external_map_.erase(it); |
| 403 return true; | 426 return true; |
| 404 } | 427 } |
| 405 | 428 |
| 406 // Add the external encoder object to the list of external decoders. | 429 // Add the external encoder object to the list of external decoders. |
| 407 // Won't be registered as a receive codec until RegisterReceiveCodec is called. | 430 // Won't be registered as a receive codec until RegisterReceiveCodec is called. |
| 408 void VCMCodecDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder, | 431 void VCMCodecDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 } | 471 } |
| 449 return true; | 472 return true; |
| 450 } | 473 } |
| 451 | 474 |
| 452 VCMGenericDecoder* VCMCodecDataBase::GetDecoder( | 475 VCMGenericDecoder* VCMCodecDataBase::GetDecoder( |
| 453 const VCMEncodedFrame& frame, | 476 const VCMEncodedFrame& frame, |
| 454 VCMDecodedFrameCallback* decoded_frame_callback) { | 477 VCMDecodedFrameCallback* decoded_frame_callback) { |
| 455 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback()); | 478 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback()); |
| 456 uint8_t payload_type = frame.PayloadType(); | 479 uint8_t payload_type = frame.PayloadType(); |
| 457 if (payload_type == receive_codec_.plType || payload_type == 0) { | 480 if (payload_type == receive_codec_.plType || payload_type == 0) { |
| 458 return ptr_decoder_; | 481 return ptr_decoder_.get(); |
| 459 } | 482 } |
| 460 // Check for exisitng decoder, if exists - delete. | 483 // Check for exisitng decoder, if exists - delete. |
| 461 if (ptr_decoder_) { | 484 if (ptr_decoder_) { |
| 462 ReleaseDecoder(ptr_decoder_); | 485 ptr_decoder_.reset(); |
| 463 ptr_decoder_ = nullptr; | |
| 464 memset(&receive_codec_, 0, sizeof(VideoCodec)); | 486 memset(&receive_codec_, 0, sizeof(VideoCodec)); |
| 465 } | 487 } |
| 466 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_); | 488 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_); |
| 467 if (!ptr_decoder_) { | 489 if (!ptr_decoder_) { |
| 468 return nullptr; | 490 return nullptr; |
| 469 } | 491 } |
| 470 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback(); | 492 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback(); |
| 471 callback->OnIncomingPayloadType(receive_codec_.plType); | 493 callback->OnIncomingPayloadType(receive_codec_.plType); |
| 472 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) < | 494 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) < |
| 473 0) { | 495 0) { |
| 474 ReleaseDecoder(ptr_decoder_); | 496 ptr_decoder_.reset(); |
| 475 ptr_decoder_ = nullptr; | |
| 476 memset(&receive_codec_, 0, sizeof(VideoCodec)); | 497 memset(&receive_codec_, 0, sizeof(VideoCodec)); |
| 477 return nullptr; | 498 return nullptr; |
| 478 } | 499 } |
| 479 return ptr_decoder_; | 500 return ptr_decoder_.get(); |
| 480 } | 501 } |
| 481 | 502 |
| 482 void VCMCodecDataBase::ReleaseDecoder(VCMGenericDecoder* decoder) const { | 503 VCMGenericDecoder* VCMCodecDataBase::GetCurrentDecoder() { |
| 483 if (decoder) { | 504 return ptr_decoder_.get(); |
| 484 RTC_DCHECK(decoder->_decoder); | |
| 485 decoder->Release(); | |
| 486 if (!decoder->External()) { | |
| 487 delete decoder->_decoder; | |
| 488 } | |
| 489 delete decoder; | |
| 490 } | |
| 491 } | 505 } |
| 492 | 506 |
| 493 bool VCMCodecDataBase::PrefersLateDecoding() const { | 507 bool VCMCodecDataBase::PrefersLateDecoding() const { |
| 494 if (!ptr_decoder_) | 508 return ptr_decoder_ ? ptr_decoder_->PrefersLateDecoding() : true; |
| 495 return true; | |
| 496 return ptr_decoder_->PrefersLateDecoding(); | |
| 497 } | 509 } |
| 498 | 510 |
| 499 bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const { | 511 bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const { |
| 500 return send_codec_.width == width && send_codec_.height == height; | 512 return send_codec_.width == width && send_codec_.height == height; |
| 501 } | 513 } |
| 502 | 514 |
| 503 VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder( | 515 std::unique_ptr<VCMGenericDecoder> VCMCodecDataBase::CreateAndInitDecoder( |
| 504 const VCMEncodedFrame& frame, | 516 const VCMEncodedFrame& frame, |
| 505 VideoCodec* new_codec) const { | 517 VideoCodec* new_codec) const { |
| 506 uint8_t payload_type = frame.PayloadType(); | 518 uint8_t payload_type = frame.PayloadType(); |
| 507 LOG(LS_INFO) << "Initializing decoder with payload type '" | 519 LOG(LS_INFO) << "Initializing decoder with payload type '" |
| 508 << static_cast<int>(payload_type) << "'."; | 520 << static_cast<int>(payload_type) << "'."; |
| 509 RTC_DCHECK(new_codec); | 521 RTC_DCHECK(new_codec); |
| 510 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type); | 522 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type); |
| 511 if (!decoder_item) { | 523 if (!decoder_item) { |
| 512 LOG(LS_ERROR) << "Can't find a decoder associated with payload type: " | 524 LOG(LS_ERROR) << "Can't find a decoder associated with payload type: " |
| 513 << static_cast<int>(payload_type); | 525 << static_cast<int>(payload_type); |
| 514 return nullptr; | 526 return nullptr; |
| 515 } | 527 } |
| 516 VCMGenericDecoder* ptr_decoder = nullptr; | 528 std::unique_ptr<VCMGenericDecoder> ptr_decoder; |
| 517 const VCMExtDecoderMapItem* external_dec_item = | 529 const VCMExtDecoderMapItem* external_dec_item = |
| 518 FindExternalDecoderItem(payload_type); | 530 FindExternalDecoderItem(payload_type); |
| 519 if (external_dec_item) { | 531 if (external_dec_item) { |
| 520 // External codec. | 532 // External codec. |
| 521 ptr_decoder = new VCMGenericDecoder( | 533 ptr_decoder.reset(new VCMGenericDecoder( |
| 522 external_dec_item->external_decoder_instance, true); | 534 external_dec_item->external_decoder_instance, true)); |
| 523 } else { | 535 } else { |
| 524 // Create decoder. | 536 // Create decoder. |
| 525 ptr_decoder = CreateDecoder(decoder_item->settings->codecType); | 537 ptr_decoder = CreateDecoder(decoder_item->settings->codecType); |
| 526 } | 538 } |
| 527 if (!ptr_decoder) | 539 if (!ptr_decoder) |
| 528 return nullptr; | 540 return nullptr; |
| 529 | 541 |
| 530 // Copy over input resolutions to prevent codec reinitialization due to | 542 // Copy over input resolutions to prevent codec reinitialization due to |
| 531 // the first frame being of a different resolution than the database values. | 543 // the first frame being of a different resolution than the database values. |
| 532 // This is best effort, since there's no guarantee that width/height have been | 544 // This is best effort, since there's no guarantee that width/height have been |
| 533 // parsed yet (and may be zero). | 545 // parsed yet (and may be zero). |
| 534 if (frame.EncodedImage()._encodedWidth > 0 && | 546 if (frame.EncodedImage()._encodedWidth > 0 && |
| 535 frame.EncodedImage()._encodedHeight > 0) { | 547 frame.EncodedImage()._encodedHeight > 0) { |
| 536 decoder_item->settings->width = frame.EncodedImage()._encodedWidth; | 548 decoder_item->settings->width = frame.EncodedImage()._encodedWidth; |
| 537 decoder_item->settings->height = frame.EncodedImage()._encodedHeight; | 549 decoder_item->settings->height = frame.EncodedImage()._encodedHeight; |
| 538 } | 550 } |
| 539 if (ptr_decoder->InitDecode(decoder_item->settings.get(), | 551 if (ptr_decoder->InitDecode(decoder_item->settings.get(), |
| 540 decoder_item->number_of_cores) < 0) { | 552 decoder_item->number_of_cores) < 0) { |
| 541 ReleaseDecoder(ptr_decoder); | |
| 542 return nullptr; | 553 return nullptr; |
| 543 } | 554 } |
| 544 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec)); | 555 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec)); |
| 545 return ptr_decoder; | 556 return ptr_decoder; |
| 546 } | 557 } |
| 547 | 558 |
| 548 void VCMCodecDataBase::DeleteEncoder() { | 559 void VCMCodecDataBase::DeleteEncoder() { |
| 549 if (!ptr_encoder_) | 560 if (!ptr_encoder_) |
| 550 return; | 561 return; |
| 551 ptr_encoder_->Release(); | 562 ptr_encoder_->Release(); |
| 552 ptr_encoder_.reset(); | 563 ptr_encoder_.reset(); |
| 553 } | 564 } |
| 554 | 565 |
| 555 VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const { | |
| 556 switch (type) { | |
| 557 case kVideoCodecVP8: | |
| 558 return new VCMGenericDecoder(VP8Decoder::Create()); | |
| 559 case kVideoCodecVP9: | |
| 560 return new VCMGenericDecoder(VP9Decoder::Create()); | |
| 561 case kVideoCodecI420: | |
| 562 return new VCMGenericDecoder(new I420Decoder()); | |
| 563 case kVideoCodecH264: | |
| 564 if (H264Decoder::IsSupported()) { | |
| 565 return new VCMGenericDecoder(H264Decoder::Create()); | |
| 566 } | |
| 567 break; | |
| 568 default: | |
| 569 break; | |
| 570 } | |
| 571 LOG(LS_WARNING) << "No internal decoder of this type exists."; | |
| 572 return nullptr; | |
| 573 } | |
| 574 | |
| 575 const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem( | 566 const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem( |
| 576 uint8_t payload_type) const { | 567 uint8_t payload_type) const { |
| 577 DecoderMap::const_iterator it = dec_map_.find(payload_type); | 568 DecoderMap::const_iterator it = dec_map_.find(payload_type); |
| 578 if (it != dec_map_.end()) { | 569 if (it != dec_map_.end()) { |
| 579 return (*it).second; | 570 return (*it).second; |
| 580 } | 571 } |
| 581 return nullptr; | 572 return nullptr; |
| 582 } | 573 } |
| 583 | 574 |
| 584 const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem( | 575 const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem( |
| 585 uint8_t payload_type) const { | 576 uint8_t payload_type) const { |
| 586 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type); | 577 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type); |
| 587 if (it != dec_external_map_.end()) { | 578 if (it != dec_external_map_.end()) { |
| 588 return (*it).second; | 579 return (*it).second; |
| 589 } | 580 } |
| 590 return nullptr; | 581 return nullptr; |
| 591 } | 582 } |
| 592 } // namespace webrtc | 583 } // namespace webrtc |
| OLD | NEW |