1f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org/* 2f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org * 4f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org * Use of this source code is governed by a BSD-style license 5f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org * that can be found in the LICENSE file in the root of the source 6f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org * tree. An additional intellectual property rights grant can be found 7f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org * in the file PATENTS. All contributing project authors may 8f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org */ 10f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 11f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org#include "webrtc/modules/video_coding/utility/quality_scaler.h" 12f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 13f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgnamespace webrtc { 14f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 15f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgstatic const int kMinFps = 10; 16f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgstatic const int kMeasureSeconds = 5; 17f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgstatic const int kFramedropPercentThreshold = 60; 18f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgstatic const int kLowQpThresholdDenominator = 3; 19f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 20f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgQualityScaler::QualityScaler() 21f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org : num_samples_(0), low_qp_threshold_(-1), downscale_shift_(0) { 22f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 23f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 24f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::Init(int max_qp) { 25f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org ClearSamples(); 26f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org downscale_shift_ = 0; 27f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org low_qp_threshold_ = max_qp / kLowQpThresholdDenominator ; 28f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 29f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 30f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::ReportFramerate(int framerate) { 31f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org num_samples_ = static_cast<size_t>( 32f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org kMeasureSeconds * (framerate < kMinFps ? kMinFps : framerate)); 33f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 34f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 35f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::ReportEncodedFrame(int qp) { 36f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org average_qp_.AddSample(qp); 37f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org framedrop_percent_.AddSample(0); 38f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 39f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 40f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::ReportDroppedFrame() { 41f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org framedrop_percent_.AddSample(100); 42f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 43f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 44f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgQualityScaler::Resolution QualityScaler::GetScaledResolution( 45f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org const I420VideoFrame& frame) { 46f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org // Both of these should be set through InitEncode -> Should be set by now. 47f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org assert(low_qp_threshold_ >= 0); 48f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org assert(num_samples_ > 0); 49f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org // Update scale factor. 50f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org int avg; 51f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org if (framedrop_percent_.GetAverage(num_samples_, &avg) && 52f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org avg >= kFramedropPercentThreshold) { 53f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org AdjustScale(false); 54f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org } else if (average_qp_.GetAverage(num_samples_, &avg) && 55f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org avg <= low_qp_threshold_) { 56f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org AdjustScale(true); 57f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org } 58f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 59f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org Resolution res; 60f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org res.width = frame.width(); 61f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org res.height = frame.height(); 62f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 63f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org assert(downscale_shift_ >= 0); 64f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org for (int shift = downscale_shift_; 65f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org shift > 0 && res.width > 1 && res.height > 1; 66f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org --shift) { 67f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org res.width >>= 1; 68f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org res.height >>= 1; 69f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org } 70f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 71f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org return res; 72f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 73f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 74f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgconst I420VideoFrame& QualityScaler::GetScaledFrame( 75f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org const I420VideoFrame& frame) { 76f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org Resolution res = GetScaledResolution(frame); 77f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org if (res.width == frame.width()) 78f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org return frame; 79f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 80f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org scaler_.Set(frame.width(), 81f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org frame.height(), 82f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org res.width, 83f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org res.height, 84f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org kI420, 85f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org kI420, 86f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org kScaleBox); 87f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org if (scaler_.Scale(frame, &scaled_frame_) != 0) 88f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org return frame; 89f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 90f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org scaled_frame_.set_ntp_time_ms(frame.ntp_time_ms()); 91f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org scaled_frame_.set_timestamp(frame.timestamp()); 92f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org scaled_frame_.set_render_time_ms(frame.render_time_ms()); 93f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 94f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org return scaled_frame_; 95f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 96f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 97f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgQualityScaler::MovingAverage::MovingAverage() : sum_(0) { 98f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 99f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 100f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::MovingAverage::AddSample(int sample) { 101f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org samples_.push_back(sample); 102f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org sum_ += sample; 103f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 104f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 105f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgbool QualityScaler::MovingAverage::GetAverage(size_t num_samples, int* avg) { 106f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org assert(num_samples > 0); 107f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org if (num_samples > samples_.size()) 108f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org return false; 109f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 110f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org // Remove old samples. 111f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org while (num_samples < samples_.size()) { 112f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org sum_ -= samples_.front(); 113f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org samples_.pop_front(); 114f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org } 115f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 116f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org *avg = sum_ / static_cast<int>(num_samples); 117f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org return true; 118f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 119f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 120f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::MovingAverage::Reset() { 121f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org sum_ = 0; 122f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org samples_.clear(); 123f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 124f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 125f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::ClearSamples() { 126f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org average_qp_.Reset(); 127f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org framedrop_percent_.Reset(); 128f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 129f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 130f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.orgvoid QualityScaler::AdjustScale(bool up) { 131f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org downscale_shift_ += up ? -1 : 1; 132f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org if (downscale_shift_ < 0) 133f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org downscale_shift_ = 0; 134f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org ClearSamples(); 135f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} 136f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org 137f51f68666c2da07ec231cba7bd44d91fff34da1dpbos@webrtc.org} // namespace webrtc 138