Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save al3xtjames/6c50b26615d12a6440441bdfd17c4bba to your computer and use it in GitHub Desktop.
Save al3xtjames/6c50b26615d12a6440441bdfd17c4bba 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 1a4df4cdc..e1505b29e 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1832,10 +1832,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
{
@@ -2327,8 +2327,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->fwdMaxScenecutWindow, p->fwdRefQpDelta[0], p->fwdNonRefQpDelta[0], p->bwdMaxScenecutWindow, p->bwdRefQpDelta[0], p->bwdNonRefQpDelta[0]);
- 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[0], p->fwdNonRefQpDelta[0], p->bwdScenecutWindow, p->bwdRefQpDelta[0], p->bwdNonRefQpDelta[0]);
+ 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");
if (p->filmGrain)
@@ -2420,9 +2420,9 @@ bool parseMaskingStrength(x265_param* p, const char* value)
{
if (window1[0] > 0)
p->fwdMaxScenecutWindow = window1[0];
- if (refQpDelta1[0] > 0)
+ if (refQpDelta1[0] >= 0)
p->fwdRefQpDelta[0] = refQpDelta1[0];
- if (nonRefQpDelta1[0] > 0)
+ if (nonRefQpDelta1[0] >= 0)
p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];
p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;
@@ -2459,9 +2459,9 @@ bool parseMaskingStrength(x265_param* p, const char* value)
{
if (window1[0] > 0)
p->bwdMaxScenecutWindow = window1[0];
- if (refQpDelta1[0] > 0)
+ if (refQpDelta1[0] >= 0)
p->bwdRefQpDelta[0] = refQpDelta1[0];
- if (nonRefQpDelta1[0] > 0)
+ if (nonRefQpDelta1[0] >= 0)
p->bwdNonRefQpDelta[0] = nonRefQpDelta1[0];
p->bwdScenecutWindow[0] = p->bwdMaxScenecutWindow / 6;
@@ -2500,15 +2500,15 @@ bool parseMaskingStrength(x265_param* p, const char* value)
{
if (window1[0] > 0)
p->fwdMaxScenecutWindow = window1[0];
- if (refQpDelta1[0] > 0)
+ if (refQpDelta1[0] >= 0)
p->fwdRefQpDelta[0] = refQpDelta1[0];
- if (nonRefQpDelta1[0] > 0)
+ if (nonRefQpDelta1[0] >= 0)
p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];
if (window2[0] > 0)
p->bwdMaxScenecutWindow = window2[0];
- if (refQpDelta2[0] > 0)
+ if (refQpDelta2[0] >= 0)
p->bwdRefQpDelta[0] = refQpDelta2[0];
- if (nonRefQpDelta2[0] > 0)
+ if (nonRefQpDelta2[0] >= 0)
p->bwdNonRefQpDelta[0] = nonRefQpDelta2[0];
p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index c2dd6f4e8..9d9ce12fc 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -2129,17 +2129,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->fwdMaxScenecutWindow / 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