Browse code

lavu/opt: introduce av_opt_serialize()

Function allows to create string containing object's serialized options.
Such string may be passed back to av_set_options_string() in order to restore options.

Signed-off-by: Lukasz Marek <lukasz.m.luki2@gmail.com>

Lukasz Marek authored on 2014/11/11 06:28:44
Showing 5 changed files
... ...
@@ -15,6 +15,9 @@ libavutil:     2014-08-09
15 15
 
16 16
 API changes, most recent first:
17 17
 
18
+2014-11-16 - xxxxxxx - lavu 54.13.0 - opt.h
19
+  Add av_opt_serialize().
20
+
18 21
 2014-11-16 - xxxxxxx - lavu 54.12.0 - opt.h
19 22
   Add av_opt_is_set_to_default().
20 23
 
... ...
@@ -37,6 +37,7 @@
37 37
 #include "pixdesc.h"
38 38
 #include "mathematics.h"
39 39
 #include "samplefmt.h"
40
+#include "bprint.h"
40 41
 
41 42
 #include <float.h>
42 43
 
... ...
@@ -1835,6 +1836,44 @@ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_fla
1835 1835
     return av_opt_is_set_to_default(target, o);
1836 1836
 }
1837 1837
 
1838
+int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
1839
+                     const char key_val_sep, const char pairs_sep)
1840
+{
1841
+    const AVOption *o = NULL;
1842
+    uint8_t *buf;
1843
+    AVBPrint bprint;
1844
+    int ret, cnt = 0;
1845
+
1846
+    if (!obj || !buffer)
1847
+        return AVERROR(EINVAL);
1848
+
1849
+    *buffer = NULL;
1850
+    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
1851
+
1852
+    while (o = av_opt_next(obj, o)) {
1853
+        if (o->type == AV_OPT_TYPE_CONST)
1854
+            continue;
1855
+        if ((flags & AV_OPT_SERIALIZE_OPT_FLAGS_EXACT) && o->flags != opt_flags)
1856
+            continue;
1857
+        else if (((o->flags & opt_flags) != opt_flags))
1858
+            continue;
1859
+        if (flags & AV_OPT_SERIALIZE_SKIP_DEFAULTS && av_opt_is_set_to_default(obj, o) > 0)
1860
+            continue;
1861
+        if ((ret = av_opt_get(obj, o->name, 0, &buf)) < 0) {
1862
+            av_bprint_finalize(&bprint, NULL);
1863
+            return ret;
1864
+        }
1865
+        if (buf) {
1866
+            if (cnt++)
1867
+                av_bprint_append_data(&bprint, &pairs_sep, 1);
1868
+            av_bprintf(&bprint, "%s%c%s", o->name, key_val_sep, buf);
1869
+            av_freep(&buf);
1870
+        }
1871
+    }
1872
+    av_bprint_finalize(&bprint, buffer);
1873
+    return 0;
1874
+}
1875
+
1838 1876
 #ifdef TEST
1839 1877
 
1840 1878
 typedef struct TestContext
... ...
@@ -1854,6 +1893,10 @@ typedef struct TestContext
1854 1854
     int64_t channel_layout;
1855 1855
     void *binary;
1856 1856
     int binary_size;
1857
+    void *binary1;
1858
+    int binary_size1;
1859
+    void *binary2;
1860
+    int binary_size2;
1857 1861
     int64_t num64;
1858 1862
     float flt;
1859 1863
     double dbl;
... ...
@@ -1882,6 +1925,8 @@ static const AVOption test_options[]= {
1882 1882
 {"color", "set color",   OFFSET(color), AV_OPT_TYPE_COLOR, {.str = "pink"}, 0, 0},
1883 1883
 {"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = AV_CH_LAYOUT_HEXAGONAL}, 0, INT64_MAX},
1884 1884
 {"bin", "set binary value",    OFFSET(binary),   AV_OPT_TYPE_BINARY,   {.str="62696e00"}, 0,        0 },
1885
+{"bin1", "set binary value",   OFFSET(binary1),  AV_OPT_TYPE_BINARY,   {.str=NULL},       0,        0 },
1886
+{"bin2", "set binary value",   OFFSET(binary2),  AV_OPT_TYPE_BINARY,   {.str=""},         0,        0 },
1885 1887
 {"num64",    "set num 64bit",  OFFSET(num64),    AV_OPT_TYPE_INT64,    {.i64 = 1},        0,        100 },
1886 1888
 {"flt",      "set float",      OFFSET(flt),      AV_OPT_TYPE_FLOAT,    {.dbl = 1.0/3},    0,        100 },
1887 1889
 {"dbl",      "set double",     OFFSET(dbl),      AV_OPT_TYPE_DOUBLE,   {.dbl = 1.0/3},    0,        100 },
... ...
@@ -1951,6 +1996,30 @@ int main(void)
1951 1951
         av_opt_free(&test_ctx);
1952 1952
     }
1953 1953
 
1954
+    printf("\nTest av_opt_serialize()\n");
1955
+    {
1956
+        TestContext test_ctx = { 0 };
1957
+        char *buf;
1958
+        test_ctx.class = &test_class;
1959
+
1960
+        av_log_set_level(AV_LOG_QUIET);
1961
+
1962
+        av_opt_set_defaults(&test_ctx);
1963
+        if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
1964
+            printf("%s\n", buf);
1965
+            av_opt_free(&test_ctx);
1966
+            memset(&test_ctx, 0, sizeof(test_ctx));
1967
+            test_ctx.class = &test_class;
1968
+            av_set_options_string(&test_ctx, buf, "=", ",");
1969
+            av_free(buf);
1970
+            if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
1971
+                printf("%s\n", buf);
1972
+                av_free(buf);
1973
+            }
1974
+        }
1975
+        av_opt_free(&test_ctx);
1976
+    }
1977
+
1954 1978
     printf("\nTesting av_set_options_string()\n");
1955 1979
     {
1956 1980
         TestContext test_ctx = { 0 };
... ...
@@ -869,6 +869,27 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o);
869 869
  */
870 870
 int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags);
871 871
 
872
+
873
+#define AV_OPT_SERIALIZE_SKIP_DEFAULTS              0x00000001  ///< Serialize options that are not set to default values only.
874
+#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT            0x00000002  ///< Serialize options that exactly match opt_flags only.
875
+
876
+/**
877
+ * Serialize object's options.
878
+ *
879
+ * Create a string containing object's serialized options.
880
+ * Such string may be passed back to av_opt_set_from_string() in order to restore option values.
881
+ *
882
+ * @param[in]  obj           AVClass object to serialize
883
+ * @param[in]  opt_flags     serialize options with all the specified flags set (AV_OPT_FLAG)
884
+ * @param[in]  flags         combination of AV_OPT_SERIALIZE_* flags
885
+ * @param[out] buffer        Pointer to buffer that will be allocated with string containg serialized options.
886
+ *                           Buffer must be freed by the caller when is no longer needed.
887
+ * @param[in]  key_val_sep   character used to separate key from value
888
+ * @param[in]  pairs_sep     character used to separate two pairs from each other
889
+ * @return                   >= 0 on success, negative on error
890
+ */
891
+int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
892
+                     const char key_val_sep, const char pairs_sep);
872 893
 /**
873 894
  * @}
874 895
  */
... ...
@@ -56,7 +56,7 @@
56 56
  */
57 57
 
58 58
 #define LIBAVUTIL_VERSION_MAJOR  54
59
-#define LIBAVUTIL_VERSION_MINOR  12
59
+#define LIBAVUTIL_VERSION_MINOR  13
60 60
 #define LIBAVUTIL_VERSION_MICRO 100
61 61
 
62 62
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
... ...
@@ -34,6 +34,8 @@ name:  duration default:0 error:
34 34
 name:     color default:0 error:
35 35
 name:        cl default:0 error:
36 36
 name:       bin default:0 error:
37
+name:      bin1 default:1 error:
38
+name:      bin2 default:1 error:
37 39
 name:     num64 default:0 error:
38 40
 name:       flt default:0 error:
39 41
 name:       dbl default:0 error:
... ...
@@ -53,10 +55,16 @@ name:  duration default:1 error:
53 53
 name:     color default:1 error:
54 54
 name:        cl default:1 error:
55 55
 name:       bin default:1 error:
56
+name:      bin1 default:1 error:
57
+name:      bin2 default:1 error:
56 58
 name:     num64 default:1 error:
57 59
 name:       flt default:1 error:
58 60
 name:       dbl default:1 error:
59 61
 
62
+Test av_opt_serialize()
63
+num=0,toggle=1,rational=1/1,string=default,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
64
+num=0,toggle=1,rational=1/1,string=default,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
65
+
60 66
 Testing av_set_options_string()
61 67
 OK    ''
62 68
 Error ':'