mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
AVOptions: add new API for enumerating children.
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.
This commit is contained in:
parent
1bca8f4bc5
commit
641c7afe3c
@ -39,22 +39,27 @@ static const char* context_to_name(void* ptr) {
|
|||||||
return "NULL";
|
return "NULL";
|
||||||
}
|
}
|
||||||
|
|
||||||
static const AVOption *opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags)
|
static void *codec_child_next(void *obj, void *prev)
|
||||||
{
|
{
|
||||||
AVCodecContext *s = obj;
|
AVCodecContext *s = obj;
|
||||||
|
if (!prev && s->codec && s->codec->priv_class && s->priv_data)
|
||||||
|
return s->priv_data;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const AVClass *codec_child_class_next(const AVClass *prev)
|
||||||
|
{
|
||||||
AVCodec *c = NULL;
|
AVCodec *c = NULL;
|
||||||
|
|
||||||
if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ) && s->priv_data) {
|
/* find the codec that corresponds to prev */
|
||||||
if (s->codec->priv_class)
|
while (prev && (c = av_codec_next(c)))
|
||||||
return av_opt_find(s->priv_data, name, unit, opt_flags, search_flags);
|
if (c->priv_class == prev)
|
||||||
return NULL;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
while ((c = av_codec_next(c))) {
|
/* find next codec with priv options */
|
||||||
const AVOption *o;
|
while (c = av_codec_next(c))
|
||||||
if (c->priv_class && (o = av_opt_find(&c->priv_class, name, unit, opt_flags, search_flags)))
|
if (c->priv_class)
|
||||||
return o;
|
return c->priv_class;
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,7 +527,8 @@ static const AVClass av_codec_context_class = {
|
|||||||
.option = options,
|
.option = options,
|
||||||
.version = LIBAVUTIL_VERSION_INT,
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
.log_level_offset_offset = OFFSET(log_level_offset),
|
.log_level_offset_offset = OFFSET(log_level_offset),
|
||||||
.opt_find = opt_find,
|
.child_next = codec_child_next,
|
||||||
|
.child_class_next = codec_child_class_next,
|
||||||
};
|
};
|
||||||
|
|
||||||
void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){
|
void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){
|
||||||
|
@ -33,30 +33,36 @@ static const char* format_to_name(void* ptr)
|
|||||||
else return "NULL";
|
else return "NULL";
|
||||||
}
|
}
|
||||||
|
|
||||||
static const AVOption *opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags)
|
static void *format_child_next(void *obj, void *prev)
|
||||||
{
|
{
|
||||||
AVFormatContext *s = obj;
|
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 *format_child_class_next(const AVClass *prev)
|
||||||
|
{
|
||||||
AVInputFormat *ifmt = NULL;
|
AVInputFormat *ifmt = NULL;
|
||||||
AVOutputFormat *ofmt = 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))) {
|
while (prev && (ifmt = av_iformat_next(ifmt)))
|
||||||
const AVOption *o;
|
if (ifmt->priv_class == prev)
|
||||||
|
break;
|
||||||
|
if ((prev && ifmt) || (!prev))
|
||||||
|
while (ifmt = av_iformat_next(ifmt))
|
||||||
|
if (ifmt->priv_class)
|
||||||
|
return ifmt->priv_class;
|
||||||
|
|
||||||
if (ifmt->priv_class && (o = av_opt_find(&ifmt->priv_class, name, unit, opt_flags, search_flags)))
|
while (prev && (ofmt = av_oformat_next(ofmt)))
|
||||||
return o;
|
if (ofmt->priv_class == prev)
|
||||||
}
|
break;
|
||||||
while ((ofmt = av_oformat_next(ofmt))) {
|
while (ofmt = av_oformat_next(ofmt))
|
||||||
const AVOption *o;
|
if (ofmt->priv_class)
|
||||||
|
return ofmt->priv_class;
|
||||||
|
|
||||||
if (ofmt->priv_class && (o = av_opt_find(&ofmt->priv_class, name, unit, opt_flags, search_flags)))
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +109,8 @@ static const AVClass av_format_context_class = {
|
|||||||
.item_name = format_to_name,
|
.item_name = format_to_name,
|
||||||
.option = options,
|
.option = options,
|
||||||
.version = LIBAVUTIL_VERSION_INT,
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
.opt_find = opt_find,
|
.child_next = format_child_next,
|
||||||
|
.child_class_next = format_child_class_next,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void avformat_get_context_defaults(AVFormatContext *s)
|
static void avformat_get_context_defaults(AVFormatContext *s)
|
||||||
|
@ -73,11 +73,19 @@ typedef struct {
|
|||||||
int parent_log_context_offset;
|
int parent_log_context_offset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function for extended searching, e.g. in possible
|
* Return next AVOptions-enabled child or NULL
|
||||||
* children objects.
|
|
||||||
*/
|
*/
|
||||||
const struct AVOption* (*opt_find)(void *obj, const char *name, const char *unit,
|
void* (*child_next)(void *obj, void *prev);
|
||||||
int opt_flags, int search_flags);
|
|
||||||
|
/**
|
||||||
|
* 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;
|
} AVClass;
|
||||||
|
|
||||||
/* av_log API */
|
/* av_log API */
|
||||||
|
@ -583,19 +583,57 @@ int av_opt_set_dict(void *obj, AVDictionary **options)
|
|||||||
const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
|
const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
|
||||||
int opt_flags, int search_flags)
|
int opt_flags, int search_flags)
|
||||||
{
|
{
|
||||||
AVClass *c = *(AVClass**)obj;
|
return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 AVOption *o = NULL;
|
const AVOption *o = NULL;
|
||||||
|
|
||||||
if (c->opt_find && search_flags & AV_OPT_SEARCH_CHILDREN &&
|
if (search_flags & AV_OPT_SEARCH_CHILDREN) {
|
||||||
(o = c->opt_find(obj, name, unit, opt_flags, search_flags)))
|
if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
|
||||||
|
const AVClass *child = NULL;
|
||||||
|
while (child = av_opt_child_class_next(c, child))
|
||||||
|
if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
|
||||||
return o;
|
return o;
|
||||||
|
} else {
|
||||||
|
void *child = NULL;
|
||||||
|
while (child = av_opt_child_next(obj, child))
|
||||||
|
if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (o = av_next_option(obj, o)) {
|
while (o = av_next_option(obj, o)) {
|
||||||
if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
|
if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
|
||||||
((!unit && o->type != FF_OPT_TYPE_CONST) ||
|
((!unit && o->type != FF_OPT_TYPE_CONST) ||
|
||||||
(unit && o->unit && !strcmp(o->unit, unit))))
|
(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 o;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "rational.h"
|
#include "rational.h"
|
||||||
#include "avutil.h"
|
#include "avutil.h"
|
||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
enum AVOptionType{
|
enum AVOptionType{
|
||||||
FF_OPT_TYPE_FLAGS,
|
FF_OPT_TYPE_FLAGS,
|
||||||
@ -255,4 +256,44 @@ int av_opt_set_dict(void *obj, struct AVDictionary **options);
|
|||||||
const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
|
const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
|
||||||
int opt_flags, int search_flags);
|
int opt_flags, int search_flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look for an option in an object. Consider only options which
|
||||||
|
* have all the specified flags set.
|
||||||
|
*
|
||||||
|
* @param[in] obj A pointer to a struct whose first element is a
|
||||||
|
* pointer to an AVClass.
|
||||||
|
* Alternatively a double pointer to an AVClass, if
|
||||||
|
* AV_OPT_SEARCH_FAKE_OBJ search flag is set.
|
||||||
|
* @param[in] name The name of the option to look for.
|
||||||
|
* @param[in] unit When searching for named constants, name of the unit
|
||||||
|
* it belongs to.
|
||||||
|
* @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG).
|
||||||
|
* @param search_flags A combination of AV_OPT_SEARCH_*.
|
||||||
|
* @param[out] target_obj if non-NULL, an object to which the option belongs will be
|
||||||
|
* written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present
|
||||||
|
* in search_flags. This parameter is ignored if search_flags contain
|
||||||
|
* AV_OPT_SEARCH_FAKE_OBJ.
|
||||||
|
*
|
||||||
|
* @return A pointer to the option found, or NULL if no option
|
||||||
|
* was found.
|
||||||
|
*/
|
||||||
|
const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
|
||||||
|
int opt_flags, int search_flags, void **target_obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 */
|
#endif /* AVUTIL_OPT_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user