From: Arun Iyengar <aiyengar1990@gmail.com>
To: Mauro Carvalho Chehab <mchehab@kernel.org>,
Paul Kocialkowski <paulk@sys-base.io>
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
Nicolas Dufresne <nicolas.dufresne@collabora.com>,
Hans Verkuil <hverkuil@kernel.org>,
Marco Felsch <m.felsch@pengutronix.de>,
Michael Tretter <m.tretter@pengutronix.de>,
Arun Iyengar <aiyengar1990@gmail.com>
Subject: [PATCH RFC 07/11] media: v4l2-core: Halve the I picture QP increase of the encode CBR
Date: Tue, 10 Nov 2026 10:05:21 +0000 [thread overview]
Message-ID: <20261110-h264-encode-fixes-v1-7-7a64486df499@gmail.com> (raw)
In-Reply-To: <20261110-h264-encode-fixes-v1-0-7a64486df499@gmail.com>
After an I picture above its share of the GOP at the largest I/P size
ratio, the constant bitrate rate control raises the QP of the following
I pictures. It adds the increase to the mean of the QP state now and at
the previous I picture, so all of it reaches the next I picture, and it
limits the increase by the QP of the I picture, four steps below the
state.
The Rockchip MPP library, whose behaviour this follows, adds the increase
to the current state before the mean, so that half of it reaches the I
picture, and limits it by the QP state. Do the same: an I picture that
came out large because of a passing scene is not penalised twice.
Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
drivers/media/v4l2-core/v4l2-enc-cbr.c | 36 ++++++++++++++++++----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-enc-cbr.c b/drivers/media/v4l2-core/v4l2-enc-cbr.c
index 32f98052e981..70810b3fea23 100644
--- a/drivers/media/v4l2-core/v4l2-enc-cbr.c
+++ b/drivers/media/v4l2-core/v4l2-enc-cbr.c
@@ -47,8 +47,10 @@
/*
* The I QP increase after oversized I pictures: at most 4 QP (1/256 units)
* per I picture for an I picture twice its largest share, and in all at most
- * a quarter QP per QP step below 45, up to 6 QP (more where the QP is low,
- * where a QP step changes the size by fewer bits).
+ * a quarter QP per step of the QP state below 45, up to 6 QP (more where the
+ * QP is low, where a QP step changes the size by fewer bits). It raises the
+ * current state in the mean of cbr_qp_intra(), so half of it reaches the I
+ * pictures.
*/
#define CBR_INTRA_ADD_STEP (4 * 256)
#define CBR_INTRA_ADD_QP_END 45
@@ -126,25 +128,25 @@ static u64 cbr_plan(const struct v4l2_enc_cbr *cbr, unsigned int fps,
}
/*
- * QP of an I picture: the mean of the QP state now and at the previous I
- * picture (the current state weighs 70% when it rose from 33 or below to 35
- * or above: content that got much harder), plus the increase after
- * oversized I pictures, less the I QP delta. All-intra streams use the
- * state alone, which then follows the I pictures fully.
+ * QP of an I picture: the mean of the QP state now, raised by the increase
+ * after oversized I pictures, and the state at the previous I picture (the
+ * current state weighs 70% when it rose from 33 or below to 35 or above:
+ * content that got much harder), less the I QP delta. All-intra streams use
+ * the state alone, which then follows the I pictures fully.
*/
static int cbr_qp_intra(const struct v4l2_enc_cbr *cbr)
{
int cur = cbr->qp_q8, ref = cbr->qp_intra_ref_q8, q8;
- if (cbr->gop == 1 || ref < 0)
+ if (cbr->gop == 1 || ref < 0) {
q8 = cur;
- else if (cur >= 35 * 256 && ref <= 33 * 256)
- q8 = (3 * ref + 7 * cur) / 10;
- else
- q8 = (ref + cur) / 2;
-
- if (cbr->gop != 1)
- q8 += cbr->qp_intra_add_q8;
+ } else {
+ cur += cbr->qp_intra_add_q8;
+ if (cur >= 35 * 256 && ref <= 33 * 256)
+ q8 = (3 * ref + 7 * cur) / 10;
+ else
+ q8 = (ref + cur) / 2;
+ }
return DIV_ROUND_CLOSEST(q8, 256) - cbr->qp_delta_intra;
}
@@ -350,8 +352,8 @@ void v4l2_enc_cbr_end(struct v4l2_enc_cbr *cbr, u64 bits,
cbr->qp_intra_add_q8;
cbr->qp_intra_add_q8 =
clamp_t(s64, add, 0,
- clamp((CBR_INTRA_ADD_QP_END -
- cbr->qp_pic) * 64, 0,
+ clamp(CBR_INTRA_ADD_QP_END * 64 -
+ cbr->qp_q8 / 4, 0,
CBR_INTRA_ADD_MAX));
}
--
2.55.0
WARNING: multiple messages have this Message-ID (diff)
From: Arun Iyengar via B4 Relay <devnull+aiyengar1990.gmail.com@kernel.org>
To: Mauro Carvalho Chehab <mchehab@kernel.org>,
Paul Kocialkowski <paulk@sys-base.io>
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
Nicolas Dufresne <nicolas.dufresne@collabora.com>,
Hans Verkuil <hverkuil@kernel.org>,
Marco Felsch <m.felsch@pengutronix.de>,
Michael Tretter <m.tretter@pengutronix.de>,
Arun Iyengar <aiyengar1990@gmail.com>
Subject: [PATCH RFC 07/11] media: v4l2-core: Halve the I picture QP increase of the encode CBR
Date: Tue, 10 Nov 2026 10:05:21 +0000 [thread overview]
Message-ID: <20261110-h264-encode-fixes-v1-7-7a64486df499@gmail.com> (raw)
In-Reply-To: <20261110-h264-encode-fixes-v1-0-7a64486df499@gmail.com>
From: Arun Iyengar <aiyengar1990@gmail.com>
After an I picture above its share of the GOP at the largest I/P size
ratio, the constant bitrate rate control raises the QP of the following
I pictures. It adds the increase to the mean of the QP state now and at
the previous I picture, so all of it reaches the next I picture, and it
limits the increase by the QP of the I picture, four steps below the
state.
The Rockchip MPP library, whose behaviour this follows, adds the increase
to the current state before the mean, so that half of it reaches the I
picture, and limits it by the QP state. Do the same: an I picture that
came out large because of a passing scene is not penalised twice.
Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
drivers/media/v4l2-core/v4l2-enc-cbr.c | 36 ++++++++++++++++++----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-enc-cbr.c b/drivers/media/v4l2-core/v4l2-enc-cbr.c
index 32f98052e981..70810b3fea23 100644
--- a/drivers/media/v4l2-core/v4l2-enc-cbr.c
+++ b/drivers/media/v4l2-core/v4l2-enc-cbr.c
@@ -47,8 +47,10 @@
/*
* The I QP increase after oversized I pictures: at most 4 QP (1/256 units)
* per I picture for an I picture twice its largest share, and in all at most
- * a quarter QP per QP step below 45, up to 6 QP (more where the QP is low,
- * where a QP step changes the size by fewer bits).
+ * a quarter QP per step of the QP state below 45, up to 6 QP (more where the
+ * QP is low, where a QP step changes the size by fewer bits). It raises the
+ * current state in the mean of cbr_qp_intra(), so half of it reaches the I
+ * pictures.
*/
#define CBR_INTRA_ADD_STEP (4 * 256)
#define CBR_INTRA_ADD_QP_END 45
@@ -126,25 +128,25 @@ static u64 cbr_plan(const struct v4l2_enc_cbr *cbr, unsigned int fps,
}
/*
- * QP of an I picture: the mean of the QP state now and at the previous I
- * picture (the current state weighs 70% when it rose from 33 or below to 35
- * or above: content that got much harder), plus the increase after
- * oversized I pictures, less the I QP delta. All-intra streams use the
- * state alone, which then follows the I pictures fully.
+ * QP of an I picture: the mean of the QP state now, raised by the increase
+ * after oversized I pictures, and the state at the previous I picture (the
+ * current state weighs 70% when it rose from 33 or below to 35 or above:
+ * content that got much harder), less the I QP delta. All-intra streams use
+ * the state alone, which then follows the I pictures fully.
*/
static int cbr_qp_intra(const struct v4l2_enc_cbr *cbr)
{
int cur = cbr->qp_q8, ref = cbr->qp_intra_ref_q8, q8;
- if (cbr->gop == 1 || ref < 0)
+ if (cbr->gop == 1 || ref < 0) {
q8 = cur;
- else if (cur >= 35 * 256 && ref <= 33 * 256)
- q8 = (3 * ref + 7 * cur) / 10;
- else
- q8 = (ref + cur) / 2;
-
- if (cbr->gop != 1)
- q8 += cbr->qp_intra_add_q8;
+ } else {
+ cur += cbr->qp_intra_add_q8;
+ if (cur >= 35 * 256 && ref <= 33 * 256)
+ q8 = (3 * ref + 7 * cur) / 10;
+ else
+ q8 = (ref + cur) / 2;
+ }
return DIV_ROUND_CLOSEST(q8, 256) - cbr->qp_delta_intra;
}
@@ -350,8 +352,8 @@ void v4l2_enc_cbr_end(struct v4l2_enc_cbr *cbr, u64 bits,
cbr->qp_intra_add_q8;
cbr->qp_intra_add_q8 =
clamp_t(s64, add, 0,
- clamp((CBR_INTRA_ADD_QP_END -
- cbr->qp_pic) * 64, 0,
+ clamp(CBR_INTRA_ADD_QP_END * 64 -
+ cbr->qp_q8 / 4, 0,
CBR_INTRA_ADD_MAX));
}
--
2.55.0
next prev parent reply other threads:[~2026-11-10 10:05 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 10:05 [PATCH RFC 00/11] media: h264: Stateless encode core follow-ups: parameter sets, POC type 2, CBR and VBR Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 01/11] media: h264: Only write the SPS and PPS of a stateless encode when they change Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 02/11] media: h264: Support picture order count type 2 in stateless encode Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 03/11] media: h264: Write the stateless encode SPS and PPS with nal_ref_idc 3 Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 04/11] media: v4l2-h264-enc-rc: Rework the constant bitrate mode Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 05/11] media: v4l2-core: Move the H.264 encode CBR rate control to a helper Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 06/11] media: v4l2-core: Bound the I picture size in the encode CBR rate control Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` Arun Iyengar [this message]
2026-11-10 10:05 ` [PATCH RFC 07/11] media: v4l2-core: Halve the I picture QP increase of the encode CBR Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 08/11] media: v4l2-core: Re-encode oversized pictures in " Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 09/11] media: v4l2-core: Fix all-intra streams in the encode CBR rate control Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 10/11] media: v4l2-core: Add a peak bitrate to the encode " Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-10 10:05 ` [PATCH RFC 11/11] media: h264: Add a VBR mode to the stateless " Arun Iyengar
2026-11-10 10:05 ` Arun Iyengar via B4 Relay
2026-11-11 1:20 ` [PATCH RFC 00/11] media: h264: Stateless encode core follow-ups: parameter sets, POC type 2, CBR and VBR Nicolas Dufresne
2026-11-12 16:20 ` Paul Kocialkowski
2026-11-13 8:47 ` Arun Iyengar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110-h264-encode-fixes-v1-7-7a64486df499@gmail.com \
--to=aiyengar1990@gmail.com \
--cc=hverkuil@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=m.felsch@pengutronix.de \
--cc=m.tretter@pengutronix.de \
--cc=mchehab@kernel.org \
--cc=nicolas.dufresne@collabora.com \
--cc=paulk@sys-base.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.