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 |