From 58812bc0b3e1994c5a5b87c29cee931e88753c19 Mon Sep 17 00:00:00 2001 From: "Bird, Christopher" Date: Wed, 8 Aug 2018 10:39:57 -0700 Subject: [PATCH 1/2] obs-qsv: Expose additional QSV encoder settings through GUI - Allow user to change # of B frames. New Default -> 1 - Allow user to enable Content Adaptive Quantization (MBBRC) if CPU is Skylake or newer. - Allow user to choose LA_CBR as a rate control. - LA depth: New Default -> 15, only when LA rate control is used. --- plugins/obs-qsv11/QSV_Encoder.cpp | 13 ++++++-- plugins/obs-qsv11/QSV_Encoder.h | 6 +++- plugins/obs-qsv11/QSV_Encoder_Internal.cpp | 31 ++++++++----------- plugins/obs-qsv11/obs-qsv11.c | 35 ++++++++++++++++++---- 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/plugins/obs-qsv11/QSV_Encoder.cpp b/plugins/obs-qsv11/QSV_Encoder.cpp index dd3a9352e..9315a48f0 100644 --- a/plugins/obs-qsv11/QSV_Encoder.cpp +++ b/plugins/obs-qsv11/QSV_Encoder.cpp @@ -223,8 +223,17 @@ enum qsv_cpu_platform qsv_get_cpu_platform() case 0x45: case 0x46: return QSV_CPU_PLATFORM_HSW; - } - //assume newer revisions are at least as capable as Haswell + case 0x3d: + case 0x47: + case 0x4f: + case 0x56: + return QSV_CPU_PLATFORM_BDW; + + case 0x4e: + case 0x5e: + return QSV_CPU_PLATFORM_SKL; + } + //assume newer revisions are at least as capable as Skylake return QSV_CPU_PLATFORM_INTEL; } diff --git a/plugins/obs-qsv11/QSV_Encoder.h b/plugins/obs-qsv11/QSV_Encoder.h index ffd2a693b..7546fe222 100644 --- a/plugins/obs-qsv11/QSV_Encoder.h +++ b/plugins/obs-qsv11/QSV_Encoder.h @@ -76,8 +76,9 @@ static const struct qsv_rate_control_info qsv_ratecontrols[] = { {"CQP", false}, {"AVBR", false}, {"ICQ", true}, + {"LA_CBR", true}, + {"LA_VBR", true}, {"LA_ICQ", true}, - {"LA", true}, {0, false} }; static const char * const qsv_profile_names[] = { @@ -117,6 +118,7 @@ typedef struct mfxU16 nKeyIntSec; mfxU16 nbFrames; mfxU16 nICQQuality; + bool bMBBRC; } qsv_param_t; enum qsv_cpu_platform { @@ -127,6 +129,8 @@ enum qsv_cpu_platform { QSV_CPU_PLATFORM_SLM, QSV_CPU_PLATFORM_CHT, QSV_CPU_PLATFORM_HSW, + QSV_CPU_PLATFORM_BDW, + QSV_CPU_PLATFORM_SKL, QSV_CPU_PLATFORM_INTEL }; diff --git a/plugins/obs-qsv11/QSV_Encoder_Internal.cpp b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp index a458236ff..2aa7eddc3 100644 --- a/plugins/obs-qsv11/QSV_Encoder_Internal.cpp +++ b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp @@ -190,6 +190,7 @@ bool QSV_Encoder_Internal::InitParams(qsv_param_t * pParams) { memset(&m_mfxEncParams, 0, sizeof(m_mfxEncParams)); + m_mfxEncParams.mfx.CodecId = MFX_CODEC_AVC; m_mfxEncParams.mfx.GopOptFlag = MFX_GOP_STRICT; m_mfxEncParams.mfx.NumSlice = 1; @@ -204,6 +205,7 @@ bool QSV_Encoder_Internal::InitParams(qsv_param_t * pParams) m_mfxEncParams.mfx.FrameInfo.CropY = 0; m_mfxEncParams.mfx.FrameInfo.CropW = pParams->nWidth; m_mfxEncParams.mfx.FrameInfo.CropH = pParams->nHeight; + m_mfxEncParams.mfx.GopRefDist = pParams->nbFrames + 1; m_mfxEncParams.mfx.RateControlMethod = pParams->nRateControl; @@ -235,6 +237,10 @@ bool QSV_Encoder_Internal::InitParams(qsv_param_t * pParams) 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; } @@ -245,28 +251,17 @@ bool QSV_Encoder_Internal::InitParams(qsv_param_t * pParams) static mfxExtBuffer* extendedBuffers[2]; int iBuffers = 0; - if (pParams->nAsyncDepth == 1) { - m_mfxEncParams.mfx.NumRefFrame = 1; - // low latency, I and P frames only - m_mfxEncParams.mfx.GopRefDist = 1; - memset(&m_co, 0, sizeof(mfxExtCodingOption)); - m_co.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; - m_co.Header.BufferSz = sizeof(mfxExtCodingOption); - m_co.MaxDecFrameBuffering = 1; - extendedBuffers[iBuffers++] = (mfxExtBuffer*)&m_co; - } - else - m_mfxEncParams.mfx.GopRefDist = pParams->nbFrames + 1; + memset(&m_co2, 0, sizeof(mfxExtCodingOption2)); + m_co2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; + m_co2.Header.BufferSz = sizeof(m_co2); + if (pParams->bMBBRC) + m_co2.MBBRC = MFX_CODINGOPTION_ON; if (pParams->nRateControl == MFX_RATECONTROL_LA_ICQ || - pParams->nRateControl == MFX_RATECONTROL_LA) { + pParams->nRateControl == MFX_RATECONTROL_LA) - memset(&m_co2, 0, sizeof(mfxExtCodingOption2)); - m_co2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; - m_co2.Header.BufferSz = sizeof(m_co2); m_co2.LookAheadDepth = pParams->nLADEPTH; - extendedBuffers[iBuffers++] = (mfxExtBuffer*)& m_co2; - } + extendedBuffers[iBuffers++] = (mfxExtBuffer*)& m_co2; if (iBuffers > 0) { m_mfxEncParams.ExtParam = extendedBuffers; diff --git a/plugins/obs-qsv11/obs-qsv11.c b/plugins/obs-qsv11/obs-qsv11.c index 2ac18ab26..0552bbcb2 100644 --- a/plugins/obs-qsv11/obs-qsv11.c +++ b/plugins/obs-qsv11/obs-qsv11.c @@ -152,9 +152,10 @@ static void obs_qsv_defaults(obs_data_t *settings) obs_data_set_default_int(settings, "qpp", 23); obs_data_set_default_int(settings, "qpb", 23); obs_data_set_default_int(settings, "icq_quality", 23); - obs_data_set_default_int(settings, "la_depth", 40); + obs_data_set_default_int(settings, "la_depth", 15); obs_data_set_default_int(settings, "keyint_sec", 3); + obs_data_set_default_int(settings, "bframes", 1); } static inline void add_strings(obs_property_t *list, const char *const *strings) @@ -176,6 +177,14 @@ static inline void add_strings(obs_property_t *list, const char *const *strings) #define TEXT_ICQ_QUALITY obs_module_text("ICQQuality") #define TEXT_LA_DEPTH obs_module_text("LookAheadDepth") #define TEXT_KEYINT_SEC obs_module_text("KeyframeIntervalSec") +#define TEXT_BFRAMES obs_module_text("B Frames") +#define TEXT_MBBRC obs_module_text("Content Adaptive Quantization") + +static inline bool is_skl_or_greater_platform() +{ + enum qsv_cpu_platform plat = qsv_get_cpu_platform(); + return (plat >= QSV_CPU_PLATFORM_SKL); +} static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, obs_data_t *settings) @@ -215,10 +224,17 @@ static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, obs_property_set_visible(p, bVisible); bVisible = astrcmpi(rate_control, "LA_ICQ") == 0 || - astrcmpi(rate_control, "LA") == 0; + astrcmpi(rate_control, "LA_CBR") == 0 || + astrcmpi(rate_control, "LA_VBR") == 0; p = obs_properties_get(ppts, "la_depth"); obs_property_set_visible(p, bVisible); + bVisible = astrcmpi(rate_control, "CBR") == 0 || + astrcmpi(rate_control, "VBR") == 0 || + astrcmpi(rate_control, "AVBR") == 0; + p = obs_properties_get(ppts, "mbbrc"); + obs_property_set_visible(p, bVisible); + return true; } @@ -267,6 +283,10 @@ static obs_properties_t *obs_qsv_props(void *unused) obs_properties_add_int(props, "qpb", "QPB", 1, 51, 1); obs_properties_add_int(props, "icq_quality", TEXT_ICQ_QUALITY, 1, 51, 1); obs_properties_add_int(props, "la_depth", TEXT_LA_DEPTH, 10, 100, 1); + obs_properties_add_int(props, "bframes", TEXT_BFRAMES, 0, 3, 1); + + if (is_skl_or_greater_platform()) + obs_properties_add_bool(props, "mbbrc", TEXT_MBBRC); return props; } @@ -291,7 +311,8 @@ static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) int la_depth = (int)obs_data_get_int(settings, "la_depth"); int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); bool cbr_override = obs_data_get_bool(settings, "cbr"); - int bFrames = 7; + int bFrames = (int)obs_data_get_int(settings, "bframes"); + bool mbbrc = obs_data_get_bool(settings, "mbbrc"); if (obs_data_has_user_value(settings, "bf")) bFrames = (int)obs_data_get_int(settings, "bf"); @@ -337,8 +358,10 @@ static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) 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") == 0) + 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; obsqsv->params.nAsyncDepth = (mfxU16)async_depth; obsqsv->params.nAccuracy = (mfxU16)accuracy; @@ -356,6 +379,7 @@ static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) obsqsv->params.nbFrames = (mfxU16)bFrames; obsqsv->params.nKeyIntSec = (mfxU16)keyint_sec; obsqsv->params.nICQQuality = (mfxU16)icq_quality; + obsqsv->params.bMBBRC = mbbrc; info("settings:\n\trate_control: %s", rate_control); @@ -379,7 +403,8 @@ static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) (int)obsqsv->params.nICQQuality); if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || - obsqsv->params.nRateControl == MFX_RATECONTROL_LA) + obsqsv->params.nRateControl == MFX_RATECONTROL_LA || + obsqsv->params.nRateControl == MFX_RATECONTROL_LA_HRD) blog(LOG_INFO, "\tLookahead Depth:%d", (int)obsqsv->params.nLADEPTH); From 99b8c8390f7832c422aa7b21b4bbb7760ae06404 Mon Sep 17 00:00:00 2001 From: "Bird, Christopher" Date: Mon, 10 Sep 2018 10:23:43 -0700 Subject: [PATCH 2/2] obs-qsv: enable High Profile for QSV h264 - New QSV Default -> H264 High profile. Previous Default -> H264 Main profile --- plugins/obs-qsv11/obs-qsv11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/obs-qsv11/obs-qsv11.c b/plugins/obs-qsv11/obs-qsv11.c index 0552bbcb2..8fc1c24f8 100644 --- a/plugins/obs-qsv11/obs-qsv11.c +++ b/plugins/obs-qsv11/obs-qsv11.c @@ -142,7 +142,7 @@ static void obs_qsv_defaults(obs_data_t *settings) obs_data_set_default_string(settings, "target_usage", "balanced"); obs_data_set_default_int(settings, "bitrate", 2500); obs_data_set_default_int(settings, "max_bitrate", 3000); - obs_data_set_default_string(settings, "profile", "main"); + obs_data_set_default_string(settings, "profile", "high"); obs_data_set_default_int(settings, "async_depth", 4); obs_data_set_default_string(settings, "rate_control", "CBR");