summaryrefslogtreecommitdiffstats
path: root/libhb/qsv_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/qsv_common.c')
-rw-r--r--libhb/qsv_common.c926
1 files changed, 745 insertions, 181 deletions
diff --git a/libhb/qsv_common.c b/libhb/qsv_common.c
index 195845200..9a21af411 100644
--- a/libhb/qsv_common.c
+++ b/libhb/qsv_common.c
@@ -9,6 +9,8 @@
#ifdef USE_QSV
+#include <stdio.h>
+
#include "hb.h"
#include "ports.h"
#include "common.h"
@@ -16,167 +18,582 @@
#include "qsv_common.h"
#include "h264_common.h"
-// for x264_vidformat_names etc.
-#include "x264.h"
-
-// avoids a warning
-#include "libavutil/cpu.h"
-extern void ff_cpu_cpuid(int index, int *eax, int *ebx, int *ecx, int *edx);
-
-// make the Intel QSV information available to the UIs
-hb_qsv_info_t *hb_qsv_info = NULL;
-
-// availability and versions
-static mfxIMPL preferred_implementation;
-static mfxVersion qsv_hardware_version;
-static mfxVersion qsv_software_version;
-static mfxVersion qsv_minimum_version;
-static int qsv_hardware_available = 0;
-static int qsv_software_available = 0;
+// QSV info for each codec
+static hb_qsv_info_t *hb_qsv_info_avc = NULL;
+static hb_qsv_info_t *hb_qsv_info_hevc = NULL;
+// API versions
+static mfxVersion qsv_software_version = { .Version = 0, };
+static mfxVersion qsv_hardware_version = { .Version = 0, };
+// AVC implementations
+static hb_qsv_info_t qsv_software_info_avc = { .available = 0, .codec_id = MFX_CODEC_AVC, .implementation = MFX_IMPL_SOFTWARE, };
+static hb_qsv_info_t qsv_hardware_info_avc = { .available = 0, .codec_id = MFX_CODEC_AVC, .implementation = MFX_IMPL_HARDWARE_ANY|MFX_IMPL_VIA_ANY, };
+// HEVC implementations
+static mfxPluginUID qsv_encode_plugin_hevc = { .Data = { 0x2F, 0xCA, 0x99, 0x74, 0x9F, 0xDB, 0x49, 0xAE, 0xB1, 0x21, 0xA5, 0xB6, 0x3E, 0xF5, 0x68, 0xF7 } };
+static hb_qsv_info_t qsv_software_info_hevc = { .available = 0, .codec_id = MFX_CODEC_HEVC, .implementation = MFX_IMPL_SOFTWARE, };
+static hb_qsv_info_t qsv_hardware_info_hevc = { .available = 0, .codec_id = MFX_CODEC_HEVC, .implementation = MFX_IMPL_HARDWARE_ANY|MFX_IMPL_VIA_ANY, };
// check available Intel Media SDK version against a minimum
#define HB_CHECK_MFX_VERSION(MFX_VERSION, MAJOR, MINOR) \
(MFX_VERSION.Major == MAJOR && MFX_VERSION.Minor >= MINOR)
+/*
+ * Determine the "generation" of QSV hardware based on the CPU microarchitecture.
+ * Anything unknown is assumed to be more recent than the latest known generation.
+ * This avoids having to order the hb_cpu_platform enum depending on QSV hardware.
+ */
+enum
+{
+ QSV_G0, // third party hardware
+ QSV_G1, // Sandy Bridge or equivalent
+ QSV_G2, // Ivy Bridge or equivalent
+ QSV_G3, // Haswell or equivalent
+};
+static int qsv_hardware_generation(int cpu_platform)
+{
+ switch (cpu_platform)
+ {
+ case HB_CPU_PLATFORM_INTEL_BNL:
+ return QSV_G0;
+ case HB_CPU_PLATFORM_INTEL_SNB:
+ return QSV_G1;
+ case HB_CPU_PLATFORM_INTEL_IVB:
+ case HB_CPU_PLATFORM_INTEL_SLM:
+ return QSV_G2;
+ case HB_CPU_PLATFORM_INTEL_HSW:
+ default:
+ return QSV_G3;
+ }
+}
+
+/*
+ * Determine whether a given mfxIMPL is hardware-accelerated.
+ */
+static int qsv_implementation_is_hardware(mfxIMPL implementation)
+{
+ return MFX_IMPL_BASETYPE(implementation) != MFX_IMPL_SOFTWARE;
+}
+
int hb_qsv_available()
{
- return hb_qsv_info != NULL && (qsv_hardware_available ||
- qsv_software_available);
+ return hb_qsv_video_encoder_is_enabled(HB_VCODEC_QSV_H264);
}
-int hb_qsv_info_init()
+int hb_qsv_video_encoder_is_enabled(int encoder)
{
- static int init_done = 0;
- if (init_done)
- return (hb_qsv_info == NULL);
- init_done = 1;
+ switch (encoder)
+ {
+ case HB_VCODEC_QSV_H264:
+ return hb_qsv_info_avc != NULL && hb_qsv_info_avc->available;
+ default:
+ return 0;
+ }
+}
- hb_qsv_info = calloc(1, sizeof(*hb_qsv_info));
- if (hb_qsv_info == NULL)
+int hb_qsv_audio_encoder_is_enabled(int encoder)
+{
+ switch (encoder)
{
- hb_error("hb_qsv_info_init: alloc failure");
- return -1;
+ default:
+ return 0;
}
+}
- mfxSession session;
- qsv_minimum_version.Major = HB_QSV_MINVERSION_MAJOR;
- qsv_minimum_version.Minor = HB_QSV_MINVERSION_MINOR;
+static void init_video_param(mfxVideoParam *videoParam)
+{
+ if (videoParam == NULL)
+ {
+ return;
+ }
- // check for software fallback
- if (MFXInit(MFX_IMPL_SOFTWARE,
- &qsv_minimum_version, &session) == MFX_ERR_NONE)
+ memset(videoParam, 0, sizeof(mfxVideoParam));
+ videoParam->mfx.CodecId = MFX_CODEC_AVC;
+ videoParam->mfx.CodecLevel = MFX_LEVEL_UNKNOWN;
+ videoParam->mfx.CodecProfile = MFX_PROFILE_UNKNOWN;
+ videoParam->mfx.RateControlMethod = MFX_RATECONTROL_VBR;
+ videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED;
+ videoParam->mfx.TargetKbps = 5000;
+ videoParam->mfx.GopOptFlag = MFX_GOP_CLOSED;
+ videoParam->mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
+ videoParam->mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
+ videoParam->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
+ videoParam->mfx.FrameInfo.FrameRateExtN = 25;
+ videoParam->mfx.FrameInfo.FrameRateExtD = 1;
+ videoParam->mfx.FrameInfo.Width = 1920;
+ videoParam->mfx.FrameInfo.CropW = 1920;
+ videoParam->mfx.FrameInfo.AspectRatioW = 1;
+ videoParam->mfx.FrameInfo.Height = 1088;
+ videoParam->mfx.FrameInfo.CropH = 1080;
+ videoParam->mfx.FrameInfo.AspectRatioH = 1;
+ videoParam->AsyncDepth = AV_QSV_ASYNC_DEPTH_DEFAULT;
+ videoParam->IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
+}
+
+static void init_ext_coding_option2(mfxExtCodingOption2 *extCodingOption2)
+{
+ if (extCodingOption2 == NULL)
{
- qsv_software_available = 1;
- preferred_implementation = MFX_IMPL_SOFTWARE;
- // our minimum is supported, but query the actual version
- MFXQueryVersion(session, &qsv_software_version);
- MFXClose(session);
+ return;
}
- // check for actual hardware support
- if (MFXInit(MFX_IMPL_HARDWARE_ANY|MFX_IMPL_VIA_ANY,
- &qsv_minimum_version, &session) == MFX_ERR_NONE)
+ memset(extCodingOption2, 0, sizeof(mfxExtCodingOption2));
+ extCodingOption2->Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
+ extCodingOption2->Header.BufferSz = sizeof(mfxExtCodingOption2);
+ extCodingOption2->MBBRC = MFX_CODINGOPTION_ON;
+ extCodingOption2->ExtBRC = MFX_CODINGOPTION_ON;
+ extCodingOption2->Trellis = MFX_TRELLIS_I|MFX_TRELLIS_P|MFX_TRELLIS_B;
+ extCodingOption2->RepeatPPS = MFX_CODINGOPTION_ON;
+ extCodingOption2->BRefType = MFX_B_REF_PYRAMID;
+ extCodingOption2->AdaptiveI = MFX_CODINGOPTION_ON;
+ extCodingOption2->AdaptiveB = MFX_CODINGOPTION_ON;
+ extCodingOption2->LookAheadDS = MFX_LOOKAHEAD_DS_4x;
+ extCodingOption2->NumMbPerSlice = 2040; // 1920x1088/4
+}
+
+static int query_capabilities(mfxSession session, mfxVersion version, hb_qsv_info_t *info)
+{
+ /*
+ * MFXVideoENCODE_Query(mfxSession, mfxVideoParam *in, mfxVideoParam *out);
+ *
+ * Mode 1:
+ * - in is NULL
+ * - out has the parameters we want to query set to 1
+ * - out->mfx.CodecId field has to be set (mandatory)
+ * - MFXVideoENCODE_Query should zero out all unsupported parameters
+ *
+ * Mode 2:
+ * - the paramaters we want to query are set for in
+ * - in ->mfx.CodecId field has to be set (mandatory)
+ * - out->mfx.CodecId field has to be set (mandatory)
+ * - MFXVideoENCODE_Query should sanitize all unsupported parameters
+ */
+ mfxStatus status;
+ mfxPluginUID *pluginUID;
+ mfxExtBuffer *videoExtParam[1];
+ mfxVideoParam videoParam, inputParam;
+ mfxExtCodingOption2 extCodingOption2;
+
+ /* Reset capabilities before querying */
+ info->capabilities = 0;
+
+ /* Load optional codec plug-ins */
+ switch (info->codec_id)
+ {
+ case MFX_CODEC_HEVC:
+ pluginUID = &qsv_encode_plugin_hevc;
+ break;
+ default:
+ pluginUID = NULL;
+ break;
+ }
+ if (pluginUID != NULL && HB_CHECK_MFX_VERSION(version, 1, 8) &&
+ MFXVideoUSER_Load(session, pluginUID, 0) < MFX_ERR_NONE)
{
- // Cloverview (Bonnell microarchitecture) supports MSDK via third-party
- // hardware - we don't support this configuration for the time being
- if (hb_get_cpu_platform() != HB_CPU_PLATFORM_INTEL_BNL)
+ // couldn't load plugin successfully
+ return 0;
+ }
+
+ /*
+ * First of all, check availability of an encoder for
+ * this combination of a codec ID and implementation.
+ *
+ * Note: can error out rather than sanitizing
+ * unsupported codec IDs, so don't log errors.
+ */
+ if (HB_CHECK_MFX_VERSION(version, HB_QSV_MINVERSION_MAJOR, HB_QSV_MINVERSION_MINOR))
+ {
+ if (info->implementation & MFX_IMPL_AUDIO)
{
- qsv_hardware_available = 1;
- preferred_implementation = MFX_IMPL_HARDWARE_ANY|MFX_IMPL_VIA_ANY;
- // our minimum is supported, but query the actual version
- MFXQueryVersion(session, &qsv_hardware_version);
+ /* Not yet supported */
+ return 0;
+ }
+ else
+ {
+ init_video_param(&inputParam);
+ inputParam.mfx.CodecId = info->codec_id;
+
+ memset(&videoParam, 0, sizeof(mfxVideoParam));
+ videoParam.mfx.CodecId = inputParam.mfx.CodecId;
+
+ if (MFXVideoENCODE_Query(session, &inputParam, &videoParam) >= MFX_ERR_NONE &&
+ videoParam.mfx.CodecId == info->codec_id)
+ {
+ info->available = 1;
+ }
}
- MFXClose(session);
+ }
+ if (!info->available)
+ {
+ /* Don't check capabilities for unavailable encoders */
+ return 0;
}
- // check for version-specific or hardware-specific capabilities
- // we only use software as a fallback, so check hardware first
- if (qsv_hardware_available)
+ if (info->implementation & MFX_IMPL_AUDIO)
+ {
+ /* We don't have any audio capability checks yet */
+ return 0;
+ }
+ else
{
- if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 6))
+ /* Implementation-specific features that can't be queried */
+ if (qsv_implementation_is_hardware(info->implementation))
{
- hb_qsv_info->capabilities |= HB_QSV_CAP_MSDK_API_1_6;
- hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_EXTBRC;
+ if (qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G3)
+ {
+ info->capabilities |= HB_QSV_CAP_B_REF_PYRAMID;
+ }
}
- if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 7))
+ else
{
- // we should really check the driver version, but since that's not
- // available here, checking the API version is the best we can do :-(
- hb_qsv_info->capabilities |= HB_QSV_CAP_CORE_COPYFRAME;
+ if (HB_CHECK_MFX_VERSION(version, 1, 6))
+ {
+ info->capabilities |= HB_QSV_CAP_B_REF_PYRAMID;
+ }
}
- if (hb_get_cpu_platform() == HB_CPU_PLATFORM_INTEL_HSW)
+
+ /* API-specific features that can't be queried */
+ if (HB_CHECK_MFX_VERSION(version, 1, 6))
{
- if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 6))
+ // API >= 1.6 (mfxBitstream::DecodeTimeStamp, mfxExtCodingOption2)
+ info->capabilities |= HB_QSV_CAP_MSDK_API_1_6;
+ }
+
+ /*
+ * Check availability of optional rate control methods.
+ *
+ * Mode 2 tends to error out, but mode 1 gives false negatives, which
+ * is worse. So use mode 2 and assume an error means it's unsupported.
+ *
+ * Also assume that LA and ICQ combined imply LA_ICQ is
+ * supported, so we don't need to check the latter too.
+ */
+ if (HB_CHECK_MFX_VERSION(version, 1, 7))
+ {
+ init_video_param(&inputParam);
+ inputParam.mfx.CodecId = info->codec_id;
+ inputParam.mfx.RateControlMethod = MFX_RATECONTROL_LA;
+
+ memset(&videoParam, 0, sizeof(mfxVideoParam));
+ videoParam.mfx.CodecId = inputParam.mfx.CodecId;
+
+ if (MFXVideoENCODE_Query(session, &inputParam, &videoParam) >= MFX_ERR_NONE &&
+ videoParam.mfx.RateControlMethod == MFX_RATECONTROL_LA)
+ {
+ info->capabilities |= HB_QSV_CAP_RATECONTROL_LA;
+
+ // also check for LA + interlaced support
+ init_video_param(&inputParam);
+ inputParam.mfx.CodecId = info->codec_id;
+ inputParam.mfx.RateControlMethod = MFX_RATECONTROL_LA;
+ inputParam.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
+
+ memset(&videoParam, 0, sizeof(mfxVideoParam));
+ videoParam.mfx.CodecId = inputParam.mfx.CodecId;
+
+ if (MFXVideoENCODE_Query(session, &inputParam, &videoParam) >= MFX_ERR_NONE &&
+ videoParam.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_FIELD_TFF &&
+ videoParam.mfx.RateControlMethod == MFX_RATECONTROL_LA)
+ {
+ info->capabilities |= HB_QSV_CAP_RATECONTROL_LAi;
+ }
+ }
+ }
+ if (HB_CHECK_MFX_VERSION(version, 1, 8))
+ {
+ init_video_param(&inputParam);
+ inputParam.mfx.CodecId = info->codec_id;
+ inputParam.mfx.RateControlMethod = MFX_RATECONTROL_ICQ;
+
+ memset(&videoParam, 0, sizeof(mfxVideoParam));
+ videoParam.mfx.CodecId = inputParam.mfx.CodecId;
+
+ if (MFXVideoENCODE_Query(session, &inputParam, &videoParam) >= MFX_ERR_NONE &&
+ videoParam.mfx.RateControlMethod == MFX_RATECONTROL_ICQ)
+ {
+ info->capabilities |= HB_QSV_CAP_RATECONTROL_ICQ;
+ }
+ }
+
+ /*
+ * Check mfxExtCodingOption2 fields.
+ *
+ * Mode 2 suffers from false negatives with some drivers, whereas mode 1
+ * suffers from false positives instead. The latter is probably easier
+ * and/or safer to sanitize for us, so use mode 1.
+ */
+ if (HB_CHECK_MFX_VERSION(version, 1, 6))
+ {
+ init_video_param(&videoParam);
+ videoParam.mfx.CodecId = info->codec_id;
+
+ init_ext_coding_option2(&extCodingOption2);
+ videoParam.ExtParam = videoExtParam;
+ videoParam.ExtParam[0] = (mfxExtBuffer*)&extCodingOption2;
+ videoParam.NumExtParam = 1;
+
+ status = MFXVideoENCODE_Query(session, NULL, &videoParam);
+ if (status >= MFX_ERR_NONE)
{
- hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_MBBRC;
+#if 0
+ // testing code that could come in handy
+ fprintf(stderr, "-------------------\n");
+ fprintf(stderr, "MBBRC: 0x%02X\n", extCodingOption2.MBBRC);
+ fprintf(stderr, "ExtBRC: 0x%02X\n", extCodingOption2.ExtBRC);
+ fprintf(stderr, "Trellis: 0x%02X\n", extCodingOption2.Trellis);
+ fprintf(stderr, "RepeatPPS: 0x%02X\n", extCodingOption2.RepeatPPS);
+ fprintf(stderr, "BRefType: %4"PRIu16"\n", extCodingOption2.BRefType);
+ fprintf(stderr, "AdaptiveI: 0x%02X\n", extCodingOption2.AdaptiveI);
+ fprintf(stderr, "AdaptiveB: 0x%02X\n", extCodingOption2.AdaptiveB);
+ fprintf(stderr, "LookAheadDS: %4"PRIu16"\n", extCodingOption2.LookAheadDS);
+ fprintf(stderr, "-------------------\n");
+#endif
+
+ /*
+ * Sanitize API 1.6 fields:
+ *
+ * - MBBRC requires G3 hardware (Haswell or equivalent)
+ * - ExtBRC requires G2 hardware (Ivy Bridge or equivalent)
+ */
+ if (qsv_implementation_is_hardware(info->implementation) &&
+ qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G3)
+ {
+ if (extCodingOption2.MBBRC)
+ {
+ info->capabilities |= HB_QSV_CAP_OPTION2_MBBRC;
+ }
+ }
+ if (qsv_implementation_is_hardware(info->implementation) &&
+ qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G2)
+ {
+ if (extCodingOption2.ExtBRC)
+ {
+ info->capabilities |= HB_QSV_CAP_OPTION2_EXTBRC;
+ }
+ }
+
+ /*
+ * Sanitize API 1.7 fields:
+ *
+ * - Trellis requires G3 hardware (Haswell or equivalent)
+ */
+ if (HB_CHECK_MFX_VERSION(version, 1, 7))
+ {
+ if (qsv_implementation_is_hardware(info->implementation) &&
+ qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G3)
+ {
+ if (extCodingOption2.Trellis)
+ {
+ info->capabilities |= HB_QSV_CAP_OPTION2_TRELLIS;
+ }
+ }
+ }
+
+ /*
+ * Sanitize API 1.8 fields:
+ *
+ * - BRefType requires B-pyramid support
+ * - LookAheadDS requires lookahead support
+ * - AdaptiveI, AdaptiveB, NumMbPerSlice unknown (trust Query)
+ */
+ if (HB_CHECK_MFX_VERSION(version, 1, 8))
+ {
+ if (info->capabilities & HB_QSV_CAP_B_REF_PYRAMID)
+ {
+ if (extCodingOption2.BRefType)
+ {
+ info->capabilities |= HB_QSV_CAP_OPTION2_BREFTYPE;
+ }
+ }
+ if (info->capabilities & HB_QSV_CAP_RATECONTROL_LA)
+ {
+ if (extCodingOption2.LookAheadDS)
+ {
+ info->capabilities |= HB_QSV_CAP_OPTION2_LA_DOWNS;
+ }
+ }
+ if (extCodingOption2.AdaptiveI && extCodingOption2.AdaptiveB)
+ {
+ info->capabilities |= HB_QSV_CAP_OPTION2_IB_ADAPT;
+ }
+ if (extCodingOption2.NumMbPerSlice)
+ {
+ info->capabilities |= HB_QSV_CAP_OPTION2_NMBSLICE;
+ }
+ }
}
- if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 7))
+ else
{
- hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_TRELLIS;
- hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_LOOKAHEAD;
+ fprintf(stderr,
+ "hb_qsv_info_init: mfxExtCodingOption2 check failed (0x%"PRIX32", 0x%"PRIX32", %d)\n",
+ info->codec_id, info->implementation, status);
}
- hb_qsv_info->capabilities |= HB_QSV_CAP_H264_BPYRAMID;
}
}
- else if (qsv_software_available)
+
+ /* Unload optional codec plug-ins */
+ if (pluginUID != NULL && HB_CHECK_MFX_VERSION(version, 1, 8))
+ {
+ MFXVideoUSER_UnLoad(session, pluginUID);
+ }
+
+ return 0;
+}
+
+int hb_qsv_info_init()
+{
+ static int init_done = 0;
+ if (init_done)
+ return 0;
+ init_done = 1;
+
+ /*
+ * First, check for any MSDK version to determine whether one or
+ * more implementations are present; then check if we can use them.
+ *
+ * I've had issues using a NULL version with some combinations of
+ * hardware and driver, so use a low version number (1.0) instead.
+ */
+ mfxSession session;
+ mfxVersion version = { .Major = 1, .Minor = 0, };
+
+ // check for software fallback
+ if (MFXInit(MFX_IMPL_SOFTWARE, &version, &session) == MFX_ERR_NONE)
{
- if (HB_CHECK_MFX_VERSION(qsv_software_version, 1, 6))
+ // Media SDK software found, but check that our minimum is supported
+ MFXQueryVersion(session, &qsv_software_version);
+ if (HB_CHECK_MFX_VERSION(qsv_software_version,
+ HB_QSV_MINVERSION_MAJOR,
+ HB_QSV_MINVERSION_MINOR))
{
- hb_qsv_info->capabilities |= HB_QSV_CAP_MSDK_API_1_6;
- hb_qsv_info->capabilities |= HB_QSV_CAP_H264_BPYRAMID;
+ query_capabilities(session, qsv_software_version, &qsv_software_info_avc);
+ query_capabilities(session, qsv_software_version, &qsv_software_info_hevc);
+ // now that we know which hardware encoders are
+ // available, we can set the preferred implementation
+ hb_qsv_impl_set_preferred("software");
}
- hb_qsv_info->capabilities |= HB_QSV_CAP_CORE_COPYFRAME;
+ MFXClose(session);
}
- // note: we pass a pointer to MFXInit but it never gets modified
- // let's make sure of it just to be safe though
- if (qsv_minimum_version.Major != HB_QSV_MINVERSION_MAJOR ||
- qsv_minimum_version.Minor != HB_QSV_MINVERSION_MINOR)
- {
- hb_error("hb_qsv_info_init: minimum version (%d.%d) was modified",
- qsv_minimum_version.Major,
- qsv_minimum_version.Minor);
+ // check for actual hardware support
+ if (MFXInit(MFX_IMPL_HARDWARE_ANY, &version, &session) == MFX_ERR_NONE)
+ {
+ // Media SDK hardware found, but check that our minimum is supported
+ //
+ // Note: this-party hardware (QSV_G0) is unsupported for the time being
+ MFXQueryVersion(session, &qsv_hardware_version);
+ if (qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G1 &&
+ HB_CHECK_MFX_VERSION(qsv_hardware_version,
+ HB_QSV_MINVERSION_MAJOR,
+ HB_QSV_MINVERSION_MINOR))
+ {
+ query_capabilities(session, qsv_hardware_version, &qsv_hardware_info_avc);
+ query_capabilities(session, qsv_hardware_version, &qsv_hardware_info_hevc);
+ // now that we know which hardware encoders are
+ // available, we can set the preferred implementation
+ hb_qsv_impl_set_preferred("hardware");
+ }
+ MFXClose(session);
}
// success
return 0;
}
-// we don't need it beyond this point
-#undef HB_CHECK_MFX_VERSION
-
-void hb_qsv_info_print()
+static void log_capabilities(int log_level, uint64_t caps, const char *prefix)
{
- if (hb_qsv_info == NULL)
+ if (!caps)
{
- hb_error("hb_qsv_info_print: QSV info not initialized!");
+ hb_deep_log(log_level, "%s none (standard feature set)", prefix);
}
+ else
+ {
+ hb_deep_log(log_level, "%s%s%s%s%s%s%s%s%s%s%s%s%s", prefix,
+ !(caps & HB_QSV_CAP_MSDK_API_1_6) ? "" : " api1.6",
+ !(caps & HB_QSV_CAP_B_REF_PYRAMID) ? "" : " bpyramid",
+ !(caps & HB_QSV_CAP_OPTION2_BREFTYPE) ? "" : " breftype",
+ !(caps & HB_QSV_CAP_RATECONTROL_LA) ? "" : " lookahead",
+ !(caps & HB_QSV_CAP_RATECONTROL_LAi) ? "" : " lookaheadi",
+ !(caps & HB_QSV_CAP_OPTION2_LA_DOWNS) ? "" : " lookaheadds",
+ !(caps & HB_QSV_CAP_RATECONTROL_ICQ) ? "" : " icq",
+ !(caps & HB_QSV_CAP_OPTION2_MBBRC) ? "" : " mbbrc",
+ !(caps & HB_QSV_CAP_OPTION2_EXTBRC) ? "" : " extbrc",
+ !(caps & HB_QSV_CAP_OPTION2_TRELLIS) ? "" : " trellis",
+ !(caps & HB_QSV_CAP_OPTION2_IB_ADAPT) ? "" : " adaptivei adaptiveb",
+ !(caps & HB_QSV_CAP_OPTION2_NMBSLICE) ? "" : " nummbperslice");
+ }
+}
- // is QSV available?
+void hb_qsv_info_print()
+{
+ // is QSV available and usable?
hb_log("Intel Quick Sync Video support: %s",
hb_qsv_available() ? "yes": "no");
- // if we have Quick Sync Video support, also print the details
+ // also print the details
+ if (qsv_hardware_version.Version)
+ {
+ hb_log(" - Intel Media SDK hardware: API %"PRIu16".%"PRIu16" (minimum: %"PRIu16".%"PRIu16")",
+ qsv_hardware_version.Major, qsv_hardware_version.Minor,
+ HB_QSV_MINVERSION_MAJOR, HB_QSV_MINVERSION_MINOR);
+ }
+ if (qsv_software_version.Version)
+ {
+ hb_log(" - Intel Media SDK software: API %"PRIu16".%"PRIu16" (minimum: %"PRIu16".%"PRIu16")",
+ qsv_software_version.Major, qsv_software_version.Minor,
+ HB_QSV_MINVERSION_MAJOR, HB_QSV_MINVERSION_MINOR);
+ }
if (hb_qsv_available())
{
- if (qsv_hardware_available)
+ if (hb_qsv_info_avc != NULL && hb_qsv_info_avc->available)
{
- hb_log(" - Intel Media SDK hardware: API %d.%d (minimum: %d.%d)",
- qsv_hardware_version.Major,
- qsv_hardware_version.Minor,
- qsv_minimum_version.Major,
- qsv_minimum_version.Minor);
+ hb_log(" - H.264 encoder: yes");
+ hb_log(" - preferred implementation: %s",
+ hb_qsv_impl_get_name(hb_qsv_info_avc->implementation));
+ if (qsv_hardware_info_avc.available)
+ {
+ log_capabilities(2, qsv_hardware_info_avc.capabilities,
+ " - capabilities (hardware): ");
+ }
+ if (qsv_software_info_avc.available)
+ {
+ log_capabilities(2, qsv_software_info_avc.capabilities,
+ " - capabilities (software): ");
+ }
}
- if (qsv_software_available)
+ else
{
- hb_log(" - Intel Media SDK software: API %d.%d (minimum: %d.%d)",
- qsv_software_version.Major,
- qsv_software_version.Minor,
- qsv_minimum_version.Major,
- qsv_minimum_version.Minor);
+ hb_log(" - H.264 encoder: no");
+ }
+ if (hb_qsv_info_hevc != NULL && hb_qsv_info_hevc->available)
+ {
+ hb_log(" - H.265 encoder: yes (unsupported)");
+ hb_log(" - preferred implementation: %s",
+ hb_qsv_impl_get_name(hb_qsv_info_hevc->implementation));
+ if (qsv_hardware_info_hevc.available)
+ {
+ log_capabilities(2, qsv_hardware_info_hevc.capabilities,
+ " - capabilities (hardware): ");
+ }
+ if (qsv_software_info_hevc.available)
+ {
+ log_capabilities(2, qsv_software_info_hevc.capabilities,
+ " - capabilities (software): ");
+ }
+ }
+ else
+ {
+ hb_log(" - H.265 encoder: no");
}
- hb_log(" - Preferred implementation: %s",
- hb_qsv_impl_get_name(preferred_implementation));
+ }
+}
+
+hb_qsv_info_t* hb_qsv_info_get(int encoder)
+{
+ switch (encoder)
+ {
+ case HB_VCODEC_QSV_H264:
+ return hb_qsv_info_avc;
+ default:
+ return NULL;
}
}
@@ -199,6 +616,18 @@ int hb_qsv_decode_is_enabled(hb_job_t *job)
(job->title->video_decode_support & HB_DECODE_SUPPORT_QSV));
}
+int hb_qsv_copyframe_is_slow(int encoder)
+{
+ hb_qsv_info_t *info = hb_qsv_info_get(encoder);
+ if (info != NULL && qsv_implementation_is_hardware(info->implementation))
+ {
+ // we should really check the driver version, but since it's not
+ // available, checking the API version is the best we can do :-(
+ return !HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 7);
+ }
+ return 0;
+}
+
int hb_qsv_codingoption_xlat(int val)
{
switch (HB_QSV_CLIP3(-1, 2, val))
@@ -305,12 +734,12 @@ float hb_qsv_atof(const char *str, int *err)
return v;
}
-int hb_qsv_param_parse(hb_qsv_param_t *param,
- const char *key, const char *value, int vcodec)
+int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info,
+ const char *key, const char *value)
{
float fvalue;
int ivalue, error = 0;
- if (param == NULL)
+ if (param == NULL || info == NULL)
{
return HB_QSV_PARAM_ERROR;
}
@@ -374,16 +803,9 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "b-pyramid"))
{
- if (hb_qsv_info->capabilities & HB_QSV_CAP_H264_BPYRAMID)
+ if (info->capabilities & HB_QSV_CAP_B_REF_PYRAMID)
{
- switch (vcodec)
- {
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoi(value, &error);
- break;
- default:
- return HB_QSV_PARAM_UNSUPPORTED;
- }
+ ivalue = hb_qsv_atoi(value, &error);
if (!error)
{
param->gop.b_pyramid = HB_QSV_CLIP3(-1, 1, ivalue);
@@ -409,6 +831,46 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
}
}
+ else if (!strcasecmp(key, "adaptive-i") ||
+ !strcasecmp(key, "i-adapt"))
+ {
+ if (info->capabilities & HB_QSV_CAP_OPTION2_IB_ADAPT)
+ {
+ ivalue = hb_qsv_atobool(value, &error);
+ if (!error)
+ {
+ param->codingOption2.AdaptiveI = hb_qsv_codingoption_xlat(ivalue);
+ }
+ }
+ else
+ {
+ return HB_QSV_PARAM_UNSUPPORTED;
+ }
+ }
+ else if (!strcasecmp(key, "adaptive-b") ||
+ !strcasecmp(key, "b-adapt"))
+ {
+ if (info->capabilities & HB_QSV_CAP_OPTION2_IB_ADAPT)
+ {
+ ivalue = hb_qsv_atobool(value, &error);
+ if (!error)
+ {
+ param->codingOption2.AdaptiveB = hb_qsv_codingoption_xlat(ivalue);
+ }
+ }
+ else
+ {
+ return HB_QSV_PARAM_UNSUPPORTED;
+ }
+ }
+ else if (!strcasecmp(key, "force-cqp"))
+ {
+ ivalue = hb_qsv_atobool(value, &error);
+ if (!error)
+ {
+ param->rc.icq = !ivalue;
+ }
+ }
else if (!strcasecmp(key, "cqp-offset-i"))
{
ivalue = hb_qsv_atoi(value, &error);
@@ -459,9 +921,9 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "cavlc") || !strcasecmp(key, "cabac"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
+ case MFX_CODEC_AVC:
ivalue = hb_qsv_atobool(value, &error);
break;
default:
@@ -478,10 +940,10 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "videoformat"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoindex(x264_vidformat_names, value, &error);
+ case MFX_CODEC_AVC:
+ ivalue = hb_qsv_atoindex(hb_h264_vidformat_names, value, &error);
break;
default:
return HB_QSV_PARAM_UNSUPPORTED;
@@ -493,10 +955,10 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "fullrange"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoindex(x264_fullrange_names, value, &error);
+ case MFX_CODEC_AVC:
+ ivalue = hb_qsv_atoindex(hb_h264_fullrange_names, value, &error);
break;
default:
return HB_QSV_PARAM_UNSUPPORTED;
@@ -508,10 +970,10 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "colorprim"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoindex(x264_colorprim_names, value, &error);
+ case MFX_CODEC_AVC:
+ ivalue = hb_qsv_atoindex(hb_h264_colorprim_names, value, &error);
break;
default:
return HB_QSV_PARAM_UNSUPPORTED;
@@ -524,10 +986,10 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "transfer"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoindex(x264_transfer_names, value, &error);
+ case MFX_CODEC_AVC:
+ ivalue = hb_qsv_atoindex(hb_h264_transfer_names, value, &error);
break;
default:
return HB_QSV_PARAM_UNSUPPORTED;
@@ -540,10 +1002,10 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "colormatrix"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoindex(x264_colmatrix_names, value, &error);
+ case MFX_CODEC_AVC:
+ ivalue = hb_qsv_atoindex(hb_h264_colmatrix_names, value, &error);
break;
default:
return HB_QSV_PARAM_UNSUPPORTED;
@@ -557,9 +1019,9 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
else if (!strcasecmp(key, "tff") ||
!strcasecmp(key, "interlaced"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
+ case MFX_CODEC_AVC:
ivalue = hb_qsv_atobool(value, &error);
break;
default:
@@ -574,9 +1036,9 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "bff"))
{
- switch (vcodec)
+ switch (info->codec_id)
{
- case HB_VCODEC_QSV_H264:
+ case MFX_CODEC_AVC:
ivalue = hb_qsv_atobool(value, &error);
break;
default:
@@ -591,7 +1053,7 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "mbbrc"))
{
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_MBBRC)
+ if (info->capabilities & HB_QSV_CAP_OPTION2_MBBRC)
{
ivalue = hb_qsv_atobool(value, &error);
if (!error)
@@ -606,7 +1068,7 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
}
else if (!strcasecmp(key, "extbrc"))
{
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_EXTBRC)
+ if (info->capabilities & HB_QSV_CAP_OPTION2_EXTBRC)
{
ivalue = hb_qsv_atobool(value, &error);
if (!error)
@@ -622,16 +1084,9 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
else if (!strcasecmp(key, "lookahead") ||
!strcasecmp(key, "la"))
{
- switch (vcodec)
- {
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atobool(value, &error);
- break;
- default:
- return HB_QSV_PARAM_UNSUPPORTED;
- }
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD)
+ if (info->capabilities & HB_QSV_CAP_RATECONTROL_LA)
{
+ ivalue = hb_qsv_atobool(value, &error);
if (!error)
{
param->rc.lookahead = ivalue;
@@ -645,16 +1100,9 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
else if (!strcasecmp(key, "lookahead-depth") ||
!strcasecmp(key, "la-depth"))
{
- switch (vcodec)
- {
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoi(value, &error);
- break;
- default:
- return HB_QSV_PARAM_UNSUPPORTED;
- }
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD)
+ if (info->capabilities & HB_QSV_CAP_RATECONTROL_LA)
{
+ ivalue = hb_qsv_atoi(value, &error);
if (!error)
{
// LookAheadDepth 10 will cause a hang with some driver versions
@@ -667,18 +1115,29 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
return HB_QSV_PARAM_UNSUPPORTED;
}
}
- else if (!strcasecmp(key, "trellis"))
+ else if (!strcasecmp(key, "lookahead-ds") ||
+ !strcasecmp(key, "la-ds"))
{
- switch (vcodec)
+ if (info->capabilities & HB_QSV_CAP_OPTION2_LA_DOWNS)
{
- case HB_VCODEC_QSV_H264:
- ivalue = hb_qsv_atoi(value, &error);
- break;
- default:
- return HB_QSV_PARAM_UNSUPPORTED;
+ ivalue = hb_qsv_atoi(value, &error);
+ if (!error)
+ {
+ param->codingOption2.LookAheadDS = HB_QSV_CLIP3(MFX_LOOKAHEAD_DS_UNKNOWN,
+ MFX_LOOKAHEAD_DS_4x,
+ ivalue);
+ }
+ }
+ else
+ {
+ return HB_QSV_PARAM_UNSUPPORTED;
}
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_TRELLIS)
+ }
+ else if (!strcasecmp(key, "trellis"))
+ {
+ if (info->capabilities & HB_QSV_CAP_OPTION2_TRELLIS)
{
+ ivalue = hb_qsv_atoi(value, &error);
if (!error)
{
param->codingOption2.Trellis = hb_qsv_trellisvalue_xlat(ivalue);
@@ -693,7 +1152,7 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
{
/*
* TODO:
- * - slice count control
+ * - slice count (num-slice/slices, num-mb-per-slice/slice-max-mbs)
* - open-gop
* - fake-interlaced (mfxExtCodingOption.FramePicture???)
* - intra-refresh
@@ -703,31 +1162,91 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
return error ? HB_QSV_PARAM_BAD_VALUE : HB_QSV_PARAM_OK;
}
+#ifdef HB_API_OLD_PRESET_GETTERS
+const char* const* hb_qsv_presets()
+{
+ return hb_qsv_preset_get_names();
+}
+#endif
+
const char* const* hb_qsv_preset_get_names()
{
- if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
+ if (qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G3)
{
return hb_qsv_preset_names2;
}
else
{
- return hb_qsv_preset_names1;
+ return hb_qsv_preset_names2;
}
}
-#ifdef HB_API_OLD_PRESET_GETTERS
-const char* const* hb_qsv_presets()
+const char* const* hb_qsv_profile_get_names(int encoder)
{
- return hb_qsv_preset_get_names();
+ switch (encoder)
+ {
+ case HB_VCODEC_QSV_H264:
+ return hb_h264_profile_names;
+ default:
+ return NULL;
+ }
+}
+
+const char* const* hb_qsv_level_get_names(int encoder)
+{
+ switch (encoder)
+ {
+ case HB_VCODEC_QSV_H264:
+ return hb_h264_level_names;
+ default:
+ return NULL;
+ }
+}
+
+const char* hb_qsv_video_quality_get_name(uint32_t codec)
+{
+ uint64_t caps;
+ switch (codec)
+ {
+ case HB_VCODEC_QSV_H264:
+ caps = hb_qsv_info_avc != NULL ? hb_qsv_info_avc->capabilities : 0;
+ return (caps & HB_QSV_CAP_RATECONTROL_ICQ) ? "ICQ" : "QP";
+
+ default:
+ return "QP";
+ }
+}
+
+void hb_qsv_video_quality_get_limits(uint32_t codec, float *low, float *high,
+ float *granularity, int *direction)
+{
+ uint64_t caps;
+ switch (codec)
+ {
+ case HB_VCODEC_QSV_H264:
+ caps = hb_qsv_info_avc != NULL ? hb_qsv_info_avc->capabilities : 0;
+ *direction = 1;
+ *granularity = 1.;
+ *low = (caps & HB_QSV_CAP_RATECONTROL_ICQ) ? 1. : 0.;
+ *high = 51.;
+ break;
+
+ default:
+ *direction = 1;
+ *granularity = 1.;
+ *low = 0.;
+ *high = 51.;
+ break;
+ }
}
-#endif
int hb_qsv_param_default_preset(hb_qsv_param_t *param,
- mfxVideoParam *videoParam, const char *preset)
+ mfxVideoParam *videoParam,
+ hb_qsv_info_t *info, const char *preset)
{
- if (param != NULL && videoParam != NULL)
+ if (param != NULL && videoParam != NULL && info != NULL)
{
- int ret = hb_qsv_param_default(param, videoParam);
+ int ret = hb_qsv_param_default(param, videoParam, info);
if (ret)
{
return ret;
@@ -769,7 +1288,7 @@ int hb_qsv_param_default_preset(hb_qsv_param_t *param,
* LookAhead: 0 (off)
* LookAheadDepth: Not Applicable
*/
- if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
+ if (qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G3)
{
param->rc.lookahead = 0;
param->videoParam->mfx.NumRefFrame = 1;
@@ -794,7 +1313,7 @@ int hb_qsv_param_default_preset(hb_qsv_param_t *param,
}
else if (!strcasecmp(preset, "speed"))
{
- if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
+ if (qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G3)
{
/*
* HSW TargetUsage: 6
@@ -840,9 +1359,10 @@ int hb_qsv_param_default_preset(hb_qsv_param_t *param,
return 0;
}
-int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam)
+int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam,
+ hb_qsv_info_t *info)
{
- if (param != NULL && videoParam != NULL)
+ if (param != NULL && videoParam != NULL && info != NULL)
{
// introduced in API 1.0
memset(&param->codingOption, 0, sizeof(mfxExtCodingOption));
@@ -902,13 +1422,21 @@ int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam)
// introduced in API 1.7
param->codingOption2.LookAheadDepth = 40;
param->codingOption2.Trellis = MFX_TRELLIS_OFF;
+ // introduced in API 1.8
+ param->codingOption2.RepeatPPS = MFX_CODINGOPTION_ON;
+ param->codingOption2.BRefType = MFX_B_REF_UNKNOWN; // controlled via gop.b_pyramid
+ param->codingOption2.AdaptiveI = MFX_CODINGOPTION_ON;
+ param->codingOption2.AdaptiveB = MFX_CODINGOPTION_ON;
+ param->codingOption2.LookAheadDS = MFX_LOOKAHEAD_DS_OFF;
+ param->codingOption2.NumMbPerSlice = 0;
// GOP & rate control
param->gop.b_pyramid = -1; // set automatically
param->gop.gop_pic_size = -1; // set automatically
param->gop.gop_ref_dist = -1; // set automatically
param->gop.int_ref_cycle_size = -1; // set automatically
- param->rc.lookahead = 1;
+ param->rc.icq = 1; // enabled by default (if supported)
+ param->rc.lookahead = 1; // enabled by default (if supported)
param->rc.cqp_offsets[0] = 0;
param->rc.cqp_offsets[1] = 2;
param->rc.cqp_offsets[2] = 4;
@@ -944,7 +1472,7 @@ int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam)
param->videoParam->ExtParam = param->ExtParamArray;
param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)&param->codingOption;
param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)&param->videoSignalInfo;
- if (hb_qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6)
+ if (info->capabilities & HB_QSV_CAP_MSDK_API_1_6)
{
param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)&param->codingOption2;
}
@@ -1015,9 +1543,37 @@ uint8_t hb_qsv_frametype_xlat(uint16_t qsv_frametype, uint16_t *out_flags)
return frametype;
}
-mfxIMPL hb_qsv_impl_get_preferred()
+int hb_qsv_impl_set_preferred(const char *name)
{
- return preferred_implementation;
+ if (name == NULL)
+ {
+ return -1;
+ }
+ if (!strcasecmp(name, "software"))
+ {
+ if (qsv_software_info_avc.available)
+ {
+ hb_qsv_info_avc = &qsv_software_info_avc;
+ }
+ if (qsv_software_info_hevc.available)
+ {
+ hb_qsv_info_hevc = &qsv_software_info_hevc;
+ }
+ return 0;
+ }
+ if (!strcasecmp(name, "hardware"))
+ {
+ if (qsv_hardware_info_avc.available)
+ {
+ hb_qsv_info_avc = &qsv_hardware_info_avc;
+ }
+ if (qsv_hardware_info_hevc.available)
+ {
+ hb_qsv_info_hevc = &qsv_hardware_info_hevc;
+ }
+ return 0;
+ }
+ return -1;
}
const char* hb_qsv_impl_get_name(int impl)
@@ -1048,4 +1604,12 @@ const char* hb_qsv_impl_get_name(int impl)
}
}
+void hb_qsv_force_workarounds()
+{
+ qsv_software_info_avc.capabilities &= ~HB_QSV_CAP_MSDK_API_1_6;
+ qsv_hardware_info_avc.capabilities &= ~HB_QSV_CAP_MSDK_API_1_6;
+ qsv_software_info_hevc.capabilities &= ~HB_QSV_CAP_MSDK_API_1_6;
+ qsv_hardware_info_hevc.capabilities &= ~HB_QSV_CAP_MSDK_API_1_6;
+}
+
#endif // USE_QSV