diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 2922138808..d327cf688b 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -45,6 +45,15 @@ const char *avfilter_license(void) return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } +static void command_queue_pop(AVFilterContext *filter) +{ + AVFilterCommand *c= filter->command_queue; + av_freep(&c->arg); + av_freep(&c->command); + filter->command_queue= c->next; + av_free(c); +} + AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) { AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef)); @@ -534,6 +543,7 @@ void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) void (*start_frame)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *dst = link->dstpad; int perms = picref->perms; + AVFilterCommand *cmd= link->dst->command_queue; FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1); @@ -556,6 +566,11 @@ void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) else link->cur_buf = picref; + if(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){ + avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags); + command_queue_pop(link->dst); + } + start_frame(link, link->cur_buf); } @@ -815,6 +830,9 @@ void avfilter_free(AVFilterContext *filter) av_freep(&filter->inputs); av_freep(&filter->outputs); av_freep(&filter->priv); + while(filter->command_queue){ + command_queue_pop(filter); + } av_free(filter); } diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 616b8b42a1..50b5d1cba2 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -29,7 +29,7 @@ #include "libavutil/rational.h" #define LIBAVFILTER_VERSION_MAJOR 2 -#define LIBAVFILTER_VERSION_MINOR 36 +#define LIBAVFILTER_VERSION_MINOR 37 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ @@ -585,6 +585,8 @@ struct AVFilterContext { AVFilterLink **outputs; ///< array of pointers to output links void *priv; ///< private data for use by the filter + + struct AVFilterCommand *command_queue; }; enum AVFilterPacking { diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index f9ae1cd1ef..430f0d1699 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -283,3 +283,28 @@ int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const return r; } + +int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *command, const char *arg, int flags, double ts) +{ + int i; + + if(!graph) + return 0; + + for (i = 0; i < graph->filter_count; i++) { + AVFilterContext *filter = graph->filters[i]; + if(filter && (!strcmp(target, "all") || !strcmp(target, filter->name) || !strcmp(target, filter->filter->name))){ + AVFilterCommand **que = &filter->command_queue; + while(*que) que = &(*que)->next; + *que= av_mallocz(sizeof(AVFilterCommand)); + (*que)->command = av_strdup(command); + (*que)->arg = av_strdup(arg); + (*que)->time = ts; + (*que)->flags = flags; + if(flags & AVFILTER_CMD_FLAG_ONE) + return 0; + } + } + + return 0; +} diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h index 5724e5717d..3062b04fd8 100644 --- a/libavfilter/avfiltergraph.h +++ b/libavfilter/avfiltergraph.h @@ -153,4 +153,22 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, */ int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags); +/** + * Queue a command for one or more filter instances. + * + * @param graph the filter graph + * @param target the filter(s) to which the command should be sent + * "all" sends to all filters + * otherwise it can be a filter or filter instance name + * which will send the command to all matching filters. + * @param cmd the command to sent, for handling simplicity all commands must be alphanummeric only + * @param arg the argument for the command + * @param ts time at which the command should be sent to the filter + * + * @note As this executes commands after this function returns, no return code + * from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported. + */ +int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts); + + #endif /* AVFILTER_AVFILTERGRAPH_H */ diff --git a/libavfilter/internal.h b/libavfilter/internal.h index b9613d5ada..bb9d0e576a 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -33,6 +33,13 @@ typedef struct AVFilterPool { int count; } AVFilterPool; +typedef struct AVFilterCommand { + double time; + char *command, *arg; + int flags; + struct AVFilterCommand *next; +} AVFilterCommand; + /** * Check for the validity of graph. *