| 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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 } | 127 } |
| 128 | 128 |
| 129 VP8Decoder* VP8Decoder::Create() { | 129 VP8Decoder* VP8Decoder::Create() { |
| 130 return new VP8DecoderImpl(); | 130 return new VP8DecoderImpl(); |
| 131 } | 131 } |
| 132 | 132 |
| 133 VP8EncoderImpl::VP8EncoderImpl() | 133 VP8EncoderImpl::VP8EncoderImpl() |
| 134 : encoded_complete_callback_(nullptr), | 134 : encoded_complete_callback_(nullptr), |
| 135 inited_(false), | 135 inited_(false), |
| 136 timestamp_(0), | 136 timestamp_(0), |
| 137 feedback_mode_(false), | |
| 138 qp_max_(56), // Setting for max quantizer. | 137 qp_max_(56), // Setting for max quantizer. |
| 139 cpu_speed_default_(-6), | 138 cpu_speed_default_(-6), |
| 140 number_of_cores_(0), | 139 number_of_cores_(0), |
| 141 rc_max_intra_target_(0), | 140 rc_max_intra_target_(0), |
| 142 token_partitions_(VP8_ONE_TOKENPARTITION), | 141 token_partitions_(VP8_ONE_TOKENPARTITION), |
| 143 down_scale_requested_(false), | 142 down_scale_requested_(false), |
| 144 down_scale_bitrate_(0), | 143 down_scale_bitrate_(0), |
| 145 use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), | 144 use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), |
| 146 key_frame_request_(kMaxSimulcastStreams, false) { | 145 key_frame_request_(kMaxSimulcastStreams, false) { |
| 147 uint32_t seed = rtc::Time32(); | 146 uint32_t seed = rtc::Time32(); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 342 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 344 } | 343 } |
| 345 | 344 |
| 346 int num_temporal_layers = | 345 int num_temporal_layers = |
| 347 doing_simulcast ? inst->simulcastStream[0].numberOfTemporalLayers | 346 doing_simulcast ? inst->simulcastStream[0].numberOfTemporalLayers |
| 348 : inst->VP8().numberOfTemporalLayers; | 347 : inst->VP8().numberOfTemporalLayers; |
| 349 RTC_DCHECK_GT(num_temporal_layers, 0); | 348 RTC_DCHECK_GT(num_temporal_layers, 0); |
| 350 | 349 |
| 351 SetupTemporalLayers(number_of_streams, num_temporal_layers, *inst); | 350 SetupTemporalLayers(number_of_streams, num_temporal_layers, *inst); |
| 352 | 351 |
| 353 feedback_mode_ = inst->VP8().feedbackModeOn; | |
| 354 | |
| 355 number_of_cores_ = number_of_cores; | 352 number_of_cores_ = number_of_cores; |
| 356 timestamp_ = 0; | 353 timestamp_ = 0; |
| 357 codec_ = *inst; | 354 codec_ = *inst; |
| 358 | 355 |
| 359 // Code expects simulcastStream resolutions to be correct, make sure they are | 356 // Code expects simulcastStream resolutions to be correct, make sure they are |
| 360 // filled even when there are no simulcast layers. | 357 // filled even when there are no simulcast layers. |
| 361 if (codec_.numberOfSimulcastStreams == 0) { | 358 if (codec_.numberOfSimulcastStreams == 0) { |
| 362 codec_.simulcastStream[0].width = codec_.width; | 359 codec_.simulcastStream[0].width = codec_.width; |
| 363 codec_.simulcastStream[0].height = codec_.height; | 360 codec_.simulcastStream[0].height = codec_.height; |
| 364 } | 361 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 configurations_[0].rc_max_quantizer = qp_max_; | 442 configurations_[0].rc_max_quantizer = qp_max_; |
| 446 configurations_[0].rc_undershoot_pct = 100; | 443 configurations_[0].rc_undershoot_pct = 100; |
| 447 configurations_[0].rc_overshoot_pct = 15; | 444 configurations_[0].rc_overshoot_pct = 15; |
| 448 configurations_[0].rc_buf_initial_sz = 500; | 445 configurations_[0].rc_buf_initial_sz = 500; |
| 449 configurations_[0].rc_buf_optimal_sz = 600; | 446 configurations_[0].rc_buf_optimal_sz = 600; |
| 450 configurations_[0].rc_buf_sz = 1000; | 447 configurations_[0].rc_buf_sz = 1000; |
| 451 | 448 |
| 452 // Set the maximum target size of any key-frame. | 449 // Set the maximum target size of any key-frame. |
| 453 rc_max_intra_target_ = MaxIntraTarget(configurations_[0].rc_buf_optimal_sz); | 450 rc_max_intra_target_ = MaxIntraTarget(configurations_[0].rc_buf_optimal_sz); |
| 454 | 451 |
| 455 if (feedback_mode_) { | 452 if (inst->VP8().keyFrameInterval > 0) { |
| 456 // Disable periodic key frames if we get feedback from the decoder | |
| 457 // through SLI and RPSI. | |
| 458 configurations_[0].kf_mode = VPX_KF_DISABLED; | |
| 459 } else if (inst->VP8().keyFrameInterval > 0) { | |
| 460 configurations_[0].kf_mode = VPX_KF_AUTO; | 453 configurations_[0].kf_mode = VPX_KF_AUTO; |
| 461 configurations_[0].kf_max_dist = inst->VP8().keyFrameInterval; | 454 configurations_[0].kf_max_dist = inst->VP8().keyFrameInterval; |
| 462 } else { | 455 } else { |
| 463 configurations_[0].kf_mode = VPX_KF_DISABLED; | 456 configurations_[0].kf_mode = VPX_KF_DISABLED; |
| 464 } | 457 } |
| 465 | 458 |
| 466 // Allow the user to set the complexity for the base stream. | 459 // Allow the user to set the complexity for the base stream. |
| 467 switch (inst->VP8().complexity) { | 460 switch (inst->VP8().complexity) { |
| 468 case kComplexityHigh: | 461 case kComplexityHigh: |
| 469 cpu_speed_[0] = -5; | 462 cpu_speed_[0] = -5; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 vpx_img_alloc(&raw_images_[i], VPX_IMG_FMT_I420, | 526 vpx_img_alloc(&raw_images_[i], VPX_IMG_FMT_I420, |
| 534 inst->simulcastStream[stream_idx].width, | 527 inst->simulcastStream[stream_idx].width, |
| 535 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); | 528 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); |
| 536 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); | 529 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); |
| 537 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; | 530 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; |
| 538 temporal_layers_[stream_idx]->OnRatesUpdated( | 531 temporal_layers_[stream_idx]->OnRatesUpdated( |
| 539 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); | 532 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); |
| 540 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); | 533 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); |
| 541 } | 534 } |
| 542 | 535 |
| 543 rps_.Init(); | |
| 544 return InitAndSetControlSettings(); | 536 return InitAndSetControlSettings(); |
| 545 } | 537 } |
| 546 | 538 |
| 547 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { | 539 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { |
| 548 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) | 540 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) |
| 549 // On mobile platform, use a lower speed setting for lower resolutions for | 541 // On mobile platform, use a lower speed setting for lower resolutions for |
| 550 // CPUs with 4 or more cores. | 542 // CPUs with 4 or more cores. |
| 551 RTC_DCHECK_GT(number_of_cores_, 0); | 543 RTC_DCHECK_GT(number_of_cores_, 0); |
| 552 if (number_of_cores_ <= 3) | 544 if (number_of_cores_ <= 3) |
| 553 return -12; | 545 return -12; |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 763 const uint32_t forceKeyFrameIntraTh = 100; | 755 const uint32_t forceKeyFrameIntraTh = 100; |
| 764 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, | 756 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, |
| 765 forceKeyFrameIntraTh); | 757 forceKeyFrameIntraTh); |
| 766 } | 758 } |
| 767 // Key frame request from caller. | 759 // Key frame request from caller. |
| 768 // Will update both golden and alt-ref. | 760 // Will update both golden and alt-ref. |
| 769 for (size_t i = 0; i < encoders_.size(); ++i) { | 761 for (size_t i = 0; i < encoders_.size(); ++i) { |
| 770 flags[i] = VPX_EFLAG_FORCE_KF; | 762 flags[i] = VPX_EFLAG_FORCE_KF; |
| 771 } | 763 } |
| 772 std::fill(key_frame_request_.begin(), key_frame_request_.end(), false); | 764 std::fill(key_frame_request_.begin(), key_frame_request_.end(), false); |
| 773 } else if (codec_specific_info && | |
| 774 codec_specific_info->codecType == kVideoCodecVP8) { | |
| 775 if (feedback_mode_) { | |
| 776 // Handle RPSI and SLI messages and set up the appropriate encode flags. | |
| 777 bool sendRefresh = false; | |
| 778 if (codec_specific_info->codecSpecific.VP8.hasReceivedRPSI) { | |
| 779 rps_.ReceivedRPSI(codec_specific_info->codecSpecific.VP8.pictureIdRPSI); | |
| 780 } | |
| 781 if (codec_specific_info->codecSpecific.VP8.hasReceivedSLI) { | |
| 782 sendRefresh = rps_.ReceivedSLI(frame.timestamp()); | |
| 783 } | |
| 784 for (size_t i = 0; i < encoders_.size(); ++i) { | |
| 785 flags[i] = rps_.EncodeFlags(picture_id_[i], sendRefresh, | |
| 786 frame.timestamp()); | |
| 787 } | |
| 788 } else { | |
| 789 if (codec_specific_info->codecSpecific.VP8.hasReceivedRPSI) { | |
| 790 // Is this our last key frame? If not ignore. | |
| 791 // |picture_id_| is defined per spatial stream/layer, so check that | |
| 792 // |RPSI| matches the last key frame from any of the spatial streams. | |
| 793 // If so, then all spatial streams for this encoding will predict from | |
| 794 // its long-term reference (last key frame). | |
| 795 int RPSI = codec_specific_info->codecSpecific.VP8.pictureIdRPSI; | |
| 796 for (size_t i = 0; i < encoders_.size(); ++i) { | |
| 797 if (last_key_frame_picture_id_[i] == RPSI) { | |
| 798 // Request for a long term reference frame. | |
| 799 // Note 1: overwrites any temporal settings. | |
| 800 // Note 2: VP8_EFLAG_NO_UPD_ENTROPY is not needed as that flag is | |
| 801 // set by error_resilient mode. | |
| 802 for (size_t j = 0; j < encoders_.size(); ++j) { | |
| 803 flags[j] = VP8_EFLAG_NO_UPD_ARF; | |
| 804 flags[j] |= VP8_EFLAG_NO_REF_GF; | |
| 805 flags[j] |= VP8_EFLAG_NO_REF_LAST; | |
| 806 } | |
| 807 only_predict_from_key_frame = true; | |
| 808 break; | |
| 809 } | |
| 810 } | |
| 811 } | |
| 812 } | |
| 813 } | 765 } |
| 766 |
| 814 // Set the encoder frame flags and temporal layer_id for each spatial stream. | 767 // Set the encoder frame flags and temporal layer_id for each spatial stream. |
| 815 // Note that |temporal_layers_| are defined starting from lowest resolution at | 768 // Note that |temporal_layers_| are defined starting from lowest resolution at |
| 816 // position 0 to highest resolution at position |encoders_.size() - 1|, | 769 // position 0 to highest resolution at position |encoders_.size() - 1|, |
| 817 // whereas |encoder_| is from highest to lowest resolution. | 770 // whereas |encoder_| is from highest to lowest resolution. |
| 818 size_t stream_idx = encoders_.size() - 1; | 771 size_t stream_idx = encoders_.size() - 1; |
| 819 for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { | 772 for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { |
| 820 // Allow the layers adapter to temporarily modify the configuration. This | 773 // Allow the layers adapter to temporarily modify the configuration. This |
| 821 // change isn't stored in configurations_ so change will be discarded at | 774 // change isn't stored in configurations_ so change will be discarded at |
| 822 // the next update. | 775 // the next update. |
| 823 vpx_codec_enc_cfg_t temp_config; | 776 vpx_codec_enc_cfg_t temp_config; |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 break; | 906 break; |
| 954 } | 907 } |
| 955 default: | 908 default: |
| 956 break; | 909 break; |
| 957 } | 910 } |
| 958 // End of frame | 911 // End of frame |
| 959 if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) { | 912 if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) { |
| 960 // check if encoded frame is a key frame | 913 // check if encoded frame is a key frame |
| 961 if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { | 914 if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { |
| 962 encoded_images_[encoder_idx]._frameType = kVideoFrameKey; | 915 encoded_images_[encoder_idx]._frameType = kVideoFrameKey; |
| 963 rps_.EncodedKeyFrame(picture_id_[stream_idx]); | |
| 964 } | 916 } |
| 965 PopulateCodecSpecific(&codec_specific, *pkt, stream_idx, | 917 PopulateCodecSpecific(&codec_specific, *pkt, stream_idx, |
| 966 input_image.timestamp(), | 918 input_image.timestamp(), |
| 967 only_predicting_from_key_frame); | 919 only_predicting_from_key_frame); |
| 968 break; | 920 break; |
| 969 } | 921 } |
| 970 } | 922 } |
| 971 encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); | 923 encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); |
| 972 encoded_images_[encoder_idx].capture_time_ms_ = | 924 encoded_images_[encoder_idx].capture_time_ms_ = |
| 973 input_image.render_time_ms(); | 925 input_image.render_time_ms(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1004 } | 956 } |
| 1005 | 957 |
| 1006 VideoEncoder::ScalingSettings VP8EncoderImpl::GetScalingSettings() const { | 958 VideoEncoder::ScalingSettings VP8EncoderImpl::GetScalingSettings() const { |
| 1007 const bool enable_scaling = encoders_.size() == 1 && | 959 const bool enable_scaling = encoders_.size() == 1 && |
| 1008 configurations_[0].rc_dropframe_thresh > 0 && | 960 configurations_[0].rc_dropframe_thresh > 0 && |
| 1009 codec_.VP8().automaticResizeOn; | 961 codec_.VP8().automaticResizeOn; |
| 1010 return VideoEncoder::ScalingSettings(enable_scaling); | 962 return VideoEncoder::ScalingSettings(enable_scaling); |
| 1011 } | 963 } |
| 1012 | 964 |
| 1013 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { | 965 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { |
| 1014 rps_.SetRtt(rtt); | |
| 1015 return WEBRTC_VIDEO_CODEC_OK; | 966 return WEBRTC_VIDEO_CODEC_OK; |
| 1016 } | 967 } |
| 1017 | 968 |
| 1018 int VP8EncoderImpl::RegisterEncodeCompleteCallback( | 969 int VP8EncoderImpl::RegisterEncodeCompleteCallback( |
| 1019 EncodedImageCallback* callback) { | 970 EncodedImageCallback* callback) { |
| 1020 encoded_complete_callback_ = callback; | 971 encoded_complete_callback_ = callback; |
| 1021 return WEBRTC_VIDEO_CODEC_OK; | 972 return WEBRTC_VIDEO_CODEC_OK; |
| 1022 } | 973 } |
| 1023 | 974 |
| 1024 VP8DecoderImpl::VP8DecoderImpl() | 975 VP8DecoderImpl::VP8DecoderImpl() |
| 1025 : buffer_pool_(false, 300 /* max_number_of_buffers*/), | 976 : buffer_pool_(false, 300 /* max_number_of_buffers*/), |
| 1026 decode_complete_callback_(NULL), | 977 decode_complete_callback_(NULL), |
| 1027 inited_(false), | 978 inited_(false), |
| 1028 feedback_mode_(false), | |
| 1029 decoder_(NULL), | 979 decoder_(NULL), |
| 1030 image_format_(VPX_IMG_FMT_NONE), | 980 image_format_(VPX_IMG_FMT_NONE), |
| 1031 ref_frame_(NULL), | 981 ref_frame_(NULL), |
| 1032 propagation_cnt_(-1), | 982 propagation_cnt_(-1), |
| 1033 last_frame_width_(0), | 983 last_frame_width_(0), |
| 1034 last_frame_height_(0), | 984 last_frame_height_(0), |
| 1035 key_frame_required_(true), | 985 key_frame_required_(true), |
| 1036 use_postproc_arm_(webrtc::field_trial::FindFullName( | 986 use_postproc_arm_(webrtc::field_trial::FindFullName( |
| 1037 kVp8PostProcArmFieldTrial) == "Enabled") {} | 987 kVp8PostProcArmFieldTrial) == "Enabled") {} |
| 1038 | 988 |
| 1039 VP8DecoderImpl::~VP8DecoderImpl() { | 989 VP8DecoderImpl::~VP8DecoderImpl() { |
| 1040 inited_ = true; // in order to do the actual release | 990 inited_ = true; // in order to do the actual release |
| 1041 Release(); | 991 Release(); |
| 1042 } | 992 } |
| 1043 | 993 |
| 1044 int VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { | 994 int VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { |
| 1045 int ret_val = Release(); | 995 int ret_val = Release(); |
| 1046 if (ret_val < 0) { | 996 if (ret_val < 0) { |
| 1047 return ret_val; | 997 return ret_val; |
| 1048 } | 998 } |
| 1049 if (decoder_ == NULL) { | 999 if (decoder_ == NULL) { |
| 1050 decoder_ = new vpx_codec_ctx_t; | 1000 decoder_ = new vpx_codec_ctx_t; |
| 1051 memset(decoder_, 0, sizeof(*decoder_)); | 1001 memset(decoder_, 0, sizeof(*decoder_)); |
| 1052 } | 1002 } |
| 1053 if (inst && inst->codecType == kVideoCodecVP8) { | |
| 1054 feedback_mode_ = inst->VP8().feedbackModeOn; | |
| 1055 } | |
| 1056 vpx_codec_dec_cfg_t cfg; | 1003 vpx_codec_dec_cfg_t cfg; |
| 1057 // Setting number of threads to a constant value (1) | 1004 // Setting number of threads to a constant value (1) |
| 1058 cfg.threads = 1; | 1005 cfg.threads = 1; |
| 1059 cfg.h = cfg.w = 0; // set after decode | 1006 cfg.h = cfg.w = 0; // set after decode |
| 1060 | 1007 |
| 1061 vpx_codec_flags_t flags = 0; | 1008 vpx_codec_flags_t flags = 0; |
| 1062 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) | 1009 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) |
| 1063 if (use_postproc_arm_) { | 1010 if (use_postproc_arm_) { |
| 1064 flags = VPX_CODEC_USE_POSTPROC; | 1011 flags = VPX_CODEC_USE_POSTPROC; |
| 1065 } | 1012 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 if (key_frame_required_) { | 1081 if (key_frame_required_) { |
| 1135 if (input_image._frameType != kVideoFrameKey) | 1082 if (input_image._frameType != kVideoFrameKey) |
| 1136 return WEBRTC_VIDEO_CODEC_ERROR; | 1083 return WEBRTC_VIDEO_CODEC_ERROR; |
| 1137 // We have a key frame - is it complete? | 1084 // We have a key frame - is it complete? |
| 1138 if (input_image._completeFrame) { | 1085 if (input_image._completeFrame) { |
| 1139 key_frame_required_ = false; | 1086 key_frame_required_ = false; |
| 1140 } else { | 1087 } else { |
| 1141 return WEBRTC_VIDEO_CODEC_ERROR; | 1088 return WEBRTC_VIDEO_CODEC_ERROR; |
| 1142 } | 1089 } |
| 1143 } | 1090 } |
| 1144 // Restrict error propagation using key frame requests. Disabled when | 1091 // Restrict error propagation using key frame requests. |
| 1145 // the feedback mode is enabled (RPS). | |
| 1146 // Reset on a key frame refresh. | 1092 // Reset on a key frame refresh. |
| 1147 if (!feedback_mode_) { | 1093 if (input_image._frameType == kVideoFrameKey && |
| 1148 if (input_image._frameType == kVideoFrameKey && | 1094 input_image._completeFrame) { |
| 1149 input_image._completeFrame) { | |
| 1150 propagation_cnt_ = -1; | 1095 propagation_cnt_ = -1; |
| 1151 // Start count on first loss. | 1096 // Start count on first loss. |
| 1152 } else if ((!input_image._completeFrame || missing_frames) && | 1097 } else if ((!input_image._completeFrame || missing_frames) && |
| 1153 propagation_cnt_ == -1) { | 1098 propagation_cnt_ == -1) { |
| 1154 propagation_cnt_ = 0; | 1099 propagation_cnt_ = 0; |
| 1155 } | 1100 } |
| 1156 if (propagation_cnt_ >= 0) { | 1101 if (propagation_cnt_ >= 0) { |
| 1157 propagation_cnt_++; | 1102 propagation_cnt_++; |
| 1158 } | |
| 1159 } | 1103 } |
| 1160 | 1104 |
| 1161 vpx_codec_iter_t iter = NULL; | 1105 vpx_codec_iter_t iter = NULL; |
| 1162 vpx_image_t* img; | 1106 vpx_image_t* img; |
| 1163 int ret; | 1107 int ret; |
| 1164 | 1108 |
| 1165 // Check for missing frames. | 1109 // Check for missing frames. |
| 1166 if (missing_frames) { | 1110 if (missing_frames) { |
| 1167 // Call decoder with zero data length to signal missing frames. | 1111 // Call decoder with zero data length to signal missing frames. |
| 1168 if (vpx_codec_decode(decoder_, NULL, 0, 0, VPX_DL_REALTIME)) { | 1112 if (vpx_codec_decode(decoder_, NULL, 0, 0, VPX_DL_REALTIME)) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1193 vpx_codec_err_t vpx_ret = | 1137 vpx_codec_err_t vpx_ret = |
| 1194 vpx_codec_control(decoder_, VPXD_GET_LAST_QUANTIZER, &qp); | 1138 vpx_codec_control(decoder_, VPXD_GET_LAST_QUANTIZER, &qp); |
| 1195 RTC_DCHECK_EQ(vpx_ret, VPX_CODEC_OK); | 1139 RTC_DCHECK_EQ(vpx_ret, VPX_CODEC_OK); |
| 1196 ret = ReturnFrame(img, input_image._timeStamp, input_image.ntp_time_ms_, qp); | 1140 ret = ReturnFrame(img, input_image._timeStamp, input_image.ntp_time_ms_, qp); |
| 1197 if (ret != 0) { | 1141 if (ret != 0) { |
| 1198 // Reset to avoid requesting key frames too often. | 1142 // Reset to avoid requesting key frames too often. |
| 1199 if (ret < 0 && propagation_cnt_ > 0) | 1143 if (ret < 0 && propagation_cnt_ > 0) |
| 1200 propagation_cnt_ = 0; | 1144 propagation_cnt_ = 0; |
| 1201 return ret; | 1145 return ret; |
| 1202 } | 1146 } |
| 1203 if (feedback_mode_) { | |
| 1204 // Whenever we receive an incomplete key frame all reference buffers will | |
| 1205 // be corrupt. If that happens we must request new key frames until we | |
| 1206 // decode a complete key frame. | |
| 1207 if (input_image._frameType == kVideoFrameKey && !input_image._completeFrame) | |
| 1208 return WEBRTC_VIDEO_CODEC_ERROR; | |
| 1209 // Check for reference updates and last reference buffer corruption and | |
| 1210 // signal successful reference propagation or frame corruption to the | |
| 1211 // encoder. | |
| 1212 int reference_updates = 0; | |
| 1213 if (vpx_codec_control(decoder_, VP8D_GET_LAST_REF_UPDATES, | |
| 1214 &reference_updates)) { | |
| 1215 // Reset to avoid requesting key frames too often. | |
| 1216 if (propagation_cnt_ > 0) { | |
| 1217 propagation_cnt_ = 0; | |
| 1218 } | |
| 1219 return WEBRTC_VIDEO_CODEC_ERROR; | |
| 1220 } | |
| 1221 int corrupted = 0; | |
| 1222 if (vpx_codec_control(decoder_, VP8D_GET_FRAME_CORRUPTED, &corrupted)) { | |
| 1223 // Reset to avoid requesting key frames too often. | |
| 1224 if (propagation_cnt_ > 0) | |
| 1225 propagation_cnt_ = 0; | |
| 1226 return WEBRTC_VIDEO_CODEC_ERROR; | |
| 1227 } | |
| 1228 int16_t picture_id = -1; | |
| 1229 if (codec_specific_info) { | |
| 1230 picture_id = codec_specific_info->codecSpecific.VP8.pictureId; | |
| 1231 } | |
| 1232 if (picture_id > -1) { | |
| 1233 if (((reference_updates & VP8_GOLD_FRAME) || | |
| 1234 (reference_updates & VP8_ALTR_FRAME)) && | |
| 1235 !corrupted) { | |
| 1236 decode_complete_callback_->ReceivedDecodedReferenceFrame(picture_id); | |
| 1237 } | |
| 1238 decode_complete_callback_->ReceivedDecodedFrame(picture_id); | |
| 1239 } | |
| 1240 if (corrupted) { | |
| 1241 // we can decode but with artifacts | |
| 1242 return WEBRTC_VIDEO_CODEC_REQUEST_SLI; | |
| 1243 } | |
| 1244 } | |
| 1245 // Check Vs. threshold | 1147 // Check Vs. threshold |
| 1246 if (propagation_cnt_ > kVp8ErrorPropagationTh) { | 1148 if (propagation_cnt_ > kVp8ErrorPropagationTh) { |
| 1247 // Reset to avoid requesting key frames too often. | 1149 // Reset to avoid requesting key frames too often. |
| 1248 propagation_cnt_ = 0; | 1150 propagation_cnt_ = 0; |
| 1249 return WEBRTC_VIDEO_CODEC_ERROR; | 1151 return WEBRTC_VIDEO_CODEC_ERROR; |
| 1250 } | 1152 } |
| 1251 return WEBRTC_VIDEO_CODEC_OK; | 1153 return WEBRTC_VIDEO_CODEC_OK; |
| 1252 } | 1154 } |
| 1253 | 1155 |
| 1254 int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, | 1156 int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 return -1; | 1227 return -1; |
| 1326 } | 1228 } |
| 1327 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != | 1229 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != |
| 1328 VPX_CODEC_OK) { | 1230 VPX_CODEC_OK) { |
| 1329 return -1; | 1231 return -1; |
| 1330 } | 1232 } |
| 1331 return 0; | 1233 return 0; |
| 1332 } | 1234 } |
| 1333 | 1235 |
| 1334 } // namespace webrtc | 1236 } // namespace webrtc |
| OLD | NEW |