]> granicus.if.org Git - libvpx/commitdiff
Add psnr/ssim tuning option
authorJohn Koleszar <jkoleszar@google.com>
Fri, 17 Dec 2010 14:43:39 +0000 (09:43 -0500)
committerJohn Koleszar <jkoleszar@google.com>
Fri, 17 Dec 2010 15:01:05 +0000 (10:01 -0500)
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

args.c
args.h
vp8/common/onyx.h
vp8/encoder/encodeframe.c
vp8/encoder/ethreading.c
vp8/vp8_cx_iface.c
vpx/vp8cx.h
vpxenc.c

diff --git a/args.c b/args.c
index 782929022a7137aa2ae041beef2bfe5978178524..7b2cc3a10104f6fdd3802af00d676fbc0bebedcc 100644 (file)
--- a/args.c
+++ b/args.c
@@ -135,6 +135,17 @@ void arg_show_usage(FILE *fp, const struct arg_def *const *defs)
                      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");
+        }
     }
 }
 
@@ -218,3 +229,37 @@ struct vpx_rational arg_parse_rational(const struct arg *arg)
 
     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);
+}
diff --git a/args.h b/args.h
index 4fafcf8a4a17b4bb5ec7c150835d0c6baf57f022..7963fa6b71643da4c5fa482229573955c9dead3b 100644 (file)
--- a/args.h
+++ b/args.h
@@ -22,14 +22,23 @@ struct arg
     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;
     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 @@ char **argv_dup(int argc, const char **argv);
 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
index 3c199d1c21af5d17385a8d951d3e555951acb8e3..3724b11e0318963be149df4e8036723f469cc541 100644 (file)
@@ -18,6 +18,7 @@ extern "C"
 #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 @@ extern "C"
 
         struct vpx_fixed_buf         two_pass_stats_in;
         struct vpx_codec_pkt_list  *output_pkt_list;
+
+        vp8e_tuning tuning;
     } VP8_CONFIG;
 
 
index 2002735d22c9b52b4c5d552d1ae2712e0aee4d64..1528389468fac8b1164d3739b3d24820182c5621 100644 (file)
@@ -497,7 +497,8 @@ void encode_mb_row(VP8_COMP *cpi,
         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
index 0611d5bf6b907f4596d1c869d1d4a20063135304..2cd24da67943b11ea1b4401ab75969cc25a05ea8 100644 (file)
@@ -115,7 +115,8 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
                         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
index ed830cca0b4ac64e840d400a7576ff9993284db8..f9592077553ca839ae30ab12c381975832680eb7 100644 (file)
@@ -37,6 +37,7 @@ struct vp8_extracfg
     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 @@ static const struct extraconfig_map extracfg_map[] =
             0,                          /* arnr_max_frames */
             3,                          /* arnr_strength */
             3,                          /* arnr_type*/
+            0,                          /* tuning*/
         }
     }
 };
@@ -336,6 +338,7 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
     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 @@ static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
         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 @@ static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
     {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},
 };
 
index efd79459aeb152fc32d04ce77af5951c094e0ee5..3ed1cf18279fd7172f2ccccc16d5bf881e938ef9 100644 (file)
@@ -140,7 +140,8 @@ enum vp8e_enc_control_id
     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 @@ typedef enum
 } 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_TOKEN_PARTITIONS,   vp8e_token_partitions)
 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 *)
index 4baeefcdf034410c904b535b788f0d4221fa6785..5e4fe3f0f107bfb80d106e539d2f145346acf5aa 100755 (executable)
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -993,18 +993,27 @@ static const arg_def_t arnr_strength = ARG_DEF(NULL, "arnr-strength", 1,
                                        "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[] =
 {
     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 @@ int main(int argc, const char **argv_)
                 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++;
                 }
             }