From bee5844ddd4efc771a85caf6168d79abe42769a2 Mon Sep 17 00:00:00 2001 From: Lukasz Marek Date: Mon, 10 Nov 2014 22:28:44 +0100 Subject: [PATCH] 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 --- doc/APIchanges | 3 ++ libavutil/opt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ libavutil/opt.h | 21 ++++++++++++++ libavutil/version.h | 2 +- tests/ref/fate/opt | 8 ++++++ 5 files changed, 102 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 079bfb5db2..b4a3ed88c5 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2014-08-09 API changes, most recent first: +2014-11-16 - xxxxxxx - lavu 54.13.0 - opt.h + Add av_opt_serialize(). + 2014-11-16 - xxxxxxx - lavu 54.12.0 - opt.h Add av_opt_is_set_to_default(). diff --git a/libavutil/opt.c b/libavutil/opt.c index 72e4caf633..0546a37b0f 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -37,6 +37,7 @@ #include "pixdesc.h" #include "mathematics.h" #include "samplefmt.h" +#include "bprint.h" #include @@ -1835,6 +1836,44 @@ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_fla return av_opt_is_set_to_default(target, o); } +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep) +{ + const AVOption *o = NULL; + uint8_t *buf; + AVBPrint bprint; + int ret, cnt = 0; + + if (!obj || !buffer) + return AVERROR(EINVAL); + + *buffer = NULL; + av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); + + while (o = av_opt_next(obj, o)) { + if (o->type == AV_OPT_TYPE_CONST) + continue; + if ((flags & AV_OPT_SERIALIZE_OPT_FLAGS_EXACT) && o->flags != opt_flags) + continue; + else if (((o->flags & opt_flags) != opt_flags)) + continue; + if (flags & AV_OPT_SERIALIZE_SKIP_DEFAULTS && av_opt_is_set_to_default(obj, o) > 0) + continue; + if ((ret = av_opt_get(obj, o->name, 0, &buf)) < 0) { + av_bprint_finalize(&bprint, NULL); + return ret; + } + if (buf) { + if (cnt++) + av_bprint_append_data(&bprint, &pairs_sep, 1); + av_bprintf(&bprint, "%s%c%s", o->name, key_val_sep, buf); + av_freep(&buf); + } + } + av_bprint_finalize(&bprint, buffer); + return 0; +} + #ifdef TEST typedef struct TestContext @@ -1854,6 +1893,10 @@ typedef struct TestContext int64_t channel_layout; void *binary; int binary_size; + void *binary1; + int binary_size1; + void *binary2; + int binary_size2; int64_t num64; float flt; double dbl; @@ -1882,6 +1925,8 @@ static const AVOption test_options[]= { {"color", "set color", OFFSET(color), AV_OPT_TYPE_COLOR, {.str = "pink"}, 0, 0}, {"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = AV_CH_LAYOUT_HEXAGONAL}, 0, INT64_MAX}, {"bin", "set binary value", OFFSET(binary), AV_OPT_TYPE_BINARY, {.str="62696e00"}, 0, 0 }, +{"bin1", "set binary value", OFFSET(binary1), AV_OPT_TYPE_BINARY, {.str=NULL}, 0, 0 }, +{"bin2", "set binary value", OFFSET(binary2), AV_OPT_TYPE_BINARY, {.str=""}, 0, 0 }, {"num64", "set num 64bit", OFFSET(num64), AV_OPT_TYPE_INT64, {.i64 = 1}, 0, 100 }, {"flt", "set float", OFFSET(flt), AV_OPT_TYPE_FLOAT, {.dbl = 1.0/3}, 0, 100 }, {"dbl", "set double", OFFSET(dbl), AV_OPT_TYPE_DOUBLE, {.dbl = 1.0/3}, 0, 100 }, @@ -1951,6 +1996,30 @@ int main(void) av_opt_free(&test_ctx); } + printf("\nTest av_opt_serialize()\n"); + { + TestContext test_ctx = { 0 }; + char *buf; + test_ctx.class = &test_class; + + av_log_set_level(AV_LOG_QUIET); + + av_opt_set_defaults(&test_ctx); + if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) { + printf("%s\n", buf); + av_opt_free(&test_ctx); + memset(&test_ctx, 0, sizeof(test_ctx)); + test_ctx.class = &test_class; + av_set_options_string(&test_ctx, buf, "=", ","); + av_free(buf); + if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) { + printf("%s\n", buf); + av_free(buf); + } + } + av_opt_free(&test_ctx); + } + printf("\nTesting av_set_options_string()\n"); { TestContext test_ctx = { 0 }; diff --git a/libavutil/opt.h b/libavutil/opt.h index 1b458e1860..7338e78368 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -869,6 +869,27 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o); */ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); + +#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. +#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. + +/** + * Serialize object's options. + * + * Create a string containing object's serialized options. + * Such string may be passed back to av_opt_set_from_string() in order to restore option values. + * + * @param[in] obj AVClass object to serialize + * @param[in] opt_flags serialize options with all the specified flags set (AV_OPT_FLAG) + * @param[in] flags combination of AV_OPT_SERIALIZE_* flags + * @param[out] buffer Pointer to buffer that will be allocated with string containg serialized options. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + */ +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep); /** * @} */ diff --git a/libavutil/version.h b/libavutil/version.h index a48ea8d73d..bf7c7ef8c2 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -56,7 +56,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 54 -#define LIBAVUTIL_VERSION_MINOR 12 +#define LIBAVUTIL_VERSION_MINOR 13 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt index 7953ce8eca..16f338732a 100644 --- a/tests/ref/fate/opt +++ b/tests/ref/fate/opt @@ -34,6 +34,8 @@ name: duration default:0 error: name: color default:0 error: name: cl default:0 error: name: bin default:0 error: +name: bin1 default:1 error: +name: bin2 default:1 error: name: num64 default:0 error: name: flt default:0 error: name: dbl default:0 error: @@ -53,10 +55,16 @@ name: duration default:1 error: name: color default:1 error: name: cl default:1 error: name: bin default:1 error: +name: bin1 default:1 error: +name: bin2 default:1 error: name: num64 default:1 error: name: flt default:1 error: name: dbl default:1 error: +Test av_opt_serialize() +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 +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 + Testing av_set_options_string() OK '' Error ':'