diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-05-30 21:04:14 +0200 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2016-03-24 10:34:15 +0200 |
commit | 564b4591bbe223bdc5f36a1131eaef103f23f5d0 (patch) | |
tree | 75f56f2edb540eaa6bbeecdedef6b8b4fe6561b4 /libavutil/opt.c | |
parent | 8833f1508b7b6afc3172a8017934a7a54428c686 (diff) | |
download | ffmpeg-564b4591bbe223bdc5f36a1131eaef103f23f5d0.tar.gz |
opt: Add av_opt_copy()
This includes documentation and other modifications by
Lukasz Marek and Martin Storsjö.
Signed-off-by: Martin Storsjö <martin@martin.st>
Diffstat (limited to 'libavutil/opt.c')
-rw-r--r-- | libavutil/opt.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/libavutil/opt.c b/libavutil/opt.c index c5a1933aa3..01502435b7 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -757,6 +757,72 @@ const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *pre return NULL; } +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_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_RATIONAL: return sizeof(AVRational); + case AV_OPT_TYPE_BINARY: return sizeof(uint8_t*) + sizeof(int); + } + return AVERROR(EINVAL); +} + +int av_opt_copy(void *dst, const void *src) +{ + const AVOption *o = NULL; + const AVClass *c; + int ret = 0; + + if (!src) + return AVERROR(EINVAL); + + c = *(AVClass**)src; + if (!c || 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); + if (len) { + *field_dst8 = av_malloc(len); + if (!*field_dst8) { + ret = AVERROR(ENOMEM); + len = 0; + } + memcpy(*field_dst8, *field_src8, len); + } else { + *field_dst8 = NULL; + } + *(int*)(field_dst8 + 1) = len; + } else if (o->type == AV_OPT_TYPE_CONST) { + // do nothing + } else { + int size = opt_size(o->type); + if (size < 0) + ret = size; + else + memcpy(field_dst, field_src, size); + } + } + return ret; +} + #ifdef TEST typedef struct TestContext |