From 9d756a1117005c064862d53134bfc6d78663c5b4 Mon Sep 17 00:00:00 2001
From: Marco Paniconi <[EMAIL REDACTED]>
Date: Tue, 6 Aug 2024 11:09:49 -0700
Subject: [PATCH] rtc: Convert the max_consec_drop to time units
This is a more natural unit to use for rtc applications.
At the start of av1_get_one_pass_rt_params() the time units
is converted to frame number (via framerate), which is the
unit used internally in the frame dropper.
Change-Id: I27f5573e6bcb3831f9159798919eab3cc9ab6991
---
aom/aomcx.h | 16 +++++++++++++---
av1/av1_cx_iface.c | 16 ++++++++++++++++
av1/encoder/encoder.h | 7 +++++++
av1/encoder/ratectrl.c | 5 +++++
av1/ratectrl_rtc.cc | 14 +++++++++++---
av1/ratectrl_rtc.h | 2 +-
examples/svc_encoder_rtc.cc | 2 +-
test/ratectrl_rtc_test.cc | 11 ++++++-----
8 files changed, 60 insertions(+), 13 deletions(-)
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 3f3eb643aa..3cf3991213 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -1527,9 +1527,10 @@ enum aome_enc_control_id {
*/
AV1E_SET_BITRATE_ONE_PASS_CBR = 163,
- /*!\brief Codec control to set the maximum number of consecutive frame drops
- * allowed for the frame dropper in 1 pass CBR mode, int parameter. Value of
- * zero has no effect.
+ /*!\brief Codec control to set the maximum number of consecutive frame drops,
+ * in units of frames, allowed for the frame dropper in 1 pass
+ * CBR mode, int parameter. Value of zero has no effect.
+ * Deprecated: use the new control AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR.
*/
AV1E_SET_MAX_CONSEC_FRAME_DROP_CBR = 164,
@@ -1563,6 +1564,12 @@ enum aome_enc_control_id {
*/
AV1E_SET_POSTENCODE_DROP_RTC = 168,
+ /*!\brief Codec control to set the maximum number of consecutive frame drops,
+ * in units of time (milliseconds), allowed for the frame dropper in 1 pass
+ * CBR mode, int parameter. Value of zero has no effect.
+ */
+ AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR = 169,
+
// Any new encoder control IDs should be added above.
// Maximum allowed encoder control ID is 229.
// No encoder control ID should be added below.
@@ -2229,6 +2236,9 @@ AOM_CTRL_USE_TYPE(AV1E_GET_HIGH_MOTION_CONTENT_SCREEN_RTC, int *)
AOM_CTRL_USE_TYPE(AV1E_SET_POSTENCODE_DROP_RTC, int)
#define AOM_CTRL_AV1E_SET_POSTENCODE_DROP_RTC
+AOM_CTRL_USE_TYPE(AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR, int)
+#define AOM_CTRL_AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR
+
/*!\endcond */
/*! @} - end defgroup aom_encoder */
#ifdef __cplusplus
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 92cd7f40da..ce6bbe9618 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -2680,6 +2680,20 @@ static aom_codec_err_t ctrl_set_max_consec_frame_drop_cbr(
return AOM_CODEC_OK;
}
+static aom_codec_err_t ctrl_set_max_consec_frame_drop_ms_cbr(
+ aom_codec_alg_priv_t *ctx, va_list args) {
+ AV1_PRIMARY *const ppi = ctx->ppi;
+ AV1_COMP *const cpi = ppi->cpi;
+ const int max_consec_drop_ms =
+ CAST(AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR, args);
+ if (max_consec_drop_ms < 0) return AOM_CODEC_INVALID_PARAM;
+ // max_consec_drop_ms will be converted to frame units inside encoder
+ // based on framerate (which can change dynamically).
+ ctx->oxcf.rc_cfg.max_consec_drop_ms = max_consec_drop_ms;
+ cpi->rc.drop_count_consec = 0;
+ return AOM_CODEC_OK;
+}
+
static aom_codec_err_t ctrl_set_svc_frame_drop_mode(aom_codec_alg_priv_t *ctx,
va_list args) {
AV1_PRIMARY *const ppi = ctx->ppi;
@@ -4610,6 +4624,8 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ AV1E_SET_SVC_FRAME_DROP_MODE, ctrl_set_svc_frame_drop_mode },
{ AV1E_SET_AUTO_TILES, ctrl_set_auto_tiles },
{ AV1E_SET_POSTENCODE_DROP_RTC, ctrl_set_postencode_drop_rtc },
+ { AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR,
+ ctrl_set_max_consec_frame_drop_ms_cbr },
// Getters
{ AOME_GET_LAST_QUANTIZER, ctrl_get_quantizer },
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 8b3ddb5776..e071b0496b 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -620,6 +620,13 @@ typedef struct {
* of the target bitrate.
*/
int vbrmax_section;
+
+ /*!
+ * Indicates the maximum consecutive amount of frame drops, in units of time
+ * (milliseconds). This is converted to frame units internally. Only used in
+ * CBR mode.
+ */
+ int max_consec_drop_ms;
} RateControlCfg;
/*!\cond */
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index ea402201f1..320d984832 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -3679,6 +3679,11 @@ void av1_get_one_pass_rt_params(AV1_COMP *cpi, FRAME_TYPE *const frame_type,
const int layer =
LAYER_IDS_TO_IDX(svc->spatial_layer_id, svc->temporal_layer_id,
svc->number_temporal_layers);
+ if (cpi->oxcf.rc_cfg.max_consec_drop_ms > 0) {
+ rc->max_consec_drop = (int)AOMMIN(
+ ceil(cpi->oxcf.rc_cfg.max_consec_drop_ms * cpi->framerate / 1000),
+ INT_MAX);
+ }
if (cpi->ppi->use_svc) {
av1_update_temporal_layer_framerate(cpi);
av1_restore_layer_context(cpi);
diff --git a/av1/ratectrl_rtc.cc b/av1/ratectrl_rtc.cc
index 7f1640a77c..e0d896c81b 100644
--- a/av1/ratectrl_rtc.cc
+++ b/av1/ratectrl_rtc.cc
@@ -11,12 +11,14 @@
#include "av1/ratectrl_rtc.h"
+#include <climits>
#include <memory>
#include <new>
#include "aom/aomcx.h"
#include "aom/aom_encoder.h"
#include "aom_mem/aom_mem.h"
+#include "aom_dsp/aom_dsp_common.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/encoder_utils.h"
#include "av1/encoder/pickcdef.h"
@@ -40,7 +42,7 @@ AV1RateControlRtcConfig::AV1RateControlRtcConfig() {
max_intra_bitrate_pct = 50;
max_inter_bitrate_pct = 0;
frame_drop_thresh = 0;
- max_consec_drop = 0;
+ max_consec_drop_ms = 0;
framerate = 30.0;
ss_number_layers = 1;
ts_number_layers = 1;
@@ -127,7 +129,10 @@ bool AV1RateControlRTC::InitRateControl(const AV1RateControlRtcConfig &rc_cfg) {
oxcf->q_cfg.aq_mode = rc_cfg.aq_mode ? CYCLIC_REFRESH_AQ : NO_AQ;
oxcf->tune_cfg.content = AOM_CONTENT_DEFAULT;
oxcf->rc_cfg.drop_frames_water_mark = rc_cfg.frame_drop_thresh;
- rc->max_consec_drop = rc_cfg.max_consec_drop;
+ if (rc_cfg.max_consec_drop_ms > 0) {
+ rc->max_consec_drop = (int)AOMMIN(
+ ceil(cpi_->framerate * rc_cfg.max_consec_drop_ms / 1000), INT_MAX);
+ }
cpi_->svc.framedrop_mode = AOM_FULL_SUPERFRAME_DROP;
oxcf->tool_cfg.bit_depth = AOM_BITS_8;
oxcf->tool_cfg.superblock_size = AOM_SUPERBLOCK_SIZE_DYNAMIC;
@@ -190,7 +195,10 @@ bool AV1RateControlRTC::UpdateRateControl(
oxcf->rc_cfg.under_shoot_pct = rc_cfg.undershoot_pct;
oxcf->rc_cfg.over_shoot_pct = rc_cfg.overshoot_pct;
oxcf->rc_cfg.drop_frames_water_mark = rc_cfg.frame_drop_thresh;
- rc->max_consec_drop = rc_cfg.max_consec_drop;
+ if (rc_cfg.max_consec_drop_ms > 0) {
+ rc->max_consec_drop = (int)AOMMIN(
+ ceil(cpi_->framerate * rc_cfg.max_consec_drop_ms / 1000), INT_MAX);
+ }
oxcf->rc_cfg.max_intra_bitrate_pct = rc_cfg.max_intra_bitrate_pct;
oxcf->rc_cfg.max_inter_bitrate_pct = rc_cfg.max_inter_bitrate_pct;
cpi_->framerate = rc_cfg.framerate;
diff --git a/av1/ratectrl_rtc.h b/av1/ratectrl_rtc.h
index a4b33039cd..e4da5d3b35 100644
--- a/av1/ratectrl_rtc.h
+++ b/av1/ratectrl_rtc.h
@@ -46,7 +46,7 @@ struct AV1RateControlRtcConfig {
int max_intra_bitrate_pct;
int max_inter_bitrate_pct;
int frame_drop_thresh;
- int max_consec_drop;
+ int max_consec_drop_ms;
double framerate;
int layer_target_bitrate[kAV1MaxLayers];
int ts_rate_decimator[kAV1MaxTemporalLayers];
diff --git a/examples/svc_encoder_rtc.cc b/examples/svc_encoder_rtc.cc
index d034b1806b..4fb160e6e0 100644
--- a/examples/svc_encoder_rtc.cc
+++ b/examples/svc_encoder_rtc.cc
@@ -1703,7 +1703,7 @@ int main(int argc, const char **argv) {
aom_codec_control(&codec, AV1E_SET_RTC_EXTERNAL_RC, 1);
}
- aom_codec_control(&codec, AV1E_SET_MAX_CONSEC_FRAME_DROP_CBR, INT_MAX);
+ aom_codec_control(&codec, AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR, INT_MAX);
aom_codec_control(&codec, AV1E_SET_SVC_FRAME_DROP_MODE,
AOM_FULL_SUPERFRAME_DROP);
diff --git a/test/ratectrl_rtc_test.cc b/test/ratectrl_rtc_test.cc
index 31ae4509a4..20c4fbb178 100644
--- a/test/ratectrl_rtc_test.cc
+++ b/test/ratectrl_rtc_test.cc
@@ -37,7 +37,7 @@ class RcInterfaceTest : public ::libaom_test::EncoderTest,
: EncoderTest(GET_PARAM(0)), aq_mode_(GET_PARAM(1)), key_interval_(3000),
encoder_exit_(false), layer_frame_cnt_(0), superframe_cnt_(0),
frame_cnt_(0), dynamic_temporal_layers_(false),
- dynamic_spatial_layers_(false), num_drops_(0), max_consec_drop_(0),
+ dynamic_spatial_layers_(false), num_drops_(0), max_consec_drop_ms_(0),
frame_drop_thresh_(0) {
memset(&svc_params_, 0, sizeof(svc_params_));
memset(&layer_id_, 0, sizeof(layer_id_));
@@ -67,7 +67,8 @@ class RcInterfaceTest : public ::libaom_test::EncoderTest,
encoder->Control(AOME_SET_MAX_INTRA_BITRATE_PCT,
rc_cfg_.max_intra_bitrate_pct);
if (use_svc) encoder->Control(AV1E_SET_SVC_PARAMS, &svc_params_);
- encoder->Control(AV1E_SET_MAX_CONSEC_FRAME_DROP_CBR, max_consec_drop_);
+ encoder->Control(AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR,
+ max_consec_drop_ms_);
}
// SVC specific settings
if (use_svc) {
@@ -210,7 +211,7 @@ class RcInterfaceTest : public ::libaom_test::EncoderTest,
void RunOneLayerDropFramesCBR() {
key_interval_ = 10000;
- max_consec_drop_ = 8;
+ max_consec_drop_ms_ = 250;
frame_drop_thresh_ = 30;
SetConfig();
rc_cfg_.target_bandwidth = 100;
@@ -319,7 +320,7 @@ class RcInterfaceTest : public ::libaom_test::EncoderTest,
rc_cfg_.min_quantizers[0] = 2;
rc_cfg_.aq_mode = aq_mode_;
rc_cfg_.frame_drop_thresh = frame_drop_thresh_;
- rc_cfg_.max_consec_drop = max_consec_drop_;
+ rc_cfg_.max_consec_drop_ms = max_consec_drop_ms_;
// Encoder settings for ground truth.
cfg_.g_w = 640;
@@ -480,7 +481,7 @@ class RcInterfaceTest : public ::libaom_test::EncoderTest,
bool dynamic_temporal_layers_;
bool dynamic_spatial_layers_;
int num_drops_;
- int max_consec_drop_;
+ int max_consec_drop_ms_;
int frame_drop_thresh_;
};