aboutsummaryrefslogtreecommitdiffstats
path: root/libavfilter
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-04-14 21:49:01 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-04-14 22:37:43 +0200
commit7432bcfe5a36331502c49fe03aefe39b9936247a (patch)
tree398b1874abbd4bcf7c103738ac4548e830af0a43 /libavfilter
parent01bf2ad7351fdaa2e21b6bdf963d22d6ffccb920 (diff)
parent7bf9e3391fa21d90ff283fc03a12287fe73db9e8 (diff)
downloadffmpeg-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.h52
-rw-r--r--libavfilter/buffersrc.h1
-rw-r--r--libavfilter/graphparser.c204
-rw-r--r--libavfilter/version.h4
-rw-r--r--libavfilter/vsrc_buffer.c32
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 = {