return ret;
}
-int ff_avfilter_graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx)
+/**
+ * Check for the validity of graph.
+ *
+ * A graph is considered valid if all its input and output pads are
+ * connected.
+ *
+ * @return 0 in case of success, a negative value otherwise
+ */
+static int graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx)
{
AVFilterContext *filt;
int i, j;
return 0;
}
-int ff_avfilter_graph_config_links(AVFilterGraph *graph, AVClass *log_ctx)
+/**
+ * Configure all the links of graphctx.
+ *
+ * @return 0 in case of success, a negative value otherwise
+ */
+static int graph_config_links(AVFilterGraph *graph, AVClass *log_ctx)
{
AVFilterContext *filt;
int i, ret;
if (graph->filters[i]->filter->query_formats)
graph->filters[i]->filter->query_formats(graph->filters[i]);
else
- avfilter_default_query_formats(graph->filters[i]);
+ ff_default_query_formats(graph->filters[i]);
}
/* go through and merge as many format lists as possible */
continue;
if (link->in_formats != link->out_formats &&
- !avfilter_merge_formats(link->in_formats,
+ !ff_merge_formats(link->in_formats,
link->out_formats))
convert_needed = 1;
if (link->type == AVMEDIA_TYPE_AUDIO) {
convert->filter->query_formats(convert);
inlink = convert->inputs[0];
outlink = convert->outputs[0];
- if (!avfilter_merge_formats( inlink->in_formats, inlink->out_formats) ||
- !avfilter_merge_formats(outlink->in_formats, outlink->out_formats))
+ if (!ff_merge_formats( inlink->in_formats, inlink->out_formats) ||
+ !ff_merge_formats(outlink->in_formats, outlink->out_formats))
ret |= AVERROR(ENOSYS);
if (inlink->type == AVMEDIA_TYPE_AUDIO &&
(!ff_merge_samplerates(inlink->in_samplerates,
link->channel_layout = link->in_channel_layouts->channel_layouts[0];
}
- avfilter_formats_unref(&link->in_formats);
- avfilter_formats_unref(&link->out_formats);
- avfilter_formats_unref(&link->in_samplerates);
- avfilter_formats_unref(&link->out_samplerates);
+ ff_formats_unref(&link->in_formats);
+ ff_formats_unref(&link->out_formats);
+ ff_formats_unref(&link->in_samplerates);
+ ff_formats_unref(&link->out_samplerates);
ff_channel_layouts_unref(&link->in_channel_layouts);
ff_channel_layouts_unref(&link->out_channel_layouts);
int i, j, k, ret = 0;
REDUCE_FORMATS(int, AVFilterFormats, formats, formats,
- format_count, avfilter_add_format);
+ format_count, ff_add_format);
REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
- format_count, avfilter_add_format);
+ format_count, ff_add_format);
REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
channel_layouts, nb_channel_layouts, ff_add_channel_layout);
swap_channel_layouts_on_filter(graph->filters[i]);
}
+static void swap_sample_fmts_on_filter(AVFilterContext *filter)
+{
+ AVFilterLink *link = NULL;
+ int format, bps;
+ int i, j;
+
+ for (i = 0; i < filter->input_count; i++) {
+ link = filter->inputs[i];
+
+ if (link->type == AVMEDIA_TYPE_AUDIO &&
+ link->out_formats->format_count == 1)
+ break;
+ }
+ if (i == filter->input_count)
+ return;
+
+ format = link->out_formats->formats[0];
+ bps = av_get_bytes_per_sample(format);
+
+ for (i = 0; i < filter->output_count; i++) {
+ AVFilterLink *outlink = filter->outputs[i];
+ int best_idx, best_score = INT_MIN;
+
+ if (outlink->type != AVMEDIA_TYPE_AUDIO ||
+ outlink->in_formats->format_count < 2)
+ continue;
+
+ for (j = 0; j < outlink->in_formats->format_count; j++) {
+ int out_format = outlink->in_formats->formats[j];
+ int out_bps = av_get_bytes_per_sample(out_format);
+ int score;
+
+ if (av_get_packed_sample_fmt(out_format) == format ||
+ av_get_planar_sample_fmt(out_format) == format) {
+ best_idx = j;
+ break;
+ }
+
+ /* for s32 and float prefer double to prevent loss of information */
+ if (bps == 4 && out_bps == 8) {
+ best_idx = j;
+ break;
+ }
+
+ /* prefer closest higher or equal bps */
+ score = -abs(out_bps - bps);
+ if (out_bps >= bps)
+ score += INT_MAX/2;
+
+ if (score > best_score) {
+ best_score = score;
+ best_idx = j;
+ }
+ }
+ FFSWAP(int, outlink->in_formats->formats[0],
+ outlink->in_formats->formats[best_idx]);
+ }
+}
+
+static void swap_sample_fmts(AVFilterGraph *graph)
+{
+ int i;
+
+ for (i = 0; i < graph->filter_count; i++)
+ swap_sample_fmts_on_filter(graph->filters[i]);
+
+}
+
static int pick_formats(AVFilterGraph *graph)
{
int i, j, ret;
return 0;
}
-int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
+/**
+ * Configure the formats of all the links in the graph.
+ */
+static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
{
int ret;
* of format conversion inside filters */
reduce_formats(graph);
- /* for audio filters, ensure the best sample rate and channel layout
+ /* for audio filters, ensure the best format, sample rate and channel layout
* is selected */
+ swap_sample_fmts(graph);
swap_samplerates(graph);
swap_channel_layouts(graph);
{
int ret;
- if ((ret = ff_avfilter_graph_check_validity(graphctx, log_ctx)))
+ if ((ret = graph_check_validity(graphctx, log_ctx)))
return ret;
- if ((ret = ff_avfilter_graph_config_formats(graphctx, log_ctx)))
+ if ((ret = graph_config_formats(graphctx, log_ctx)))
return ret;
- if ((ret = ff_avfilter_graph_config_links(graphctx, log_ctx)))
+ if ((ret = graph_config_links(graphctx, log_ctx)))
return ret;
return 0;