diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-04-14 21:49:01 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-04-14 22:37:43 +0200 |
commit | 7432bcfe5a36331502c49fe03aefe39b9936247a (patch) | |
tree | 398b1874abbd4bcf7c103738ac4548e830af0a43 /libavfilter | |
parent | 01bf2ad7351fdaa2e21b6bdf963d22d6ffccb920 (diff) | |
parent | 7bf9e3391fa21d90ff283fc03a12287fe73db9e8 (diff) | |
download | ffmpeg-7432bcfe5a36331502c49fe03aefe39b9936247a.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
vsrc_buffer: fix check from 7ae7c41.
libxvid: Reorder functions to avoid forward declarations; make functions static.
libxvid: drop some pointless dead code
wmal: vertical alignment cosmetics
wmal: Warn about missing bitstream splicing feature and ask for sample.
wmal: Skip seekable_frame_in_packet.
wmal: Drop unused variable num_possible_block_size.
avfiltergraph: make the AVFilterInOut alloc/free API public
graphparser: allow specifying sws flags in the graph description.
graphparser: fix the order of connecting unlabeled links.
graphparser: add avfilter_graph_parse2().
vsrc_buffer: allow using a NULL buffer to signal EOF.
swscale: handle last pixel if lines have an odd width.
qdm2: fix a dubious pointer cast
WMAL: Do not try to read rawpcm coefficients if bits is invalid
mov: Fix detecting there is no sync sample.
tiffdec: K&R cosmetics
avf: has_duration does not check the global one
dsputil: fix optimized emu_edge function on Win64.
Conflicts:
doc/APIchanges
libavcodec/libxvid_rc.c
libavcodec/libxvidff.c
libavcodec/tiff.c
libavcodec/wmalosslessdec.c
libavfilter/avfiltergraph.h
libavfilter/graphparser.c
libavfilter/version.h
libavfilter/vsrc_buffer.c
libswscale/output.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/avfiltergraph.h | 52 | ||||
-rw-r--r-- | libavfilter/buffersrc.h | 1 | ||||
-rw-r--r-- | libavfilter/graphparser.c | 204 | ||||
-rw-r--r-- | libavfilter/version.h | 4 | ||||
-rw-r--r-- | libavfilter/vsrc_buffer.c | 32 |
5 files changed, 268 insertions, 25 deletions
diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h index cca9488f87..2c612b481d 100644 --- a/libavfilter/avfiltergraph.h +++ b/libavfilter/avfiltergraph.h @@ -91,11 +91,11 @@ void avfilter_graph_free(AVFilterGraph **graph); /** * A linked-list of the inputs/outputs of the filter chain. * - * This is mainly useful for avfilter_graph_parse(), since this - * function may accept a description of a graph with not connected - * input/output pads. This struct specifies, per each not connected - * pad contained in the graph, the filter context and the pad index - * required for establishing a link. + * This is mainly useful for avfilter_graph_parse() / avfilter_graph_parse2(), + * where it is used to communicate open (unlinked) inputs and outputs from and + * to the caller. + * This struct specifies, per each not connected pad contained in the graph, the + * filter context and the pad index required for establishing a link. */ typedef struct AVFilterInOut { /** unique name for this input/output in the list */ @@ -112,13 +112,14 @@ typedef struct AVFilterInOut { } AVFilterInOut; /** - * Create an AVFilterInOut. - * Must be free with avfilter_inout_free(). + * Allocate a single AVFilterInOut entry. + * Must be freed with avfilter_inout_free(). + * @return allocated AVFilterInOut on success, NULL on failure. */ AVFilterInOut *avfilter_inout_alloc(void); /** - * Free the AVFilterInOut in *inout, and set its pointer to NULL. + * Free the supplied list of AVFilterInOut and set *inout to NULL. * If *inout is NULL, do nothing. */ void avfilter_inout_free(AVFilterInOut **inout); @@ -141,6 +142,41 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, void *log_ctx); /** + * Add a graph described by a string to a graph. + * + * @param[in] graph the filter graph where to link the parsed graph context + * @param[in] filters string to be parsed + * @param[out] inputs a linked list of all free (unlinked) inputs of the + * parsed graph will be returned here. It is to be freed + * by the caller using avfilter_inout_free(). + * @param[out] outputs a linked list of all free (unlinked) outputs of the + * parsed graph will be returned here. It is to be freed by the + * caller using avfilter_inout_free(). + * @return zero on success, a negative AVERROR code on error + * + * @note the difference between avfilter_graph_parse2() and + * avfilter_graph_parse() is that in avfilter_graph_parse(), the caller provides + * the lists of inputs and outputs, which therefore must be known before calling + * the function. On the other hand, avfilter_graph_parse2() \em returns the + * inputs and outputs that are left unlinked after parsing the graph and the + * caller then deals with them. Another difference is that in + * avfilter_graph_parse(), the inputs parameter describes inputs of the + * <em>already existing</em> part of the graph; i.e. from the point of view of + * the newly created part, they are outputs. Similarly the outputs parameter + * describes outputs of the already existing filters, which are provided as + * inputs to the parsed filters. + * avfilter_graph_parse2() takes the opposite approach -- it makes no reference + * whatsoever to already existing parts of the graph and the inputs parameter + * will on return contain inputs of the newly parsed part of the graph. + * Analogously the outputs parameter will contain outputs of the newly created + * filters. + */ +int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, + AVFilterInOut **inputs, + AVFilterInOut **outputs); + + +/** * Send a command to one or more filter instances. * * @param graph the filter graph diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h index bd82c065e4..918a54faee 100644 --- a/libavfilter/buffersrc.h +++ b/libavfilter/buffersrc.h @@ -32,6 +32,7 @@ * * @param buf buffer containing frame data to be passed down the filtergraph. * This function will take ownership of buf, the user must not free it. + * A NULL buf signals EOF -- i.e. no more frames will be sent to this filter. */ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf); diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index bd3022e035..af4b566f1b 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -189,13 +189,15 @@ static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links) { AVFilterInOut *ret; - while (*links && strcmp((*links)->name, label)) + while (*links && (!(*links)->name || strcmp((*links)->name, label))) links = &((*links)->next); ret = *links; - if (ret) + if (ret) { *links = ret->next; + ret->next = NULL; + } return ret; } @@ -206,22 +208,31 @@ static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element) *inouts = element; } +static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element) +{ + while (*inouts && (*inouts)->next) + inouts = &((*inouts)->next); + + if (!*inouts) + *inouts = *element; + else + (*inouts)->next = *element; + *element = NULL; +} + static int link_filter_inouts(AVFilterContext *filt_ctx, AVFilterInOut **curr_inputs, AVFilterInOut **open_inputs, void *log_ctx) { - int pad = filt_ctx->input_count, ret; + int pad, ret; - while (pad--) { + for (pad = 0; pad < filt_ctx->input_count; pad++) { AVFilterInOut *p = *curr_inputs; - if (!p) { - av_log(log_ctx, AV_LOG_ERROR, - "Not enough inputs specified for the \"%s\" filter.\n", - filt_ctx->filter->name); - return AVERROR(EINVAL); - } - *curr_inputs = (*curr_inputs)->next; + if (p) + *curr_inputs = (*curr_inputs)->next; + else if (!(p = av_mallocz(sizeof(*p)))) + return AVERROR(ENOMEM); if (p->filter_ctx) { if ((ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx)) < 0) @@ -258,6 +269,7 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, AVFilterInOut **open_outputs, void *log_ctx) { + AVFilterInOut *parsed_inputs = NULL; int pad = 0; while (**buf == '[') { @@ -280,12 +292,15 @@ static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, match->pad_idx = pad; } - insert_inout(curr_inputs, match); + append_inout(&parsed_inputs, &match); *buf += strspn(*buf, WHITESPACES); pad++; } + append_inout(&parsed_inputs, curr_inputs); + *curr_inputs = parsed_inputs; + return pad; } @@ -334,10 +349,173 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, return pad; } +#if FF_API_GRAPH_AVCLASS +#define log_ctx graph +#else +#define log_ctx NULL +#endif + +static int parse_sws_flags(const char **buf, AVFilterGraph *graph) +{ + char *p = strchr(*buf, ';'); + + if (strncmp(*buf, "sws_flags=", 10)) + return 0; + + if (!p) { + av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n"); + return AVERROR(EINVAL); + } + + *buf += 4; // keep the 'flags=' part + + av_freep(&graph->scale_sws_opts); + if (!(graph->scale_sws_opts = av_mallocz(p - *buf + 1))) + return AVERROR(ENOMEM); + av_strlcpy(graph->scale_sws_opts, *buf, p - *buf + 1); + + *buf = p + 1; + return 0; +} + +int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, + AVFilterInOut **inputs, + AVFilterInOut **outputs) +{ + int index = 0, ret = 0; + char chr = 0; + + AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL; + + filters += strspn(filters, WHITESPACES); + + if ((ret = parse_sws_flags(&filters, graph)) < 0) + goto fail; + + do { + AVFilterContext *filter; + filters += strspn(filters, WHITESPACES); + + if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) + goto end; + + if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) + goto end; + + if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) + goto end; + + if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, + log_ctx)) < 0) + goto end; + + filters += strspn(filters, WHITESPACES); + chr = *filters++; + + if (chr == ';' && curr_inputs) + append_inout(&open_outputs, &curr_inputs); + index++; + } while (chr == ',' || chr == ';'); + + if (chr) { + av_log(log_ctx, AV_LOG_ERROR, + "Unable to parse graph description substring: \"%s\"\n", + filters - 1); + ret = AVERROR(EINVAL); + goto end; + } + + append_inout(&open_outputs, &curr_inputs); + + + *inputs = open_inputs; + *outputs = open_outputs; + return 0; + + fail:end: + for (; graph->filter_count > 0; graph->filter_count--) + avfilter_free(graph->filters[graph->filter_count - 1]); + av_freep(&graph->filters); + avfilter_inout_free(&open_inputs); + avfilter_inout_free(&open_outputs); + avfilter_inout_free(&curr_inputs); + + *inputs = NULL; + *outputs = NULL; + + return ret; +} +#undef log_ctx + int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, void *log_ctx) { +#if 0 + int ret; + AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; + AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; + AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL; + + if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0) + goto fail; + + /* First input can be omitted if it is "[in]" */ + if (inputs && !inputs->name) + inputs->name = av_strdup("in"); + for (cur = inputs; cur; cur = cur->next) { + if (!cur->name) { + av_log(log_ctx, AV_LOG_ERROR, + "Not enough inputs specified for the \"%s\" filter.\n", + cur->filter_ctx->filter->name); + ret = AVERROR(EINVAL); + goto fail; + } + if (!(match = extract_inout(cur->name, &open_outputs))) + continue; + ret = avfilter_link(match->filter_ctx, match->pad_idx, + cur->filter_ctx, cur->pad_idx); + avfilter_inout_free(&match); + if (ret < 0) + goto fail; + } + + /* Last output can be omitted if it is "[out]" */ + if (outputs && !outputs->name) + outputs->name = av_strdup("out"); + for (cur = outputs; cur; cur = cur->next) { + if (!cur->name) { + av_log(log_ctx, AV_LOG_ERROR, + "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", + filters); + ret = AVERROR(EINVAL); + goto fail; + } + if (!(match = extract_inout(cur->name, &open_inputs))) + continue; + ret = avfilter_link(cur->filter_ctx, cur->pad_idx, + match->filter_ctx, match->pad_idx); + avfilter_inout_free(&match); + if (ret < 0) + goto fail; + } + + fail: + if (ret < 0) { + for (; graph->filter_count > 0; graph->filter_count--) + avfilter_free(graph->filters[graph->filter_count - 1]); + av_freep(&graph->filters); + } + avfilter_inout_free(&inputs); + avfilter_inout_free(&outputs); + /* clear open_in/outputs only if not passed as parameters */ + if (open_inputs_ptr) *open_inputs_ptr = open_inputs; + else avfilter_inout_free(&open_inputs); + if (open_outputs_ptr) *open_outputs_ptr = open_outputs; + else avfilter_inout_free(&open_outputs); + return ret; +} +#else int index = 0, ret = 0; char chr = 0; @@ -414,3 +592,5 @@ end: } return ret; } + +#endif diff --git a/libavfilter/version.h b/libavfilter/version.h index 7df43a3915..e8e9f27566 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,8 +29,8 @@ #include "libavutil/avutil.h" #define LIBAVFILTER_VERSION_MAJOR 2 -#define LIBAVFILTER_VERSION_MINOR 69 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MINOR 70 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vsrc_buffer.c b/libavfilter/vsrc_buffer.c index 73866a8c4a..d003add88b 100644 --- a/libavfilter/vsrc_buffer.c +++ b/libavfilter/vsrc_buffer.c @@ -39,6 +39,7 @@ typedef struct { AVRational time_base; ///< time_base to set in the output link AVRational sample_aspect_ratio; char sws_param[256]; + int eof; } BufferSourceContext; #define CHECK_PARAM_CHANGE(s, c, width, height, format)\ @@ -55,6 +56,12 @@ int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter, AVFilterBufferRef *buf; int ret; + if (!picref) { + c->eof = 1; + return 0; + } else if (c->eof) + return AVERROR(EINVAL); + if (!av_fifo_space(c->fifo) && (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + sizeof(buf))) < 0) @@ -125,6 +132,12 @@ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf) BufferSourceContext *c = s->priv; int ret; + if (!buf) { + c->eof = 1; + return 0; + } else if (c->eof) + return AVERROR(EINVAL); + if (!av_fifo_space(c->fifo) && (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + sizeof(buf))) < 0) @@ -144,9 +157,17 @@ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf) int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src, const AVFrame *frame, int flags) { + BufferSourceContext *c = buffer_src->priv; + AVFilterBufferRef *picref; int ret; - AVFilterBufferRef *picref = - avfilter_get_video_buffer_ref_from_frame(frame, AV_PERM_WRITE); + + if (!frame) { + c->eof = 1; + return 0; + } else if (c->eof) + return AVERROR(EINVAL); + + picref = avfilter_get_video_buffer_ref_from_frame(frame, AV_PERM_WRITE); if (!picref) return AVERROR(ENOMEM); ret = av_vsrc_buffer_add_video_buffer_ref(buffer_src, picref, flags); @@ -226,6 +247,8 @@ static int request_frame(AVFilterLink *link) AVFilterBufferRef *buf; if (!av_fifo_size(c->fifo)) { + if (c->eof) + return AVERROR_EOF; av_log(link->src, AV_LOG_WARNING, "request_frame() called with no available frame!\n"); return AVERROR(EINVAL); @@ -243,7 +266,10 @@ static int request_frame(AVFilterLink *link) static int poll_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; - return !!av_fifo_size(c->fifo); + int size = av_fifo_size(c->fifo); + if (!size && c->eof) + return AVERROR_EOF; + return size/sizeof(AVFilterBufferRef*); } AVFilter avfilter_vsrc_buffer = { |