X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavutil%2Fopt.c;h=694295dc3529fa2eac1c04ed6519315ca9ad58a6;hb=8159fe255ccadbb81c52f192f48d9dc6fc3e5537;hp=199eadbc05db9cdedd0e1b3adb2064d5d5fabf21;hpb=2320731614945a5a719ae3798b2e9d9d672f2d24;p=ffmpeg diff --git a/libavutil/opt.c b/libavutil/opt.c index 199eadbc05d..694295dc352 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -1517,6 +1517,70 @@ void *av_opt_ptr(const AVClass *class, void *obj, const char *name) return (uint8_t*)obj + opt->offset; } +static int opt_size(enum AVOptionType type) +{ + switch(type) { + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_FLAGS: return sizeof(int); + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_CHANNEL_LAYOUT: + case AV_OPT_TYPE_INT64: return sizeof(int64_t); + case AV_OPT_TYPE_DOUBLE: return sizeof(double); + case AV_OPT_TYPE_FLOAT: return sizeof(float); + case AV_OPT_TYPE_STRING: return sizeof(uint8_t*); + case AV_OPT_TYPE_VIDEO_RATE: + case AV_OPT_TYPE_RATIONAL: return sizeof(AVRational); + case AV_OPT_TYPE_BINARY: return sizeof(uint8_t*) + sizeof(int); + case AV_OPT_TYPE_IMAGE_SIZE:return sizeof(int[2]); + case AV_OPT_TYPE_PIXEL_FMT: return sizeof(enum AVPixelFormat); + case AV_OPT_TYPE_SAMPLE_FMT:return sizeof(enum AVSampleFormat); + case AV_OPT_TYPE_COLOR: return 4; + } + return 0; +} + +int av_opt_copy(void *dst, void *src) +{ + const AVOption *o = NULL; + const AVClass *c; + int ret = 0; + + if (!src) + return 0; + + c = *(AVClass**)src; + if (*(AVClass**)dst && c != *(AVClass**)dst) + return AVERROR(EINVAL); + + while ((o = av_opt_next(src, o))) { + void *field_dst = ((uint8_t*)dst) + o->offset; + void *field_src = ((uint8_t*)src) + o->offset; + uint8_t **field_dst8 = (uint8_t**)field_dst; + uint8_t **field_src8 = (uint8_t**)field_src; + + if (o->type == AV_OPT_TYPE_STRING) { + set_string(dst, o, *field_src8, field_dst8); + if (*field_src8 && !*field_dst8) + ret = AVERROR(ENOMEM); + } else if (o->type == AV_OPT_TYPE_BINARY) { + int len = *(int*)(field_src8 + 1); + if (*field_dst8 != *field_src8) + av_freep(field_dst8); + *field_dst8 = av_memdup(*field_src8, len); + if (len && !*field_dst8) { + ret = AVERROR(ENOMEM); + len = 0; + } + *(int*)(field_dst8 + 1) = len; + } else if (o->type == AV_OPT_TYPE_CONST) { + // do nothing + } else { + memcpy(field_dst, field_src, opt_size(o->type)); + } + } + return ret; +} + int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags) { int ret;