Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Unified Diff: webrtc/modules/video_coding/utility/quality_scaler.cc

Issue 2398963003: Move usage of QualityScaler to ViEEncoder. (Closed)
Patch Set: rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/video_coding/utility/quality_scaler.cc
diff --git a/webrtc/modules/video_coding/utility/quality_scaler.cc b/webrtc/modules/video_coding/utility/quality_scaler.cc
index 0f63edca7d126d520fff5fd28eb39a8adf8ca66c..ba1d9789c783230b5cf48fad2699a723669ae411 100644
--- a/webrtc/modules/video_coding/utility/quality_scaler.cc
+++ b/webrtc/modules/video_coding/utility/quality_scaler.cc
@@ -13,8 +13,11 @@
#include <math.h>
#include <algorithm>
+#include <memory>
#include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/base/task_queue.h"
// TODO(kthelgason): Some versions of Android have issues with log2.
// See https://code.google.com/p/android/issues/detail?id=212634 for details
@@ -26,21 +29,9 @@ namespace webrtc {
namespace {
// Threshold constant used until first downscale (to permit fast rampup).
-static const int kMeasureSecondsFastUpscale = 2;
-static const int kMeasureSecondsUpscale = 5;
-static const int kMeasureSecondsDownscale = 5;
+static const int kMeasureMs = 2000;
+static const float kSamplePeriodScaleFactor = 2.5;
static const int kFramedropPercentThreshold = 60;
-// Min width/height to downscale to, set to not go below QVGA, but with some
-// margin to permit "almost-QVGA" resolutions, such as QCIF.
-static const int kMinDownscaleDimension = 140;
-// Initial resolutions corresponding to a bitrate. Aa bit above their actual
-// values to permit near-VGA and near-QVGA resolutions to use the same
-// mechanism.
-static const int kVgaBitrateThresholdKbps = 500;
-static const int kVgaNumPixels = 700 * 500; // 640x480
-static const int kQvgaBitrateThresholdKbps = 250;
-static const int kQvgaNumPixels = 400 * 300; // 320x240
-
// QP scaling threshold defaults:
static const int kLowH264QpThreshold = 24;
static const int kHighH264QpThreshold = 37;
@@ -48,20 +39,13 @@ static const int kHighH264QpThreshold = 37;
// bitstream range of [0, 127] and not the user-level range of [0,63].
static const int kLowVp8QpThreshold = 29;
static const int kHighVp8QpThreshold = 95;
-} // namespace
+const ScalingObserverInterface::ScaleReason scale_reason_ =
+ ScalingObserverInterface::ScaleReason::kQuality;
-// Default values. Should immediately get set to something more sensible.
-QualityScaler::QualityScaler()
- : average_qp_(kMeasureSecondsUpscale * 30),
- framedrop_percent_(kMeasureSecondsUpscale * 30),
- low_qp_threshold_(-1) {}
-
-void QualityScaler::Init(VideoCodecType codec_type,
- int initial_bitrate_kbps,
- int width,
- int height,
- int fps) {
- int low = -1, high = -1;
+static VideoEncoder::QpThresholds CodecTypeToDefaultThresholds(
+ VideoCodecType codec_type) {
+ int low = -1;
+ int high = -1;
switch (codec_type) {
case kVideoCodecH264:
low = kLowH264QpThreshold;
@@ -74,138 +58,132 @@ void QualityScaler::Init(VideoCodecType codec_type,
default:
RTC_NOTREACHED() << "Invalid codec type for QualityScaler.";
}
- Init(low, high, initial_bitrate_kbps, width, height, fps);
+ return VideoEncoder::QpThresholds(low, high);
}
+} // namespace
-void QualityScaler::Init(int low_qp_threshold,
- int high_qp_threshold,
- int initial_bitrate_kbps,
- int width,
- int height,
- int fps) {
- ClearSamples();
- low_qp_threshold_ = low_qp_threshold;
- high_qp_threshold_ = high_qp_threshold;
- downscale_shift_ = 0;
- fast_rampup_ = true;
-
- const int init_width = width;
- const int init_height = height;
- if (initial_bitrate_kbps > 0) {
- int init_num_pixels = width * height;
- if (initial_bitrate_kbps < kVgaBitrateThresholdKbps)
- init_num_pixels = kVgaNumPixels;
- if (initial_bitrate_kbps < kQvgaBitrateThresholdKbps)
- init_num_pixels = kQvgaNumPixels;
- while (width * height > init_num_pixels) {
- ++downscale_shift_;
- width /= 2;
- height /= 2;
- }
+class QualityScaler::CheckQPTask : public rtc::QueuedTask {
+ public:
+ explicit CheckQPTask(QualityScaler* scaler) : scaler_(scaler) {
+ LOG(LS_INFO) << "Created CheckQPTask. Scheduling on queue...";
+ rtc::TaskQueue::Current()->PostDelayedTask(
+ std::unique_ptr<rtc::QueuedTask>(this), scaler_->GetSamplingPeriodMs());
}
- UpdateTargetResolution(init_width, init_height);
- ReportFramerate(fps);
+ void Stop() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ LOG(LS_INFO) << "Stopping QP Check task.";
+ stop_ = true;
+ }
+
+ private:
+ bool Run() override {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ if (stop_)
+ return true; // TaskQueue will free this task.
+ scaler_->CheckQP();
+ rtc::TaskQueue::Current()->PostDelayedTask(
+ std::unique_ptr<rtc::QueuedTask>(this), scaler_->GetSamplingPeriodMs());
+ return false; // Retain the task in order to reuse it.
+ }
+
+ QualityScaler* const scaler_;
+ bool stop_ = false;
+ rtc::SequencedTaskChecker task_checker_;
+};
+
+QualityScaler::QualityScaler(ScalingObserverInterface* observer,
+ VideoCodecType codec_type)
+ : QualityScaler(observer, CodecTypeToDefaultThresholds(codec_type)) {}
+
+QualityScaler::QualityScaler(ScalingObserverInterface* observer,
+ VideoEncoder::QpThresholds thresholds)
+ : QualityScaler(observer, thresholds, kMeasureMs) {}
+
+// Protected ctor, should not be called directly.
+QualityScaler::QualityScaler(ScalingObserverInterface* observer,
+ VideoEncoder::QpThresholds thresholds,
+ int64_t sampling_period)
+ : check_qp_task_(nullptr),
+ observer_(observer),
+ sampling_period_ms_(sampling_period),
+ fast_rampup_(true),
+ // Arbitrarily choose size based on 30 fps for 5 seconds.
+ average_qp_(5 * 30),
+ framedrop_percent_(5 * 30),
+ thresholds_(thresholds) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ RTC_DCHECK(observer_ != nullptr);
+ check_qp_task_ = new CheckQPTask(this);
}
-// Report framerate(fps) to estimate # of samples.
-void QualityScaler::ReportFramerate(int framerate) {
- // Use a faster window for upscaling initially.
- // This enables faster initial rampups without risking strong up-down
- // behavior later.
- num_samples_upscale_ = framerate * (fast_rampup_ ? kMeasureSecondsFastUpscale
- : kMeasureSecondsUpscale);
- num_samples_downscale_ = framerate * kMeasureSecondsDownscale;
+QualityScaler::~QualityScaler() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ check_qp_task_->Stop();
}
-void QualityScaler::ReportQP(int qp) {
- framedrop_percent_.AddSample(0);
- average_qp_.AddSample(qp);
+int64_t QualityScaler::GetSamplingPeriodMs() const {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ return fast_rampup_ ? sampling_period_ms_
+ : (sampling_period_ms_ * kSamplePeriodScaleFactor);
}
void QualityScaler::ReportDroppedFrame() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
framedrop_percent_.AddSample(100);
}
-void QualityScaler::OnEncodeFrame(int width, int height) {
- // Should be set through InitEncode -> Should be set by now.
- RTC_DCHECK_GE(low_qp_threshold_, 0);
- if (target_res_.width != width || target_res_.height != height) {
- UpdateTargetResolution(width, height);
- }
+void QualityScaler::ReportQP(int qp) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ framedrop_percent_.AddSample(0);
+ average_qp_.AddSample(qp);
+}
+void QualityScaler::CheckQP() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ // Should be set through InitEncode -> Should be set by now.
+ RTC_DCHECK_GE(thresholds_.low, 0);
+ LOG(LS_INFO) << "Checking if average QP exceeds threshold";
// Check if we should scale down due to high frame drop.
- const auto drop_rate = framedrop_percent_.GetAverage(num_samples_downscale_);
+ const rtc::Optional<int> drop_rate = framedrop_percent_.GetAverage();
if (drop_rate && *drop_rate >= kFramedropPercentThreshold) {
- ScaleDown();
+ ReportQPHigh();
return;
}
// Check if we should scale up or down based on QP.
- const auto avg_qp_down = average_qp_.GetAverage(num_samples_downscale_);
- if (avg_qp_down && *avg_qp_down > high_qp_threshold_) {
- ScaleDown();
+ const rtc::Optional<int> avg_qp = average_qp_.GetAverage();
+ if (avg_qp && *avg_qp > thresholds_.high) {
+ ReportQPHigh();
return;
}
- const auto avg_qp_up = average_qp_.GetAverage(num_samples_upscale_);
- if (avg_qp_up && *avg_qp_up <= low_qp_threshold_) {
+ if (avg_qp && *avg_qp <= thresholds_.low) {
// QP has been low. We want to try a higher resolution.
- ScaleUp();
+ ReportQPLow();
return;
}
}
-void QualityScaler::ScaleUp() {
- downscale_shift_ = std::max(0, downscale_shift_ - 1);
+void QualityScaler::ReportQPLow() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ LOG(LS_INFO) << "QP has been low, asking for higher resolution.";
ClearSamples();
+ observer_->ScaleUp(scale_reason_);
}
-void QualityScaler::ScaleDown() {
- downscale_shift_ = std::min(maximum_shift_, downscale_shift_ + 1);
+void QualityScaler::ReportQPHigh() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
+ LOG(LS_INFO) << "QP has been high , asking for lower resolution.";
ClearSamples();
+ observer_->ScaleDown(scale_reason_);
// If we've scaled down, wait longer before scaling up again.
if (fast_rampup_) {
fast_rampup_ = false;
- num_samples_upscale_ = (num_samples_upscale_ / kMeasureSecondsFastUpscale) *
- kMeasureSecondsUpscale;
}
}
-QualityScaler::Resolution QualityScaler::GetScaledResolution() const {
- const int frame_width = target_res_.width >> downscale_shift_;
- const int frame_height = target_res_.height >> downscale_shift_;
- return Resolution{frame_width, frame_height};
-}
-
-rtc::scoped_refptr<VideoFrameBuffer> QualityScaler::GetScaledBuffer(
- const rtc::scoped_refptr<VideoFrameBuffer>& frame) {
- Resolution res = GetScaledResolution();
- const int src_width = frame->width();
- const int src_height = frame->height();
-
- if (res.width == src_width && res.height == src_height)
- return frame;
- rtc::scoped_refptr<I420Buffer> scaled_buffer =
- pool_.CreateBuffer(res.width, res.height);
-
- scaled_buffer->ScaleFrom(*frame);
-
- return scaled_buffer;
-}
-
-void QualityScaler::UpdateTargetResolution(int width, int height) {
- if (width < kMinDownscaleDimension || height < kMinDownscaleDimension) {
- maximum_shift_ = 0;
- } else {
- maximum_shift_ = static_cast<int>(
- log2(std::min(width, height) / kMinDownscaleDimension));
- }
- target_res_ = Resolution{width, height};
-}
-
void QualityScaler::ClearSamples() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
framedrop_percent_.Reset();
average_qp_.Reset();
}
-
-
} // namespace webrtc
« no previous file with comments | « webrtc/modules/video_coding/utility/quality_scaler.h ('k') | webrtc/modules/video_coding/utility/quality_scaler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698