avutil/opt: Add AV_OPT_TYPE_UINT64
authorMichael Niedermayer <michael@niedermayer.cc>
Sun, 20 Nov 2016 11:57:43 +0000 (12:57 +0100)
committerMichael Niedermayer <michael@niedermayer.cc>
Wed, 23 Nov 2016 01:01:05 +0000 (02:01 +0100)
Requested-by: wm4 ([FFmpeg-devel] [PATCH] avutil/opt: Support max > INT64_MAX in write_number() with AV_OPT_TYPE_INT64)
Requested-by: ronald ([FFmpeg-devel] [PATCH] avutil/opt: Support max > INT64_MAX in write_number() with AV_OPT_TYPE_INT64)
Reviewed-by: Andreas Cadhalpun <andreas.cadhalpun@googlemail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
libavutil/opt.c
libavutil/opt.h

index cd46a56..f855ccb 100644 (file)
@@ -74,6 +74,7 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_INT64:
+    case AV_OPT_TYPE_UINT64:
         *intnum = *(int64_t *)dst;
         return 0;
     case AV_OPT_TYPE_FLOAT:
@@ -133,6 +134,20 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
         } else
             *(int64_t *)dst = llrint(d) * intnum;
         break;}
+    case AV_OPT_TYPE_UINT64:{
+        double d = num / den;
+        // We must special case uint64_t here as llrint() does not support values
+        // outside the int64_t range and there is no portable function which does
+        // "INT64_MAX + 1ULL" is used as it is representable exactly as IEEE double
+        // while INT64_MAX is not
+        if (intnum == 1 && d == (double)UINT64_MAX) {
+            *(uint64_t *)dst = UINT64_MAX;
+        } else if (d > INT64_MAX + 1ULL) {
+            *(uint64_t *)dst = (llrint(d - (INT64_MAX + 1ULL)) + (INT64_MAX + 1ULL))*intnum;
+        } else {
+            *(uint64_t *)dst = llrint(d) * intnum;
+        }
+        break;}
     case AV_OPT_TYPE_FLOAT:
         *(float *)dst = num * intnum / den;
         break;
@@ -204,6 +219,7 @@ static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **d
 }
 
 #define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \
+                              opt->type == AV_OPT_TYPE_UINT64 || \
                               opt->type == AV_OPT_TYPE_CONST || \
                               opt->type == AV_OPT_TYPE_FLAGS || \
                               opt->type == AV_OPT_TYPE_INT)     \
@@ -460,6 +476,7 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
     case AV_OPT_TYPE_FLAGS:
     case AV_OPT_TYPE_INT:
     case AV_OPT_TYPE_INT64:
+    case AV_OPT_TYPE_UINT64:
     case AV_OPT_TYPE_FLOAT:
     case AV_OPT_TYPE_DOUBLE:
     case AV_OPT_TYPE_RATIONAL:
@@ -760,6 +777,9 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
     case AV_OPT_TYPE_INT64:
         ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t *)dst);
         break;
+    case AV_OPT_TYPE_UINT64:
+        ret = snprintf(buf, sizeof(buf), "%"PRIu64, *(uint64_t *)dst);
+        break;
     case AV_OPT_TYPE_FLOAT:
         ret = snprintf(buf, sizeof(buf), "%f", *(float *)dst);
         break;
@@ -1108,6 +1128,9 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
             case AV_OPT_TYPE_INT64:
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int64>");
                 break;
+            case AV_OPT_TYPE_UINT64:
+                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<uint64>");
+                break;
             case AV_OPT_TYPE_DOUBLE:
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<double>");
                 break;
@@ -1168,6 +1191,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
             switch (opt->type) {
             case AV_OPT_TYPE_INT:
             case AV_OPT_TYPE_INT64:
+            case AV_OPT_TYPE_UINT64:
             case AV_OPT_TYPE_DOUBLE:
             case AV_OPT_TYPE_FLOAT:
             case AV_OPT_TYPE_RATIONAL:
@@ -1212,6 +1236,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
                 break;
             }
             case AV_OPT_TYPE_INT:
+            case AV_OPT_TYPE_UINT64:
             case AV_OPT_TYPE_INT64: {
                 const char *def_const = get_opt_const_name(obj, opt->unit, opt->default_val.i64);
                 if (def_const)
@@ -1290,6 +1315,7 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
             case AV_OPT_TYPE_FLAGS:
             case AV_OPT_TYPE_INT:
             case AV_OPT_TYPE_INT64:
+            case AV_OPT_TYPE_UINT64:
             case AV_OPT_TYPE_DURATION:
             case AV_OPT_TYPE_CHANNEL_LAYOUT:
             case AV_OPT_TYPE_PIXEL_FMT:
@@ -1650,6 +1676,7 @@ static int opt_size(enum AVOptionType type)
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
     case AV_OPT_TYPE_INT64:
+    case AV_OPT_TYPE_UINT64:
         return sizeof(int64_t);
     case AV_OPT_TYPE_DOUBLE:
         return sizeof(double);
@@ -1779,6 +1806,7 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch
     case AV_OPT_TYPE_BOOL:
     case AV_OPT_TYPE_INT:
     case AV_OPT_TYPE_INT64:
+    case AV_OPT_TYPE_UINT64:
     case AV_OPT_TYPE_PIXEL_FMT:
     case AV_OPT_TYPE_SAMPLE_FMT:
     case AV_OPT_TYPE_FLOAT:
@@ -1868,6 +1896,7 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o)
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_INT64:
+    case AV_OPT_TYPE_UINT64:
         read_number(o, dst, NULL, NULL, &i64);
         return o->default_val.i64 == i64;
     case AV_OPT_TYPE_STRING:
index 9430b98..0d89379 100644 (file)
@@ -228,6 +228,7 @@ enum AVOptionType{
     AV_OPT_TYPE_RATIONAL,
     AV_OPT_TYPE_BINARY,  ///< offset must point to a pointer immediately followed by an int for the length
     AV_OPT_TYPE_DICT,
+    AV_OPT_TYPE_UINT64,
     AV_OPT_TYPE_CONST = 128,
     AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), ///< offset must point to two consecutive integers
     AV_OPT_TYPE_PIXEL_FMT  = MKBETAG('P','F','M','T'),