From fa4abd915a82e1c301911b30aa9919d43eec9c2c Mon Sep 17 00:00:00 2001
From: Rodeo <tdskywalker@gmail.com>
Date: Thu, 5 Dec 2013 13:52:54 +0000
Subject: [PATCH] QSV: update libhb presets to match a more recent
 recommendation.

Based on a patch by Maxym Dmytrychenko.


git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5913 b64f7644-9d1e-0410-96f1-a4d463321fa5
---
 libhb/enc_qsv.c    | 30 ++++++++++++++++-
 libhb/qsv_common.c | 82 +++++++++++++++++++++++++++++++++++++---------
 libhb/qsv_common.h |  1 +
 3 files changed, 96 insertions(+), 17 deletions(-)

diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c
index 9ddfeb5a8..8236e0049 100644
--- a/libhb/enc_qsv.c
+++ b/libhb/enc_qsv.c
@@ -666,6 +666,34 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
         return -1;
     }
 
+    // set B-pyramid
+    if (pv->param.gop.b_pyramid < 0)
+    {
+        if (pv->param.videoParam->mfx.RateControlMethod == MFX_RATECONTROL_CQP)
+        {
+            pv->param.gop.b_pyramid = 1;
+        }
+        else
+        {
+            pv->param.gop.b_pyramid = 0;
+        }
+    }
+    pv->param.gop.b_pyramid = !!pv->param.gop.b_pyramid;
+
+    // set the GOP structure
+    if (pv->param.gop.gop_ref_dist < 0)
+    {
+        if (pv->param.videoParam->mfx.RateControlMethod == MFX_RATECONTROL_CQP)
+        {
+            pv->param.gop.gop_ref_dist = 4;
+        }
+        else
+        {
+            pv->param.gop.gop_ref_dist = 3;
+        }
+    }
+    pv->param.videoParam->mfx.GopRefDist = pv->param.gop.gop_ref_dist;
+
     // set the keyframe interval
     if (pv->param.gop.gop_pic_size < 0)
     {
@@ -678,7 +706,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
         else
         {
             // set the keyframe interval based on the framerate
-            pv->param.gop.gop_pic_size = 5 * rate + 1;
+            pv->param.gop.gop_pic_size = rate;
         }
     }
     pv->param.videoParam->mfx.GopPicSize = pv->param.gop.gop_pic_size;
diff --git a/libhb/qsv_common.c b/libhb/qsv_common.c
index 44f11ffad..9465a972e 100644
--- a/libhb/qsv_common.c
+++ b/libhb/qsv_common.c
@@ -355,7 +355,7 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
         ivalue = hb_qsv_atoi(value, &error);
         if (!error)
         {
-            param->videoParam->mfx.GopRefDist = HB_QSV_CLIP3(0, 32, ivalue);
+            param->gop.gop_ref_dist = HB_QSV_CLIP3(-1, 32, ivalue);
         }
     }
     else if (!strcasecmp(key, "gop-pic-size") ||
@@ -374,14 +374,14 @@ int hb_qsv_param_parse(hb_qsv_param_t *param,
             switch (vcodec)
             {
                 case HB_VCODEC_QSV_H264:
-                    ivalue = hb_qsv_atobool(value, &error);
+                    ivalue = hb_qsv_atoi(value, &error);
                     break;
                 default:
                     return HB_QSV_PARAM_UNSUPPORTED;
             }
             if (!error)
             {
-                param->gop.b_pyramid = ivalue;
+                param->gop.b_pyramid = HB_QSV_CLIP3(-1, 1, ivalue);
             }
         }
         else
@@ -738,42 +738,91 @@ int hb_qsv_param_default_preset(hb_qsv_param_t *param,
         if (!strcasecmp(preset, "quality"))
         {
             /*
-             * Haswell or later: default settings.
-             * Before Haswell: preset unavailable.
+             * HSW TargetUsage:     2
+             *     NumRefFrame:     0
+             *     GopRefDist:      4 (CQP), 3 (VBR)        -> -1 (set by encoder)
+             *     GopPicSize:     32 (CQP), 1 second (VBR) -> -1 (set by encoder)
+             *     BPyramid:        1 (CQP), 0 (VBR)        -> -1 (set by encoder)
+             *     LookAhead:       1 (on)
+             *     LookAheadDepth: 40
+             *
+             *
+             * SNB
+             * IVB Preset Not Available
+             *
+             * Note: this preset is the libhb default (like x264's "medium").
              */
         }
         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.
+             * HSW TargetUsage:     4
+             *     NumRefFrame:     1
+             *     GopRefDist:      4 (CQP), 3 (VBR)        -> -1 (set by encoder)
+             *     GopPicSize:     32 (CQP), 1 second (VBR) -> -1 (set by encoder)
+             *     BPyramid:        1 (CQP), 0 (VBR)        -> -1 (set by encoder)
+             *     LookAhead:       0 (off)
+             *     LookAheadDepth: Not Applicable
              */
             if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
             {
                 param->rc.lookahead                = 0;
-                param->videoParam->mfx.GopRefDist  = 1;
+                param->videoParam->mfx.NumRefFrame = 1;
                 param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_4;
             }
             else
             {
-                /* Before Haswell: default settings */
+                /*
+                 * SNB
+                 * IVB TargetUsage:     2
+                 *     NumRefFrame:     0
+                 *     GopRefDist:      4 (CQP), 3 (VBR)        -> -1 (set by encoder)
+                 *     GopPicSize:     32 (CQP), 1 second (VBR) -> -1 (set by encoder)
+                 *     BPyramid:       Not Applicable
+                 *     LookAhead:      Not Applicable
+                 *     LookAheadDepth: Not Applicable
+                 *
+                 * Note: this preset is not the libhb default,
+                 * but the settings are the same so do nothing.
+                 */
             }
         }
         else if (!strcasecmp(preset, "speed"))
         {
             if (hb_get_cpu_platform() >= HB_CPU_PLATFORM_INTEL_HSW)
             {
+                /*
+                 * HSW TargetUsage:     6
+                 *     NumRefFrame:     0 (CQP), 1 (VBR)        -> see note
+                 *     GopRefDist:      4 (CQP), 3 (VBR)        -> -1 (set by encoder)
+                 *     GopPicSize:     32 (CQP), 1 second (VBR) -> -1 (set by encoder)
+                 *     BPyramid:        1 (CQP), 0 (VBR)        -> -1 (set by encoder)
+                 *     LookAhead:       0 (off)
+                 *     LookAheadDepth: Not Applicable
+                 *
+                 * Note: NumRefFrame depends on the RC method, which we don't
+                 *       know here. Rather than have an additional variable and
+                 *       having the encoder set it, we set it to 1 and let the
+                 *       B-pyramid code sanitize it. Since BPyramid is 1 w/CQP,
+                 *       the result (3) is the same as what MSDK would pick for
+                 *       NumRefFrame 0 GopRefDist 4 GopPicSize 32.
+                 */
                 param->rc.lookahead                = 0;
-                param->videoParam->mfx.GopRefDist  = 1;
+                param->videoParam->mfx.NumRefFrame = 1;
                 param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_6;
             }
             else
             {
+                /*
+                 * SNB
+                 * IVB TargetUsage:     4
+                 *     NumRefFrame:     0
+                 *     GopRefDist:      4 (CQP), 3 (VBR)        -> -1 (set by encoder)
+                 *     GopPicSize:     32 (CQP), 1 second (VBR) -> -1 (set by encoder)
+                 *     BPyramid:       Not Applicable
+                 *     LookAhead:      Not Applicable
+                 *     LookAheadDepth: Not Applicable
+                 */
                 param->videoParam->mfx.TargetUsage = MFX_TARGETUSAGE_4;
             }
         }
@@ -850,8 +899,9 @@ int hb_qsv_param_default(hb_qsv_param_t *param, mfxVideoParam *videoParam)
         param->codingOption2.Trellis         = MFX_TRELLIS_OFF;
 
         // GOP & rate control
-        param->gop.b_pyramid          =  0;
+        param->gop.b_pyramid          = -1; // set automatically
         param->gop.gop_pic_size       = -1; // set automatically
+        param->gop.gop_ref_dist       = -1; // set automatically
         param->gop.int_ref_cycle_size = -1; // set automatically
         param->rc.lookahead           =  1;
         param->rc.cqp_offsets[0]      =  0;
diff --git a/libhb/qsv_common.h b/libhb/qsv_common.h
index 31e1bb36b..8a3b8c79b 100644
--- a/libhb/qsv_common.h
+++ b/libhb/qsv_common.h
@@ -94,6 +94,7 @@ typedef struct
     {
         int b_pyramid;
         int gop_pic_size;
+        int gop_ref_dist;
         int int_ref_cycle_size;
     } gop;
     struct
-- 
2.40.0