summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorRodeo <[email protected]>2015-06-27 22:04:16 +0000
committerRodeo <[email protected]>2015-06-27 22:04:16 +0000
commit28766d686195854538de63620209c04c9533d26f (patch)
tree340689b7f9ff4fd518eebc8e159e53eb0dadd530 /libhb
parent41fb0a2658824e99b534dcde867c59413c0108b7 (diff)
QSV: parse and print profile & level in a codec-agnostic way.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@7325 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r--libhb/enc_qsv.c105
-rw-r--r--libhb/qsv_common.c172
-rw-r--r--libhb/qsv_common.h17
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);