]> granicus.if.org Git - handbrake/commitdiff
QSV: libhb-based preset system.
authorRodeo <tdskywalker@gmail.com>
Tue, 24 Sep 2013 13:22:19 +0000 (13:22 +0000)
committerRodeo <tdskywalker@gmail.com>
Tue, 24 Sep 2013 13:22:19 +0000 (13:22 +0000)
Modeled after x264's preset system.

MMBRC and LookAhead RC are now enabled by default, whereas Trellis is disabled by default.

Please note that Windows GUI support will come later, and that preset names are not definitive.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5806 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/common.c
libhb/common.h
libhb/enc_qsv.c
libhb/qsv_common.c
libhb/qsv_common.h
libhb/work.c
test/test.c
win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs

index 7087046b6d8b51e2bbe1a5f023298a7e7094f49b..9df282cbc9dfd7bae2b09e90bd3d34be1bb7dfaf 100644 (file)
@@ -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);
index abc799ef177a5c147a53a5d013f43aabb5b47aa2..42fd0a212f3030919f5df477d3da9bb7b820ef14 100644 (file)
@@ -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();
 
index 46a398c672688d59c52268843e4d5f27960856c9..337befeca71da91a7c31ef3c387e4feef22f5ff6 100644 (file)
@@ -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)
index cbd427f5d02e5e82e21aaf2a527675f30cf95514..e96a715fd4b2e00fcaa8070c030d5d50a539c815 100644 (file)
@@ -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;
index 796d791b5370fee125164f1856b1043f8b4c9ced..083065be64b05fa18b7c4ddee5dde8595a073a0e 100644 (file)
@@ -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);
index d44f763beabf7089710e802153dc31cd5346074b..a5c3190d180c29d6697b8ae7c45bb7e46d06234e 100644 (file)
@@ -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))
         {
index b7f8e9ac220370d3aa9247d234a0ba5bedc446d6..b642039371dfe275c97d142595ae84aba566144e 100644 (file)
@@ -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] );
index 6d990dc67b3b324bd97688f8e29b7117a09bb10f..7d0a76c68a17f3289659eaab48ba3f6c0b17992c 100644 (file)
@@ -217,6 +217,9 @@ namespace HandBrake.Interop.HbLib
 \r
                public int async_depth;\r
 \r
+               /// const char*\r
+               public IntPtr preset;\r
+\r
                /// av_qsv_context* \r
                public IntPtr ctx;\r
 \r