shithub: libvpx

Download patch

ref: b0da9b399d8e9129f47c81366902e66823063878
parent: 64baa8df2e3f5cd8036fac9715d3f7d348620fa6
author: John Koleszar <jkoleszar@google.com>
date: Fri Dec 17 04:43:39 EST 2010

Add psnr/ssim tuning option

Add a new encoder control, VP8E_SET_TUNING, to allow the application
to inform the encoder that the material will benefit from certain
tuning. Expose this control as the --tune option to vpxenc. The args
helper is expanded to support enumerated arguments by name or value.

Two tunings are provided by this patch, PSNR (default) and SSIM.
Activity masking is made dependent on setting --tune=ssim, as the
current implementation hurts speed (10%) and PSNR (2.7% avg,
10% peak) too much for it to be a default yet.

Change-Id: I110d969381c4805347ff5a0ffaf1a14ca1965257

--- a/args.c
+++ b/args.c
@@ -135,6 +135,17 @@
                      def->long_name, long_val);
 
         fprintf(fp, "  %-37s\t%s\n", option_text, def->desc);
+
+        if(def->enums)
+        {
+            const struct arg_enum_list *listptr;
+
+            fprintf(fp, "  %-37s\t  ", "");
+
+            for(listptr = def->enums; listptr->name; listptr++)
+                fprintf(fp, "%s%s", listptr->name,
+                        listptr[1].name ? ", " : "\n");
+        }
     }
 }
 
@@ -217,4 +228,38 @@
     else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
 
     return rat;
+}
+
+
+int arg_parse_enum(const struct arg *arg)
+{
+    const struct arg_enum_list *listptr;
+    long int                    rawval;
+    char                       *endptr;
+
+    /* First see if the value can be parsed as a raw value */
+    rawval = strtol(arg->val, &endptr, 10);
+    if (arg->val[0] != '\0' && endptr[0] == '\0')
+    {
+        /* Got a raw value, make sure it's valid */
+        for(listptr = arg->def->enums; listptr->name; listptr++)
+            if(listptr->val == rawval)
+                return rawval;
+    }
+
+    /* Next see if it can be parsed as a string */
+    for(listptr = arg->def->enums; listptr->name; listptr++)
+        if(!strcmp(arg->val, listptr->name))
+            return listptr->val;
+
+    die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
+    return 0;
+}
+
+
+int arg_parse_enum_or_int(const struct arg *arg)
+{
+    if(arg->def->enums)
+        return arg_parse_enum(arg);
+    return arg_parse_int(arg);
 }
--- a/args.h
+++ b/args.h
@@ -22,6 +22,13 @@
     const struct arg_def  *def;
 };
 
+struct arg_enum_list
+{
+    const char *name;
+    int         val;
+};
+#define ARG_ENUM_LIST_END {0}
+
 typedef struct arg_def
 {
     const char *short_name;
@@ -28,8 +35,10 @@
     const char *long_name;
     int         has_val;
     const char *desc;
+    const struct arg_enum_list *enums;
 } arg_def_t;
-#define ARG_DEF(s,l,v,d) {s,l,v,d}
+#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL}
+#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e}
 #define ARG_DEF_LIST_END {0}
 
 struct arg arg_init(char **argv);
@@ -41,4 +50,5 @@
 unsigned int arg_parse_uint(const struct arg *arg);
 int arg_parse_int(const struct arg *arg);
 struct vpx_rational arg_parse_rational(const struct arg *arg);
+int arg_parse_enum_or_int(const struct arg *arg);
 #endif
--- a/vp8/common/onyx.h
+++ b/vp8/common/onyx.h
@@ -18,6 +18,7 @@
 #endif
 
 #include "vpx/internal/vpx_codec_internal.h"
+#include "vpx/vp8cx.h"
 #include "vpx_scale/yv12config.h"
 #include "type_aliases.h"
 #include "ppflags.h"
@@ -189,6 +190,8 @@
 
         struct vpx_fixed_buf         two_pass_stats_in;
         struct vpx_codec_pkt_list  *output_pkt_list;
+
+        vp8e_tuning tuning;
     } VP8_CONFIG;
 
 
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -497,7 +497,8 @@
         x->rddiv = cpi->RDDIV;
         x->rdmult = cpi->RDMULT;
 
-        activity_sum += vp8_activity_masking(cpi, x);
+        if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
+            activity_sum += vp8_activity_masking(cpi, x);
 
         // Is segmentation enabled
         // MB level adjutment to quantizer
--- a/vp8/encoder/ethreading.c
+++ b/vp8/encoder/ethreading.c
@@ -115,7 +115,8 @@
                         x->rddiv = cpi->RDDIV;
                         x->rdmult = cpi->RDMULT;
 
-                        activity_sum += vp8_activity_masking(cpi, x);
+                        if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
+                            activity_sum += vp8_activity_masking(cpi, x);
 
                         // Is segmentation enabled
                         // MB level adjutment to quantizer
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -37,6 +37,7 @@
     unsigned int                arnr_max_frames;    /* alt_ref Noise Reduction Max Frame Count */
     unsigned int                arnr_strength;    /* alt_ref Noise Reduction Strength */
     unsigned int                arnr_type;        /* alt_ref filter type */
+    vp8e_tuning                 tuning;
 
 };
 
@@ -67,6 +68,7 @@
             0,                          /* arnr_max_frames */
             3,                          /* arnr_strength */
             3,                          /* arnr_type*/
+            0,                          /* tuning*/
         }
     }
 };
@@ -336,6 +338,7 @@
     oxcf->arnr_strength =  vp8_cfg.arnr_strength;
     oxcf->arnr_type =      vp8_cfg.arnr_type;
 
+    oxcf->tuning = vp8_cfg.tuning;
 
     /*
         printf("Current VP8 Settings: \n");
@@ -449,6 +452,7 @@
         MAP(VP8E_SET_ARNR_MAXFRAMES,        xcfg.arnr_max_frames);
         MAP(VP8E_SET_ARNR_STRENGTH ,        xcfg.arnr_strength);
         MAP(VP8E_SET_ARNR_TYPE     ,        xcfg.arnr_type);
+        MAP(VP8E_SET_TUNING,                xcfg.tuning);
 
     }
 
@@ -1029,6 +1033,7 @@
     {VP8E_SET_ARNR_MAXFRAMES,           set_param},
     {VP8E_SET_ARNR_STRENGTH ,           set_param},
     {VP8E_SET_ARNR_TYPE     ,           set_param},
+    {VP8E_SET_TUNING,                   set_param},
     { -1, NULL},
 };
 
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -140,7 +140,8 @@
     VP8E_SET_ARNR_MAXFRAMES,         /**< control function to set the max number of frames blurred creating arf*/
     VP8E_SET_ARNR_STRENGTH ,         /**< control function to set the filter strength for the arf */
     VP8E_SET_ARNR_TYPE     ,         /**< control function to set the type of filter to use for the arf*/
-} ;
+    VP8E_SET_TUNING,                 /**< control function to set visual tuning */
+};
 
 /*!\brief vpx 1-D scaling mode
  *
@@ -224,6 +225,18 @@
 } vp8e_token_partitions;
 
 
+/*!\brief VP8 model tuning parameters
+ *
+ * Changes the encoder to tune for certain types of input material.
+ *
+ */
+typedef enum
+{
+    VP8_TUNE_PSNR,
+    VP8_TUNE_SSIM
+} vp8e_tuning;
+
+
 /*!\brief VP8 encoder control function parameter type
  *
  * Defines the data types that VP8E control functions take. Note that
@@ -253,7 +266,7 @@
 VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_MAXFRAMES,     unsigned int)
 VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH ,     unsigned int)
 VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_TYPE     ,     unsigned int)
-
+VPX_CTRL_USE_TYPE(VP8E_SET_TUNING,             vp8e_tuning)
 
 VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER,     int *)
 VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64,  int *)
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -993,11 +993,19 @@
                                        "AltRef Strength");
 static const arg_def_t arnr_type = ARG_DEF(NULL, "arnr-type", 1,
                                    "AltRef Type");
+static const struct arg_enum_list tuning_enum[] = {
+    {"psnr", VP8_TUNE_PSNR},
+    {"ssim", VP8_TUNE_SSIM},
+    {NULL, 0}
+};
+static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
+                                   "Material to favor", tuning_enum);
 
 static const arg_def_t *vp8_args[] =
 {
     &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
-    &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type, NULL
+    &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
+    &tune_ssim, NULL
 };
 static const int vp8_arg_ctrl_map[] =
 {
@@ -1004,7 +1012,8 @@
     VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
     VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
     VP8E_SET_TOKEN_PARTITIONS,
-    VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH , VP8E_SET_ARNR_TYPE, 0
+    VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH , VP8E_SET_ARNR_TYPE,
+    VP8E_SET_TUNING, 0
 };
 #endif
 
@@ -1317,7 +1326,7 @@
                 if (arg_ctrl_cnt < ARG_CTRL_CNT_MAX)
                 {
                     arg_ctrls[arg_ctrl_cnt][0] = ctrl_args_map[i];
-                    arg_ctrls[arg_ctrl_cnt][1] = arg_parse_int(&arg);
+                    arg_ctrls[arg_ctrl_cnt][1] = arg_parse_enum_or_int(&arg);
                     arg_ctrl_cnt++;
                 }
             }