summaryrefslogtreecommitdiffstats
path: root/libavutil/opt.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavutil/opt.c')
-rw-r--r--libavutil/opt.c94
1 files changed, 78 insertions, 16 deletions
diff --git a/libavutil/opt.c b/libavutil/opt.c
index b75eb94..18af0ed 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -2,20 +2,20 @@
* AVOptions
* Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -32,16 +32,17 @@
#include "eval.h"
#include "dict.h"
#include "log.h"
+#include "parseutils.h"
+#include "pixdesc.h"
#include "mathematics.h"
#if FF_API_FIND_OPT
//FIXME order them and do a bin search
const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
{
- AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
- const AVOption *o= c->option;
+ const AVOption *o = NULL;
- for (; o && o->name; o++) {
+ while ((o = av_next_option(v, o))) {
if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags)
return o;
}
@@ -59,7 +60,8 @@ const AVOption *av_next_option(void *obj, const AVOption *last)
const AVOption *av_opt_next(void *obj, const AVOption *last)
{
AVClass *class = *(AVClass**)obj;
- if (!last && class->option[0].name) return class->option;
+ if (!last && class->option && class->option[0].name)
+ return class->option;
if (last && last[1].name) return ++last;
return NULL;
}
@@ -75,6 +77,7 @@ static int read_number(const AVOption *o, void *dst, double *num, int *den, int6
case AV_OPT_TYPE_RATIONAL: *intnum = ((AVRational*)dst)->num;
*den = ((AVRational*)dst)->den;
return 0;
+ case AV_OPT_TYPE_CONST: *num = o->default_val.dbl; return 0;
}
return AVERROR(EINVAL);
}
@@ -82,7 +85,7 @@ static int read_number(const AVOption *o, void *dst, double *num, int *den, int6
static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
{
if (o->max*den < num*intnum || o->min*den > num*intnum) {
- av_log(obj, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range\n",
+ av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range\n",
num*intnum/den, o->name);
return AVERROR(ERANGE);
}
@@ -233,11 +236,12 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
{
+ int ret;
void *dst, *target_obj;
const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
if (!o || !target_obj)
return AVERROR_OPTION_NOT_FOUND;
- if (!val)
+ if (!val && o->type != AV_OPT_TYPE_STRING)
return AVERROR(EINVAL);
dst = ((uint8_t*)target_obj) + o->offset;
@@ -250,6 +254,23 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
case AV_OPT_TYPE_FLOAT:
case AV_OPT_TYPE_DOUBLE:
case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ ret = av_parse_video_size(dst, ((int *)dst) + 1, val);
+ if (ret < 0)
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val);
+ return ret;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ ret = av_get_pix_fmt(val);
+ if (ret == PIX_FMT_NONE) {
+ char *tail;
+ ret = strtol(val, &tail, 0);
+ if (*tail || (unsigned)ret >= PIX_FMT_NB) {
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as pixel format\n", val);
+ return AVERROR(EINVAL);
+ }
+ }
+ *(enum PixelFormat *)dst = ret;
+ return 0;
}
av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
@@ -362,7 +383,7 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int
*/
const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
{
- const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
+ const AVOption *o = av_opt_find(obj, name, NULL, 0, AV_OPT_SEARCH_CHILDREN);
void *dst;
uint8_t *bin;
int len, i;
@@ -381,6 +402,7 @@ const char *av_get_string(void *obj, const char *name, const AVOption **o_out, c
case AV_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break;
case AV_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break;
case AV_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
+ case AV_OPT_TYPE_CONST: snprintf(buf, buf_len, "%f" , o->default_val.dbl);break;
case AV_OPT_TYPE_STRING: return *(void**)dst;
case AV_OPT_TYPE_BINARY:
len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
@@ -401,7 +423,7 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
uint8_t *bin, buf[128];
int len, i, ret;
- if (!o || !target_obj)
+ if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST))
return AVERROR_OPTION_NOT_FOUND;
dst = (uint8_t*)target_obj + o->offset;
@@ -414,6 +436,7 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
case AV_OPT_TYPE_FLOAT: ret = snprintf(buf, sizeof(buf), "%f" , *(float *)dst);break;
case AV_OPT_TYPE_DOUBLE: ret = snprintf(buf, sizeof(buf), "%f" , *(double *)dst);break;
case AV_OPT_TYPE_RATIONAL: ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
+ case AV_OPT_TYPE_CONST: ret = snprintf(buf, sizeof(buf), "%f" , o->default_val.dbl);break;
case AV_OPT_TYPE_STRING:
if (*(uint8_t**)dst)
*out_val = av_strdup(*(uint8_t**)dst);
@@ -430,6 +453,12 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
for (i = 0; i < len; i++)
snprintf(*out_val + i*2, 3, "%02X", bin[i]);
return 0;
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]);
+ break;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum PixelFormat *)dst), "?"));
+ break;
default:
return AVERROR(EINVAL);
}
@@ -599,6 +628,12 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
case AV_OPT_TYPE_BINARY:
av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
break;
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<image_size>");
+ break;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<pix_fmt>");
+ break;
case AV_OPT_TYPE_CONST:
default:
av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
@@ -606,6 +641,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
}
av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_FILTERING_PARAM)? 'F' : '.');
av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.');
av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.');
av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
@@ -669,6 +705,8 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
}
break;
case AV_OPT_TYPE_STRING:
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ case AV_OPT_TYPE_PIXEL_FMT:
av_opt_set(s, opt->name, opt->default_val.str, 0);
break;
case AV_OPT_TYPE_BINARY:
@@ -713,7 +751,7 @@ static int parse_key_value_pair(void *ctx, const char **buf,
return AVERROR(EINVAL);
}
- av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
+ av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val);
ret = av_opt_set(ctx, key, val, 0);
if (ret == AVERROR_OPTION_NOT_FOUND)
@@ -782,9 +820,14 @@ const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
int opt_flags, int search_flags, void **target_obj)
{
- const AVClass *c = *(AVClass**)obj;
+ const AVClass *c;
const AVOption *o = NULL;
+ if(!obj)
+ return NULL;
+
+ c= *(AVClass**)obj;
+
if (search_flags & AV_OPT_SEARCH_CHILDREN) {
if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
const AVClass *child = NULL;
@@ -802,7 +845,7 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
while (o = av_opt_next(obj, o)) {
if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
((!unit && o->type != AV_OPT_TYPE_CONST) ||
- (unit && o->unit && !strcmp(o->unit, unit)))) {
+ (unit && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) {
if (target_obj) {
if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
*target_obj = obj;
@@ -830,6 +873,14 @@ const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *pre
return NULL;
}
+void *av_opt_ptr(const AVClass *class, void *obj, const char *name)
+{
+ const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL);
+ if(!opt)
+ return NULL;
+ return (uint8_t*)obj + opt->offset;
+}
+
#ifdef TEST
#undef printf
@@ -842,6 +893,8 @@ typedef struct TestContext
char *string;
int flags;
AVRational rational;
+ int w, h;
+ enum PixelFormat pix_fmt;
} TestContext;
#define OFFSET(x) offsetof(TestContext, x)
@@ -859,6 +912,8 @@ static const AVOption test_options[]= {
{"cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_COOL}, INT_MIN, INT_MAX, 0, "flags" },
{"lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_LAME}, INT_MIN, INT_MAX, 0, "flags" },
{"mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_MU}, INT_MIN, INT_MAX, 0, "flags" },
+{"size", "set size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE,{0}, 0, 0 },
+{"pix_fmt", "set pixfmt", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT,{0}, 0, 0 },
{NULL},
};
@@ -879,7 +934,7 @@ int main(void)
printf("\nTesting av_set_options_string()\n");
{
- TestContext test_ctx;
+ TestContext test_ctx = { 0 };
const char *options[] = {
"",
":",
@@ -900,6 +955,12 @@ int main(void)
"num=42 : string=blahblah",
"rational=0 : rational=1/2 : rational=1/-1",
"rational=-1/0",
+ "size=1024x768",
+ "size=pal",
+ "size=bogus",
+ "pix_fmt=yuv420p",
+ "pix_fmt=2",
+ "pix_fmt=bogus",
};
test_ctx.class = &test_class;
@@ -914,6 +975,7 @@ int main(void)
av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
printf("\n");
}
+ av_freep(&test_ctx.string);
}
return 0;
OpenPOWER on IntegriCloud