Skip to content

svt encoder: use fractional QP via "cqp" option with SVT-AV1 >= 4.2.0 - #1867

Closed
pszemus wants to merge 1 commit into
strukturag:masterfrom
pszemus:svt-av1-set-cq
Closed

pszemus wants to merge 1 commit into
strukturag:masterfrom
pszemus:svt-av1-set-cq

Conversation

@pszemus

@pszemus pszemus commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

When libheif is built against SVT-AV1 >= 4.2.0, the encoder QP is passed through svt_av1_enc_parse_parameter(&config, "cqp", ...) instead of assigning svt_config.qp directly. The "cqp" option (introduced in SVT-AV1 4.2.0):

  • accepts fractional QP values with quarter-QP precision
  • sets rate_control_mode = 0

The QP derived from the quality parameter is no longer rounded to an integer:
e.g. quality=50 now maps to CQP 31.50 instead of 32, so the 0–100 quality scale gets finer granularity. For SVT-AV1 < 4.2.0 the behavior is unchanged — the fractional value is rounded to the same integer the previous formula produced.

Testing

Built against SVT-AV1 v4.2.0:

  • heif-enc -A -q 50 → SVT log shows BRC mode / CQP Assignment: CQP / 31.50
  • heif-enc -A -p qp=40 → CQP / 40.00,
  • out-of-range QP values are rejected by SVT-AV1 at encoder initialization.

Possible follow-ups (separate PRs)

Things worth considering next, intentionally left out of this PR:

  • Use svt_av1_enc_parse_parameter() for setting the other encoder parameters as well — libheif would gain SVT-AV1's own validation of the values it sets.
  • Allow setting a fractional CQP directly from the CLI / encoder parameter API. This PR only enables the fractional quality → QP mapping; the qp parameter still accepts integers only.

The "cqp" option accepts fractional QP values (quarter-QP steps) and
switches rate control to constant-QP mode (aq-mode=0) instead of CRF.
QP computed from "quality" is no longer rounded to an integer.
Older SVT-AV1 versions keep the previous integer-QP behavior.
@pszemus

pszemus commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Hello @farindk
What do you think about this change?

@farindk

farindk commented Sep 1, 2026 •

Copy link
Copy Markdown
Member

AV1 uses an 8-bit quantizer index. Moving from a 0-63 scale to fractional gives 4x the resolution. Not sure whether that is noticeable, but it doesn't hurt either.

Setting this value through a parameter string is unnecessary (and dangerous because of potentially different locales). You can also set it through extended_crf_qindex_offset (0-3, fractional part). This should even work with SVT-AV1 4.0.0.

Also make sure that you do not switch the rate-control mode from CRF to CQP as your original PR does.

farindk added a commit that referenced this pull request Sep 1, 2026
…meter string (#1867)

Setting the QP through svt_av1_enc_parse_parameter("cqp", ...) has two
problems: the string round-trip through snprintf/strtod depends on the
process locale (LC_NUMERIC), and the "cqp" option also sets aq_mode=0,
silently switching the rate control from CRF to plain CQP. For still
images this makes no difference because TPL is disabled for all-intra
encoding anyway, but for image sequences it would disable TPL and
reduce quality.

Instead, write the quarter-QP fraction directly into the public
'extended_crf_qindex_offset' configuration field, which exists since
SVT-AV1 4.0.0. This also lowers the version requirement for fractional
QP from 4.2.0 to 4.0.0.
@farindk

farindk commented Sep 1, 2026

Copy link
Copy Markdown
Member

I've merged it and implemented the proposed changes on top of it.
4d638f1 + 32e3afc

Thanks for the PR.

@farindk farindk closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants