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: | ||||
| 
 | ||||
| 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 | ||||
|   AVCodecContext.decoded_side_data may now be set by libavcodec after | ||||
|   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); | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|                      const char key_val_sep, const char pairs_sep) | ||||
| { | ||||
|     const AVOption *o = NULL; | ||||
|     uint8_t *buf; | ||||
|     AVBPrint bprint; | ||||
|     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 || | ||||
|         pairs_sep == '\\' || key_val_sep == '\\') { | ||||
| @ -2407,28 +2447,11 @@ int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, | ||||
|     *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); | ||||
|     ret = opt_serialize(obj, opt_flags, flags, &cnt, &bprint, | ||||
|                         key_val_sep, pairs_sep); | ||||
|     if (ret < 0) | ||||
|         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); | ||||
|     if (ret < 0) | ||||
|         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_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. | ||||
|  | ||||
| @ -30,6 +30,7 @@ | ||||
| 
 | ||||
| typedef struct TestContext { | ||||
|     const AVClass *class; | ||||
|     struct ChildContext *child; | ||||
|     int num; | ||||
|     int toggle; | ||||
|     char *string; | ||||
| @ -123,10 +124,46 @@ static const char *test_get_name(void *ctx) | ||||
|     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 = { | ||||
|     .class_name = "TestContext", | ||||
|     .item_name  = test_get_name, | ||||
|     .option     = test_options, | ||||
|     .child_next = test_child_next, | ||||
|     .version    = LIBAVUTIL_VERSION_INT, | ||||
| }; | ||||
| 
 | ||||
| @ -277,13 +314,19 @@ int main(void) | ||||
|             av_set_options_string(&test_ctx, buf, "=", ","); | ||||
|             av_free(buf); | ||||
|             if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) { | ||||
|                 ChildContext child_ctx = { 0 }; | ||||
|                 printf("%s\n", buf); | ||||
|                 av_free(buf); | ||||
|                 if (av_opt_serialize(&test_ctx, 0, AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',') >= 0) { | ||||
|                     if (strlen(buf)) | ||||
|                 child_ctx.class = &child_class; | ||||
|                 test_ctx.child = &child_ctx; | ||||
|                 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_opt_free(&child_ctx); | ||||
|                 test_ctx.child = NULL; | ||||
|             } | ||||
|         } | ||||
|         av_opt_free(&test_ctx); | ||||
|  | ||||
| @ -79,7 +79,7 @@ | ||||
|  */ | ||||
| 
 | ||||
| #define LIBAVUTIL_VERSION_MAJOR  59 | ||||
| #define LIBAVUTIL_VERSION_MINOR  15 | ||||
| #define LIBAVUTIL_VERSION_MINOR  16 | ||||
| #define LIBAVUTIL_VERSION_MICRO 100 | ||||
| 
 | ||||
| #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_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 | ||||
| flt=0.333333,dbl=0.333333,array_int= | ||||
| child_num=0,flt=0.333333,dbl=0.333333,array_int= | ||||
| 
 | ||||
| Testing av_set_options_string() | ||||
| Setting options string '' | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user