AVOptions: split av_set_string3 into opt type-specific functions
Also stop attempting to honor the alloc parameter, as things break horribly in that case. It will be removed in upcoming successor to av_set_string3.
This commit is contained in:
parent
1703013cb7
commit
c8d787d2ef
179
libavutil/opt.c
179
libavutil/opt.c
@ -116,10 +116,98 @@ static int hexchar2int(char c) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
|
||||||
|
{
|
||||||
|
int *lendst = (int *)(dst + 1);
|
||||||
|
uint8_t *bin, *ptr;
|
||||||
|
int len = strlen(val);
|
||||||
|
|
||||||
|
av_freep(dst);
|
||||||
|
*lendst = 0;
|
||||||
|
|
||||||
|
if (len & 1)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
len /= 2;
|
||||||
|
|
||||||
|
ptr = bin = av_malloc(len);
|
||||||
|
while (*val) {
|
||||||
|
int a = hexchar2int(*val++);
|
||||||
|
int b = hexchar2int(*val++);
|
||||||
|
if (a < 0 || b < 0) {
|
||||||
|
av_free(bin);
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
*ptr++ = (a << 4) | b;
|
||||||
|
}
|
||||||
|
*dst = bin;
|
||||||
|
*lendst = len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
|
||||||
|
{
|
||||||
|
av_freep(dst);
|
||||||
|
*dst = av_strdup(val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_string_number(void *obj, const AVOption *o, const char *val, void *dst)
|
||||||
|
{
|
||||||
|
int ret = 0, notfirst = 0;
|
||||||
|
for (;;) {
|
||||||
|
int i;
|
||||||
|
char buf[256];
|
||||||
|
int cmd = 0;
|
||||||
|
double d;
|
||||||
|
|
||||||
|
if (*val == '+' || *val == '-')
|
||||||
|
cmd = *(val++);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
|
||||||
|
buf[i] = val[i];
|
||||||
|
buf[i] = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
|
||||||
|
if (o_named && o_named->type == FF_OPT_TYPE_CONST)
|
||||||
|
d = o_named->default_val.dbl;
|
||||||
|
else if (!strcmp(buf, "default")) d = o->default_val.dbl;
|
||||||
|
else if (!strcmp(buf, "max" )) d = o->max;
|
||||||
|
else if (!strcmp(buf, "min" )) d = o->min;
|
||||||
|
else if (!strcmp(buf, "none" )) d = 0;
|
||||||
|
else if (!strcmp(buf, "all" )) d = ~0;
|
||||||
|
else {
|
||||||
|
int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
|
||||||
|
if (res < 0) {
|
||||||
|
av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o->type == FF_OPT_TYPE_FLAGS) {
|
||||||
|
if (cmd == '+') d = av_get_int(obj, o->name, NULL) | (int64_t)d;
|
||||||
|
else if (cmd == '-') d = av_get_int(obj, o->name, NULL) &~(int64_t)d;
|
||||||
|
} else {
|
||||||
|
if (cmd == '+') d = notfirst*av_get_double(obj, o->name, NULL) + d;
|
||||||
|
else if (cmd == '-') d = notfirst*av_get_double(obj, o->name, NULL) - d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = av_set_number2(obj, o->name, d, 1, 1, NULL)) < 0)
|
||||||
|
return ret;
|
||||||
|
val += i;
|
||||||
|
if (!*val)
|
||||||
|
return 0;
|
||||||
|
notfirst = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
|
int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
|
const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
|
||||||
|
void *dst;
|
||||||
if (o_out)
|
if (o_out)
|
||||||
*o_out = o;
|
*o_out = o;
|
||||||
if (!o)
|
if (!o)
|
||||||
@ -127,85 +215,20 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
|
|||||||
if (!val)
|
if (!val)
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
if (o->type == FF_OPT_TYPE_BINARY) {
|
dst = ((uint8_t*)obj) + o->offset;
|
||||||
uint8_t **dst = (uint8_t **)(((uint8_t*)obj) + o->offset);
|
switch (o->type) {
|
||||||
int *lendst = (int *)(dst + 1);
|
case FF_OPT_TYPE_STRING: return set_string(obj, o, val, dst);
|
||||||
uint8_t *bin, *ptr;
|
case FF_OPT_TYPE_BINARY: return set_string_binary(obj, o, val, dst);
|
||||||
int len = strlen(val);
|
case FF_OPT_TYPE_FLAGS:
|
||||||
av_freep(dst);
|
case FF_OPT_TYPE_INT:
|
||||||
*lendst = 0;
|
case FF_OPT_TYPE_INT64:
|
||||||
if (len & 1) return AVERROR(EINVAL);
|
case FF_OPT_TYPE_FLOAT:
|
||||||
len /= 2;
|
case FF_OPT_TYPE_DOUBLE:
|
||||||
ptr = bin = av_malloc(len);
|
case FF_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
|
||||||
while (*val) {
|
|
||||||
int a = hexchar2int(*val++);
|
|
||||||
int b = hexchar2int(*val++);
|
|
||||||
if (a < 0 || b < 0) {
|
|
||||||
av_free(bin);
|
|
||||||
return AVERROR(EINVAL);
|
|
||||||
}
|
|
||||||
*ptr++ = (a << 4) | b;
|
|
||||||
}
|
|
||||||
*dst = bin;
|
|
||||||
*lendst = len;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (o->type != FF_OPT_TYPE_STRING) {
|
|
||||||
int notfirst=0;
|
|
||||||
for (;;) {
|
|
||||||
int i;
|
|
||||||
char buf[256];
|
|
||||||
int cmd=0;
|
|
||||||
double d;
|
|
||||||
|
|
||||||
if (*val == '+' || *val == '-')
|
|
||||||
cmd= *(val++);
|
|
||||||
|
|
||||||
for (i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++)
|
|
||||||
buf[i]= val[i];
|
|
||||||
buf[i]=0;
|
|
||||||
|
|
||||||
{
|
|
||||||
const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
|
|
||||||
if (o_named && o_named->type == FF_OPT_TYPE_CONST)
|
|
||||||
d= o_named->default_val.dbl;
|
|
||||||
else if (!strcmp(buf, "default")) d= o->default_val.dbl;
|
|
||||||
else if (!strcmp(buf, "max" )) d= o->max;
|
|
||||||
else if (!strcmp(buf, "min" )) d= o->min;
|
|
||||||
else if (!strcmp(buf, "none" )) d= 0;
|
|
||||||
else if (!strcmp(buf, "all" )) d= ~0;
|
|
||||||
else {
|
|
||||||
int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
|
|
||||||
if (res < 0) {
|
|
||||||
av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (o->type == FF_OPT_TYPE_FLAGS) {
|
|
||||||
if (cmd=='+') d= av_get_int(obj, name, NULL) | (int64_t)d;
|
|
||||||
else if (cmd=='-') d= av_get_int(obj, name, NULL) &~(int64_t)d;
|
|
||||||
} else {
|
|
||||||
if (cmd=='+') d= notfirst*av_get_double(obj, name, NULL) + d;
|
|
||||||
else if (cmd=='-') d= notfirst*av_get_double(obj, name, NULL) - d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ret = av_set_number2(obj, name, d, 1, 1, o_out)) < 0)
|
|
||||||
return ret;
|
|
||||||
val+= i;
|
|
||||||
if (!*val)
|
|
||||||
return 0;
|
|
||||||
notfirst=1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alloc) {
|
av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
|
||||||
av_free(*(void**)(((uint8_t*)obj) + o->offset));
|
return AVERROR(EINVAL);
|
||||||
val= av_strdup(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(((uint8_t*)obj) + o->offset, &val, sizeof(val));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const AVOption *av_set_double(void *obj, const char *name, double n)
|
const AVOption *av_set_double(void *obj, const char *name, double n)
|
||||||
|
@ -129,9 +129,7 @@ const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int m
|
|||||||
* similarly, '-' unsets a flag.
|
* similarly, '-' unsets a flag.
|
||||||
* @param[out] o_out if non-NULL put here a pointer to the AVOption
|
* @param[out] o_out if non-NULL put here a pointer to the AVOption
|
||||||
* found
|
* found
|
||||||
* @param alloc when 1 then the old value will be av_freed() and the
|
* @param alloc this parameter is currently ignored
|
||||||
* new av_strduped()
|
|
||||||
* when 0 then no av_free() nor av_strdup() will be used
|
|
||||||
* @return 0 if the value has been set, or an AVERROR code in case of
|
* @return 0 if the value has been set, or an AVERROR code in case of
|
||||||
* error:
|
* error:
|
||||||
* AVERROR_OPTION_NOT_FOUND if no matching option exists
|
* AVERROR_OPTION_NOT_FOUND if no matching option exists
|
||||||
|
Loading…
x
Reference in New Issue
Block a user