| Index: webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
|
| index dd9da0f4a6c82e76212d0863bd83a64d547e740e..3f9f879befcf75e8f4f682a3997853653a013401 100644
|
| --- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
|
| +++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
|
| @@ -29,6 +29,7 @@
|
| #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
|
| #include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
| #include "webrtc/rtc_base/checks.h"
|
| +#include "webrtc/rtc_base/numerics/exp_filter.h"
|
| #include "webrtc/rtc_base/random.h"
|
| #include "webrtc/rtc_base/timeutils.h"
|
| #include "webrtc/rtc_base/trace_event.h"
|
| @@ -122,6 +123,28 @@ bool GetGfBoostPercentageFromFieldTrialGroup(int* boost_percentage) {
|
|
|
| return true;
|
| }
|
| +
|
| +void GetPostProcParamsFromFieldTrialGroup(
|
| + VP8DecoderImpl::DeblockParams* deblock_params) {
|
| + std::string group =
|
| + webrtc::field_trial::FindFullName(kVp8PostProcArmFieldTrial);
|
| + if (group.empty())
|
| + return;
|
| +
|
| + VP8DecoderImpl::DeblockParams params;
|
| + if (sscanf(group.c_str(), "Enabled-%d,%d,%d", ¶ms.max_level,
|
| + ¶ms.min_qp, ¶ms.degrade_qp) != 3)
|
| + return;
|
| +
|
| + if (params.max_level < 0 || params.max_level > 16)
|
| + return;
|
| +
|
| + if (params.min_qp < 0 || params.degrade_qp <= params.min_qp)
|
| + return;
|
| +
|
| + *deblock_params = params;
|
| +}
|
| +
|
| } // namespace
|
|
|
| VP8Encoder* VP8Encoder::Create() {
|
| @@ -925,9 +948,33 @@ int VP8EncoderImpl::RegisterEncodeCompleteCallback(
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| }
|
|
|
| +class VP8DecoderImpl::QpSmoother {
|
| + public:
|
| + QpSmoother() : last_sample_ms_(rtc::TimeMillis()), smoother_(kAlpha) {}
|
| +
|
| + int GetAvg() const {
|
| + float value = smoother_.filtered();
|
| + return (value == rtc::ExpFilter::kValueUndefined) ? 0
|
| + : static_cast<int>(value);
|
| + }
|
| +
|
| + void Add(float sample) {
|
| + int64_t now_ms = rtc::TimeMillis();
|
| + smoother_.Apply(static_cast<float>(now_ms - last_sample_ms_), sample);
|
| + last_sample_ms_ = now_ms;
|
| + }
|
| +
|
| + void Reset() { smoother_.Reset(kAlpha); }
|
| +
|
| + private:
|
| + const float kAlpha = 0.95f;
|
| + int64_t last_sample_ms_;
|
| + rtc::ExpFilter smoother_;
|
| +};
|
| +
|
| VP8DecoderImpl::VP8DecoderImpl()
|
| - : use_postproc_arm_(webrtc::field_trial::FindFullName(
|
| - kVp8PostProcArmFieldTrial) == "Enabled"),
|
| + : use_postproc_arm_(
|
| + webrtc::field_trial::IsEnabled(kVp8PostProcArmFieldTrial)),
|
| buffer_pool_(false, 300 /* max_number_of_buffers*/),
|
| decode_complete_callback_(NULL),
|
| inited_(false),
|
| @@ -935,7 +982,11 @@ VP8DecoderImpl::VP8DecoderImpl()
|
| propagation_cnt_(-1),
|
| last_frame_width_(0),
|
| last_frame_height_(0),
|
| - key_frame_required_(true) {}
|
| + key_frame_required_(true),
|
| + qp_smoother_(use_postproc_arm_ ? new QpSmoother() : nullptr) {
|
| + if (use_postproc_arm_)
|
| + GetPostProcParamsFromFieldTrialGroup(&deblock_);
|
| +}
|
|
|
| VP8DecoderImpl::~VP8DecoderImpl() {
|
| inited_ = true; // in order to do the actual release
|
| @@ -999,12 +1050,23 @@ int VP8DecoderImpl::Decode(const EncodedImage& input_image,
|
| if (use_postproc_arm_) {
|
| vp8_postproc_cfg_t ppcfg;
|
| ppcfg.post_proc_flag = VP8_MFQE;
|
| - // For low resolutions, use stronger deblocking filter and enable the
|
| - // deblock and demacroblocker.
|
| + // For low resolutions, use stronger deblocking filter.
|
| int last_width_x_height = last_frame_width_ * last_frame_height_;
|
| if (last_width_x_height > 0 && last_width_x_height <= 320 * 240) {
|
| - ppcfg.deblocking_level = 6; // Only affects VP8_DEMACROBLOCK.
|
| - ppcfg.post_proc_flag |= VP8_DEBLOCK | VP8_DEMACROBLOCK;
|
| + // Enable the deblock and demacroblocker based on qp thresholds.
|
| + RTC_DCHECK(qp_smoother_);
|
| + int qp = qp_smoother_->GetAvg();
|
| + if (qp > deblock_.min_qp) {
|
| + int level = deblock_.max_level;
|
| + if (qp < deblock_.degrade_qp) {
|
| + // Use lower level.
|
| + level = deblock_.max_level * (qp - deblock_.min_qp) /
|
| + (deblock_.degrade_qp - deblock_.min_qp);
|
| + }
|
| + // Deblocking level only affects VP8_DEMACROBLOCK.
|
| + ppcfg.deblocking_level = std::max(level, 1);
|
| + ppcfg.post_proc_flag |= VP8_DEBLOCK | VP8_DEMACROBLOCK;
|
| + }
|
| }
|
| vpx_codec_control(decoder_, VP8_SET_POSTPROC, &ppcfg);
|
| }
|
| @@ -1104,6 +1166,13 @@ int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img,
|
| // Decoder OK and NULL image => No show frame
|
| return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
|
| }
|
| + if (qp_smoother_) {
|
| + if (last_frame_width_ != static_cast<int>(img->d_w) ||
|
| + last_frame_height_ != static_cast<int>(img->d_h)) {
|
| + qp_smoother_->Reset();
|
| + }
|
| + qp_smoother_->Add(qp);
|
| + }
|
| last_frame_width_ = img->d_w;
|
| last_frame_height_ = img->d_h;
|
| // Allocate memory for decoded image.
|
|
|