summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/common.c1
-rw-r--r--libhb/common.h6
-rw-r--r--libhb/enc_qsv.c25
-rw-r--r--libhb/qsv_common.c90
-rw-r--r--libhb/qsv_common.h8
-rw-r--r--libhb/work.c7
-rw-r--r--test/test.c53
-rw-r--r--win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs3
8 files changed, 157 insertions, 36 deletions
diff --git a/libhb/common.c b/libhb/common.c
index 7087046b6..9df282cbc 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -2906,6 +2906,7 @@ static void job_setup( hb_job_t * job, hb_title_t * title )
#ifdef USE_QSV
job->qsv.enc_info.is_init_done = 0;
+ job->qsv.preset = NULL;
job->qsv.async_depth = AV_QSV_ASYNC_DEPTH_DEFAULT;
job->qsv.decode = !!(title->video_decode_support &
HB_DECODE_SUPPORT_QSV);
diff --git a/libhb/common.h b/libhb/common.h
index abc799ef1..42fd0a212 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -537,6 +537,7 @@ struct hb_job_s
{
int decode;
int async_depth;
+ const char *preset;
av_qsv_context *ctx;
// shared encoding parameters
// initialized by the QSV encoder, then used upstream (e.g. by filters)
@@ -1238,9 +1239,12 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
const char *x264_encopts, const char *h264_profile,
const char *h264_level, int width, int height);
-// x264 preset/tune & h264 profile/level helpers
+// x264 preset/tune, qsv preset & h264 profile/level helpers
const char * const * hb_x264_presets();
const char * const * hb_x264_tunes();
+#ifdef USE_QSV
+const char * const * hb_qsv_presets();
+#endif
const char * const * hb_h264_profiles();
const char * const * hb_h264_levels();
diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c
index 46a398c67..337befeca 100644
--- a/libhb/enc_qsv.c
+++ b/libhb/enc_qsv.c
@@ -374,9 +374,10 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
pv->next_chapter.start = INT64_MIN;
// default encoding parameters
- if (hb_qsv_param_default(&pv->param, &pv->enc_space.m_mfxVideoParam))
+ if (hb_qsv_param_default_preset(&pv->param, &pv->enc_space.m_mfxVideoParam,
+ job->qsv.preset))
{
- hb_error("encqsvInit: hb_qsv_param_default failed");
+ hb_error("encqsvInit: hb_qsv_param_default_preset failed");
return -1;
}
@@ -597,31 +598,15 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
// lookahead not supported
pv->param.rc.lookahead = 0;
}
- else if (pv->param.rc.lookahead > 0 &&
+ else if (pv->param.rc.lookahead &&
pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
{
- // user force-enabled lookahead but we can't use it
+ // lookahead enabled but we can't use it
hb_log("encqsvInit: MFX_RATECONTROL_LA not used (LookAhead is progressive-only)");
pv->param.rc.lookahead = 0;
}
- else if (pv->param.rc.lookahead < 0)
- {
- if (pv->param.rc.vbv_max_bitrate > 0 ||
- pv->param.rc.vbv_buffer_size > 0 ||
- pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
- {
- // lookahead doesn't support VBV or interlaced encoding
- pv->param.rc.lookahead = 0;
- }
- else
- {
- // set automatically based on target usage
- pv->param.rc.lookahead = (pv->param.videoParam->mfx.TargetUsage <= MFX_TARGETUSAGE_2);
- }
- }
else
{
- // user force-enabled or force-disabled lookahead
pv->param.rc.lookahead = !!pv->param.rc.lookahead;
}
if (pv->param.rc.lookahead)
diff --git a/libhb/qsv_common.c b/libhb/qsv_common.c
index cbd427f5d..e96a715fd 100644
--- a/libhb/qsv_common.c
+++ b/libhb/qsv_common.c
@@ -201,7 +201,7 @@ int hb_qsv_codingoption_xlat(int val)
int hb_qsv_trellisvalue_xlat(int val)
{
- switch (HB_QSV_CLIP3(-1, 3, val))
+ switch (HB_QSV_CLIP3(0, 3, val))
{
case 0:
return MFX_TRELLIS_OFF;
@@ -211,7 +211,6 @@ int hb_qsv_trellisvalue_xlat(int val)
return MFX_TRELLIS_I|MFX_TRELLIS_P;
case 3: // all frames
return MFX_TRELLIS_I|MFX_TRELLIS_P|MFX_TRELLIS_B;
- case -1:
default:
return MFX_TRELLIS_UNKNOWN;
}
@@ -700,6 +699,87 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
return error ? HB_QSV_PARAM_BAD_VALUE : HB_QSV_PARAM_OK;
}
+const char* const* hb_qsv_presets()
+{
+ if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
+ {
+ return hb_qsv_preset_names2;
+ }
+ else
+ {
+ return hb_qsv_preset_names1;
+ }
+}
+
+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"))
+ {
+ /*
+ * Haswell or later: default settings.
+ * Before Haswell: preset unavailable.
+ */
+ }
+ else if (!strcasecmp(preset, "balanced"))
+ {
+ /*
+ * Haswell or later: adjust settings.
+ *
+ * The idea behind this is that we should try and get a performance
+ * match between platforms (so using the "balanced" preset would
+ * give you similar encoding speeds on Ivy Bridge and Haswell).
+ *
+ * FIXME: figure out whether this actually is a good idea.
+ */
+ if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
+ {
+ param->rc.lookahead = 0;
+ param->videoParam->mfx.GopRefDist = 1;
+ param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_4;
+ }
+ else
+ {
+ /* Before Haswell: default settings */
+ }
+ }
+ else if (!strcasecmp(preset, "speed"))
+ {
+ if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
+ {
+ param->rc.lookahead = 0;
+ param->videoParam->mfx.GopRefDist = 1;
+ param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_6;
+ }
+ else
+ {
+ 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)
@@ -757,17 +837,17 @@ int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam)
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;
- param->codingOption2.MBBRC = MFX_CODINGOPTION_UNKNOWN;
// introduced in API 1.7
param->codingOption2.LookAheadDepth = 40;
- param->codingOption2.Trellis = MFX_TRELLIS_UNKNOWN;
+ param->codingOption2.Trellis = MFX_TRELLIS_OFF;
// GOP & rate control
param->gop.b_pyramid = 0;
param->gop.gop_pic_size = -1; // set automatically
param->gop.int_ref_cycle_size = -1; // set automatically
- param->rc.lookahead = -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;
diff --git a/libhb/qsv_common.h b/libhb/qsv_common.h
index 796d791b5..083065be6 100644
--- a/libhb/qsv_common.h
+++ b/libhb/qsv_common.h
@@ -106,6 +106,9 @@ typedef struct
mfxVideoParam *videoParam;
} hb_qsv_param_t;
+static const char* const hb_qsv_preset_names1[] = { "speed", "balanced", NULL, };
+static const char* const hb_qsv_preset_names2[] = { "speed", "balanced", "quality", NULL, };
+
#define HB_QSV_CLIP3(min, max, val) ((val < min) ? min : (val > max) ? max : val)
int hb_qsv_codingoption_xlat (int val);
const char* hb_qsv_codingoption_get_name(int val);
@@ -116,8 +119,9 @@ int hb_qsv_atobool (const char *str, int *err);
int hb_qsv_atoi (const char *str, int *err);
float hb_qsv_atof (const char *str, int *err);
-int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam);
-int hb_qsv_param_parse (hb_qsv_param_t *param, const char *key, const char *value, int vcodec);
+int hb_qsv_param_default_preset(hb_qsv_param_t *param, mfxVideoParam *videoParam, const char *preset);
+int hb_qsv_param_default (hb_qsv_param_t *param, mfxVideoParam *videoParam);
+int hb_qsv_param_parse (hb_qsv_param_t *param, const char *key, const char *value, int vcodec);
mfxIMPL hb_qsv_impl_get_preferred();
const char* hb_qsv_impl_get_name(int impl);
diff --git a/libhb/work.c b/libhb/work.c
index d44f763be..a5c3190d1 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -318,6 +318,13 @@ void hb_display_job_info(hb_job_t *job)
{
hb_log( " + x264 tune: %s", job->x264_tune );
}
+#ifdef USE_QSV
+ if ((job->qsv.preset != NULL && *job->qsv.preset) &&
+ (job->vcodec & HB_VCODEC_QSV_MASK))
+ {
+ hb_log(" + QSV preset: %s", job->qsv.preset);
+ }
+#endif
if (job->advanced_opts != NULL && *job->advanced_opts &&
(job->vcodec != HB_VCODEC_THEORA))
{
diff --git a/test/test.c b/test/test.c
index b7f8e9ac2..b64203937 100644
--- a/test/test.c
+++ b/test/test.c
@@ -141,8 +141,9 @@ static uint64_t min_title_duration = 10;
static int use_opencl = 0;
static int use_hwd = 0;
#ifdef USE_QSV
-static int qsv_decode = 1;
-static int qsv_async_depth = -1;
+static int qsv_async_depth = -1;
+static int qsv_decode = 1;
+static const char *qsv_preset = NULL;
#endif
/* Exit cleanly on Ctrl-C */
@@ -1952,6 +1953,7 @@ static int HandleEvents( hb_handle_t * h )
job->qsv.async_depth = qsv_async_depth;
}
job->qsv.decode = qsv_decode;
+ job->qsv.preset = qsv_preset;
#endif
/* Grab audio tracks */
@@ -3165,6 +3167,36 @@ static void ShowHelp()
}
if( len )
fprintf( out, "%s\n", tmp );
+#ifdef USE_QSV
+if (hb_qsv_available())
+{
+ fprintf(out,
+ " --qsv-preset When using QSV, selects the QSV preset:\n"
+ " <string> ");
+ x264_opts = hb_qsv_presets();
+ tmp[0] = 0;
+ len = 0;
+ while (x264_opts != NULL && *x264_opts != NULL)
+ {
+ strncat(tmp, *x264_opts++, sizeof(tmp) - 1 - len);
+ if (*x264_opts != NULL)
+ {
+ strcat(tmp, "/");
+ }
+ len = strlen(tmp);
+ if (len > 40 && *x264_opts != NULL)
+ {
+ fprintf(out, "%s\n ", tmp);
+ tmp[0] = 0;
+ len = 0;
+ }
+ }
+ if (len > 0)
+ {
+ fprintf(out, "%s\n", tmp);
+ }
+}
+#endif
fprintf(out,
" -x, --encopts <string> Specify advanced encoder options in the\n");
#ifdef USE_QSV
@@ -3182,7 +3214,7 @@ else
fprintf(out,
" option1=value1:option2=value2\n"
- " --h264-profile When using x264, ensures compliance with the\n"
+ " --h264-profile When using H.264, ensures compliance with the\n"
" <string> specified H.264 profile:\n"
" ");
x264_opts = hb_h264_profiles();
@@ -3204,7 +3236,7 @@ else
if( len )
fprintf( out, "%s\n", tmp );
fprintf( out,
- " --h264-level When using x264, ensures compliance with the\n"
+ " --h264-level When using H.264, ensures compliance with the\n"
" <string> specified H.264 level:\n"
" ");
x264_opts = hb_h264_levels();
@@ -3687,6 +3719,7 @@ static int ParseOptions( int argc, char ** argv )
#define AUDIO_DITHER 289
#define QSV_BASELINE 290
#define QSV_ASYNC_DEPTH 291
+ #define QSV_PRESET 292
for( ;; )
{
@@ -3697,11 +3730,12 @@ static int ParseOptions( int argc, char ** argv )
{ "verbose", optional_argument, NULL, 'v' },
{ "no-dvdnav", no_argument, NULL, DVDNAV },
{ "no-opencl", no_argument, NULL, NO_OPENCL },
-
+
#ifdef USE_QSV
- { "qsv-baseline", no_argument, NULL, QSV_BASELINE },
- { "qsv-async-depth", required_argument, NULL, QSV_ASYNC_DEPTH },
- { "disable-qsv-decoding", no_argument, &qsv_decode, 0 },
+ { "qsv-preset", required_argument, NULL, QSV_PRESET, },
+ { "qsv-baseline", no_argument, NULL, QSV_BASELINE, },
+ { "qsv-async-depth", required_argument, NULL, QSV_ASYNC_DEPTH, },
+ { "disable-qsv-decoding", no_argument, &qsv_decode, 0, },
#endif
{ "format", required_argument, NULL, 'f' },
@@ -4345,6 +4379,9 @@ static int ParseOptions( int argc, char ** argv )
case QSV_ASYNC_DEPTH:
qsv_async_depth = atoi(optarg);
break;
+ case QSV_PRESET:
+ qsv_preset = strdup(optarg);
+ break;
#endif
default:
fprintf( stderr, "unknown option (%s)\n", argv[cur_optind] );
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs
index 6d990dc67..7d0a76c68 100644
--- a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs
+++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs
@@ -217,6 +217,9 @@ namespace HandBrake.Interop.HbLib
public int async_depth;
+ /// const char*
+ public IntPtr preset;
+
/// av_qsv_context*
public IntPtr ctx;