mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-01-12 10:29:39 +00:00
Use a filter graph description for creating simple chain graphs so we
can reuse the same graph creation code. Commited in SoC by Bobby Bingham on 2007-12-22 19:13:04 Originally committed as revision 12715 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
16db7fe0ac
commit
d22ebb1b98
@ -492,156 +492,6 @@ int avfilter_graph_config_links(AVFilterContext *graphctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static AVFilterContext *create_filter_with_args(AVFilterContext *graphctx,
|
||||
const char *filt, void *opaque)
|
||||
{
|
||||
AVFilterContext *ret;
|
||||
char *filter = av_strdup(filt); /* copy - don't mangle the input string */
|
||||
char *name, *args;
|
||||
|
||||
name = filter;
|
||||
if((args = strchr(filter, '='))) {
|
||||
/* ensure we at least have a name */
|
||||
if(args == filter)
|
||||
goto fail;
|
||||
|
||||
*args ++ = 0;
|
||||
}
|
||||
|
||||
av_log(graphctx, AV_LOG_INFO, "creating filter \"%s\" with args \"%s\"\n",
|
||||
name, args ? args : "(none)");
|
||||
|
||||
if((ret = avfilter_open(avfilter_get_by_name(name), NULL))) {
|
||||
if(avfilter_init_filter(ret, args, opaque)) {
|
||||
av_log(graphctx, AV_LOG_ERROR, "error initializing filter!\n");
|
||||
avfilter_destroy(ret);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
av_log(graphctx, AV_LOG_ERROR,
|
||||
"error creating filter \"%s\" with args \"%s\"\n",
|
||||
name, args ? args : "(none)");
|
||||
}
|
||||
|
||||
av_free(filter);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
av_free(filter);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int graph_load_chain(AVFilterContext *graphctx,
|
||||
unsigned count, char **filter_list, void **opaque,
|
||||
AVFilterContext **first, AVFilterContext **last)
|
||||
{
|
||||
unsigned i;
|
||||
AVFilterContext *filters[2] = {NULL,NULL};
|
||||
|
||||
for(i = 0; i < count; i ++) {
|
||||
void *op;
|
||||
|
||||
if(opaque) op = opaque[i];
|
||||
else op = NULL;
|
||||
|
||||
if(!(filters[1] = create_filter_with_args(graphctx, filter_list[i], op)))
|
||||
goto fail;
|
||||
if(i == 0) {
|
||||
if(first) *first = filters[1];
|
||||
} else {
|
||||
if(avfilter_link(filters[0], 0, filters[1], 0)) {
|
||||
av_log(graphctx, AV_LOG_ERROR, "error linking filters!\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
avfilter_graph_add_filter(graphctx, filters[1]);
|
||||
if(i == 0 && filters[1]->input_count > 0)
|
||||
add_graph_input(graphctx, filters[1], 0, "default");
|
||||
filters[0] = filters[1];
|
||||
}
|
||||
|
||||
if(filters[1]->output_count > 0)
|
||||
add_graph_output(graphctx, filters[1], 0, "default");
|
||||
|
||||
if(last) *last = filters[1];
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
uninit(graphctx);
|
||||
if(first) *first = NULL;
|
||||
if(last) *last = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int graph_load_chain_from_string(AVFilterContext *ctx, const char *str,
|
||||
AVFilterContext **first,
|
||||
AVFilterContext **last)
|
||||
{
|
||||
int count, ret = 0;
|
||||
char **strings;
|
||||
char *filt;
|
||||
|
||||
strings = av_malloc(sizeof(char *));
|
||||
strings[0] = av_strdup(str);
|
||||
|
||||
filt = strchr(strings[0], ',');
|
||||
for(count = 1; filt; count ++) {
|
||||
if(filt == strings[count-1]) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
strings = av_realloc(strings, sizeof(char *) * (count+1));
|
||||
strings[count] = filt + 1;
|
||||
*filt = '\0';
|
||||
filt = strchr(strings[count], ',');
|
||||
}
|
||||
|
||||
ret = graph_load_chain(ctx, count, strings, NULL, first, last);
|
||||
|
||||
done:
|
||||
av_free(strings[0]);
|
||||
av_free(strings);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init(AVFilterContext *ctx, const char *args, void *opaque)
|
||||
{
|
||||
GraphContext *gctx = ctx->priv;
|
||||
|
||||
if(!(gctx->link_filter = avfilter_open(&vf_graph_dummy, NULL)))
|
||||
return -1;
|
||||
if(avfilter_init_filter(gctx->link_filter, NULL, ctx))
|
||||
goto fail;
|
||||
|
||||
if(!args)
|
||||
return 0;
|
||||
|
||||
return graph_load_chain_from_string(ctx, args, NULL, NULL);
|
||||
|
||||
fail:
|
||||
avfilter_destroy(gctx->link_filter);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AVFilter avfilter_vf_graph =
|
||||
{
|
||||
.name = "graph",
|
||||
.author = "Bobby Bingham",
|
||||
|
||||
.priv_size = sizeof(GraphContext),
|
||||
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
|
||||
.query_formats = query_formats,
|
||||
|
||||
.inputs = (AVFilterPad[]) {{ .name = NULL, }},
|
||||
.outputs = (AVFilterPad[]) {{ .name = NULL, }},
|
||||
};
|
||||
|
||||
static int graph_load_from_desc(AVFilterContext *ctx, AVFilterGraphDesc *desc)
|
||||
{
|
||||
AVFilterGraphDescFilter *curfilt;
|
||||
@ -706,6 +556,48 @@ fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int init(AVFilterContext *ctx, const char *args, void *opaque)
|
||||
{
|
||||
GraphContext *gctx = ctx->priv;
|
||||
AVFilterGraphDesc *desc;
|
||||
int ret;
|
||||
|
||||
if(!(gctx->link_filter = avfilter_open(&vf_graph_dummy, NULL)))
|
||||
return -1;
|
||||
if(avfilter_init_filter(gctx->link_filter, NULL, ctx))
|
||||
goto fail;
|
||||
|
||||
if(!args)
|
||||
return 0;
|
||||
|
||||
if(!(desc = avfilter_graph_parse_chain(args)))
|
||||
goto fail;
|
||||
|
||||
ret = graph_load_from_desc(ctx, desc);
|
||||
avfilter_graph_free_desc(desc);
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
avfilter_destroy(gctx->link_filter);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AVFilter avfilter_vf_graph =
|
||||
{
|
||||
.name = "graph",
|
||||
.author = "Bobby Bingham",
|
||||
|
||||
.priv_size = sizeof(GraphContext),
|
||||
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
|
||||
.query_formats = query_formats,
|
||||
|
||||
.inputs = (AVFilterPad[]) {{ .name = NULL, }},
|
||||
.outputs = (AVFilterPad[]) {{ .name = NULL, }},
|
||||
};
|
||||
|
||||
static int init_desc(AVFilterContext *ctx, const char *args, void *opaque)
|
||||
{
|
||||
GraphContext *gctx = ctx->priv;
|
||||
|
@ -86,6 +86,14 @@ typedef struct
|
||||
AVFilterGraphDescExport **outputp; ///< last parsed exported output
|
||||
} AVFilterGraphDescParser;
|
||||
|
||||
/**
|
||||
* Parse a graph composed of a simple chain of filters which is described by
|
||||
* a single string.
|
||||
* @param filters String listing filters and their arguments.
|
||||
* @return The parsed graph description.
|
||||
*/
|
||||
AVFilterGraphDesc *avfilter_graph_parse_chain(const char *filters);
|
||||
|
||||
/** Parse a line of a filter graph description.
|
||||
* @param desc Pointer to an AVFilterGraphDesc pointer. If *desc is NULL,
|
||||
* a new AVFilterGraphDesc structure will be created for you.
|
||||
|
Loading…
Reference in New Issue
Block a user