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 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 | 417 |
394 bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) { | 418 bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) { |
395 ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type); | 419 ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type); |
396 if (it == dec_external_map_.end()) { | 420 if (it == dec_external_map_.end()) { |
397 // Not found | 421 // Not found |
398 return false; | 422 return false; |
399 } | 423 } |
400 // We can't use payload_type to check if the decoder is currently in use, | 424 // We can't use payload_type to check if the decoder is currently in use, |
401 // because payload type may be out of date (e.g. before we decode the first | 425 // because payload type may be out of date (e.g. before we decode the first |
402 // frame after RegisterReceiveCodec) | 426 // frame after RegisterReceiveCodec) |
403 if (ptr_decoder_ != nullptr && | 427 if (ptr_decoder_ && |
404 ptr_decoder_->_decoder == (*it).second->external_decoder_instance) { | 428 ptr_decoder_->IsSameDecoder((*it).second->external_decoder_instance)) { |
405 // Release it if it was registered and in use. | 429 // Release it if it was registered and in use. |
406 ReleaseDecoder(ptr_decoder_); | 430 ptr_decoder_.reset(); |
407 ptr_decoder_ = nullptr; | |
408 } | 431 } |
409 DeregisterReceiveCodec(payload_type); | 432 DeregisterReceiveCodec(payload_type); |
410 delete it->second; | 433 delete it->second; |
411 dec_external_map_.erase(it); | 434 dec_external_map_.erase(it); |
412 return true; | 435 return true; |
413 } | 436 } |
414 | 437 |
415 // Add the external encoder object to the list of external decoders. | 438 // Add the external encoder object to the list of external decoders. |
416 // Won't be registered as a receive codec until RegisterReceiveCodec is called. | 439 // Won't be registered as a receive codec until RegisterReceiveCodec is called. |
417 void VCMCodecDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder, | 440 void VCMCodecDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 } | 480 } |
458 return true; | 481 return true; |
459 } | 482 } |
460 | 483 |
461 VCMGenericDecoder* VCMCodecDataBase::GetDecoder( | 484 VCMGenericDecoder* VCMCodecDataBase::GetDecoder( |
462 const VCMEncodedFrame& frame, | 485 const VCMEncodedFrame& frame, |
463 VCMDecodedFrameCallback* decoded_frame_callback) { | 486 VCMDecodedFrameCallback* decoded_frame_callback) { |
464 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback()); | 487 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback()); |
465 uint8_t payload_type = frame.PayloadType(); | 488 uint8_t payload_type = frame.PayloadType(); |
466 if (payload_type == receive_codec_.plType || payload_type == 0) { | 489 if (payload_type == receive_codec_.plType || payload_type == 0) { |
467 return ptr_decoder_; | 490 return ptr_decoder_.get(); |
468 } | 491 } |
469 // Check for exisitng decoder, if exists - delete. | 492 // Check for exisitng decoder, if exists - delete. |
470 if (ptr_decoder_) { | 493 if (ptr_decoder_) { |
471 ReleaseDecoder(ptr_decoder_); | 494 ptr_decoder_.reset(); |
472 ptr_decoder_ = nullptr; | |
473 memset(&receive_codec_, 0, sizeof(VideoCodec)); | 495 memset(&receive_codec_, 0, sizeof(VideoCodec)); |
474 } | 496 } |
475 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_); | 497 ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_); |
476 if (!ptr_decoder_) { | 498 if (!ptr_decoder_) { |
477 return nullptr; | 499 return nullptr; |
478 } | 500 } |
479 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback(); | 501 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback(); |
480 callback->OnIncomingPayloadType(receive_codec_.plType); | 502 callback->OnIncomingPayloadType(receive_codec_.plType); |
481 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) < | 503 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) < |
482 0) { | 504 0) { |
483 ReleaseDecoder(ptr_decoder_); | 505 ptr_decoder_.reset(); |
484 ptr_decoder_ = nullptr; | |
485 memset(&receive_codec_, 0, sizeof(VideoCodec)); | 506 memset(&receive_codec_, 0, sizeof(VideoCodec)); |
486 return nullptr; | 507 return nullptr; |
487 } | 508 } |
488 return ptr_decoder_; | 509 return ptr_decoder_.get(); |
489 } | 510 } |
490 | 511 |
491 void VCMCodecDataBase::ReleaseDecoder(VCMGenericDecoder* decoder) const { | 512 VCMGenericDecoder* VCMCodecDataBase::GetCurrentDecoder() { |
492 if (decoder) { | 513 return ptr_decoder_.get(); |
493 RTC_DCHECK(decoder->_decoder); | |
494 decoder->Release(); | |
495 if (!decoder->External()) { | |
496 delete decoder->_decoder; | |
497 } | |
498 delete decoder; | |
499 } | |
500 } | 514 } |
501 | 515 |
502 bool VCMCodecDataBase::PrefersLateDecoding() const { | 516 bool VCMCodecDataBase::PrefersLateDecoding() const { |
503 if (!ptr_decoder_) | 517 return ptr_decoder_ ? ptr_decoder_->PrefersLateDecoding() : true; |
504 return true; | |
505 return ptr_decoder_->PrefersLateDecoding(); | |
506 } | 518 } |
507 | 519 |
508 bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const { | 520 bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const { |
509 return send_codec_.width == width && send_codec_.height == height; | 521 return send_codec_.width == width && send_codec_.height == height; |
510 } | 522 } |
511 | 523 |
512 VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder( | 524 std::unique_ptr<VCMGenericDecoder> VCMCodecDataBase::CreateAndInitDecoder( |
513 const VCMEncodedFrame& frame, | 525 const VCMEncodedFrame& frame, |
514 VideoCodec* new_codec) const { | 526 VideoCodec* new_codec) const { |
515 uint8_t payload_type = frame.PayloadType(); | 527 uint8_t payload_type = frame.PayloadType(); |
516 LOG(LS_INFO) << "Initializing decoder with payload type '" | 528 LOG(LS_INFO) << "Initializing decoder with payload type '" |
517 << static_cast<int>(payload_type) << "'."; | 529 << static_cast<int>(payload_type) << "'."; |
518 RTC_DCHECK(new_codec); | 530 RTC_DCHECK(new_codec); |
519 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type); | 531 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type); |
520 if (!decoder_item) { | 532 if (!decoder_item) { |
521 LOG(LS_ERROR) << "Can't find a decoder associated with payload type: " | 533 LOG(LS_ERROR) << "Can't find a decoder associated with payload type: " |
522 << static_cast<int>(payload_type); | 534 << static_cast<int>(payload_type); |
523 return nullptr; | 535 return nullptr; |
524 } | 536 } |
525 VCMGenericDecoder* ptr_decoder = nullptr; | 537 std::unique_ptr<VCMGenericDecoder> ptr_decoder; |
526 const VCMExtDecoderMapItem* external_dec_item = | 538 const VCMExtDecoderMapItem* external_dec_item = |
527 FindExternalDecoderItem(payload_type); | 539 FindExternalDecoderItem(payload_type); |
528 if (external_dec_item) { | 540 if (external_dec_item) { |
529 // External codec. | 541 // External codec. |
530 ptr_decoder = new VCMGenericDecoder( | 542 ptr_decoder.reset(new VCMGenericDecoder( |
531 external_dec_item->external_decoder_instance, true); | 543 external_dec_item->external_decoder_instance, true)); |
532 } else { | 544 } else { |
533 // Create decoder. | 545 // Create decoder. |
534 ptr_decoder = CreateDecoder(decoder_item->settings->codecType); | 546 ptr_decoder = CreateDecoder(decoder_item->settings->codecType); |
535 } | 547 } |
536 if (!ptr_decoder) | 548 if (!ptr_decoder) |
537 return nullptr; | 549 return nullptr; |
538 | 550 |
539 // Copy over input resolutions to prevent codec reinitialization due to | 551 // Copy over input resolutions to prevent codec reinitialization due to |
540 // the first frame being of a different resolution than the database values. | 552 // the first frame being of a different resolution than the database values. |
541 // This is best effort, since there's no guarantee that width/height have been | 553 // This is best effort, since there's no guarantee that width/height have been |
542 // parsed yet (and may be zero). | 554 // parsed yet (and may be zero). |
543 if (frame.EncodedImage()._encodedWidth > 0 && | 555 if (frame.EncodedImage()._encodedWidth > 0 && |
544 frame.EncodedImage()._encodedHeight > 0) { | 556 frame.EncodedImage()._encodedHeight > 0) { |
545 decoder_item->settings->width = frame.EncodedImage()._encodedWidth; | 557 decoder_item->settings->width = frame.EncodedImage()._encodedWidth; |
546 decoder_item->settings->height = frame.EncodedImage()._encodedHeight; | 558 decoder_item->settings->height = frame.EncodedImage()._encodedHeight; |
547 } | 559 } |
548 if (ptr_decoder->InitDecode(decoder_item->settings.get(), | 560 if (ptr_decoder->InitDecode(decoder_item->settings.get(), |
549 decoder_item->number_of_cores) < 0) { | 561 decoder_item->number_of_cores) < 0) { |
550 ReleaseDecoder(ptr_decoder); | |
551 return nullptr; | 562 return nullptr; |
552 } | 563 } |
553 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec)); | 564 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec)); |
554 return ptr_decoder; | 565 return ptr_decoder; |
555 } | 566 } |
556 | 567 |
557 void VCMCodecDataBase::DeleteEncoder() { | 568 void VCMCodecDataBase::DeleteEncoder() { |
558 if (!ptr_encoder_) | 569 if (!ptr_encoder_) |
559 return; | 570 return; |
560 ptr_encoder_->Release(); | 571 ptr_encoder_->Release(); |
561 ptr_encoder_.reset(); | 572 ptr_encoder_.reset(); |
562 } | 573 } |
563 | 574 |
564 VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const { | |
565 switch (type) { | |
566 case kVideoCodecVP8: | |
567 return new VCMGenericDecoder(VP8Decoder::Create()); | |
568 case kVideoCodecVP9: | |
569 return new VCMGenericDecoder(VP9Decoder::Create()); | |
570 case kVideoCodecI420: | |
571 return new VCMGenericDecoder(new I420Decoder()); | |
572 case kVideoCodecH264: | |
573 if (H264Decoder::IsSupported()) { | |
574 return new VCMGenericDecoder(H264Decoder::Create()); | |
575 } | |
576 break; | |
577 default: | |
578 break; | |
579 } | |
580 LOG(LS_WARNING) << "No internal decoder of this type exists."; | |
581 return nullptr; | |
582 } | |
583 | |
584 const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem( | 575 const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem( |
585 uint8_t payload_type) const { | 576 uint8_t payload_type) const { |
586 DecoderMap::const_iterator it = dec_map_.find(payload_type); | 577 DecoderMap::const_iterator it = dec_map_.find(payload_type); |
587 if (it != dec_map_.end()) { | 578 if (it != dec_map_.end()) { |
588 return (*it).second; | 579 return (*it).second; |
589 } | 580 } |
590 return nullptr; | 581 return nullptr; |
591 } | 582 } |
592 | 583 |
593 const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem( | 584 const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem( |
594 uint8_t payload_type) const { | 585 uint8_t payload_type) const { |
595 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type); | 586 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type); |
596 if (it != dec_external_map_.end()) { | 587 if (it != dec_external_map_.end()) { |
597 return (*it).second; | 588 return (*it).second; |
598 } | 589 } |
599 return nullptr; | 590 return nullptr; |
600 } | 591 } |
601 } // namespace webrtc | 592 } // namespace webrtc |
OLD | NEW |