]> git.sesse.net Git - ffmpeg/blobdiff - libavutil/parseutils.c
hwcontext_vaapi: Try to support the VDPAU wrapper
[ffmpeg] / libavutil / parseutils.c
index 09eebcf56f25ea09d3def39231785f29e839042c..d9d5839f67c6e372fcaa5144c7b45763a1e2346b 100644 (file)
@@ -1,18 +1,18 @@
 /*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
  *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
  * misc parsing utilities
  */
 
-#include <strings.h>
+#include <time.h>
+
+#include "avstring.h"
+#include "avutil.h"
+#include "common.h"
+#include "eval.h"
+#include "log.h"
+#include "random_seed.h"
+#include "time_internal.h"
 #include "parseutils.h"
-#include "libavutil/avutil.h"
-#include "libavutil/eval.h"
-#include "libavutil/avstring.h"
-#include "libavutil/random_seed.h"
 
-typedef struct {
+typedef struct VideoSizeAbbr {
     const char *abbr;
     int width, height;
 } VideoSizeAbbr;
 
-typedef struct {
+typedef struct VideoRateAbbr {
     const char *abbr;
     AVRational rate;
 } VideoRateAbbr;
@@ -76,6 +80,10 @@ static const VideoSizeAbbr video_size_abbrs[] = {
     { "hd480",     852, 480 },
     { "hd720",    1280, 720 },
     { "hd1080",   1920,1080 },
+    { "2kdci",    2048,1080 },
+    { "4kdci",    4096,2160 },
+    { "uhd2160",  3840,2160 },
+    { "uhd4320",  7680,4320 },
 };
 
 static const VideoRateAbbr video_rate_abbrs[]= {
@@ -104,8 +112,7 @@ int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
         }
     }
     if (i == n) {
-        p = str;
-        width = strtol(p, &p, 10);
+        width = strtol(str, &p, 10);
         if (*p)
             p++;
         height = strtol(p, &p, 10);
@@ -140,12 +147,12 @@ int av_parse_video_rate(AVRational *rate, const char *arg)
     return 0;
 }
 
-typedef struct {
+typedef struct ColorEntry {
     const char *name;            ///< a string representing the name of the color
     uint8_t     rgb_color[3];    ///< RGB values for the color
 } ColorEntry;
 
-static ColorEntry color_table[] = {
+static const ColorEntry color_table[] = {
     { "AliceBlue",            { 0xF0, 0xF8, 0xFF } },
     { "AntiqueWhite",         { 0xFA, 0xEB, 0xD7 } },
     { "Aqua",                 { 0x00, 0xFF, 0xFF } },
@@ -290,7 +297,7 @@ static ColorEntry color_table[] = {
 
 static int color_table_compare(const void *lhs, const void *rhs)
 {
-    return strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
+    return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
 }
 
 #define ALPHA_SEP '@'
@@ -316,7 +323,7 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
     len = strlen(color_string2);
     rgba_color[3] = 255;
 
-    if (!strcasecmp(color_string2, "random") || !strcasecmp(color_string2, "bikeshed")) {
+    if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
         int rgba = av_get_random_seed();
         rgba_color[0] = rgba >> 24;
         rgba_color[1] = rgba >> 16;
@@ -352,7 +359,7 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
     }
 
     if (tail) {
-        unsigned long int alpha;
+        double alpha;
         const char *alpha_string = tail;
         if (!strncmp(alpha_string, "0x", 2)) {
             alpha = strtoul(alpha_string, &tail, 16);
@@ -360,7 +367,7 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
             alpha = 255 * strtod(alpha_string, &tail);
         }
 
-        if (tail == alpha_string || *tail || alpha > 255) {
+        if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
             av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
                    alpha_string, color_string);
             return AVERROR(EINVAL);
@@ -371,104 +378,279 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
     return 0;
 }
 
-#ifdef TEST
+/* get a positive number between n_min and n_max, for a maximum length
+   of len_max. Return -1 if error. */
+static int date_get_num(const char **pp,
+                        int n_min, int n_max, int len_max)
+{
+    int i, val, c;
+    const char *p;
+
+    p = *pp;
+    val = 0;
+    for(i = 0; i < len_max; i++) {
+        c = *p;
+        if (!av_isdigit(c))
+            break;
+        val = (val * 10) + c - '0';
+        p++;
+    }
+    /* no number read ? */
+    if (p == *pp)
+        return -1;
+    if (val < n_min || val > n_max)
+        return -1;
+    *pp = p;
+    return val;
+}
+
+const char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
+{
+    int c, val;
+
+    while((c = *fmt++)) {
+        if (c != '%') {
+            if (av_isspace(c))
+                for (; *p && av_isspace(*p); p++);
+            else if (*p != c)
+                return NULL;
+            else p++;
+            continue;
+        }
+
+        c = *fmt++;
+        switch(c) {
+        case 'H':
+            val = date_get_num(&p, 0, 23, 2);
+            if (val == -1)
+                return NULL;
+            dt->tm_hour = val;
+            break;
+        case 'M':
+            val = date_get_num(&p, 0, 59, 2);
+            if (val == -1)
+                return NULL;
+            dt->tm_min = val;
+            break;
+        case 'S':
+            val = date_get_num(&p, 0, 59, 2);
+            if (val == -1)
+                return NULL;
+            dt->tm_sec = val;
+            break;
+        case 'Y':
+            val = date_get_num(&p, 0, 9999, 4);
+            if (val == -1)
+                return NULL;
+            dt->tm_year = val - 1900;
+            break;
+        case 'm':
+            val = date_get_num(&p, 1, 12, 2);
+            if (val == -1)
+                return NULL;
+            dt->tm_mon = val - 1;
+            break;
+        case 'd':
+            val = date_get_num(&p, 1, 31, 2);
+            if (val == -1)
+                return NULL;
+            dt->tm_mday = val;
+            break;
+        case 'T':
+            p = av_small_strptime(p, "%H:%M:%S", dt);
+            if (!p)
+                return NULL;
+            break;
+        case '%':
+            if (*p++ != '%')
+                return NULL;
+            break;
+        default:
+            return NULL;
+        }
+    }
+
+    return p;
+}
+
+time_t av_timegm(struct tm *tm)
+{
+    time_t t;
 
-#undef printf
+    int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
 
-int main(void)
+    if (m < 3) {
+        m += 12;
+        y--;
+    }
+
+    t = 86400 *
+        (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
+
+    t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
+
+    return t;
+}
+
+int av_parse_time(int64_t *timeval, const char *timestr, int duration)
 {
-    printf("Testing av_parse_video_rate()\n");
-    {
-        int i;
-        const char *rates[] = {
-            "-inf",
-            "inf",
-            "nan",
-            "123/0",
-            "-123 / 0",
-            "",
-            "/",
-            " 123  /  321",
-            "foo/foo",
-            "foo/1",
-            "1/foo",
-            "0/0",
-            "/0",
-            "1/",
-            "1",
-            "0",
-            "-123/123",
-            "-foo",
-            "123.23",
-            ".23",
-            "-.23",
-            "-0.234",
-            "-0.0000001",
-            "  21332.2324   ",
-            " -21332.2324   ",
-        };
-
-        for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
-            int ret;
-            AVRational q = (AVRational){0, 0};
-            ret = av_parse_video_rate(&q, rates[i]),
-            printf("'%s' -> %d/%d ret:%d\n",
-                   rates[i], q.num, q.den, ret);
+    const char *p;
+    int64_t t;
+    struct tm dt = { 0 }, tmbuf;
+    int i;
+    static const char * const date_fmt[] = {
+        "%Y-%m-%d",
+        "%Y%m%d",
+    };
+    static const char * const time_fmt[] = {
+        "%H:%M:%S",
+        "%H%M%S",
+    };
+    const char *q;
+    int is_utc, len;
+    char lastch;
+    int negative = 0;
+
+    time_t now = time(0);
+
+    len = strlen(timestr);
+    if (len > 0)
+        lastch = timestr[len - 1];
+    else
+        lastch = '\0';
+    is_utc = (lastch == 'z' || lastch == 'Z');
+
+    p = timestr;
+    q = NULL;
+    if (!duration) {
+        if (!av_strncasecmp(timestr, "now", len)) {
+            *timeval = (int64_t) now * 1000000;
+            return 0;
+        }
+
+        /* parse the year-month-day part */
+        for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
+            q = av_small_strptime(p, date_fmt[i], &dt);
+            if (q) {
+                break;
+            }
+        }
+
+        /* if the year-month-day part is missing, then take the
+         * current year-month-day time */
+        if (!q) {
+            if (is_utc) {
+                dt = *gmtime_r(&now, &tmbuf);
+            } else {
+                dt = *localtime_r(&now, &tmbuf);
+            }
+            dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
+        } else {
+            p = q;
         }
+
+        if (*p == 'T' || *p == 't' || *p == ' ')
+            p++;
+
+        /* parse the hour-minute-second part */
+        for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
+            q = av_small_strptime(p, time_fmt[i], &dt);
+            if (q) {
+                break;
+            }
+        }
+    } else {
+        /* parse timestr as a duration */
+        if (p[0] == '-') {
+            negative = 1;
+            ++p;
+        }
+        /* parse timestr as HH:MM:SS */
+        q = av_small_strptime(p, time_fmt[0], &dt);
+        if (!q) {
+            char *o;
+            /* parse timestr as S+ */
+            dt.tm_sec = strtol(p, &o, 10);
+            if (o == p) {
+                /* the parsing didn't succeed */
+                *timeval = INT64_MIN;
+                return AVERROR(EINVAL);
+            }
+            dt.tm_min = 0;
+            dt.tm_hour = 0;
+            q = o;
+        }
+    }
+
+    /* Now we have all the fields that we can get */
+    if (!q) {
+        *timeval = INT64_MIN;
+        return AVERROR(EINVAL);
     }
 
-    printf("\nTesting av_parse_color()\n");
-    {
-        int i;
-        uint8_t rgba[4];
-        const char *color_names[] = {
-            "bikeshed",
-            "RaNdOm",
-            "foo",
-            "red",
-            "Red ",
-            "RED",
-            "Violet",
-            "Yellow",
-            "Red",
-            "0x000000",
-            "0x0000000",
-            "0xff000000",
-            "0x3e34ff",
-            "0x3e34ffaa",
-            "0xffXXee",
-            "0xfoobar",
-            "0xffffeeeeeeee",
-            "#ff0000",
-            "#ffXX00",
-            "ff0000",
-            "ffXX00",
-            "red@foo",
-            "random@10",
-            "0xff0000@1.0",
-            "red@",
-            "red@0xfff",
-            "red@0xf",
-            "red@2",
-            "red@0.1",
-            "red@-1",
-            "red@0.5",
-            "red@1.0",
-            "red@256",
-            "red@10foo",
-            "red@-1.0",
-            "red@-0.0",
-        };
-
-        av_log_set_level(AV_LOG_DEBUG);
-
-        for (i = 0;  i < FF_ARRAY_ELEMS(color_names); i++) {
-            if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
-                printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
+    if (duration) {
+        t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
+    } else {
+        dt.tm_isdst = -1;       /* unknown */
+        if (is_utc) {
+            t = av_timegm(&dt);
+        } else {
+            t = mktime(&dt);
         }
     }
 
+    t *= 1000000;
+
+    /* parse the .m... part */
+    if (*q == '.') {
+        int val, n;
+        q++;
+        for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
+            if (!av_isdigit(*q))
+                break;
+            val += n * (*q - '0');
+        }
+        t += val;
+    }
+    *timeval = negative ? -t : t;
     return 0;
 }
 
-#endif /* TEST */
+int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
+{
+    const char *p;
+    char tag[128], *q;
+
+    p = info;
+    if (*p == '?')
+        p++;
+    for(;;) {
+        q = tag;
+        while (*p != '\0' && *p != '=' && *p != '&') {
+            if ((q - tag) < sizeof(tag) - 1)
+                *q++ = *p;
+            p++;
+        }
+        *q = '\0';
+        q = arg;
+        if (*p == '=') {
+            p++;
+            while (*p != '&' && *p != '\0') {
+                if ((q - arg) < arg_size - 1) {
+                    if (*p == '+')
+                        *q++ = ' ';
+                    else
+                        *q++ = *p;
+                }
+                p++;
+            }
+        }
+        *q = '\0';
+        if (!strcmp(tag, tag1))
+            return 1;
+        if (*p != '&')
+            break;
+        p++;
+    }
+    return 0;
+}