Give priority to pixel formats closer to the input.
---
I kept it as simple as possible on purpose.
libavfilter/avfiltergraph.c | 97 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 0fc385c..91a9d71 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -31,6 +31,7 @@
#include "libavutil/internal.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
#include "avfilter.h"
#include "formats.h"
@@ -742,6 +743,100 @@ static int pick_formats(AVFilterGraph *graph)
return 0;
}
+#define same_flag(d1, d2, flag) \
+ !(!!(d1->flags & flag) ^ !!(d2->flags & flag))
+
+static int find_best_pix_fmt_match(AVFilterLink *outlink,
+ const AVPixFmtDescriptor *in_desc,
+ int in_format)
+{
+ int j;
+ int best_idx = -1, best_score = INT_MIN;
+
+ for (j = 0; j < outlink->in_formats->nb_formats; j++) {
+ int format = outlink->in_formats->formats[j];
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
+
+ int score;
+
+ int same_alpha = same_flag(desc, in_desc, AV_PIX_FMT_FLAG_ALPHA);
+ int same_rgb = same_flag(desc, in_desc, AV_PIX_FMT_FLAG_RGB);
+ int bpc = desc->comp[0].depth_minus1;
+ int in_bpc = in_desc->comp[0].depth_minus1;
+
+ if (bpc < in_bpc)
+ score = bpc - in_bpc;
+ else
+ score = 0;
+
+ score += -10 * abs(desc->nb_components -
+ in_desc->nb_components);
+
+ if (same_alpha && same_rgb) {
+ score += 2;
+ } else if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
+ if (same_alpha)
+ score += 1;
+ } else {
+ if (same_rgb)
+ score += 1;
+ }
+
+ if (score > best_score) {
+ best_score = score;
+ best_idx = j;
+ }
+ }
+
+ return best_idx;
+}
+
+static void swap_pix_fmts_on_filter(AVFilterContext *filter)
+{
+ AVFilterLink *link = NULL;
+ const AVPixFmtDescriptor *desc;
+ int format;
+ int i;
+
+ for (i = 0; i < filter->nb_inputs; i++) {
+ link = filter->inputs[i];
+
+ if (link->type == AVMEDIA_TYPE_VIDEO &&
+ link->out_formats->nb_formats == 1)
+ break;
+ }
+ if (i == filter->nb_inputs)
+ return;
+
+ format = link->out_formats->formats[0];
+ desc = av_pix_fmt_desc_get(format);
+
+ for (i = 0; i < filter->nb_outputs; i++) {
+ AVFilterLink *outlink = filter->outputs[i];
+ int best_idx;
+
+ if (outlink->type != AVMEDIA_TYPE_VIDEO ||
+ outlink->in_formats->nb_formats < 2)
+ continue;
+
+ best_idx = find_best_pix_fmt_match(outlink, desc, format);
+
+ if (best_idx > -1)
+ FFSWAP(int, outlink->in_formats->formats[0],
+ outlink->in_formats->formats[best_idx]);
+ }
+}
+
+static void swap_pix_fmts(AVFilterGraph *graph)
+{
+ int i;
+
+ for (i = 0; i < graph->nb_filters; i++) {
+ swap_pix_fmts_on_filter(graph->filters[i]);
+ }
+}
+
+
/**
* Configure the formats of all the links in the graph.
*/
@@ -763,6 +858,8 @@ static int graph_config_formats(AVFilterGraph *graph,
AVClass *log_ctx)
swap_sample_fmts(graph);
swap_samplerates(graph);
swap_channel_layouts(graph);
+ /* for video filters, ensure the best format is selected */
+ swap_pix_fmts(graph);
if ((ret = pick_formats(graph)) < 0)
return ret;
--
1.9.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel