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 11 matching lines...) Expand all Loading... |
22 | 22 |
23 #include "webrtc/common_types.h" | 23 #include "webrtc/common_types.h" |
24 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 24 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
25 #include "webrtc/modules/include/module_common_types.h" | 25 #include "webrtc/modules/include/module_common_types.h" |
26 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" | 26 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" |
27 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" | 27 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" |
28 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_rate_allocator.h" | 28 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_rate_allocator.h" |
29 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" | 29 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" |
30 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 30 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
31 #include "webrtc/rtc_base/checks.h" | 31 #include "webrtc/rtc_base/checks.h" |
| 32 #include "webrtc/rtc_base/numerics/exp_filter.h" |
32 #include "webrtc/rtc_base/random.h" | 33 #include "webrtc/rtc_base/random.h" |
33 #include "webrtc/rtc_base/timeutils.h" | 34 #include "webrtc/rtc_base/timeutils.h" |
34 #include "webrtc/rtc_base/trace_event.h" | 35 #include "webrtc/rtc_base/trace_event.h" |
35 #include "webrtc/system_wrappers/include/clock.h" | 36 #include "webrtc/system_wrappers/include/clock.h" |
36 #include "webrtc/system_wrappers/include/field_trial.h" | 37 #include "webrtc/system_wrappers/include/field_trial.h" |
37 #include "webrtc/system_wrappers/include/metrics.h" | 38 #include "webrtc/system_wrappers/include/metrics.h" |
38 | 39 |
39 namespace webrtc { | 40 namespace webrtc { |
40 namespace { | 41 namespace { |
41 | 42 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 return false; | 116 return false; |
116 | 117 |
117 if (sscanf(group.c_str(), "Enabled-%d", boost_percentage) != 1) | 118 if (sscanf(group.c_str(), "Enabled-%d", boost_percentage) != 1) |
118 return false; | 119 return false; |
119 | 120 |
120 if (*boost_percentage < 0 || *boost_percentage > 100) | 121 if (*boost_percentage < 0 || *boost_percentage > 100) |
121 return false; | 122 return false; |
122 | 123 |
123 return true; | 124 return true; |
124 } | 125 } |
| 126 |
| 127 void GetPostProcParamsFromFieldTrialGroup( |
| 128 VP8DecoderImpl::DeblockParams* deblock_params) { |
| 129 std::string group = |
| 130 webrtc::field_trial::FindFullName(kVp8PostProcArmFieldTrial); |
| 131 if (group.empty()) |
| 132 return; |
| 133 |
| 134 VP8DecoderImpl::DeblockParams params; |
| 135 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", ¶ms.max_level, |
| 136 ¶ms.min_qp, ¶ms.degrade_qp) != 3) |
| 137 return; |
| 138 |
| 139 if (params.max_level < 0 || params.max_level > 16) |
| 140 return; |
| 141 |
| 142 if (params.min_qp < 0 || params.degrade_qp <= params.min_qp) |
| 143 return; |
| 144 |
| 145 *deblock_params = params; |
| 146 } |
| 147 |
125 } // namespace | 148 } // namespace |
126 | 149 |
127 VP8Encoder* VP8Encoder::Create() { | 150 VP8Encoder* VP8Encoder::Create() { |
128 return new VP8EncoderImpl(); | 151 return new VP8EncoderImpl(); |
129 } | 152 } |
130 | 153 |
131 VP8Decoder* VP8Decoder::Create() { | 154 VP8Decoder* VP8Decoder::Create() { |
132 return new VP8DecoderImpl(); | 155 return new VP8DecoderImpl(); |
133 } | 156 } |
134 | 157 |
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
918 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { | 941 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { |
919 return WEBRTC_VIDEO_CODEC_OK; | 942 return WEBRTC_VIDEO_CODEC_OK; |
920 } | 943 } |
921 | 944 |
922 int VP8EncoderImpl::RegisterEncodeCompleteCallback( | 945 int VP8EncoderImpl::RegisterEncodeCompleteCallback( |
923 EncodedImageCallback* callback) { | 946 EncodedImageCallback* callback) { |
924 encoded_complete_callback_ = callback; | 947 encoded_complete_callback_ = callback; |
925 return WEBRTC_VIDEO_CODEC_OK; | 948 return WEBRTC_VIDEO_CODEC_OK; |
926 } | 949 } |
927 | 950 |
| 951 class VP8DecoderImpl::QpSmoother { |
| 952 public: |
| 953 QpSmoother() : last_sample_ms_(rtc::TimeMillis()), smoother_(kAlpha) {} |
| 954 |
| 955 int GetAvg() const { |
| 956 float value = smoother_.filtered(); |
| 957 return (value == rtc::ExpFilter::kValueUndefined) ? 0 |
| 958 : static_cast<int>(value); |
| 959 } |
| 960 |
| 961 void Add(float sample) { |
| 962 int64_t now_ms = rtc::TimeMillis(); |
| 963 smoother_.Apply(static_cast<float>(now_ms - last_sample_ms_), sample); |
| 964 last_sample_ms_ = now_ms; |
| 965 } |
| 966 |
| 967 void Reset() { smoother_.Reset(kAlpha); } |
| 968 |
| 969 private: |
| 970 const float kAlpha = 0.95f; |
| 971 int64_t last_sample_ms_; |
| 972 rtc::ExpFilter smoother_; |
| 973 }; |
| 974 |
928 VP8DecoderImpl::VP8DecoderImpl() | 975 VP8DecoderImpl::VP8DecoderImpl() |
929 : use_postproc_arm_(webrtc::field_trial::FindFullName( | 976 : use_postproc_arm_( |
930 kVp8PostProcArmFieldTrial) == "Enabled"), | 977 webrtc::field_trial::IsEnabled(kVp8PostProcArmFieldTrial)), |
931 buffer_pool_(false, 300 /* max_number_of_buffers*/), | 978 buffer_pool_(false, 300 /* max_number_of_buffers*/), |
932 decode_complete_callback_(NULL), | 979 decode_complete_callback_(NULL), |
933 inited_(false), | 980 inited_(false), |
934 decoder_(NULL), | 981 decoder_(NULL), |
935 propagation_cnt_(-1), | 982 propagation_cnt_(-1), |
936 last_frame_width_(0), | 983 last_frame_width_(0), |
937 last_frame_height_(0), | 984 last_frame_height_(0), |
938 key_frame_required_(true) {} | 985 key_frame_required_(true), |
| 986 qp_smoother_(use_postproc_arm_ ? new QpSmoother() : nullptr) { |
| 987 if (use_postproc_arm_) |
| 988 GetPostProcParamsFromFieldTrialGroup(&deblock_); |
| 989 } |
939 | 990 |
940 VP8DecoderImpl::~VP8DecoderImpl() { | 991 VP8DecoderImpl::~VP8DecoderImpl() { |
941 inited_ = true; // in order to do the actual release | 992 inited_ = true; // in order to do the actual release |
942 Release(); | 993 Release(); |
943 } | 994 } |
944 | 995 |
945 int VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { | 996 int VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { |
946 int ret_val = Release(); | 997 int ret_val = Release(); |
947 if (ret_val < 0) { | 998 if (ret_val < 0) { |
948 return ret_val; | 999 return ret_val; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 if (propagation_cnt_ > 0) | 1043 if (propagation_cnt_ > 0) |
993 propagation_cnt_ = 0; | 1044 propagation_cnt_ = 0; |
994 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 1045 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
995 } | 1046 } |
996 | 1047 |
997 // Post process configurations. | 1048 // Post process configurations. |
998 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) | 1049 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) |
999 if (use_postproc_arm_) { | 1050 if (use_postproc_arm_) { |
1000 vp8_postproc_cfg_t ppcfg; | 1051 vp8_postproc_cfg_t ppcfg; |
1001 ppcfg.post_proc_flag = VP8_MFQE; | 1052 ppcfg.post_proc_flag = VP8_MFQE; |
1002 // For low resolutions, use stronger deblocking filter and enable the | 1053 // For low resolutions, use stronger deblocking filter. |
1003 // deblock and demacroblocker. | |
1004 int last_width_x_height = last_frame_width_ * last_frame_height_; | 1054 int last_width_x_height = last_frame_width_ * last_frame_height_; |
1005 if (last_width_x_height > 0 && last_width_x_height <= 320 * 240) { | 1055 if (last_width_x_height > 0 && last_width_x_height <= 320 * 240) { |
1006 ppcfg.deblocking_level = 6; // Only affects VP8_DEMACROBLOCK. | 1056 // Enable the deblock and demacroblocker based on qp thresholds. |
1007 ppcfg.post_proc_flag |= VP8_DEBLOCK | VP8_DEMACROBLOCK; | 1057 RTC_DCHECK(qp_smoother_); |
| 1058 int qp = qp_smoother_->GetAvg(); |
| 1059 if (qp > deblock_.min_qp) { |
| 1060 int level = deblock_.max_level; |
| 1061 if (qp < deblock_.degrade_qp) { |
| 1062 // Use lower level. |
| 1063 level = deblock_.max_level * (qp - deblock_.min_qp) / |
| 1064 (deblock_.degrade_qp - deblock_.min_qp); |
| 1065 } |
| 1066 // Deblocking level only affects VP8_DEMACROBLOCK. |
| 1067 ppcfg.deblocking_level = std::max(level, 1); |
| 1068 ppcfg.post_proc_flag |= VP8_DEBLOCK | VP8_DEMACROBLOCK; |
| 1069 } |
1008 } | 1070 } |
1009 vpx_codec_control(decoder_, VP8_SET_POSTPROC, &ppcfg); | 1071 vpx_codec_control(decoder_, VP8_SET_POSTPROC, &ppcfg); |
1010 } | 1072 } |
1011 #else | 1073 #else |
1012 vp8_postproc_cfg_t ppcfg; | 1074 vp8_postproc_cfg_t ppcfg; |
1013 // MFQE enabled to reduce key frame popping. | 1075 // MFQE enabled to reduce key frame popping. |
1014 ppcfg.post_proc_flag = VP8_MFQE | VP8_DEBLOCK; | 1076 ppcfg.post_proc_flag = VP8_MFQE | VP8_DEBLOCK; |
1015 // For VGA resolutions and lower, enable the demacroblocker postproc. | 1077 // For VGA resolutions and lower, enable the demacroblocker postproc. |
1016 if (last_frame_width_ * last_frame_height_ <= 640 * 360) { | 1078 if (last_frame_width_ * last_frame_height_ <= 640 * 360) { |
1017 ppcfg.post_proc_flag |= VP8_DEMACROBLOCK; | 1079 ppcfg.post_proc_flag |= VP8_DEMACROBLOCK; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1097 } | 1159 } |
1098 | 1160 |
1099 int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, | 1161 int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, |
1100 uint32_t timestamp, | 1162 uint32_t timestamp, |
1101 int64_t ntp_time_ms, | 1163 int64_t ntp_time_ms, |
1102 int qp) { | 1164 int qp) { |
1103 if (img == NULL) { | 1165 if (img == NULL) { |
1104 // Decoder OK and NULL image => No show frame | 1166 // Decoder OK and NULL image => No show frame |
1105 return WEBRTC_VIDEO_CODEC_NO_OUTPUT; | 1167 return WEBRTC_VIDEO_CODEC_NO_OUTPUT; |
1106 } | 1168 } |
| 1169 if (qp_smoother_) { |
| 1170 if (last_frame_width_ != static_cast<int>(img->d_w) || |
| 1171 last_frame_height_ != static_cast<int>(img->d_h)) { |
| 1172 qp_smoother_->Reset(); |
| 1173 } |
| 1174 qp_smoother_->Add(qp); |
| 1175 } |
1107 last_frame_width_ = img->d_w; | 1176 last_frame_width_ = img->d_w; |
1108 last_frame_height_ = img->d_h; | 1177 last_frame_height_ = img->d_h; |
1109 // Allocate memory for decoded image. | 1178 // Allocate memory for decoded image. |
1110 rtc::scoped_refptr<I420Buffer> buffer = | 1179 rtc::scoped_refptr<I420Buffer> buffer = |
1111 buffer_pool_.CreateBuffer(img->d_w, img->d_h); | 1180 buffer_pool_.CreateBuffer(img->d_w, img->d_h); |
1112 if (!buffer.get()) { | 1181 if (!buffer.get()) { |
1113 // Pool has too many pending frames. | 1182 // Pool has too many pending frames. |
1114 RTC_HISTOGRAM_BOOLEAN("WebRTC.Video.VP8DecoderImpl.TooManyPendingFrames", | 1183 RTC_HISTOGRAM_BOOLEAN("WebRTC.Video.VP8DecoderImpl.TooManyPendingFrames", |
1115 1); | 1184 1); |
1116 return WEBRTC_VIDEO_CODEC_NO_OUTPUT; | 1185 return WEBRTC_VIDEO_CODEC_NO_OUTPUT; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 buffer_pool_.Release(); | 1218 buffer_pool_.Release(); |
1150 inited_ = false; | 1219 inited_ = false; |
1151 return WEBRTC_VIDEO_CODEC_OK; | 1220 return WEBRTC_VIDEO_CODEC_OK; |
1152 } | 1221 } |
1153 | 1222 |
1154 const char* VP8DecoderImpl::ImplementationName() const { | 1223 const char* VP8DecoderImpl::ImplementationName() const { |
1155 return "libvpx"; | 1224 return "libvpx"; |
1156 } | 1225 } |
1157 | 1226 |
1158 } // namespace webrtc | 1227 } // namespace webrtc |
OLD | NEW |