diff options
-rw-r--r-- | libhb/enc_qsv.c | 20 | ||||
-rw-r--r-- | libhb/qsv_common.c | 274 | ||||
-rw-r--r-- | libhb/qsv_common.h | 21 |
3 files changed, 246 insertions, 69 deletions
diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c index 6e52edb73..27cd378e7 100644 --- a/libhb/enc_qsv.c +++ b/libhb/enc_qsv.c @@ -911,14 +911,16 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job) memset(option1, 0, sizeof(mfxExtCodingOption)); option1->Header.BufferId = MFX_EXTBUFF_CODING_OPTION; option1->Header.BufferSz = sizeof(mfxExtCodingOption); - videoParam.ExtParam[videoParam.NumExtParam++] = (mfxExtBuffer*)option1; + if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION1) + { + videoParam.ExtParam[videoParam.NumExtParam++] = (mfxExtBuffer*)option1; + } // introduced in API 1.6 memset(option2, 0, sizeof(mfxExtCodingOption2)); option2->Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; option2->Header.BufferSz = sizeof(mfxExtCodingOption2); - if (pv->qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6) + if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION2) { - // attach to get the final output mfxExtCodingOption2 settings videoParam.ExtParam[videoParam.NumExtParam++] = (mfxExtBuffer*)option2; } err = MFXVideoENCODE_GetVideoParam(session, &videoParam); @@ -1099,10 +1101,16 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job) videoParam.mfx.FrameInfo.PicStruct); return -1; } - if (option1->CAVLC != MFX_CODINGOPTION_OFF) + if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION1) { - hb_log("encqsvInit: CAVLC %s", - hb_qsv_codingoption_get_name(option1->CAVLC)); + if (videoParam.mfx.CodecId == MFX_CODEC_AVC) + { + if (option1->CAVLC != MFX_CODINGOPTION_OFF) + { + hb_log("encqsvInit: CAVLC %s", + hb_qsv_codingoption_get_name(option1->CAVLC)); + } + } } if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION2_EXTBRC) { diff --git a/libhb/qsv_common.c b/libhb/qsv_common.c index ac15d7856..3b8179886 100644 --- a/libhb/qsv_common.c +++ b/libhb/qsv_common.c @@ -167,6 +167,39 @@ static void init_video_param(mfxVideoParam *videoParam) videoParam->IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; } +static void init_ext_video_signal_info(mfxExtVideoSignalInfo *extVideoSignalInfo) +{ + if (extVideoSignalInfo == NULL) + { + return; + } + + memset(extVideoSignalInfo, 0, sizeof(mfxExtVideoSignalInfo)); + extVideoSignalInfo->Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO; + extVideoSignalInfo->Header.BufferSz = sizeof(mfxExtVideoSignalInfo); + extVideoSignalInfo->VideoFormat = 5; // undefined + extVideoSignalInfo->VideoFullRange = 0; // TV range + extVideoSignalInfo->ColourDescriptionPresent = 0; // don't write to bitstream + extVideoSignalInfo->ColourPrimaries = 2; // undefined + extVideoSignalInfo->TransferCharacteristics = 2; // undefined + extVideoSignalInfo->MatrixCoefficients = 2; // undefined +} + +static void init_ext_coding_option(mfxExtCodingOption *extCodingOption) +{ + if (extCodingOption == NULL) + { + return; + } + + memset(extCodingOption, 0, sizeof(mfxExtCodingOption)); + extCodingOption->Header.BufferId = MFX_EXTBUFF_CODING_OPTION; + extCodingOption->Header.BufferSz = sizeof(mfxExtCodingOption); + extCodingOption->AUDelimiter = MFX_CODINGOPTION_OFF; + extCodingOption->PicTimingSEI = MFX_CODINGOPTION_OFF; + extCodingOption->CAVLC = MFX_CODINGOPTION_OFF; +} + static void init_ext_coding_option2(mfxExtCodingOption2 *extCodingOption2) { if (extCodingOption2 == NULL) @@ -209,7 +242,9 @@ static int query_capabilities(mfxSession session, mfxVersion version, hb_qsv_inf hb_list_t *mfxPluginList; mfxExtBuffer *videoExtParam[1]; mfxVideoParam videoParam, inputParam; - mfxExtCodingOption2 extCodingOption2; + mfxExtCodingOption extCodingOption; + mfxExtCodingOption2 extCodingOption2; + mfxExtVideoSignalInfo extVideoSignalInfo; /* Reset capabilities before querying */ info->capabilities = 0; @@ -361,7 +396,71 @@ static int query_capabilities(mfxSession session, mfxVersion version, hb_qsv_inf } /* - * Check mfxExtCodingOption2 fields. + * Determine whether mfxExtVideoSignalInfo is supported. + */ + if (HB_CHECK_MFX_VERSION(version, 1, 3)) + { + init_video_param(&videoParam); + videoParam.mfx.CodecId = info->codec_id; + + init_ext_video_signal_info(&extVideoSignalInfo); + videoParam.ExtParam = videoExtParam; + videoParam.ExtParam[0] = (mfxExtBuffer*)&extVideoSignalInfo; + videoParam.NumExtParam = 1; + + status = MFXVideoENCODE_Query(session, NULL, &videoParam); + if (status >= MFX_ERR_NONE) + { + /* Encoder can be configured via mfxExtVideoSignalInfo */ + info->capabilities |= HB_QSV_CAP_VUI_VSINFO; + } + else if (info->codec_id == MFX_CODEC_AVC) + { + /* + * This should not fail for AVC encoders, so we want to know + * about it - however, it may fail for other encoders (ignore) + */ + fprintf(stderr, + "hb_qsv_info_init: mfxExtVideoSignalInfo check" + " failed (0x%"PRIX32", 0x%"PRIX32", %d)\n", + info->codec_id, info->implementation, status); + } + } + + /* + * Determine whether mfxExtCodingOption is supported. + */ + if (HB_CHECK_MFX_VERSION(version, 1, 0)) + { + init_video_param(&videoParam); + videoParam.mfx.CodecId = info->codec_id; + + init_ext_coding_option(&extCodingOption); + videoParam.ExtParam = videoExtParam; + videoParam.ExtParam[0] = (mfxExtBuffer*)&extCodingOption; + videoParam.NumExtParam = 1; + + status = MFXVideoENCODE_Query(session, NULL, &videoParam); + if (status >= MFX_ERR_NONE) + { + /* Encoder can be configured via mfxExtCodingOption */ + info->capabilities |= HB_QSV_CAP_OPTION1; + } + else if (info->codec_id == MFX_CODEC_AVC) + { + /* + * This should not fail for AVC encoders, so we want to know + * about it - however, it may fail for other encoders (ignore) + */ + fprintf(stderr, + "hb_qsv_info_init: mfxExtCodingOption check" + " failed (0x%"PRIX32", 0x%"PRIX32", %d)\n", + info->codec_id, info->implementation, status); + } + } + + /* + * Determine whether mfxExtCodingOption2 and its fields are supported. * * Mode 2 suffers from false negatives with some drivers, whereas mode 1 * suffers from false positives instead. The latter is probably easier @@ -394,6 +493,9 @@ static int query_capabilities(mfxSession session, mfxVersion version, hb_qsv_inf fprintf(stderr, "-------------------\n"); #endif + /* Encoder can be configured via mfxExtCodingOption2 */ + info->capabilities |= HB_QSV_CAP_OPTION2; + /* * Sanitize API 1.6 fields: * @@ -598,25 +700,39 @@ static void log_capabilities(int log_level, uint64_t caps, const char *prefix) { strcat(buffer, " icq"); } - if (caps & HB_QSV_CAP_OPTION2_MBBRC) - { - strcat(buffer, " mbbrc"); - } - if (caps & HB_QSV_CAP_OPTION2_EXTBRC) + if (caps & HB_QSV_CAP_VUI_VSINFO) { - strcat(buffer, " extbrc"); + strcat(buffer, " vsinfo"); } - if (caps & HB_QSV_CAP_OPTION2_TRELLIS) + if (caps & HB_QSV_CAP_OPTION1) { - strcat(buffer, " trellis"); + strcat(buffer, " opt1"); } - if (caps & HB_QSV_CAP_OPTION2_IB_ADAPT) + if (caps & HB_QSV_CAP_OPTION2) { - strcat(buffer, " ib_adapt"); - } - if (caps & HB_QSV_CAP_OPTION2_NMPSLICE) - { - strcat(buffer, " nmpslice"); + { + strcat(buffer, " opt2"); + } + if (caps & HB_QSV_CAP_OPTION2_MBBRC) + { + strcat(buffer, "+mbbrc"); + } + if (caps & HB_QSV_CAP_OPTION2_EXTBRC) + { + strcat(buffer, "+extbrc"); + } + if (caps & HB_QSV_CAP_OPTION2_TRELLIS) + { + strcat(buffer, "+trellis"); + } + if (caps & HB_QSV_CAP_OPTION2_IB_ADAPT) + { + strcat(buffer, "+ib_adapt"); + } + if (caps & HB_QSV_CAP_OPTION2_NMPSLICE) + { + strcat(buffer, "+nmpslice"); + } } hb_deep_log(log_level, "%s%s", prefix, @@ -1022,13 +1138,20 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, } else if (!strcasecmp(key, "cavlc") || !strcasecmp(key, "cabac")) { - switch (info->codec_id) + if (info->capabilities & HB_QSV_CAP_OPTION1) { - case MFX_CODEC_AVC: - ivalue = hb_qsv_atobool(value, &error); - break; - default: - return HB_QSV_PARAM_UNSUPPORTED; + switch (info->codec_id) + { + case MFX_CODEC_AVC: + ivalue = hb_qsv_atobool(value, &error); + break; + default: + return HB_QSV_PARAM_UNSUPPORTED; + } + } + else + { + return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { @@ -1041,13 +1164,20 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, } else if (!strcasecmp(key, "videoformat")) { - switch (info->codec_id) + if (info->capabilities & HB_QSV_CAP_VUI_VSINFO) { - case MFX_CODEC_AVC: - ivalue = hb_qsv_atoindex(hb_h264_vidformat_names, value, &error); - break; - default: - return HB_QSV_PARAM_UNSUPPORTED; + switch (info->codec_id) + { + case MFX_CODEC_AVC: + ivalue = hb_qsv_atoindex(hb_h264_vidformat_names, value, &error); + break; + default: + return HB_QSV_PARAM_UNSUPPORTED; + } + } + else + { + return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { @@ -1056,13 +1186,20 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, } else if (!strcasecmp(key, "fullrange")) { - switch (info->codec_id) + if (info->capabilities & HB_QSV_CAP_VUI_VSINFO) { - case MFX_CODEC_AVC: - ivalue = hb_qsv_atoindex(hb_h264_fullrange_names, value, &error); - break; - default: - return HB_QSV_PARAM_UNSUPPORTED; + switch (info->codec_id) + { + case MFX_CODEC_AVC: + ivalue = hb_qsv_atoindex(hb_h264_fullrange_names, value, &error); + break; + default: + return HB_QSV_PARAM_UNSUPPORTED; + } + } + else + { + return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { @@ -1071,13 +1208,20 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, } else if (!strcasecmp(key, "colorprim")) { - switch (info->codec_id) + if (info->capabilities & HB_QSV_CAP_VUI_VSINFO) { - case MFX_CODEC_AVC: - ivalue = hb_qsv_atoindex(hb_h264_colorprim_names, value, &error); - break; - default: - return HB_QSV_PARAM_UNSUPPORTED; + switch (info->codec_id) + { + case MFX_CODEC_AVC: + ivalue = hb_qsv_atoindex(hb_h264_colorprim_names, value, &error); + break; + default: + return HB_QSV_PARAM_UNSUPPORTED; + } + } + else + { + return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { @@ -1087,13 +1231,20 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, } else if (!strcasecmp(key, "transfer")) { - switch (info->codec_id) + if (info->capabilities & HB_QSV_CAP_VUI_VSINFO) { - case MFX_CODEC_AVC: - ivalue = hb_qsv_atoindex(hb_h264_transfer_names, value, &error); - break; - default: - return HB_QSV_PARAM_UNSUPPORTED; + switch (info->codec_id) + { + case MFX_CODEC_AVC: + ivalue = hb_qsv_atoindex(hb_h264_transfer_names, value, &error); + break; + default: + return HB_QSV_PARAM_UNSUPPORTED; + } + } + else + { + return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { @@ -1103,13 +1254,20 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, } else if (!strcasecmp(key, "colormatrix")) { - switch (info->codec_id) + if (info->capabilities & HB_QSV_CAP_VUI_VSINFO) { - case MFX_CODEC_AVC: - ivalue = hb_qsv_atoindex(hb_h264_colmatrix_names, value, &error); - break; - default: - return HB_QSV_PARAM_UNSUPPORTED; + switch (info->codec_id) + { + case MFX_CODEC_AVC: + ivalue = hb_qsv_atoindex(hb_h264_colmatrix_names, value, &error); + break; + default: + return HB_QSV_PARAM_UNSUPPORTED; + } + } + else + { + return HB_QSV_PARAM_UNSUPPORTED; } if (!error) { @@ -1622,9 +1780,15 @@ int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam, // 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 (info->capabilities & HB_QSV_CAP_MSDK_API_1_6) + if (info->capabilities & HB_QSV_CAP_VUI_VSINFO) + { + param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)¶m->videoSignalInfo; + } + if (info->capabilities & HB_QSV_CAP_OPTION1) + { + param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)¶m->codingOption; + } + if (info->capabilities & HB_QSV_CAP_OPTION2) { param->videoParam->ExtParam[param->videoParam->NumExtParam++] = (mfxExtBuffer*)¶m->codingOption2; } diff --git a/libhb/qsv_common.h b/libhb/qsv_common.h index 9ac2085ec..da045422e 100644 --- a/libhb/qsv_common.h +++ b/libhb/qsv_common.h @@ -42,18 +42,23 @@ typedef struct hb_qsv_info_s #define HB_QSV_CAP_MSDK_API_1_6 (1LL << 0) // H.264, H.265: B-frames can be used as references #define HB_QSV_CAP_B_REF_PYRAMID (1LL << 1) + // mfxExtVideoSignalInfo +#define HB_QSV_CAP_VUI_VSINFO (1LL << 3) // optional rate control methods #define HB_QSV_CAP_RATECONTROL_LA (1LL << 10) #define HB_QSV_CAP_RATECONTROL_LAi (1LL << 11) #define HB_QSV_CAP_RATECONTROL_ICQ (1LL << 12) - // mfxExtCodingOption2 fields -#define HB_QSV_CAP_OPTION2_MBBRC (1LL << 20) -#define HB_QSV_CAP_OPTION2_EXTBRC (1LL << 21) -#define HB_QSV_CAP_OPTION2_TRELLIS (1LL << 22) -#define HB_QSV_CAP_OPTION2_BREFTYPE (1LL << 23) -#define HB_QSV_CAP_OPTION2_IB_ADAPT (1LL << 24) -#define HB_QSV_CAP_OPTION2_LA_DOWNS (1LL << 25) -#define HB_QSV_CAP_OPTION2_NMPSLICE (1LL << 26) + // mfxExtCodingOption +#define HB_QSV_CAP_OPTION1 (1LL << 20) + // mfxExtCodingOption2 +#define HB_QSV_CAP_OPTION2 (1LL << 30) +#define HB_QSV_CAP_OPTION2_MBBRC (1LL << 31) +#define HB_QSV_CAP_OPTION2_EXTBRC (1LL << 32) +#define HB_QSV_CAP_OPTION2_TRELLIS (1LL << 33) +#define HB_QSV_CAP_OPTION2_BREFTYPE (1LL << 34) +#define HB_QSV_CAP_OPTION2_IB_ADAPT (1LL << 35) +#define HB_QSV_CAP_OPTION2_LA_DOWNS (1LL << 36) +#define HB_QSV_CAP_OPTION2_NMPSLICE (1LL << 37) // TODO: add maximum encode resolution, etc. } hb_qsv_info_t; |