This will allow the caller to enumerate child contexts in a generic way
and since the API is recursive, it also allows for deeper nesting (e.g.
AVFormatContext->AVIOContext->URLContext)
This will also allow the new setting/reading API to transparently apply
to children contexts.
---
libavcodec/options.c | 32 +++++++++++++++----------
libavformat/options.c | 51 +++++++++++++++++++++++------------------
libavutil/log.h | 16 +++++++++---
libavutil/opt.c | 60 ++++++++++++++++++++++++++++++++++++++++---------
libavutil/opt.h | 17 ++++++++++++++
5 files changed, 126 insertions(+), 50 deletions(-)
diff --git a/libavcodec/options.c b/libavcodec/options.c
index 1c52406..6386ab3 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -39,22 +39,27 @@ static const char* context_to_name(void* ptr) {
return "NULL";
}
-static const AVOption *opt_find(void *obj, const char *name, const char *unit,
int opt_flags, int search_flags)
+static void *child_next(void *obj, void *prev)
{
AVCodecContext *s = obj;
- AVCodec *c = NULL;
+ if (!prev && s->codec && s->codec->priv_class && s->priv_data)
+ return s->priv_data;
+ return NULL;
+}
- if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ) && s->priv_data) {
- if (s->codec->priv_class)
- return av_opt_find(s->priv_data, name, unit, opt_flags,
search_flags);
- return NULL;
- }
+static const AVClass *child_class_next(const AVClass *prev)
+{
+ AVCodec *c = NULL;
- while ((c = av_codec_next(c))) {
- const AVOption *o;
- if (c->priv_class && (o = av_opt_find(&c->priv_class, name, unit,
opt_flags, search_flags)))
- return o;
- }
+ /* find the codec that corresponds to prev */
+ while (prev && (c = av_codec_next(c)))
+ if (c->priv_class == prev)
+ break;
+
+ /* find next codec with priv options */
+ while (c = av_codec_next(c))
+ if (c->priv_class)
+ return c->priv_class;
return NULL;
}
@@ -522,7 +527,8 @@ static const AVClass av_codec_context_class = {
.option = options,
.version = LIBAVUTIL_VERSION_INT,
.log_level_offset_offset = OFFSET(log_level_offset),
- .opt_find = opt_find,
+ .child_next = child_next,
+ .child_class_next = child_class_next,
};
void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType
codec_type){
diff --git a/libavformat/options.c b/libavformat/options.c
index 43a6dec..1711cae 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -33,30 +33,36 @@ static const char* format_to_name(void* ptr)
else return "NULL";
}
-static const AVOption *opt_find(void *obj, const char *name, const char *unit,
int opt_flags, int search_flags)
+static void *child_next(void *obj, void *prev)
+{
+ AVFormatContext *s = obj;
+ if (!prev && s->priv_data &&
+ ((s->iformat && s->iformat->priv_class) ||
+ s->oformat && s->oformat->priv_class))
+ return s->priv_data;
+ return NULL;
+}
+
+static const AVClass *child_class_next(const AVClass *prev)
{
- AVFormatContext *s = obj;
AVInputFormat *ifmt = NULL;
AVOutputFormat *ofmt = NULL;
- if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ) && s->priv_data) {
- if ((s->iformat && !s->iformat->priv_class) ||
- (s->oformat && !s->oformat->priv_class))
- return NULL;
- return av_opt_find(s->priv_data, name, unit, opt_flags, search_flags);
- }
-
- while ((ifmt = av_iformat_next(ifmt))) {
- const AVOption *o;
-
- if (ifmt->priv_class && (o = av_opt_find(&ifmt->priv_class, name,
unit, opt_flags, search_flags)))
- return o;
- }
- while ((ofmt = av_oformat_next(ofmt))) {
- const AVOption *o;
-
- if (ofmt->priv_class && (o = av_opt_find(&ofmt->priv_class, name,
unit, opt_flags, search_flags)))
- return o;
- }
+
+ while (prev && (ifmt = av_iformat_next(ifmt)))
+ if (ifmt->priv_class == prev)
+ break;
+ if ((prev && ifmt) || (!prev))
+ while (ifmt = av_iformat_next(ifmt))
+ if (ifmt->priv_class)
+ return ifmt->priv_class;
+
+ while (prev && (ofmt = av_oformat_next(ofmt)))
+ if (ofmt->priv_class == prev)
+ break;
+ while (ofmt = av_oformat_next(ofmt))
+ if (ofmt->priv_class)
+ return ofmt->priv_class;
+
return NULL;
}
@@ -103,7 +109,8 @@ static const AVClass av_format_context_class = {
.item_name = format_to_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
- .opt_find = opt_find,
+ .child_next = child_next,
+ .child_class_next = child_class_next,
};
static void avformat_get_context_defaults(AVFormatContext *s)
diff --git a/libavutil/log.h b/libavutil/log.h
index c1d9a6c..18d0ddf 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -73,11 +73,19 @@ typedef struct {
int parent_log_context_offset;
/**
- * A function for extended searching, e.g. in possible
- * children objects.
+ * Return next AVOptions-enabled child or NULL
*/
- const struct AVOption* (*opt_find)(void *obj, const char *name, const char
*unit,
- int opt_flags, int search_flags);
+ void* (*child_next)(void *obj, void *prev);
+
+ /**
+ * Return an AVClass corresponding to next potential
+ * AVOptions-enabled child.
+ *
+ * The difference between child_next and this is that
+ * child_next iterates over _already existing_ objects, while
+ * child_class_next iterates over _all possible_ children.
+ */
+ const struct AVClass* (*child_class_next)(const struct AVClass *prev);
} AVClass;
/* av_log API */
diff --git a/libavutil/opt.c b/libavutil/opt.c
index 78fdf63..b0ca9a4 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -54,6 +54,42 @@ const AVOption *av_next_option(void *obj, const AVOption
*last)
else return (*(AVClass**)obj)->option;
}
+static const AVOption *opt_find(void *obj, const char *name, const char *unit,
+ int opt_flags, int search_flags, void
**target_obj)
+{
+ const AVClass *c = *(AVClass**)obj;
+ const AVOption *o = NULL;
+
+ if (search_flags & AV_OPT_SEARCH_CHILDREN) {
+ if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
+ const AVClass *child = NULL;
+ while (child = av_opt_child_class_next(c, child))
+ if (o = opt_find(&child, name, unit, opt_flags, search_flags,
NULL))
+ return o;
+ } else {
+ void *child = NULL;
+ while (child = av_opt_child_next(obj, child))
+ if (o = opt_find(child, name, unit, opt_flags, search_flags,
target_obj))
+ return o;
+ }
+ }
+
+ while (o = av_next_option(obj, o)) {
+ if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
+ ((!unit && o->type != FF_OPT_TYPE_CONST) ||
+ (unit && o->unit && !strcmp(o->unit, unit)))) {
+ if (target_obj) {
+ if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
+ *target_obj = obj;
+ else
+ *target_obj = NULL;
+ }
+ return o;
+ }
+ }
+ return NULL;
+}
+
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) {
@@ -583,19 +619,21 @@ int av_opt_set_dict(void *obj, AVDictionary **options)
const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
int opt_flags, int search_flags)
{
- AVClass *c = *(AVClass**)obj;
- const AVOption *o = NULL;
+ return opt_find(obj, name, unit, opt_flags, search_flags, NULL);
+}
- if (c->opt_find && search_flags & AV_OPT_SEARCH_CHILDREN &&
- (o = c->opt_find(obj, name, unit, opt_flags, search_flags)))
- return o;
+void *av_opt_child_next(void *obj, void *prev)
+{
+ const AVClass *c = *(AVClass**)obj;
+ if (c->child_next)
+ return c->child_next(obj, prev);
+ return NULL;
+}
- while (o = av_next_option(obj, o)) {
- if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
- ((!unit && o->type != FF_OPT_TYPE_CONST) ||
- (unit && o->unit && !strcmp(o->unit, unit))))
- return o;
- }
+const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass
*prev)
+{
+ if (parent->child_class_next)
+ return parent->child_class_next(prev);
return NULL;
}
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 50c0a33..e8c8632 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -30,6 +30,7 @@
#include "rational.h"
#include "avutil.h"
#include "dict.h"
+#include "log.h"
enum AVOptionType{
FF_OPT_TYPE_FLAGS,
@@ -255,4 +256,20 @@ int av_opt_set_dict(void *obj, struct AVDictionary
**options);
const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
int opt_flags, int search_flags);
+/**
+ * Iterate over AVOptions-enabled children of obj.
+ *
+ * @param prev result of a previous call to this function or NULL
+ * @return next AVOptions-enabled child or NULL
+ */
+void *av_opt_child_next(void *obj, void *prev);
+
+/**
+ * Iterate over potential AVOptions-enabled children of parent.
+ *
+ * @param prev result of a previous call to this function or NULL
+ * @return AVClass corresponding to next potential child or NULL
+ */
+const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass
*prev);
+
#endif /* AVUTIL_OPT_H */
--
1.7.6.3
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel