lavfi: support unknown channel layouts.

This commit is contained in:
Nicolas George
2013-01-02 15:11:30 +01:00
parent fccd8c21c4
commit b6afb2dde1
5 changed files with 184 additions and 19 deletions

View File

@@ -185,9 +185,24 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
return NULL;
}
static void sanitize_channel_layouts(void *log, AVFilterChannelLayouts *l)
{
if (!l)
return;
if (l->nb_channel_layouts) {
if (l->all_layouts || l->all_counts)
av_log(log, AV_LOG_WARNING, "All layouts set on non-empty list\n");
l->all_layouts = l->all_counts = 0;
} else {
if (l->all_counts && !l->all_layouts)
av_log(log, AV_LOG_WARNING, "All counts without all layouts\n");
l->all_layouts = 1;
}
}
static int filter_query_formats(AVFilterContext *ctx)
{
int ret;
int ret, i;
AVFilterFormats *formats;
AVFilterChannelLayouts *chlayouts;
AVFilterFormats *samplerates;
@@ -201,6 +216,11 @@ static int filter_query_formats(AVFilterContext *ctx)
return ret;
}
for (i = 0; i < ctx->nb_inputs; i++)
sanitize_channel_layouts(ctx, ctx->inputs[i]->out_channel_layouts);
for (i = 0; i < ctx->nb_outputs; i++)
sanitize_channel_layouts(ctx, ctx->outputs[i]->in_channel_layouts);
formats = ff_all_formats(type);
if (!formats)
return AVERROR(ENOMEM);
@@ -470,7 +490,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
link->in_samplerates->format_count = 1;
link->sample_rate = link->in_samplerates->formats[0];
if (!link->in_channel_layouts->nb_channel_layouts) {
if (link->in_channel_layouts->all_layouts) {
av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
"the link between filters %s and %s.\n", link->src->name,
link->dst->name);
@@ -478,7 +498,10 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
}
link->in_channel_layouts->nb_channel_layouts = 1;
link->channel_layout = link->in_channel_layouts->channel_layouts[0];
link->channels = av_get_channel_layout_nb_channels(link->channel_layout);
if ((link->channels = FF_LAYOUT2COUNT(link->channel_layout)))
link->channel_layout = 0;
else
link->channels = av_get_channel_layout_nb_channels(link->channel_layout);
}
ff_formats_unref(&link->in_formats);
@@ -534,8 +557,42 @@ static int reduce_formats_on_filter(AVFilterContext *filter)
format_count, ff_add_format);
REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
format_count, ff_add_format);
REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
channel_layouts, nb_channel_layouts, ff_add_channel_layout);
/* reduce channel layouts */
for (i = 0; i < filter->nb_inputs; i++) {
AVFilterLink *inlink = filter->inputs[i];
uint64_t fmt;
if (!inlink->out_channel_layouts ||
inlink->out_channel_layouts->nb_channel_layouts != 1)
continue;
fmt = inlink->out_channel_layouts->channel_layouts[0];
for (j = 0; j < filter->nb_outputs; j++) {
AVFilterLink *outlink = filter->outputs[j];
AVFilterChannelLayouts *fmts;
fmts = outlink->in_channel_layouts;
if (inlink->type != outlink->type || fmts->nb_channel_layouts == 1)
continue;
if (fmts->all_layouts) {
/* Turn the infinite list into a singleton */
fmts->all_layouts = fmts->all_counts = 0;
ff_add_channel_layout(&outlink->in_channel_layouts, fmt);
break;
}
for (k = 0; k < outlink->in_channel_layouts->nb_channel_layouts; k++) {
if (fmts->channel_layouts[k] == fmt) {
fmts->channel_layouts[0] = fmt;
fmts->nb_channel_layouts = 1;
ret = 1;
break;
}
}
}
}
return ret;
}
@@ -663,7 +720,23 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
int count_diff = out_channels - in_channels;
int matched_channels, extra_channels;
int score = 0;
int score = 100000;
if (FF_LAYOUT2COUNT(in_chlayout) || FF_LAYOUT2COUNT(out_chlayout)) {
/* Compute score in case the input or output layout encodes
a channel count; in this case the score is not altered by
the computation afterwards, as in_chlayout and
out_chlayout have both been set to 0 */
if (FF_LAYOUT2COUNT(in_chlayout))
in_channels = FF_LAYOUT2COUNT(in_chlayout);
if (FF_LAYOUT2COUNT(out_chlayout))
out_channels = FF_LAYOUT2COUNT(out_chlayout);
score -= 10000 + FFABS(out_channels - in_channels) +
(in_channels > out_channels ? 10000 : 0);
in_chlayout = out_chlayout = 0;
/* Let the remaining computation run, even if the score
value is not altered */
}
/* channel substitution */
for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {