diff options
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/enc_qsv.c | 105 | ||||
-rw-r--r-- | libhb/qsv_common.c | 172 | ||||
-rw-r--r-- | libhb/qsv_common.h | 17 |
3 files changed, 207 insertions, 87 deletions
diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c index fdb6a91f6..6e52edb73 100644 --- a/libhb/enc_qsv.c +++ b/libhb/enc_qsv.c @@ -152,43 +152,6 @@ static int64_t get_frame_duration(hb_work_private_t *pv, hb_buffer_t *buf) return pv->frame_duration[i]; } -static const char* qsv_h264_profile_xlat(int profile) -{ - switch (profile) - { - case MFX_PROFILE_AVC_CONSTRAINED_BASELINE: - return "Constrained Baseline"; - case MFX_PROFILE_AVC_BASELINE: - return "Baseline"; - case MFX_PROFILE_AVC_EXTENDED: - return "Extended"; - case MFX_PROFILE_AVC_MAIN: - return "Main"; - case MFX_PROFILE_AVC_CONSTRAINED_HIGH: - return "Constrained High"; - case MFX_PROFILE_AVC_PROGRESSIVE_HIGH: - return "Progressive High"; - case MFX_PROFILE_AVC_HIGH: - return "High"; - case MFX_PROFILE_UNKNOWN: - default: - return NULL; - } -} - -static const char* qsv_h264_level_xlat(int level) -{ - int i; - for (i = 0; hb_h264_level_names[i] != NULL; i++) - { - if (hb_h264_level_values[i] == level) - { - return hb_h264_level_names[i]; - } - } - return NULL; -} - static void qsv_handle_breftype(hb_work_private_t *pv) { /* @@ -588,7 +551,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job) hb_value_t *value = hb_dict_iter_value(iter); char *str = hb_value_get_string_xform(value); - switch (hb_qsv_param_parse(&pv->param, pv->qsv_info, key, str)) + switch (hb_qsv_param_parse(&pv->param, pv->qsv_info, key, str)) { case HB_QSV_PARAM_OK: break; @@ -667,63 +630,29 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job) pv->param.videoParam->mfx.FrameInfo.Width = job->qsv.enc_info.align_width; pv->param.videoParam->mfx.FrameInfo.Height = job->qsv.enc_info.align_height; - // set H.264 profile and level - if (job->encoder_profile != NULL && *job->encoder_profile && - strcasecmp(job->encoder_profile, "auto")) + // parse user-specified codec profile and level + if (hb_qsv_profile_parse(&pv->param, pv->qsv_info, job->encoder_profile)) { - if (!strcasecmp(job->encoder_profile, "baseline")) - { - pv->param.videoParam->mfx.CodecProfile = MFX_PROFILE_AVC_BASELINE; - } - else if (!strcasecmp(job->encoder_profile, "main")) - { - pv->param.videoParam->mfx.CodecProfile = MFX_PROFILE_AVC_MAIN; - } - else if (!strcasecmp(job->encoder_profile, "high")) - { - pv->param.videoParam->mfx.CodecProfile = MFX_PROFILE_AVC_HIGH; - } - else - { - hb_error("encqsvInit: bad profile %s", job->encoder_profile); - return -1; - } + hb_error("encqsvInit: bad profile %s", job->encoder_profile); + return -1; } - if (job->encoder_level != NULL && *job->encoder_level && - strcasecmp(job->encoder_level, "auto")) + if (hb_qsv_level_parse(&pv->param, pv->qsv_info, job->encoder_level)) { - int err; - int i = hb_qsv_atoindex(hb_h264_level_names, job->encoder_level, &err); - if (err || i >= (sizeof(hb_h264_level_values) / - sizeof(hb_h264_level_values[0]))) - { - hb_error("encqsvInit: bad level %s", job->encoder_level); - return -1; - } - else if (pv->qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6) - { - pv->param.videoParam->mfx.CodecLevel = HB_QSV_CLIP3(MFX_LEVEL_AVC_1, - MFX_LEVEL_AVC_52, - hb_h264_level_values[i]); - } - else - { - // Media SDK API < 1.6, MFX_LEVEL_AVC_52 unsupported - pv->param.videoParam->mfx.CodecLevel = HB_QSV_CLIP3(MFX_LEVEL_AVC_1, - MFX_LEVEL_AVC_51, - hb_h264_level_values[i]); - } + hb_error("encqsvInit: bad level %s", job->encoder_level); + return -1; } // interlaced encoding is not always possible - if (pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE) + if (pv->param.videoParam->mfx.CodecId == MFX_CODEC_AVC && + pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE) { if (pv->param.videoParam->mfx.CodecProfile == MFX_PROFILE_AVC_CONSTRAINED_BASELINE || pv->param.videoParam->mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE || pv->param.videoParam->mfx.CodecProfile == MFX_PROFILE_AVC_PROGRESSIVE_HIGH) { hb_error("encqsvInit: profile %s doesn't support interlaced encoding", - qsv_h264_profile_xlat(pv->param.videoParam->mfx.CodecProfile)); + hb_qsv_profile_name(MFX_CODEC_AVC, + pv->param.videoParam->mfx.CodecProfile)); return -1; } if ((pv->param.videoParam->mfx.CodecLevel >= MFX_LEVEL_AVC_1b && @@ -731,7 +660,8 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job) (pv->param.videoParam->mfx.CodecLevel >= MFX_LEVEL_AVC_42)) { hb_error("encqsvInit: level %s doesn't support interlaced encoding", - qsv_h264_level_xlat(pv->param.videoParam->mfx.CodecLevel)); + hb_qsv_level_name(MFX_CODEC_AVC, + pv->param.videoParam->mfx.CodecLevel)); return -1; } } @@ -1053,6 +983,10 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job) // log code path and main output settings hb_log("encqsvInit: using %s path", pv->is_sys_mem ? "encode-only" : "full QSV"); + hb_log("encqsvInit: %s %s profile @ level %s", + hb_qsv_codec_name (videoParam.mfx.CodecId), + hb_qsv_profile_name(videoParam.mfx.CodecId, videoParam.mfx.CodecProfile), + hb_qsv_level_name (videoParam.mfx.CodecId, videoParam.mfx.CodecLevel)); hb_log("encqsvInit: TargetUsage %"PRIu16" AsyncDepth %"PRIu16"", videoParam.mfx.TargetUsage, videoParam.AsyncDepth); hb_log("encqsvInit: GopRefDist %"PRIu16" GopPicSize %"PRIu16" NumRefFrame %"PRIu16"", @@ -1205,9 +1139,6 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job) break; } } - hb_log("encqsvInit: H.264 profile %s @ level %s", - qsv_h264_profile_xlat(videoParam.mfx.CodecProfile), - qsv_h264_level_xlat (videoParam.mfx.CodecLevel)); // AsyncDepth has now been set and/or modified by Media SDK pv->max_async_depth = videoParam.AsyncDepth; diff --git a/libhb/qsv_common.c b/libhb/qsv_common.c index 8a808b80c..ac15d7856 100644 --- a/libhb/qsv_common.c +++ b/libhb/qsv_common.c @@ -32,6 +32,41 @@ static hb_qsv_info_t qsv_hardware_info_avc = { .available = 0, .codec_id = MFX_ 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, }; +// QSV-supported profile and level lists (not all exposed to the user) +static hb_triplet_t hb_qsv_h264_profiles[] = +{ + { "Baseline", "baseline", MFX_PROFILE_AVC_BASELINE, }, + { "Main", "main", MFX_PROFILE_AVC_MAIN, }, + { "Extended", "extended", MFX_PROFILE_AVC_EXTENDED, }, + { "High", "high", MFX_PROFILE_AVC_HIGH, }, + { "High 4:2:2", "high422", MFX_PROFILE_AVC_HIGH_422, }, + { "Constrained Baseline", "baseline|set1", MFX_PROFILE_AVC_CONSTRAINED_BASELINE, }, + { "Constrained High", "high|set4|set5", MFX_PROFILE_AVC_CONSTRAINED_HIGH, }, + { "Progressive High", "high|set4", MFX_PROFILE_AVC_PROGRESSIVE_HIGH, }, + { NULL, }, +}; +static hb_triplet_t hb_qsv_h264_levels[] = +{ + { "1.0", "1.0", MFX_LEVEL_AVC_1, }, + { "1b", "1b", MFX_LEVEL_AVC_1b, }, + { "1.1", "1.1", MFX_LEVEL_AVC_11, }, + { "1.2", "1.2", MFX_LEVEL_AVC_12, }, + { "1.3", "1.3", MFX_LEVEL_AVC_13, }, + { "2.0", "2.0", MFX_LEVEL_AVC_2, }, + { "2.1", "2.1", MFX_LEVEL_AVC_21, }, + { "2.2", "2.2", MFX_LEVEL_AVC_22, }, + { "3.0", "3.0", MFX_LEVEL_AVC_3, }, + { "3.1", "3.1", MFX_LEVEL_AVC_31, }, + { "3.2", "3.2", MFX_LEVEL_AVC_32, }, + { "4.0", "4.0", MFX_LEVEL_AVC_4, }, + { "4.1", "4.1", MFX_LEVEL_AVC_41, }, + { "4.2", "4.2", MFX_LEVEL_AVC_42, }, + { "5.0", "5.0", MFX_LEVEL_AVC_5, }, + { "5.1", "5.1", MFX_LEVEL_AVC_51, }, + { "5.2", "5.2", MFX_LEVEL_AVC_52, }, + { NULL, }, +}; + // 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) @@ -1227,6 +1262,65 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, return error ? HB_QSV_PARAM_BAD_VALUE : HB_QSV_PARAM_OK; } +int hb_qsv_profile_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, const char *profile_key) +{ + hb_triplet_t *profile = NULL; + if (profile_key != NULL && *profile_key && strcasecmp(profile_key, "auto")) + { + switch (param->videoParam->mfx.CodecId) + { + case MFX_CODEC_AVC: + profile = hb_triplet4key(hb_qsv_h264_profiles, profile_key); + break; + default: + break; + } + if (profile == NULL) + { + return -1; + } + param->videoParam->mfx.CodecProfile = profile->value; + } + return 0; +} + +int hb_qsv_level_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, const char *level_key) +{ + hb_triplet_t *level = NULL; + if (level_key != NULL && *level_key && strcasecmp(level_key, "auto")) + { + switch (param->videoParam->mfx.CodecId) + { + case MFX_CODEC_AVC: + level = hb_triplet4key(hb_qsv_h264_levels, level_key); + break; + default: + break; + } + if (level == NULL) + { + return -1; + } + if (param->videoParam->mfx.CodecId == MFX_CODEC_AVC) + { + if (info->capabilities & HB_QSV_CAP_MSDK_API_1_6) + { + param->videoParam->mfx.CodecLevel = FFMIN(MFX_LEVEL_AVC_52, level->value); + } + else + { + // Media SDK API < 1.6, MFX_LEVEL_AVC_52 unsupported + param->videoParam->mfx.CodecLevel = FFMIN(MFX_LEVEL_AVC_51, level->value); + } + } + else + { + param->videoParam->mfx.CodecLevel = level->value; + } + } + return 0; +} + const char* const* hb_qsv_preset_get_names() { if (qsv_hardware_generation(hb_get_cpu_platform()) >= QSV_G3) @@ -1543,6 +1637,84 @@ int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam, return 0; } +hb_triplet_t* hb_triplet4value(hb_triplet_t *triplets, const int value) +{ + for (int i = 0; triplets[i].name != NULL; i++) + { + if (triplets[i].value == value) + { + return &triplets[i]; + } + } + return NULL; +} + +hb_triplet_t* hb_triplet4name(hb_triplet_t *triplets, const char *name) +{ + for (int i = 0; triplets[i].name != NULL; i++) + { + if (!strcasecmp(triplets[i].name, name)) + { + return &triplets[i]; + } + } + return NULL; +} + +hb_triplet_t* hb_triplet4key(hb_triplet_t *triplets, const char *key) +{ + for (int i = 0; triplets[i].name != NULL; i++) + { + if (!strcasecmp(triplets[i].key, key)) + { + return &triplets[i]; + } + } + return NULL; +} + +const char* hb_qsv_codec_name(uint32_t codec_id) +{ + switch (codec_id) + { + case MFX_CODEC_AVC: + return "H.264/AVC"; + + default: + return NULL; + } +} + +const char* hb_qsv_profile_name(uint32_t codec_id, uint16_t profile_id) +{ + hb_triplet_t *profile = NULL; + switch (codec_id) + { + case MFX_CODEC_AVC: + profile = hb_triplet4value(hb_qsv_h264_profiles, profile_id); + break; + + default: + break; + } + return profile != NULL ? profile->name : NULL; +} + +const char* hb_qsv_level_name(uint32_t codec_id, uint16_t level_id) +{ + hb_triplet_t *level = NULL; + switch (codec_id) + { + case MFX_CODEC_AVC: + level = hb_triplet4value(hb_qsv_h264_levels, level_id); + break; + + default: + break; + } + return level != NULL ? level->name : NULL; +} + const char* hb_qsv_frametype_name(uint16_t qsv_frametype) { if (qsv_frametype & MFX_FRAMETYPE_IDR) diff --git a/libhb/qsv_common.h b/libhb/qsv_common.h index 602f3be67..9ac2085ec 100644 --- a/libhb/qsv_common.h +++ b/libhb/qsv_common.h @@ -153,7 +153,24 @@ float hb_qsv_atof (const char *str, int *err); int hb_qsv_param_default_preset(hb_qsv_param_t *param, mfxVideoParam *videoParam, hb_qsv_info_t *info, const char *preset); int hb_qsv_param_default (hb_qsv_param_t *param, mfxVideoParam *videoParam, hb_qsv_info_t *info); int hb_qsv_param_parse (hb_qsv_param_t *param, hb_qsv_info_t *info, const char *key, const char *value); +int hb_qsv_profile_parse (hb_qsv_param_t *param, hb_qsv_info_t *info, const char *profile_key); +int hb_qsv_level_parse (hb_qsv_param_t *param, hb_qsv_info_t *info, const char *level_key); +typedef struct +{ + const char *name; + const char *key; + const int value; +} +hb_triplet_t; + +hb_triplet_t* hb_triplet4value(hb_triplet_t *triplets, const int value); +hb_triplet_t* hb_triplet4name (hb_triplet_t *triplets, const char *name); +hb_triplet_t* hb_triplet4key (hb_triplet_t *triplets, const char *key); + +const char* hb_qsv_codec_name (uint32_t codec_id); +const char* hb_qsv_profile_name (uint32_t codec_id, uint16_t profile_id); +const char* hb_qsv_level_name (uint32_t codec_id, uint16_t level_id); const char* hb_qsv_frametype_name(uint16_t qsv_frametype); uint8_t hb_qsv_frametype_xlat(uint16_t qsv_frametype, uint16_t *out_flags); |