From a790302dbddb89111da651374a5d45b28ca0b6d9 Mon Sep 17 00:00:00 2001 From: Gale Date: Thu, 13 Jul 2023 16:17:10 -0700 Subject: [PATCH] obs-qsv11: Refactor and tune Look-ahead settings Enable Low Power Look-ahead (VDENC LA) after Intel Arc Graphics. Change LA_DEPTH defaults (60 frames for normal latency and 30 frames for low latency). Keep VME Look-ahead only for certain Intel platforms (ICL, TGL, ADL, and RPL). Disable VME LA for HEVC --- plugins/obs-qsv11/QSV_Encoder_Internal.cpp | 110 +++++++++++---------- plugins/obs-qsv11/obs-qsv11.c | 69 ++++++------- 2 files changed, 90 insertions(+), 89 deletions(-) diff --git a/plugins/obs-qsv11/QSV_Encoder_Internal.cpp b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp index 6c948474a..f7663308e 100644 --- a/plugins/obs-qsv11/QSV_Encoder_Internal.cpp +++ b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp @@ -258,22 +258,18 @@ mfxStatus QSV_Encoder_Internal::InitParams(qsv_param_t *pParams, m_mfxEncParams.mfx.FrameInfo.CropH = pParams->nHeight; m_mfxEncParams.mfx.GopRefDist = pParams->nbFrames + 1; - if (codec == QSV_CODEC_HEVC) - m_mfxEncParams.mfx.LowPower = MFX_CODINGOPTION_OFF; - + mfxPlatform platform; + MFXVideoCORE_QueryPlatform(m_session, &platform); #if defined(_WIN32) - // TODO: Why isn't LowPower coding supported on VAAPI backend. - enum qsv_cpu_platform qsv_platform = qsv_get_cpu_platform(); - if ((m_isDGPU || qsv_platform >= QSV_CPU_PLATFORM_ICL || - qsv_platform == QSV_CPU_PLATFORM_UNKNOWN) && - (pParams->nbFrames == 0) && - (m_ver.Major == 1 && m_ver.Minor >= 31)) { + PRAGMA_WARN_PUSH + PRAGMA_WARN_DEPRECATION + if (codec == QSV_CODEC_AVC || codec == QSV_CODEC_HEVC) { + if (platform.CodeName >= MFX_PLATFORM_DG2) + m_mfxEncParams.mfx.LowPower = MFX_CODINGOPTION_ON; + } else if (codec == QSV_CODEC_AV1) { m_mfxEncParams.mfx.LowPower = MFX_CODINGOPTION_ON; - if (pParams->nRateControl == MFX_RATECONTROL_LA_ICQ || - pParams->nRateControl == MFX_RATECONTROL_LA_HRD || - pParams->nRateControl == MFX_RATECONTROL_LA) - pParams->nRateControl = MFX_RATECONTROL_VBR; } + PRAGMA_WARN_POP #endif m_mfxEncParams.mfx.RateControlMethod = pParams->nRateControl; @@ -307,16 +303,6 @@ mfxStatus QSV_Encoder_Internal::InitParams(qsv_param_t *pParams, case MFX_RATECONTROL_ICQ: m_mfxEncParams.mfx.ICQQuality = pParams->nICQQuality; break; - case MFX_RATECONTROL_LA: - m_mfxEncParams.mfx.TargetKbps = pParams->nTargetBitRate; - break; - case MFX_RATECONTROL_LA_ICQ: - m_mfxEncParams.mfx.ICQQuality = pParams->nICQQuality; - break; - case MFX_RATECONTROL_LA_HRD: - m_mfxEncParams.mfx.TargetKbps = pParams->nTargetBitRate; - m_mfxEncParams.mfx.MaxKbps = pParams->nTargetBitRate; - break; default: break; } @@ -328,37 +314,59 @@ mfxStatus QSV_Encoder_Internal::InitParams(qsv_param_t *pParams, (float)pParams->nFpsDen) : 240; - if (m_ver.Major == 1 && m_ver.Minor >= 8) { - memset(&m_co2, 0, sizeof(mfxExtCodingOption2)); - m_co2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; - m_co2.Header.BufferSz = sizeof(m_co2); - if (codec != QSV_CODEC_AVC) - m_co2.RepeatPPS = MFX_CODINGOPTION_ON; - if (pParams->nRateControl == MFX_RATECONTROL_LA_ICQ || - pParams->nRateControl == MFX_RATECONTROL_LA) - m_co2.LookAheadDepth = pParams->nLADEPTH; - if (pParams->nbFrames > 1) - m_co2.BRefType = MFX_B_REF_PYRAMID; - if (m_mfxEncParams.mfx.LowPower == MFX_CODINGOPTION_ON) { - if (codec == QSV_CODEC_AVC) - m_co2.RepeatPPS = MFX_CODINGOPTION_OFF; - if (pParams->nRateControl == MFX_RATECONTROL_CBR || - pParams->nRateControl == MFX_RATECONTROL_VBR) { - m_co2.LookAheadDepth = pParams->nLADEPTH; - } + memset(&m_co2, 0, sizeof(mfxExtCodingOption2)); + m_co2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; + m_co2.Header.BufferSz = sizeof(m_co2); + m_co2.RepeatPPS = MFX_CODINGOPTION_OFF; + + memset(&m_co3, 0, sizeof(mfxExtCodingOption3)); + m_co3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; + m_co3.Header.BufferSz = sizeof(m_co3); + + if (codec != QSV_CODEC_AVC) + m_co2.RepeatPPS = MFX_CODINGOPTION_ON; + if (pParams->nbFrames > 1) + m_co2.BRefType = MFX_B_REF_PYRAMID; + + PRAGMA_WARN_PUSH + PRAGMA_WARN_DEPRECATION + // LA VME/ENC case for older platforms + if (pParams->nLADEPTH && codec == QSV_CODEC_AVC && + m_mfxEncParams.mfx.LowPower != MFX_CODINGOPTION_ON && + platform.CodeName >= MFX_PLATFORM_ICELAKE) { + if (pParams->nRateControl == MFX_RATECONTROL_CBR) { + pParams->nRateControl = MFX_RATECONTROL_LA_HRD; + } else if (pParams->nRateControl == MFX_RATECONTROL_VBR) { + pParams->nRateControl = MFX_RATECONTROL_LA; + } else if (pParams->nRateControl == MFX_RATECONTROL_ICQ) { + pParams->nRateControl = MFX_RATECONTROL_LA_ICQ; + } + m_co2.LookAheadDepth = pParams->nLADEPTH; + } + PRAGMA_WARN_POP + + // LA VDENC case for newer platform, works only under CBR / VBR + if (pParams->nRateControl == MFX_RATECONTROL_CBR || + pParams->nRateControl == MFX_RATECONTROL_VBR) { + if (pParams->nLADEPTH && + m_mfxEncParams.mfx.LowPower == MFX_CODINGOPTION_ON) { + m_co2.LookAheadDepth = pParams->nLADEPTH; + m_co3.ScenarioInfo = MFX_SCENARIO_GAME_STREAMING; + } + // CQM to follow UI setting + if (pParams->bCQM) { + m_co3.AdaptiveCQM = MFX_CODINGOPTION_ON; + if (m_co3.ScenarioInfo != MFX_SCENARIO_GAME_STREAMING) { + m_co3.ScenarioInfo = + MFX_SCENARIO_GAME_STREAMING; + } + } else { + m_co3.AdaptiveCQM = MFX_CODINGOPTION_OFF; } - extendedBuffers.push_back((mfxExtBuffer *)&m_co2); } - if ((m_mfxEncParams.mfx.LowPower == MFX_CODINGOPTION_ON) || - (pParams->bCQM && m_ver.Major == 1 && m_ver.Minor >= 16)) { - memset(&m_co3, 0, sizeof(mfxExtCodingOption3)); - m_co3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; - m_co3.Header.BufferSz = sizeof(m_co3); - m_co3.ScenarioInfo = MFX_SCENARIO_GAME_STREAMING; - m_co3.AdaptiveCQM = MFX_CODINGOPTION_ON; - extendedBuffers.push_back((mfxExtBuffer *)&m_co3); - } + extendedBuffers.push_back((mfxExtBuffer *)&m_co2); + extendedBuffers.push_back((mfxExtBuffer *)&m_co3); if (codec == QSV_CODEC_HEVC) { if ((pParams->nWidth & 15) || (pParams->nHeight & 15)) { diff --git a/plugins/obs-qsv11/obs-qsv11.c b/plugins/obs-qsv11/obs-qsv11.c index 6fc008e51..a75390327 100644 --- a/plugins/obs-qsv11/obs-qsv11.c +++ b/plugins/obs-qsv11/obs-qsv11.c @@ -257,14 +257,22 @@ static bool update_latency(obs_data_t *settings) update = true; } + const char *rate_control = + obs_data_get_string(settings, "rate_control"); + + bool lookahead = false; + if (astrcmpi(rate_control, "LA_CBR") == 0) { + obs_data_set_string(settings, "rate_control", "CBR"); + lookahead = true; + } else if (astrcmpi(rate_control, "LA_VBR") == 0) { + obs_data_set_string(settings, "rate_control", "VBR"); + lookahead = true; + } else if (astrcmpi(rate_control, "LA_ICQ") == 0) { + obs_data_set_string(settings, "rate_control", "ICQ"); + lookahead = true; + } + if (update) { - const char *rate_control = - obs_data_get_string(settings, "rate_control"); - - bool lookahead = astrcmpi(rate_control, "LA_CBR") == 0 || - astrcmpi(rate_control, "LA_VBR") == 0 || - astrcmpi(rate_control, "LA_ICQ") == 0; - if (lookahead) { if (la_depth == 0 || la_depth >= 15) obs_data_set_string(settings, "latency", @@ -350,7 +358,6 @@ static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, obs_property_set_visible(p, bVisible); bVisible = astrcmpi(rate_control, "CQP") == 0 || - astrcmpi(rate_control, "LA_ICQ") == 0 || astrcmpi(rate_control, "ICQ") == 0; p = obs_properties_get(ppts, "bitrate"); obs_property_set_visible(p, !bVisible); @@ -375,8 +382,7 @@ static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, if (p) obs_property_set_visible(p, bVisible); - bVisible = astrcmpi(rate_control, "ICQ") == 0 || - astrcmpi(rate_control, "LA_ICQ") == 0; + bVisible = astrcmpi(rate_control, "ICQ") == 0; p = obs_properties_get(ppts, "icq_quality"); obs_property_set_visible(p, bVisible); @@ -687,29 +693,20 @@ static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) obsqsv->params.nRateControl = MFX_RATECONTROL_AVBR; else if (astrcmpi(rate_control, "ICQ") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_ICQ; - else if (astrcmpi(rate_control, "LA_ICQ") == 0) - obsqsv->params.nRateControl = MFX_RATECONTROL_LA_ICQ; - else if (astrcmpi(rate_control, "LA_VBR") == 0) - obsqsv->params.nRateControl = MFX_RATECONTROL_LA; - else if (astrcmpi(rate_control, "LA_CBR") == 0) - obsqsv->params.nRateControl = MFX_RATECONTROL_LA_HRD; - if (obsqsv->codec == QSV_CODEC_AV1) { + obsqsv->params.nLADEPTH = (mfxU16)0; + if (astrcmpi(latency, "ultra-low") == 0) { + obsqsv->params.nAsyncDepth = 1; + } else if (astrcmpi(latency, "low") == 0) { obsqsv->params.nAsyncDepth = 4; - obsqsv->params.nLADEPTH = 0; - } else { - if (astrcmpi(latency, "ultra-low") == 0) { - obsqsv->params.nAsyncDepth = 1; - obsqsv->params.nLADEPTH = (mfxU16)0; - } else if (astrcmpi(latency, "low") == 0) { - obsqsv->params.nAsyncDepth = 4; - obsqsv->params.nLADEPTH = - (mfxU16)(voi->fps_num / voi->fps_den / 2); - } else if (astrcmpi(latency, "normal") == 0) { - obsqsv->params.nAsyncDepth = 4; - obsqsv->params.nLADEPTH = - (mfxU16)(voi->fps_num / voi->fps_den); - } + if (obsqsv->params.nRateControl == MFX_RATECONTROL_CBR || + obsqsv->params.nRateControl == MFX_RATECONTROL_VBR) + obsqsv->params.nLADEPTH = 30; + } else if (astrcmpi(latency, "normal") == 0) { + obsqsv->params.nAsyncDepth = 4; + if (obsqsv->params.nRateControl == MFX_RATECONTROL_CBR || + obsqsv->params.nRateControl == MFX_RATECONTROL_VBR) + obsqsv->params.nLADEPTH = 60; } if (obsqsv->params.nLADEPTH > 0) { @@ -749,8 +746,7 @@ static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) "\trate_control: %s", codec, rate_control); - if (obsqsv->params.nRateControl != MFX_RATECONTROL_LA_ICQ && - obsqsv->params.nRateControl != MFX_RATECONTROL_ICQ && + if (obsqsv->params.nRateControl != MFX_RATECONTROL_ICQ && obsqsv->params.nRateControl != MFX_RATECONTROL_CQP) blog(LOG_INFO, "\ttarget_bitrate: %d", (int)obsqsv->params.nTargetBitRate); @@ -760,14 +756,11 @@ static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) blog(LOG_INFO, "\tmax_bitrate: %d", (int)obsqsv->params.nMaxBitRate); - if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || - obsqsv->params.nRateControl == MFX_RATECONTROL_ICQ) + if (obsqsv->params.nRateControl == MFX_RATECONTROL_ICQ) blog(LOG_INFO, "\tICQ Quality: %d", (int)obsqsv->params.nICQQuality); - if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || - obsqsv->params.nRateControl == MFX_RATECONTROL_LA || - obsqsv->params.nRateControl == MFX_RATECONTROL_LA_HRD) + if (obsqsv->params.nLADEPTH) blog(LOG_INFO, "\tLookahead Depth:%d", (int)obsqsv->params.nLADEPTH);