/* qsv_common.c * * Copyright (c) 2003-2013 HandBrake Team * This file is part of the HandBrake source code. * Homepage: . * It may be used under the terms of the GNU General Public License v2. * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html */ #ifdef USE_QSV #include "hb.h" #include "ports.h" #include "common.h" #include "hb_dict.h" #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; // 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) int hb_qsv_available() { return hb_qsv_info != NULL && (qsv_hardware_available || qsv_software_available); } int hb_qsv_info_init() { static int init_done = 0; if (init_done) return (hb_qsv_info == NULL); init_done = 1; hb_qsv_info = calloc(1, sizeof(*hb_qsv_info)); if (hb_qsv_info == NULL) { hb_error("hb_qsv_info_init: alloc failure"); return -1; } mfxSession session; qsv_minimum_version.Major = HB_QSV_MINVERSION_MAJOR; qsv_minimum_version.Minor = HB_QSV_MINVERSION_MINOR; // check for software fallback if (MFXInit(MFX_IMPL_SOFTWARE, &qsv_minimum_version, &session) == MFX_ERR_NONE) { 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); } // check for actual hardware support if (MFXInit(MFX_IMPL_HARDWARE_ANY|MFX_IMPL_VIA_ANY, &qsv_minimum_version, &session) == 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) { 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); } MFXClose(session); } // check for version-specific or hardware-specific capabilities // we only use software as a fallback, so check hardware first if (qsv_hardware_available) { if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 6)) { hb_qsv_info->capabilities |= HB_QSV_CAP_MSDK_API_1_6; hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_EXTBRC; } if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 7)) { // 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_get_cpu_platform() == HB_CPU_PLATFORM_INTEL_HSW) { if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 6)) { hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_MBBRC; } if (HB_CHECK_MFX_VERSION(qsv_hardware_version, 1, 7)) { hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_TRELLIS; hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_LOOKAHEAD; } hb_qsv_info->capabilities |= HB_QSV_CAP_H264_BPYRAMID; } } else if (qsv_software_available) { if (HB_CHECK_MFX_VERSION(qsv_software_version, 1, 6)) { hb_qsv_info->capabilities |= HB_QSV_CAP_MSDK_API_1_6; hb_qsv_info->capabilities |= HB_QSV_CAP_H264_BPYRAMID; } hb_qsv_info->capabilities |= HB_QSV_CAP_CORE_COPYFRAME; } // 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); } // success return 0; } // we don't need it beyond this point #undef HB_CHECK_MFX_VERSION void hb_qsv_info_print() { if (hb_qsv_info == NULL) { hb_error("hb_qsv_info_print: QSV info not initialized!"); } // is QSV available? hb_log("Intel Quick Sync Video support: %s", hb_qsv_available() ? "yes": "no"); // if we have Quick Sync Video support, also print the details if (hb_qsv_available()) { if (qsv_hardware_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); } if (qsv_software_available) { 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(" - Preferred implementation: %s", hb_qsv_impl_get_name(preferred_implementation)); } } const char* hb_qsv_decode_get_codec_name(enum AVCodecID codec_id) { switch (codec_id) { case AV_CODEC_ID_H264: return "h264_qsv"; default: return NULL; } } int hb_qsv_decode_is_enabled(hb_job_t *job) { return ((job != NULL && job->qsv.decode) && (job->vcodec & HB_VCODEC_QSV_MASK) && (job->title->video_decode_support & HB_DECODE_SUPPORT_QSV)); } int hb_qsv_codingoption_xlat(int val) { switch (HB_QSV_CLIP3(-1, 2, val)) { case 0: return MFX_CODINGOPTION_OFF; case 1: case 2: // MFX_CODINGOPTION_ADAPTIVE, reserved return MFX_CODINGOPTION_ON; case -1: default: return MFX_CODINGOPTION_UNKNOWN; } } int hb_qsv_trellisvalue_xlat(int val) { switch (HB_QSV_CLIP3(0, 3, val)) { case 0: return MFX_TRELLIS_OFF; case 1: // I-frames only return MFX_TRELLIS_I; case 2: // I- and P-frames return MFX_TRELLIS_I|MFX_TRELLIS_P; case 3: // all frames return MFX_TRELLIS_I|MFX_TRELLIS_P|MFX_TRELLIS_B; default: return MFX_TRELLIS_UNKNOWN; } } const char* hb_qsv_codingoption_get_name(int val) { switch (val) { case MFX_CODINGOPTION_ON: return "on"; case MFX_CODINGOPTION_OFF: return "off"; case MFX_CODINGOPTION_ADAPTIVE: return "adaptive"; case MFX_CODINGOPTION_UNKNOWN: return "unknown (auto)"; default: return NULL; } } int hb_qsv_atoindex(const char* const *arr, const char *str, int *err) { int i; for (i = 0; arr[i] != NULL; i++) { if (!strcasecmp(arr[i], str)) { break; } } *err = (arr[i] == NULL); return i; } // adapted from libx264 int hb_qsv_atobool(const char *str, int *err) { if (!strcasecmp(str, "1") || !strcasecmp(str, "yes") || !strcasecmp(str, "true")) { return 1; } if (!strcasecmp(str, "0") || !strcasecmp(str, "no") || !strcasecmp(str, "false")) { return 0; } *err = 1; return 0; } // adapted from libx264 int hb_qsv_atoi(const char *str, int *err) { char *end; int v = strtol(str, &end, 0); if (end == str || end[0] != '\0') { *err = 1; } return v; } // adapted from libx264 float hb_qsv_atof(const char *str, int *err) { char *end; float v = strtod(str, &end); if (end == str || end[0] != '\0') { *err = 1; } return v; } int hb_qsv_param_parse(hb_qsv_param_t *param, const char *key, const char *value, int vcodec) { float fvalue; int ivalue, error = 0; if (param == NULL) { return HB_QSV_PARAM_ERROR; } if (value == NULL || value[0] == '\0') { value = "true"; } else if (value[0] == '=') { value++; } if (key == NULL || key[0] == '\0') { return HB_QSV_PARAM_BAD_NAME; } else if (!strncasecmp(key, "no-", 3)) { key += 3; value = hb_qsv_atobool(value, &error) ? "false" : "true"; if (error) { return HB_QSV_PARAM_BAD_VALUE; } } if (!strcasecmp(key, "target-usage") || !strcasecmp(key, "tu")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->videoParam->mfx.TargetUsage = HB_QSV_CLIP3(MFX_TARGETUSAGE_1, MFX_TARGETUSAGE_7, ivalue); } } else if (!strcasecmp(key, "num-ref-frame") || !strcasecmp(key, "ref")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->videoParam->mfx.NumRefFrame = HB_QSV_CLIP3(0, 16, ivalue); } } else if (!strcasecmp(key, "gop-ref-dist")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->gop.gop_ref_dist = HB_QSV_CLIP3(-1, 32, ivalue); } } else if (!strcasecmp(key, "gop-pic-size") || !strcasecmp(key, "keyint")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->gop.gop_pic_size = HB_QSV_CLIP3(-1, UINT16_MAX, ivalue); } } else if (!strcasecmp(key, "b-pyramid")) { if (hb_qsv_info->capabilities & HB_QSV_CAP_H264_BPYRAMID) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atoi(value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->gop.b_pyramid = HB_QSV_CLIP3(-1, 1, ivalue); } } else { return HB_QSV_PARAM_UNSUPPORTED; } } else if (!strcasecmp(key, "scenecut")) { ivalue = hb_qsv_atobool(value, &error); if (!error) { if (!ivalue) { param->videoParam->mfx.GopOptFlag |= MFX_GOP_STRICT; } else { param->videoParam->mfx.GopOptFlag &= ~MFX_GOP_STRICT; } } } else if (!strcasecmp(key, "cqp-offset-i")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->rc.cqp_offsets[0] = HB_QSV_CLIP3(INT16_MIN, INT16_MAX, ivalue); } } else if (!strcasecmp(key, "cqp-offset-p")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->rc.cqp_offsets[1] = HB_QSV_CLIP3(INT16_MIN, INT16_MAX, ivalue); } } else if (!strcasecmp(key, "cqp-offset-b")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->rc.cqp_offsets[2] = HB_QSV_CLIP3(INT16_MIN, INT16_MAX, ivalue); } } else if (!strcasecmp(key, "vbv-init")) { fvalue = hb_qsv_atof(value, &error); if (!error) { param->rc.vbv_buffer_init = HB_QSV_CLIP3(0, UINT16_MAX, fvalue); } } else if (!strcasecmp(key, "vbv-bufsize")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->rc.vbv_buffer_size = HB_QSV_CLIP3(0, UINT16_MAX, ivalue); } } else if (!strcasecmp(key, "vbv-maxrate")) { ivalue = hb_qsv_atoi(value, &error); if (!error) { param->rc.vbv_max_bitrate = HB_QSV_CLIP3(0, UINT16_MAX, ivalue); } } else if (!strcasecmp(key, "cavlc") || !strcasecmp(key, "cabac")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atobool(value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { if (!strcasecmp(key, "cabac")) { ivalue = !ivalue; } param->codingOption.CAVLC = hb_qsv_codingoption_xlat(ivalue); } } else if (!strcasecmp(key, "videoformat")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atoindex(x264_vidformat_names, value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->videoSignalInfo.VideoFormat = ivalue; } } else if (!strcasecmp(key, "fullrange")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atoindex(x264_fullrange_names, value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->videoSignalInfo.VideoFullRange = ivalue; } } else if (!strcasecmp(key, "colorprim")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atoindex(x264_colorprim_names, value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->videoSignalInfo.ColourDescriptionPresent = 1; param->videoSignalInfo.ColourPrimaries = ivalue; } } else if (!strcasecmp(key, "transfer")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atoindex(x264_transfer_names, value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->videoSignalInfo.ColourDescriptionPresent = 1; param->videoSignalInfo.TransferCharacteristics = ivalue; } } else if (!strcasecmp(key, "colormatrix")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atoindex(x264_colmatrix_names, value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->videoSignalInfo.ColourDescriptionPresent = 1; param->videoSignalInfo.MatrixCoefficients = ivalue; } } else if (!strcasecmp(key, "tff") || !strcasecmp(key, "interlaced")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atobool(value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->videoParam->mfx.FrameInfo.PicStruct = (ivalue ? MFX_PICSTRUCT_FIELD_TFF : MFX_PICSTRUCT_PROGRESSIVE); } } else if (!strcasecmp(key, "bff")) { switch (vcodec) { case HB_VCODEC_QSV_H264: ivalue = hb_qsv_atobool(value, &error); break; default: return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { param->videoParam->mfx.FrameInfo.PicStruct = (ivalue ? MFX_PICSTRUCT_FIELD_BFF : MFX_PICSTRUCT_PROGRESSIVE); } } else if (!strcasecmp(key, "mbbrc")) { if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_MBBRC) { ivalue = hb_qsv_atobool(value, &error); if (!error) { param->codingOption2.MBBRC = hb_qsv_codingoption_xlat(ivalue); } } else { return HB_QSV_PARAM_UNSUPPORTED; } } else if (!strcasecmp(key, "extbrc")) { if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_EXTBRC) { ivalue = hb_qsv_atobool(value, &error); if (!error) { param->codingOption2.ExtBRC = hb_qsv_codingoption_xlat(ivalue); } } else { return HB_QSV_PARAM_UNSUPPORTED; } } 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 (!error) { param->rc.lookahead = ivalue; } } else { return HB_QSV_PARAM_UNSUPPORTED; } } 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 (!error) { // LookAheadDepth 10 will cause a hang with some driver versions param->codingOption2.LookAheadDepth = HB_QSV_CLIP3(11, 100, ivalue); } } else { return HB_QSV_PARAM_UNSUPPORTED; } } else if (!strcasecmp(key, "trellis")) { 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_TRELLIS) { if (!error) { param->codingOption2.Trellis = hb_qsv_trellisvalue_xlat(ivalue); } } else { return HB_QSV_PARAM_UNSUPPORTED; } } else { /* * TODO: * - slice count control * - open-gop * - fake-interlaced (mfxExtCodingOption.FramePicture???) * - intra-refresh */ return HB_QSV_PARAM_BAD_NAME; } return error ? HB_QSV_PARAM_BAD_VALUE : HB_QSV_PARAM_OK; } const char* const* hb_qsv_preset_get_names() { if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW) { return hb_qsv_preset_names2; } else { return hb_qsv_preset_names1; } } #ifdef HB_API_OLD_PRESET_GETTERS const char* const* hb_qsv_presets() { return hb_qsv_preset_get_names(); } #endif int hb_qsv_param_default_preset(hb_qsv_param_t *param, mfxVideoParam *videoParam, const char *preset) { if (param != NULL && videoParam != NULL) { int ret = hb_qsv_param_default(param, videoParam); if (ret) { return ret; } } else { hb_error("hb_qsv_param_default_preset: invalid pointer(s)"); return -1; } if (preset != NULL && preset[0] != '\0') { if (!strcasecmp(preset, "quality")) { /* * HSW TargetUsage: 2 * NumRefFrame: 0 * GopRefDist: 4 (CQP), 3 (VBR) -> -1 (set by encoder) * GopPicSize: 32 (CQP), 1 second (VBR) -> -1 (set by encoder) * BPyramid: 1 (CQP), 0 (VBR) -> -1 (set by encoder) * LookAhead: 1 (on) * LookAheadDepth: 40 * * * SNB * IVB Preset Not Available * * Note: this preset is the libhb default (like x264's "medium"). */ } else if (!strcasecmp(preset, "balanced")) { /* * HSW TargetUsage: 4 * NumRefFrame: 1 * GopRefDist: 4 (CQP), 3 (VBR) -> -1 (set by encoder) * GopPicSize: 32 (CQP), 1 second (VBR) -> -1 (set by encoder) * BPyramid: 1 (CQP), 0 (VBR) -> -1 (set by encoder) * LookAhead: 0 (off) * LookAheadDepth: Not Applicable */ if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW) { param->rc.lookahead = 0; param->videoParam->mfx.NumRefFrame = 1; param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_4; } else { /* * SNB * IVB TargetUsage: 2 * NumRefFrame: 0 * GopRefDist: 4 (CQP), 3 (VBR) -> -1 (set by encoder) * GopPicSize: 32 (CQP), 1 second (VBR) -> -1 (set by encoder) * BPyramid: Not Applicable * LookAhead: Not Applicable * LookAheadDepth: Not Applicable * * Note: this preset is not the libhb default, * but the settings are the same so do nothing. */ } } else if (!strcasecmp(preset, "speed")) { if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW) { /* * HSW TargetUsage: 6 * NumRefFrame: 0 (CQP), 1 (VBR) -> see note * GopRefDist: 4 (CQP), 3 (VBR) -> -1 (set by encoder) * GopPicSize: 32 (CQP), 1 second (VBR) -> -1 (set by encoder) * BPyramid: 1 (CQP), 0 (VBR) -> -1 (set by encoder) * LookAhead: 0 (off) * LookAheadDepth: Not Applicable * * Note: NumRefFrame depends on the RC method, which we don't * know here. Rather than have an additional variable and * having the encoder set it, we set it to 1 and let the * B-pyramid code sanitize it. Since BPyramid is 1 w/CQP, * the result (3) is the same as what MSDK would pick for * NumRefFrame 0 GopRefDist 4 GopPicSize 32. */ param->rc.lookahead = 0; param->videoParam->mfx.NumRefFrame = 1; param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_6; } else { /* * SNB * IVB TargetUsage: 4 * NumRefFrame: 0 * GopRefDist: 4 (CQP), 3 (VBR) -> -1 (set by encoder) * GopPicSize: 32 (CQP), 1 second (VBR) -> -1 (set by encoder) * BPyramid: Not Applicable * LookAhead: Not Applicable * LookAheadDepth: Not Applicable */ param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_4; } } else { hb_error("hb_qsv_param_default_preset: invalid preset '%s'", preset); return -1; } } return 0; } int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam) { if (param != NULL && videoParam != NULL) { // introduced in API 1.0 memset(¶m->codingOption, 0, sizeof(mfxExtCodingOption)); param->codingOption.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; param->codingOption.Header.BufferSz = sizeof(mfxExtCodingOption); param->codingOption.MECostType = 0; // reserved, must be 0 param->codingOption.MESearchType = 0; // reserved, must be 0 param->codingOption.MVSearchWindow.x = 0; // reserved, must be 0 param->codingOption.MVSearchWindow.y = 0; // reserved, must be 0 param->codingOption.RefPicListReordering = 0; // reserved, must be 0 param->codingOption.IntraPredBlockSize = 0; // reserved, must be 0 param->codingOption.InterPredBlockSize = 0; // reserved, must be 0 param->codingOption.MVPrecision = 0; // reserved, must be 0 param->codingOption.EndOfSequence = MFX_CODINGOPTION_UNKNOWN; param->codingOption.RateDistortionOpt = MFX_CODINGOPTION_UNKNOWN; param->codingOption.ResetRefList = MFX_CODINGOPTION_UNKNOWN; param->codingOption.MaxDecFrameBuffering = 0; // unspecified param->codingOption.AUDelimiter = MFX_CODINGOPTION_OFF; param->codingOption.SingleSeiNalUnit = MFX_CODINGOPTION_UNKNOWN; param->codingOption.PicTimingSEI = MFX_CODINGOPTION_OFF; param->codingOption.VuiNalHrdParameters = MFX_CODINGOPTION_UNKNOWN; param->codingOption.FramePicture = MFX_CODINGOPTION_UNKNOWN; param->codingOption.CAVLC = MFX_CODINGOPTION_OFF; // introduced in API 1.3 param->codingOption.RefPicMarkRep = MFX_CODINGOPTION_UNKNOWN; param->codingOption.FieldOutput = MFX_CODINGOPTION_UNKNOWN; param->codingOption.NalHrdConformance = MFX_CODINGOPTION_UNKNOWN; param->codingOption.SingleSeiNalUnit = MFX_CODINGOPTION_UNKNOWN; param->codingOption.VuiVclHrdParameters = MFX_CODINGOPTION_UNKNOWN; // introduced in API 1.4 param->codingOption.ViewOutput = MFX_CODINGOPTION_UNKNOWN; // introduced in API 1.6 param->codingOption.RecoveryPointSEI = MFX_CODINGOPTION_UNKNOWN; // introduced in API 1.3 memset(¶m->videoSignalInfo, 0, sizeof(mfxExtVideoSignalInfo)); param->videoSignalInfo.Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO; param->videoSignalInfo.Header.BufferSz = sizeof(mfxExtVideoSignalInfo); param->videoSignalInfo.VideoFormat = 5; // undefined param->videoSignalInfo.VideoFullRange = 0; // TV range param->videoSignalInfo.ColourDescriptionPresent = 0; // don't write to bitstream param->videoSignalInfo.ColourPrimaries = 2; // undefined param->videoSignalInfo.TransferCharacteristics = 2; // undefined param->videoSignalInfo.MatrixCoefficients = 2; // undefined // introduced in API 1.6 memset(¶m->codingOption2, 0, sizeof(mfxExtCodingOption2)); param->codingOption2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; param->codingOption2.Header.BufferSz = sizeof(mfxExtCodingOption2); param->codingOption2.IntRefType = 0; param->codingOption2.IntRefCycleSize = 2; param->codingOption2.IntRefQPDelta = 0; param->codingOption2.MaxFrameSize = 0; param->codingOption2.BitrateLimit = MFX_CODINGOPTION_ON; param->codingOption2.MBBRC = MFX_CODINGOPTION_ON; param->codingOption2.ExtBRC = MFX_CODINGOPTION_OFF; // introduced in API 1.7 param->codingOption2.LookAheadDepth = 40; param->codingOption2.Trellis = MFX_TRELLIS_OFF; // 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.cqp_offsets[0] = 0; param->rc.cqp_offsets[1] = 2; param->rc.cqp_offsets[2] = 4; param->rc.vbv_max_bitrate = 0; // set automatically param->rc.vbv_buffer_size = 0; // set automatically param->rc.vbv_buffer_init = .0; // set automatically // introduced in API 1.0 memset(videoParam, 0, sizeof(mfxVideoParam)); param->videoParam = videoParam; param->videoParam->Protected = 0; // reserved, must be 0 param->videoParam->NumExtParam = 0; param->videoParam->IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_2; param->videoParam->mfx.GopOptFlag = MFX_GOP_CLOSED; param->videoParam->mfx.NumThread = 0; // deprecated, must be 0 param->videoParam->mfx.EncodedOrder = 0; // input is in display order param->videoParam->mfx.IdrInterval = 0; // all I-frames are IDR param->videoParam->mfx.NumSlice = 0; // use Media SDK default param->videoParam->mfx.NumRefFrame = 0; // use Media SDK default param->videoParam->mfx.GopPicSize = 0; // use Media SDK default param->videoParam->mfx.GopRefDist = 0; // use Media SDK default // introduced in API 1.1 param->videoParam->AsyncDepth = AV_QSV_ASYNC_DEPTH_DEFAULT; // introduced in API 1.3 param->videoParam->mfx.BRCParamMultiplier = 0; // no multiplier // FrameInfo: set by video encoder, except PicStruct param->videoParam->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; // attach supported mfxExtBuffer structures to the mfxVideoParam param->videoParam->NumExtParam = 0; param->videoParam->ExtParam = param->ExtParamArray; param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)¶m->codingOption; param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)¶m->videoSignalInfo; if (hb_qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6) { param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)¶m->codingOption2; } } else { hb_error("hb_qsv_param_default: invalid pointer(s)"); return -1; } return 0; } const char* hb_qsv_frametype_name(uint16_t qsv_frametype) { if (qsv_frametype & MFX_FRAMETYPE_IDR) { return qsv_frametype & MFX_FRAMETYPE_REF ? "IDR (ref)" : "IDR"; } else if (qsv_frametype & MFX_FRAMETYPE_I) { return qsv_frametype & MFX_FRAMETYPE_REF ? "I (ref)" : "I"; } else if (qsv_frametype & MFX_FRAMETYPE_P) { return qsv_frametype & MFX_FRAMETYPE_REF ? "P (ref)" : "P"; } else if (qsv_frametype & MFX_FRAMETYPE_B) { return qsv_frametype & MFX_FRAMETYPE_REF ? "B (ref)" : "B"; } else { return "unknown"; } } uint8_t hb_qsv_frametype_xlat(uint16_t qsv_frametype, uint16_t *out_flags) { uint16_t flags = 0; uint8_t frametype = 0; if (qsv_frametype & MFX_FRAMETYPE_IDR) { frametype = HB_FRAME_IDR; } else if (qsv_frametype & MFX_FRAMETYPE_I) { frametype = HB_FRAME_I; } else if (qsv_frametype & MFX_FRAMETYPE_P) { frametype = HB_FRAME_P; } else if (qsv_frametype & MFX_FRAMETYPE_B) { frametype = HB_FRAME_B; } if (qsv_frametype & MFX_FRAMETYPE_REF) { flags |= HB_FRAME_REF; } if (out_flags != NULL) { *out_flags = flags; } return frametype; } mfxIMPL hb_qsv_impl_get_preferred() { return preferred_implementation; } const char* hb_qsv_impl_get_name(int impl) { switch (MFX_IMPL_BASETYPE(impl)) { case MFX_IMPL_SOFTWARE: return "software"; case MFX_IMPL_HARDWARE: return "hardware (1)"; case MFX_IMPL_HARDWARE2: return "hardware (2)"; case MFX_IMPL_HARDWARE3: return "hardware (3)"; case MFX_IMPL_HARDWARE4: return "hardware (4)"; case MFX_IMPL_HARDWARE_ANY: return "hardware (any)"; case MFX_IMPL_AUTO: return "automatic"; case MFX_IMPL_AUTO_ANY: return "automatic (any)"; default: return NULL; } } #endif // USE_QSV