mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-01-07 14:45:29 +01:00
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>
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user