mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00

This CL breaks up the CheckQp() operation into several steps managed by the inner helper class CheckQpTask, making responding to high or low QP an asynchronous operation. Why? Reconfiguring the stream in response to QP overuse will in the future be handled on a separate task queue. See Call-Level Adaptation Processing for more details: https://docs.google.com/document/d/1ZyC26yOCknrrcYa839ZWLxD6o6Gig5A3lVTh4E41074/edit?usp=sharing Instead of "bool AdaptDown()" when high QP is reported, synchronously returning true or false depending on the result of adaptation, this CL introduces void QualityScalerQpUsageHandlerInterface::OnReportQpUsageHigh( rtc::scoped_refptr<QualityScalerQpUsageHandlerCallback>); Where QualityScalerQpUsageHandlerCallback::OnQpUsageHandled( bool clear_qp_samples); Instructs the QualityScaler whether to clear samples before checking QP the next time or to increase the frequency of checking (corresponding to AdaptDown's return value prior to this CL). QualityScaler no longer using AdaptationObserverInterface, this class is renamed and moved to overuse_frame_detector.h. The dependency between CheckQpTasks is made explicit with CheckQpTask::Result and variables like observed_enough_frames_, adapt_called_ and adapt_failed_ are moved there and given more descriptive names. Bug: webrtc:11521 Change-Id: I7faf795aeee5ded18ce75eb1617f88226e337228 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/173760 Reviewed-by: Evan Shrubsole <eshr@google.com> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31140}
151 lines
5.8 KiB
C++
151 lines
5.8 KiB
C++
/*
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#ifndef MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
|
|
#define MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/scoped_refptr.h"
|
|
#include "api/video_codecs/video_encoder.h"
|
|
#include "rtc_base/experiments/quality_scaling_experiment.h"
|
|
#include "rtc_base/numerics/moving_average.h"
|
|
#include "rtc_base/ref_count.h"
|
|
#include "rtc_base/ref_counted_object.h"
|
|
#include "rtc_base/synchronization/sequence_checker.h"
|
|
#include "rtc_base/task_queue.h"
|
|
|
|
namespace webrtc {
|
|
|
|
class QualityScalerQpUsageHandlerCallbackInterface;
|
|
class QualityScalerQpUsageHandlerInterface;
|
|
|
|
// QualityScaler runs asynchronously and monitors QP values of encoded frames.
|
|
// It holds a reference to a QualityScalerQpUsageHandlerInterface implementation
|
|
// to signal an overuse or underuse of QP (which indicate a desire to scale the
|
|
// video stream down or up).
|
|
class QualityScaler {
|
|
public:
|
|
// Construct a QualityScaler with given |thresholds| and |handler|.
|
|
// This starts the quality scaler periodically checking what the average QP
|
|
// has been recently.
|
|
QualityScaler(QualityScalerQpUsageHandlerInterface* handler,
|
|
VideoEncoder::QpThresholds thresholds);
|
|
virtual ~QualityScaler();
|
|
// Should be called each time a frame is dropped at encoding.
|
|
void ReportDroppedFrameByMediaOpt();
|
|
void ReportDroppedFrameByEncoder();
|
|
// Inform the QualityScaler of the last seen QP.
|
|
void ReportQp(int qp, int64_t time_sent_us);
|
|
|
|
void SetQpThresholds(VideoEncoder::QpThresholds thresholds);
|
|
bool QpFastFilterLow() const;
|
|
|
|
// The following members declared protected for testing purposes.
|
|
protected:
|
|
QualityScaler(QualityScalerQpUsageHandlerInterface* handler,
|
|
VideoEncoder::QpThresholds thresholds,
|
|
int64_t sampling_period_ms);
|
|
|
|
private:
|
|
class QpSmoother;
|
|
class CheckQpTask;
|
|
class CheckQpTaskHandlerCallback;
|
|
|
|
enum class CheckQpResult {
|
|
kInsufficientSamples,
|
|
kNormalQp,
|
|
kHighQp,
|
|
kLowQp,
|
|
};
|
|
|
|
// Starts checking for QP in a delayed task. When the resulting CheckQpTask
|
|
// completes, it will invoke this method again, ensuring that we always
|
|
// periodically check for QP. See CheckQpTask for more details. We never run
|
|
// more than one CheckQpTask at a time.
|
|
void StartNextCheckQpTask();
|
|
|
|
CheckQpResult CheckQp() const;
|
|
void ClearSamples();
|
|
|
|
std::unique_ptr<CheckQpTask> pending_qp_task_ RTC_GUARDED_BY(&task_checker_);
|
|
QualityScalerQpUsageHandlerInterface* const handler_
|
|
RTC_GUARDED_BY(&task_checker_);
|
|
SequenceChecker task_checker_;
|
|
|
|
VideoEncoder::QpThresholds thresholds_ RTC_GUARDED_BY(&task_checker_);
|
|
const int64_t sampling_period_ms_;
|
|
bool fast_rampup_ RTC_GUARDED_BY(&task_checker_);
|
|
rtc::MovingAverage average_qp_ RTC_GUARDED_BY(&task_checker_);
|
|
rtc::MovingAverage framedrop_percent_media_opt_
|
|
RTC_GUARDED_BY(&task_checker_);
|
|
rtc::MovingAverage framedrop_percent_all_ RTC_GUARDED_BY(&task_checker_);
|
|
|
|
// Used by QualityScalingExperiment.
|
|
const bool experiment_enabled_;
|
|
QualityScalingExperiment::Config config_ RTC_GUARDED_BY(&task_checker_);
|
|
std::unique_ptr<QpSmoother> qp_smoother_high_ RTC_GUARDED_BY(&task_checker_);
|
|
std::unique_ptr<QpSmoother> qp_smoother_low_ RTC_GUARDED_BY(&task_checker_);
|
|
|
|
const size_t min_frames_needed_;
|
|
const double initial_scale_factor_;
|
|
const absl::optional<double> scale_factor_;
|
|
};
|
|
|
|
// Reacts to QP being too high or too low. For best quality, when QP is high it
|
|
// is desired to decrease the resolution or frame rate of the stream and when QP
|
|
// is low it is desired to increase the resolution or frame rate of the stream.
|
|
// Whether to reconfigure the stream is ultimately up to the handler, which is
|
|
// able to respond asynchronously.
|
|
class QualityScalerQpUsageHandlerInterface {
|
|
public:
|
|
virtual ~QualityScalerQpUsageHandlerInterface();
|
|
|
|
// Reacts to QP usage being too high or too low. The |callback| MUST be
|
|
// invoked when the handler is done, allowing the QualityScaler to resume
|
|
// checking for QP.
|
|
virtual void OnReportQpUsageHigh(
|
|
rtc::scoped_refptr<QualityScalerQpUsageHandlerCallbackInterface>
|
|
callback) = 0;
|
|
virtual void OnReportQpUsageLow(
|
|
rtc::scoped_refptr<QualityScalerQpUsageHandlerCallbackInterface>
|
|
callback) = 0;
|
|
};
|
|
|
|
// When QP is reported as high or low by the QualityScaler, it pauses checking
|
|
// for QP until the QP usage has been handled. When OnQpUsageHandled() is
|
|
// invoked, the QualityScaler resumes checking for QP. This ensures that if the
|
|
// stream is reconfigured in response to QP usage we do not include QP samples
|
|
// from before the reconfiguration the next time we check for QP.
|
|
//
|
|
// OnQpUsageHandled() MUST be invoked exactly once before this object is
|
|
// destroyed.
|
|
class QualityScalerQpUsageHandlerCallbackInterface
|
|
: public rtc::RefCountedObject<rtc::RefCountInterface> {
|
|
public:
|
|
virtual ~QualityScalerQpUsageHandlerCallbackInterface();
|
|
|
|
// If |clear_qp_samples| is true, existing QP samples are cleared before the
|
|
// next time QualityScaler checks for QP. This is usually a good idea when the
|
|
// stream is reconfigured. If |clear_qp_samples| is false, samples are not
|
|
// cleared and QualityScaler increases its frequency of checking for QP.
|
|
virtual void OnQpUsageHandled(bool clear_qp_samples) = 0;
|
|
|
|
protected:
|
|
QualityScalerQpUsageHandlerCallbackInterface();
|
|
};
|
|
|
|
} // namespace webrtc
|
|
|
|
#endif // MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
|