avutil/opt: add support for children objects in av_opt_serialize
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
855d4b5254
commit
8616cfe089
@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
|
|||||||
|
|
||||||
API changes, most recent first:
|
API changes, most recent first:
|
||||||
|
|
||||||
|
2024-04-11 - xxxxxxxxxx - lavu 59.16.100 - opt.h
|
||||||
|
Add AV_OPT_SERIALIZE_SEARCH_CHILDREN.
|
||||||
|
|
||||||
2024-04-11 - xxxxxxxxxx - lavc 61.5.102 - avcodec.h
|
2024-04-11 - xxxxxxxxxx - lavc 61.5.102 - avcodec.h
|
||||||
AVCodecContext.decoded_side_data may now be set by libavcodec after
|
AVCodecContext.decoded_side_data may now be set by libavcodec after
|
||||||
calling avcodec_open2().
|
calling avcodec_open2().
|
||||||
|
|||||||
@ -2386,14 +2386,54 @@ 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);
|
return av_opt_is_set_to_default(target, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int opt_serialize(void *obj, int opt_flags, int flags, int *cnt,
|
||||||
|
AVBPrint *bprint, const char key_val_sep, const char pairs_sep)
|
||||||
|
{
|
||||||
|
const AVOption *o = NULL;
|
||||||
|
void *child = NULL;
|
||||||
|
uint8_t *buf;
|
||||||
|
int ret;
|
||||||
|
const char special_chars[] = {pairs_sep, key_val_sep, '\0'};
|
||||||
|
|
||||||
|
if (flags & AV_OPT_SERIALIZE_SEARCH_CHILDREN)
|
||||||
|
while (child = av_opt_child_next(obj, child)) {
|
||||||
|
ret = opt_serialize(child, opt_flags, flags, cnt, bprint,
|
||||||
|
key_val_sep, pairs_sep);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_bprint_escape(bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
|
||||||
|
av_bprint_append_data(bprint, &key_val_sep, 1);
|
||||||
|
av_bprint_escape(bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
|
||||||
|
av_freep(&buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
|
int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
|
||||||
const char key_val_sep, const char pairs_sep)
|
const char key_val_sep, const char pairs_sep)
|
||||||
{
|
{
|
||||||
const AVOption *o = NULL;
|
|
||||||
uint8_t *buf;
|
|
||||||
AVBPrint bprint;
|
AVBPrint bprint;
|
||||||
int ret, cnt = 0;
|
int ret, cnt = 0;
|
||||||
const char special_chars[] = {pairs_sep, key_val_sep, '\0'};
|
|
||||||
|
|
||||||
if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
|
if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
|
||||||
pairs_sep == '\\' || key_val_sep == '\\') {
|
pairs_sep == '\\' || key_val_sep == '\\') {
|
||||||
@ -2407,28 +2447,11 @@ int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
|
|||||||
*buffer = NULL;
|
*buffer = NULL;
|
||||||
av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
|
av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
|
||||||
|
|
||||||
while (o = av_opt_next(obj, o)) {
|
ret = opt_serialize(obj, opt_flags, flags, &cnt, &bprint,
|
||||||
if (o->type == AV_OPT_TYPE_CONST)
|
key_val_sep, pairs_sep);
|
||||||
continue;
|
if (ret < 0)
|
||||||
if ((flags & AV_OPT_SERIALIZE_OPT_FLAGS_EXACT) && o->flags != opt_flags)
|
return ret;
|
||||||
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_bprint_escape(&bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
|
|
||||||
av_bprint_append_data(&bprint, &key_val_sep, 1);
|
|
||||||
av_bprint_escape(&bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
|
|
||||||
av_freep(&buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = av_bprint_finalize(&bprint, buffer);
|
ret = av_bprint_finalize(&bprint, buffer);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@ -929,6 +929,7 @@ int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
|
|||||||
|
|
||||||
#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only.
|
#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.
|
#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only.
|
||||||
|
#define AV_OPT_SERIALIZE_SEARCH_CHILDREN 0x00000004 ///< Serialize options in possible children of the given object.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize object's options.
|
* Serialize object's options.
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
typedef struct TestContext {
|
typedef struct TestContext {
|
||||||
const AVClass *class;
|
const AVClass *class;
|
||||||
|
struct ChildContext *child;
|
||||||
int num;
|
int num;
|
||||||
int toggle;
|
int toggle;
|
||||||
char *string;
|
char *string;
|
||||||
@ -123,10 +124,46 @@ static const char *test_get_name(void *ctx)
|
|||||||
return "test";
|
return "test";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct ChildContext {
|
||||||
|
const AVClass *class;
|
||||||
|
int64_t child_num64;
|
||||||
|
int child_num;
|
||||||
|
} ChildContext;
|
||||||
|
|
||||||
|
#undef OFFSET
|
||||||
|
#define OFFSET(x) offsetof(ChildContext, x)
|
||||||
|
|
||||||
|
static const AVOption child_options[]= {
|
||||||
|
{"child_num64", "set num 64bit", OFFSET(child_num64), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, 100, 1 },
|
||||||
|
{"child_num", "set child_num", OFFSET(child_num), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 100, 1 },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *child_get_name(void *ctx)
|
||||||
|
{
|
||||||
|
return "child";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const AVClass child_class = {
|
||||||
|
.class_name = "ChildContext",
|
||||||
|
.item_name = child_get_name,
|
||||||
|
.option = child_options,
|
||||||
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *test_child_next(void *obj, void *prev)
|
||||||
|
{
|
||||||
|
TestContext *test_ctx = obj;
|
||||||
|
if (!prev)
|
||||||
|
return test_ctx->child;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static const AVClass test_class = {
|
static const AVClass test_class = {
|
||||||
.class_name = "TestContext",
|
.class_name = "TestContext",
|
||||||
.item_name = test_get_name,
|
.item_name = test_get_name,
|
||||||
.option = test_options,
|
.option = test_options,
|
||||||
|
.child_next = test_child_next,
|
||||||
.version = LIBAVUTIL_VERSION_INT,
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -277,13 +314,19 @@ int main(void)
|
|||||||
av_set_options_string(&test_ctx, buf, "=", ",");
|
av_set_options_string(&test_ctx, buf, "=", ",");
|
||||||
av_free(buf);
|
av_free(buf);
|
||||||
if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
|
if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
|
||||||
|
ChildContext child_ctx = { 0 };
|
||||||
printf("%s\n", buf);
|
printf("%s\n", buf);
|
||||||
av_free(buf);
|
av_free(buf);
|
||||||
if (av_opt_serialize(&test_ctx, 0, AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',') >= 0) {
|
child_ctx.class = &child_class;
|
||||||
if (strlen(buf))
|
test_ctx.child = &child_ctx;
|
||||||
printf("%s\n", buf);
|
if (av_opt_serialize(&test_ctx, 0,
|
||||||
|
AV_OPT_SERIALIZE_SKIP_DEFAULTS|AV_OPT_SERIALIZE_SEARCH_CHILDREN,
|
||||||
|
&buf, '=', ',') >= 0) {
|
||||||
|
printf("%s\n", buf);
|
||||||
av_free(buf);
|
av_free(buf);
|
||||||
}
|
}
|
||||||
|
av_opt_free(&child_ctx);
|
||||||
|
test_ctx.child = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
av_opt_free(&test_ctx);
|
av_opt_free(&test_ctx);
|
||||||
|
|||||||
@ -79,7 +79,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define LIBAVUTIL_VERSION_MAJOR 59
|
#define LIBAVUTIL_VERSION_MAJOR 59
|
||||||
#define LIBAVUTIL_VERSION_MINOR 15
|
#define LIBAVUTIL_VERSION_MINOR 16
|
||||||
#define LIBAVUTIL_VERSION_MICRO 100
|
#define LIBAVUTIL_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
|
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
|
||||||
|
|||||||
@ -179,7 +179,7 @@ Setting entry with key 'array_int' to value ''
|
|||||||
Setting entry with key 'array_str' to value 'str0|str\|1|str\\2'
|
Setting entry with key 'array_str' to value 'str0|str\|1|str\\2'
|
||||||
Setting entry with key 'array_dict' to value 'k00=v\\\\00:k01=v\,01,k10=v\\=1\\:0'
|
Setting entry with key 'array_dict' to value 'k00=v\\\\00:k01=v\,01,k10=v\\=1\\:0'
|
||||||
num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=hexagonal,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-),array_int=,array_str=str0|str\\|1|str\\\\2,array_dict=k00\=v\\\\\\\\00:k01\=v\\\,01\,k10\=v\\\\\=1\\\\:0
|
num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=hexagonal,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-),array_int=,array_str=str0|str\\|1|str\\\\2,array_dict=k00\=v\\\\\\\\00:k01\=v\\\,01\,k10\=v\\\\\=1\\\\:0
|
||||||
flt=0.333333,dbl=0.333333,array_int=
|
child_num=0,flt=0.333333,dbl=0.333333,array_int=
|
||||||
|
|
||||||
Testing av_set_options_string()
|
Testing av_set_options_string()
|
||||||
Setting options string ''
|
Setting options string ''
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user