diff options
-rw-r--r-- | libhb/common.c | 1 | ||||
-rw-r--r-- | libhb/common.h | 6 | ||||
-rw-r--r-- | libhb/enc_qsv.c | 25 | ||||
-rw-r--r-- | libhb/qsv_common.c | 90 | ||||
-rw-r--r-- | libhb/qsv_common.h | 8 | ||||
-rw-r--r-- | libhb/work.c | 7 | ||||
-rw-r--r-- | test/test.c | 53 | ||||
-rw-r--r-- | win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs | 3 |
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;
|