Skip to content

Instantly share code, notes, and snippets.

@quietvoid
Last active July 24, 2023 00:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save quietvoid/49d9dbca87ad373ad51516e306d5fa0d to your computer and use it in GitHub Desktop.
Save quietvoid/49d9dbca87ad373ad51516e306d5fa0d to your computer and use it in GitHub Desktop.
Enables x265 --scenecut-aware-qp for single pass, fixes float precision in settings string and allows offset to be set to 0
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 8695ad686..f3aaccd54 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1359,9 +1359,9 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
{
if (window1 > 0)
p->fwdScenecutWindow = window1;
- if (refQpDelta1 > 0)
+ if (refQpDelta1 >= 0)
p->fwdRefQpDelta = refQpDelta1;
- if (nonRefQpDelta1 > 0)
+ if (nonRefQpDelta1 >= 0)
p->fwdNonRefQpDelta = nonRefQpDelta1;
}
else
@@ -1376,9 +1376,9 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
{
if (window1 > 0)
p->bwdScenecutWindow = window1;
- if (refQpDelta1 > 0)
+ if (refQpDelta1 >= 0)
p->bwdRefQpDelta = refQpDelta1;
- if (nonRefQpDelta1 > 0)
+ if (nonRefQpDelta1 >= 0)
p->bwdNonRefQpDelta = nonRefQpDelta1;
}
else
@@ -1395,15 +1395,15 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
{
if (window1 > 0)
p->fwdScenecutWindow = window1;
- if (refQpDelta1 > 0)
+ if (refQpDelta1 >= 0)
p->fwdRefQpDelta = refQpDelta1;
- if (nonRefQpDelta1 > 0)
+ if (nonRefQpDelta1 >= 0)
p->fwdNonRefQpDelta = nonRefQpDelta1;
if (window2 > 0)
p->bwdScenecutWindow = window2;
- if (refQpDelta2 > 0)
+ if (refQpDelta2 >= 0)
p->bwdRefQpDelta = refQpDelta2;
- if (nonRefQpDelta2 > 0)
+ if (nonRefQpDelta2 >= 0)
p->bwdNonRefQpDelta = nonRefQpDelta2;
}
else
@@ -1845,10 +1845,10 @@ int x265_check_params(x265_param* param)
"Invalid SAO tune level. Value must be between 0 and 4 (inclusive)");
if (param->bEnableSceneCutAwareQp)
{
- if (!param->rc.bStatRead)
+ if (param->bEnableSceneCutAwareQp != FORWARD && !param->rc.bStatRead)
{
param->bEnableSceneCutAwareQp = 0;
- x265_log(param, X265_LOG_WARNING, "Disabling Scenecut Aware Frame Quantizer Selection since it works only in pass 2\n");
+ x265_log(param, X265_LOG_WARNING, "Disabling Scenecut Aware Frame Quantizer Selection since single pass only works with Forward masking\n");
}
else
{
@@ -2328,8 +2328,8 @@ char *x265_param2string(x265_param* p, int padx, int pady)
s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange);
s += sprintf(s, " scenecut-aware-qp=%d", p->bEnableSceneCutAwareQp);
if (p->bEnableSceneCutAwareQp)
- s += sprintf(s, " fwd-scenecut-window=%d fwd-ref-qp-delta=%f fwd-nonref-qp-delta=%f bwd-scenecut-window=%d bwd-ref-qp-delta=%f bwd-nonref-qp-delta=%f", p->fwdScenecutWindow, p->fwdRefQpDelta, p->fwdNonRefQpDelta, p->bwdScenecutWindow, p->bwdRefQpDelta, p->bwdNonRefQpDelta);
- s += sprintf(s, "conformance-window-offsets right=%d bottom=%d", p->confWinRightOffset, p->confWinBottomOffset);
+ s += sprintf(s, " fwd-scenecut-window=%d fwd-ref-qp-delta=%.2f fwd-nonref-qp-delta=%.2f bwd-scenecut-window=%d bwd-ref-qp-delta=%.2f bwd-nonref-qp-delta=%.2f", p->fwdScenecutWindow, p->fwdRefQpDelta, p->fwdNonRefQpDelta, p->bwdScenecutWindow, p->bwdRefQpDelta, p->bwdNonRefQpDelta);
+ s += sprintf(s, " conformance-window-offsets right=%d bottom=%d", p->confWinRightOffset, p->confWinBottomOffset);
s += sprintf(s, " decoder-max-rate=%d", p->decoderVbvMaxRate);
BOOL(p->bliveVBV2pass, "vbv-live-multi-pass");
#undef BOOL
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 4386334ad..d08984217 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -2242,17 +2242,27 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
frameEnc = m_lookahead->getDecidedPicture();
if (frameEnc && !pass && (!m_param->chunkEnd || (m_encodedFrameNum < m_param->chunkEnd)))
{
- if ((m_param->bEnableSceneCutAwareQp & FORWARD) && m_param->rc.bStatRead)
+ if (m_param->bEnableSceneCutAwareQp & FORWARD)
{
- RateControlEntry * rcEntry;
- rcEntry = &(m_rateControl->m_rce2Pass[frameEnc->m_poc]);
+ bool isSceneCut = frameEnc->m_lowres.bScenecut;
- if (rcEntry->scenecut)
+ // If multi pass, overwrite with stats file scenecut info
+ if (m_param->rc.bStatRead)
+ {
+ RateControlEntry * rcEntry;
+ rcEntry = &(m_rateControl->m_rce2Pass[frameEnc->m_poc]);
+
+ isSceneCut = rcEntry->scenecut;
+ }
+
+ if (isSceneCut)
{
+ // No previous scenecut
if (m_rateControl->m_lastScenecut == -1)
m_rateControl->m_lastScenecut = frameEnc->m_poc;
else
{
+ // Only set as scenecut if it's not within an existing scenecut forward window
int maxWindowSize = int((m_param->fwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);
if (frameEnc->m_poc > (m_rateControl->m_lastScenecut + maxWindowSize))
m_rateControl->m_lastScenecut = frameEnc->m_poc;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment