On 08/07/2015 06:13 PM, Luca Barbato wrote:
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]); + } +}
I'm not so sure I like how the scoring is implemented here. The most logical to me would be a strict layered matching. Ideally, my preference would be, in order or priority:
- preserve alpha only if the input has alpha - preserve average, non-alpha, bit depth - preserve colorspace - preserve individual component (including alpha) bit depths, if applicable - preserve component ordering/packing Something like this could still be done within a scoring system. Cheers, Justin _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
