[libav-devel] [PATCH] filtergraph: Select the best pixel format

Luca Barbato lu_zero at gentoo.org
Mon Aug 10 01:35:41 CEST 2015


On 09/08/15 23:16, Justin Ruggles wrote:
> 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

Can be done.

> - preserve average, non-alpha, bit depth

You end up with 16bits gray while 8bits gray is more than enough.

> - preserve colorspace

Ok

> - preserve individual component (including alpha) bit depths, if applicable

Ok, I can extend what I put there, that part seems working quite well.

> - preserve component ordering/packing
> 
> Something like this could still be done within a scoring system.

I'll update the rules soon.

lu






More information about the libav-devel mailing list