summaryrefslogtreecommitdiff
path: root/ffmpeg/libavutil/opt.c
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
committerTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
commitf7813a5324be39d13ab536c245d15dfc602a7849 (patch)
treefad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/libavutil/opt.c
parentb7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff)
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavutil/opt.c')
-rw-r--r--ffmpeg/libavutil/opt.c356
1 files changed, 277 insertions, 79 deletions
diff --git a/ffmpeg/libavutil/opt.c b/ffmpeg/libavutil/opt.c
index a2cdcb4..07864f2 100644
--- a/ffmpeg/libavutil/opt.c
+++ b/ffmpeg/libavutil/opt.c
@@ -27,6 +27,7 @@
#include "avutil.h"
#include "avstring.h"
+#include "channel_layout.h"
#include "common.h"
#include "opt.h"
#include "eval.h"
@@ -63,7 +64,7 @@ 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 && class->option[0].name)
+ if (!last && class && class->option && class->option[0].name)
return class->option;
if (last && last[1].name)
return ++last;
@@ -77,6 +78,7 @@ static int read_number(const AVOption *o, void *dst, double *num, int *den, int6
case AV_OPT_TYPE_PIXEL_FMT:
case AV_OPT_TYPE_SAMPLE_FMT:
case AV_OPT_TYPE_INT: *intnum = *(int *)dst;return 0;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
case AV_OPT_TYPE_DURATION:
case AV_OPT_TYPE_INT64: *intnum = *(int64_t *)dst;return 0;
case AV_OPT_TYPE_FLOAT: *num = *(float *)dst;return 0;
@@ -91,11 +93,21 @@ 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) {
+ if (o->type != AV_OPT_TYPE_FLAGS &&
+ (o->max * den < num * intnum || o->min * den > num * intnum)) {
av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n",
num*intnum/den, o->name, o->min, o->max);
return AVERROR(ERANGE);
}
+ if (o->type == AV_OPT_TYPE_FLAGS) {
+ double d = num*intnum/den;
+ if (d < -1.5 || d > 0xFFFFFFFF+0.5 || (llrint(d*256) & 255)) {
+ av_log(obj, AV_LOG_ERROR,
+ "Value %f for parameter '%s' is not a valid set of 32bit integer flags\n",
+ num*intnum/den, o->name);
+ return AVERROR(ERANGE);
+ }
+ }
switch (o->type) {
case AV_OPT_TYPE_FLAGS:
@@ -103,6 +115,7 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
case AV_OPT_TYPE_SAMPLE_FMT:
case AV_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break;
case AV_OPT_TYPE_DURATION:
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
case AV_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break;
case AV_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break;
case AV_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break;
@@ -239,6 +252,95 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
return 0;
}
+static int set_string_image_size(void *obj, const AVOption *o, const char *val, int *dst)
+{
+ int ret;
+
+ if (!val || !strcmp(val, "none")) {
+ dst[0] =
+ dst[1] = 0;
+ return 0;
+ }
+ ret = av_parse_video_size(dst, 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;
+}
+
+static int set_string_video_rate(void *obj, const AVOption *o, const char *val, AVRational *dst)
+{
+ int ret;
+ if (!val) {
+ ret = AVERROR(EINVAL);
+ } else {
+ ret = av_parse_video_rate(dst, val);
+ }
+ if (ret < 0)
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val);
+ return ret;
+}
+
+static int set_string_color(void *obj, const AVOption *o, const char *val, uint8_t *dst)
+{
+ int ret;
+
+ if (!val) {
+ return 0;
+ } else {
+ ret = av_parse_color(dst, val, -1, obj);
+ if (ret < 0)
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as color\n", val);
+ return ret;
+ }
+ return 0;
+}
+
+static int set_string_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst,
+ int fmt_nb, int ((*get_fmt)(const char *)), const char *desc)
+{
+ int fmt, min, max;
+
+ if (!val || !strcmp(val, "none")) {
+ fmt = -1;
+ } else {
+ fmt = get_fmt(val);
+ if (fmt == -1) {
+ char *tail;
+ fmt = strtol(val, &tail, 0);
+ if (*tail || (unsigned)fmt >= fmt_nb) {
+ av_log(obj, AV_LOG_ERROR,
+ "Unable to parse option value \"%s\" as %s\n", val, desc);
+ return AVERROR(EINVAL);
+ }
+ }
+ }
+
+ min = FFMAX(o->min, -1);
+ max = FFMIN(o->max, fmt_nb-1);
+
+ if (fmt < min || fmt > max) {
+ av_log(obj, AV_LOG_ERROR,
+ "Value %d for parameter '%s' out of %s format range [%d - %d]\n",
+ fmt, o->name, desc, min, max);
+ return AVERROR(ERANGE);
+ }
+
+ *(int *)dst = fmt;
+ return 0;
+}
+
+static int set_string_pixel_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst)
+{
+ return set_string_fmt(obj, o, val, dst,
+ AV_PIX_FMT_NB, av_get_pix_fmt, "pixel format");
+}
+
+static int set_string_sample_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst)
+{
+ return set_string_fmt(obj, o, val, dst,
+ AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format");
+}
+
#if FF_API_OLD_AVOPTIONS
int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
{
@@ -251,7 +353,7 @@ 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;
+ int ret = 0;
void *dst, *target_obj;
const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
if (!o || !target_obj)
@@ -259,7 +361,8 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
if (!val && (o->type != AV_OPT_TYPE_STRING &&
o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT &&
o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE &&
- o->type != AV_OPT_TYPE_DURATION))
+ o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR &&
+ o->type != AV_OPT_TYPE_CHANNEL_LAYOUT))
return AVERROR(EINVAL);
dst = ((uint8_t*)target_obj) + o->offset;
@@ -272,56 +375,10 @@ 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, target_obj, o, val, dst);
- case AV_OPT_TYPE_IMAGE_SIZE:
- if (!val || !strcmp(val, "none")) {
- *(int *)dst = *((int *)dst + 1) = 0;
- return 0;
- }
- 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_VIDEO_RATE:
- if (!val) {
- ret = AVERROR(EINVAL);
- } else {
- ret = av_parse_video_rate(dst, val);
- }
- if (ret < 0)
- av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val);
- return ret;
- case AV_OPT_TYPE_PIXEL_FMT:
- if (!val || !strcmp(val, "none")) {
- ret = AV_PIX_FMT_NONE;
- } else {
- ret = av_get_pix_fmt(val);
- if (ret == AV_PIX_FMT_NONE) {
- char *tail;
- ret = strtol(val, &tail, 0);
- if (*tail || (unsigned)ret >= AV_PIX_FMT_NB) {
- av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as pixel format\n", val);
- return AVERROR(EINVAL);
- }
- }
- }
- *(enum AVPixelFormat *)dst = ret;
- return 0;
- case AV_OPT_TYPE_SAMPLE_FMT:
- if (!val || !strcmp(val, "none")) {
- ret = AV_SAMPLE_FMT_NONE;
- } else {
- ret = av_get_sample_fmt(val);
- if (ret == AV_SAMPLE_FMT_NONE) {
- char *tail;
- ret = strtol(val, &tail, 0);
- if (*tail || (unsigned)ret >= AV_SAMPLE_FMT_NB) {
- av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as sample format\n", val);
- return AVERROR(EINVAL);
- }
- }
- }
- *(enum AVSampleFormat *)dst = ret;
- return 0;
+ case AV_OPT_TYPE_IMAGE_SIZE: return set_string_image_size(obj, o, val, dst);
+ case AV_OPT_TYPE_VIDEO_RATE: return set_string_video_rate(obj, o, val, dst);
+ case AV_OPT_TYPE_PIXEL_FMT: return set_string_pixel_fmt(obj, o, val, dst);
+ case AV_OPT_TYPE_SAMPLE_FMT: return set_string_sample_fmt(obj, o, val, dst);
case AV_OPT_TYPE_DURATION:
if (!val) {
*(int64_t *)dst = 0;
@@ -331,6 +388,25 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", val);
return ret;
}
+ break;
+ case AV_OPT_TYPE_COLOR: return set_string_color(obj, o, val, dst);
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ if (!val || !strcmp(val, "none")) {
+ *(int64_t *)dst = 0;
+ } else {
+#if FF_API_GET_CHANNEL_LAYOUT_COMPAT
+ int64_t cl = ff_get_channel_layout(val, 0);
+#else
+ int64_t cl = av_get_channel_layout(val);
+#endif
+ if (!cl) {
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val);
+ ret = AVERROR(EINVAL);
+ }
+ *(int64_t *)dst = cl;
+ return ret;
+ }
+ break;
}
av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
@@ -420,8 +496,8 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int
if (o->type != AV_OPT_TYPE_BINARY)
return AVERROR(EINVAL);
- ptr = av_malloc(len);
- if (!ptr)
+ ptr = len ? av_malloc(len) : NULL;
+ if (len && !ptr)
return AVERROR(ENOMEM);
dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset);
@@ -430,7 +506,8 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int
av_free(*dst);
*dst = ptr;
*lendst = len;
- memcpy(ptr, val, len);
+ if (len)
+ memcpy(ptr, val, len);
return 0;
}
@@ -491,15 +568,15 @@ static int set_format(void *obj, const char *name, int fmt, int search_flags,
return AVERROR(EINVAL);
}
-#if LIBAVUTIL_VERSION_MAJOR < 53
+#if LIBAVUTIL_VERSION_MAJOR < 54
if (class->version && class->version < AV_VERSION_INT(52, 11, 100)) {
min = -1;
max = nb_fmts-1;
} else
#endif
{
- min = FFMIN(o->min, -1);
- max = FFMAX(o->max, nb_fmts-1);
+ min = FFMAX(o->min, -1);
+ max = FFMIN(o->max, nb_fmts-1);
}
if (fmt < min || fmt > max) {
av_log(obj, AV_LOG_ERROR,
@@ -521,6 +598,22 @@ int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt,
return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB);
}
+int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags)
+{
+ void *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 (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value set by option '%s' is not a channel layout.\n", o->name);
+ return AVERROR(EINVAL);
+ }
+ *(int *)(((int64_t *)target_obj) + o->offset) = cl;
+ return 0;
+}
+
#if FF_API_OLD_AVOPTIONS
/**
*
@@ -616,6 +709,13 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
i64 / 3600000000, (int)((i64 / 60000000) % 60),
(int)((i64 / 1000000) % 60), (int)(i64 % 1000000));
break;
+ case AV_OPT_TYPE_COLOR:
+ ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x", ((int *)dst)[0], ((int *)dst)[1], ((int *)dst)[2], ((int *)dst)[3]);
+ break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ i64 = *(int64_t *)dst;
+ ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64);
+ break;
default:
return AVERROR(EINVAL);
}
@@ -785,6 +885,23 @@ int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AV
return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample");
}
+int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl)
+{
+ 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 (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value for option '%s' is not a channel layout.\n", name);
+ return AVERROR(EINVAL);
+ }
+
+ dst = ((uint8_t*)target_obj) + o->offset;
+ *cl = *(int64_t *)dst;
+ return 0;
+}
+
int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
{
const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
@@ -839,9 +956,11 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
continue;
else if (unit && opt->type == AV_OPT_TYPE_CONST)
- av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
+ av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
else
- av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
+ av_log(av_log_obj, AV_LOG_INFO, " %s%-17s ",
+ (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? "" : "-",
+ opt->name);
switch (opt->type) {
case AV_OPT_TYPE_FLAGS:
@@ -883,6 +1002,12 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
case AV_OPT_TYPE_DURATION:
av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<duration>");
break;
+ case AV_OPT_TYPE_COLOR:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color>");
+ break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<channel_layout>");
+ break;
case AV_OPT_TYPE_CONST:
default:
av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "");
@@ -917,6 +1042,50 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
av_opt_freep_ranges(&r);
}
+ if (opt->type != AV_OPT_TYPE_CONST &&
+ opt->type != AV_OPT_TYPE_BINARY &&
+ !((opt->type == AV_OPT_TYPE_COLOR ||
+ opt->type == AV_OPT_TYPE_IMAGE_SIZE ||
+ opt->type == AV_OPT_TYPE_STRING ||
+ opt->type == AV_OPT_TYPE_VIDEO_RATE) &&
+ !opt->default_val.str)) {
+ av_log(av_log_obj, AV_LOG_INFO, " (default ");
+ switch (opt->type) {
+ case AV_OPT_TYPE_FLAGS:
+ av_log(av_log_obj, AV_LOG_INFO, "%"PRIX64, opt->default_val.i64);
+ break;
+ case AV_OPT_TYPE_DURATION:
+ case AV_OPT_TYPE_INT:
+ case AV_OPT_TYPE_INT64:
+ log_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64);
+ break;
+ case AV_OPT_TYPE_DOUBLE:
+ case AV_OPT_TYPE_FLOAT:
+ log_value(av_log_obj, AV_LOG_INFO, opt->default_val.dbl);
+ break;
+ case AV_OPT_TYPE_RATIONAL: {
+ AVRational q = av_d2q(opt->default_val.dbl, INT_MAX);
+ av_log(av_log_obj, AV_LOG_INFO, "%d/%d", q.num, q.den); }
+ break;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(opt->default_val.i64), "none"));
+ break;
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none"));
+ break;
+ case AV_OPT_TYPE_COLOR:
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ case AV_OPT_TYPE_STRING:
+ case AV_OPT_TYPE_VIDEO_RATE:
+ av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str);
+ break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64);
+ break;
+ }
+ av_log(av_log_obj, AV_LOG_INFO, ")");
+ }
+
av_log(av_log_obj, AV_LOG_INFO, "\n");
if (opt->unit && opt->type != AV_OPT_TYPE_CONST) {
opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
@@ -948,6 +1117,7 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
const AVClass *class = *(AVClass **)s;
const AVOption *opt = NULL;
while ((opt = av_opt_next(s, opt)) != NULL) {
+ void *dst = ((uint8_t*)s) + opt->offset;
#if FF_API_OLD_AVOPTIONS
if ((opt->flags & mask) != flags)
continue;
@@ -960,41 +1130,49 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
case AV_OPT_TYPE_INT:
case AV_OPT_TYPE_INT64:
case AV_OPT_TYPE_DURATION:
- av_opt_set_int(s, opt->name, opt->default_val.i64, 0);
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ write_number(s, opt, dst, 1, 1, opt->default_val.i64);
break;
case AV_OPT_TYPE_DOUBLE:
case AV_OPT_TYPE_FLOAT: {
double val;
val = opt->default_val.dbl;
- av_opt_set_double(s, opt->name, val, 0);
+ write_number(s, opt, dst, val, 1, 1);
}
break;
case AV_OPT_TYPE_RATIONAL: {
AVRational val;
val = av_d2q(opt->default_val.dbl, INT_MAX);
- av_opt_set_q(s, opt->name, val, 0);
+ write_number(s, opt, dst, 1, val.den, val.num);
}
break;
+ case AV_OPT_TYPE_COLOR:
+ set_string_color(s, opt, opt->default_val.str, dst);
+ break;
case AV_OPT_TYPE_STRING:
+ set_string(s, opt, opt->default_val.str, dst);
+ break;
case AV_OPT_TYPE_IMAGE_SIZE:
+ set_string_image_size(s, opt, opt->default_val.str, dst);
+ break;
case AV_OPT_TYPE_VIDEO_RATE:
- av_opt_set(s, opt->name, opt->default_val.str, 0);
+ set_string_video_rate(s, opt, opt->default_val.str, dst);
break;
case AV_OPT_TYPE_PIXEL_FMT:
-#if LIBAVUTIL_VERSION_MAJOR < 53
+#if LIBAVUTIL_VERSION_MAJOR < 54
if (class->version && class->version < AV_VERSION_INT(52, 10, 100))
av_opt_set(s, opt->name, opt->default_val.str, 0);
else
#endif
- av_opt_set_pixel_fmt(s, opt->name, opt->default_val.i64, 0);
+ write_number(s, opt, dst, 1, 1, opt->default_val.i64);
break;
case AV_OPT_TYPE_SAMPLE_FMT:
-#if LIBAVUTIL_VERSION_MAJOR < 53
+#if LIBAVUTIL_VERSION_MAJOR < 54
if (class->version && class->version < AV_VERSION_INT(52, 10, 100))
av_opt_set(s, opt->name, opt->default_val.str, 0);
else
#endif
- av_opt_set_sample_fmt(s, opt->name, opt->default_val.i64, 0);
+ write_number(s, opt, dst, 1, 1, opt->default_val.i64);
break;
case AV_OPT_TYPE_BINARY:
/* Cannot set default for binary */
@@ -1029,9 +1207,16 @@ static int parse_key_value_pair(void *ctx, const char **buf,
char *val;
int ret;
+ if (!key)
+ return AVERROR(ENOMEM);
+
if (*key && strspn(*buf, key_val_sep)) {
(*buf)++;
val = av_get_token(buf, pairs_sep);
+ if (!val) {
+ av_freep(&key);
+ return AVERROR(ENOMEM);
+ }
} else {
av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
av_free(key);
@@ -1040,7 +1225,7 @@ static int parse_key_value_pair(void *ctx, const char **buf,
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);
+ ret = av_opt_set(ctx, key, val, AV_OPT_SEARCH_CHILDREN);
if (ret == AVERROR_OPTION_NOT_FOUND)
av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
@@ -1227,6 +1412,9 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
c= *(AVClass**)obj;
+ if (!c)
+ return NULL;
+
if (search_flags & AV_OPT_SEARCH_CHILDREN) {
if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
const AVClass *child = NULL;
@@ -1324,6 +1512,8 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch
case AV_OPT_TYPE_FLOAT:
case AV_OPT_TYPE_DOUBLE:
case AV_OPT_TYPE_DURATION:
+ case AV_OPT_TYPE_COLOR:
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
break;
case AV_OPT_TYPE_STRING:
range->component_min = 0;
@@ -1390,6 +1580,8 @@ typedef struct TestContext
enum AVPixelFormat pix_fmt;
enum AVSampleFormat sample_fmt;
int64_t duration;
+ uint8_t color[4];
+ int64_t channel_layout;
} TestContext;
#define OFFSET(x) offsetof(TestContext, x)
@@ -1408,10 +1600,12 @@ static const AVOption test_options[]= {
{"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, {.i64 = AV_PIX_FMT_NONE}, -1, AV_PIX_FMT_NB-1},
-{"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_NONE}, -1, AV_SAMPLE_FMT_NB-1},
+{"pix_fmt", "set pixfmt", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX},
+{"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_NONE}, -1, INT_MAX},
{"video_rate", "set videorate", OFFSET(video_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0 },
{"duration", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX},
+{"color", "set color", OFFSET(color), AV_OPT_TYPE_COLOR, {.str = "pink"}, 0, 0},
+{"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = AV_CH_LAYOUT_HEXAGONAL}, 0, INT64_MAX},
{NULL},
};
@@ -1433,7 +1627,7 @@ int main(void)
printf("\nTesting av_set_options_string()\n");
{
TestContext test_ctx = { 0 };
- const char *options[] = {
+ static const char * const options[] = {
"",
":",
"=",
@@ -1470,6 +1664,11 @@ int main(void)
"duration=bogus",
"duration=123.45",
"duration=1\\:23\\:45.67",
+ "color=blue",
+ "color=0x223300",
+ "color=0x42FF07AA",
+ "cl=stereo+downmix",
+ "cl=foo",
};
test_ctx.class = &test_class;
@@ -1483,13 +1682,13 @@ 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);
+ av_opt_free(&test_ctx);
}
printf("\nTesting av_opt_set_from_string()\n");
{
TestContext test_ctx = { 0 };
- const char *options[] = {
+ static const char * const options[] = {
"",
"5",
"5:hello",
@@ -1500,11 +1699,10 @@ int main(void)
" 5 : hello : size = pal ",
"a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42"
};
- const char *shorthand[] = { "num", "string", NULL };
+ static const char * const shorthand[] = { "num", "string", NULL };
test_ctx.class = &test_class;
av_opt_set_defaults(&test_ctx);
- test_ctx.string = av_strdup("default");
av_log_set_level(AV_LOG_DEBUG);
@@ -1514,7 +1712,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);
+ av_opt_free(&test_ctx);
}
return 0;