diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c index 5032019..4e1e4d1 100644 --- a/libavfilter/vf_fade.c +++ b/libavfilter/vf_fade.c @@ -27,6 +27,7 @@ #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "drawutils.h" #include "internal.h" typedef struct { @@ -34,6 +35,9 @@ typedef struct { unsigned int frame_index, start_frame, stop_frame; int hsub, vsub, bpp; unsigned int black_level, black_level_scaled; + uint8_t is_packed_rgb; + uint8_t rgba_map[4]; + uint8_t alpha; } FadeContext; static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) @@ -76,7 +80,10 @@ static int query_formats(AVFilterContext *ctx) PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_YUVJ444P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ420P, PIX_FMT_YUV440P, PIX_FMT_YUVJ440P, + PIX_FMT_YUVA420P, PIX_FMT_RGB24, PIX_FMT_BGR24, + PIX_FMT_ARGB, PIX_FMT_ABGR, + PIX_FMT_RGBA, PIX_FMT_BGRA, PIX_FMT_NONE }; @@ -91,6 +98,13 @@ const static enum PixelFormat studio_level_pix_fmts[] = { PIX_FMT_NONE }; +static enum PixelFormat alpha_pix_fmts[] = { + PIX_FMT_YUVA420P, + PIX_FMT_ARGB, PIX_FMT_ABGR, + PIX_FMT_RGBA, PIX_FMT_BGRA, + PIX_FMT_NONE +}; + static int config_props(AVFilterLink *inlink) { FadeContext *fade = inlink->dst->priv; @@ -100,14 +114,36 @@ static int config_props(AVFilterLink *inlink) fade->vsub = pixdesc->log2_chroma_h; fade->bpp = av_get_bits_per_pixel(pixdesc) >> 3; + fade->alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts); + fade->is_packed_rgb = ff_fill_rgba_map(fade->rgba_map, inlink->format) >= 0; - fade->black_level = ff_fmt_is_in(inlink->format, studio_level_pix_fmts) ? 16 : 0; + /* CCIR601/709 black level unless input is RGB or has alpha */ + fade->black_level = ff_fmt_is_in(inlink->format, studio_level_pix_fmts) ? + fade->alpha ? 0 : 16 : 0; /* 32768 = 1 << 15, it is an integer representation * of 0.5 and is for rounding. */ fade->black_level_scaled = (fade->black_level << 16) + 32768; return 0; } +static void fade_luma(int y, int h, int w, int ff, int bl, int bls, + uint8_t offset, uint8_t step, int bpp, + uint8_t *data, int linesize) +{ + uint8_t *p; + int i, j; + + /* luma, alpha or rgb plane */ + for (i = 0; i < h; i++) { + p = data + offset + (y+i) * linesize; + for (j = 0; j < w * bpp; j++) { + /* fade->factor is using 16 lower-order bits for decimal places. */ + *p = ((*p - bl) * ff + bls) >> 16; + p+=step; + } + } +} + static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { FadeContext *fade = inlink->dst->priv; @@ -116,27 +152,28 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) int i, j, plane; if (fade->factor < UINT16_MAX) { - /* luma or rgb plane */ - for (i = 0; i < h; i++) { - p = outpic->data[0] + (y+i) * outpic->linesize[0]; - for (j = 0; j < inlink->w * fade->bpp; j++) { - /* fade->factor is using 16 lower-order bits for decimal places. */ - *p = ((*p - fade->black_level) * fade->factor + fade->black_level_scaled) >> 16; - p++; - } - } - - if (outpic->data[1] && outpic->data[2]) { - /* chroma planes */ - for (plane = 1; plane < 3; plane++) { - for (i = 0; i < h; i++) { - p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane]; - for (j = 0; j < inlink->w >> fade->hsub; j++) { - /* 8421367 = ((128 << 1) + 1) << 15. It is an integer - * representation of 128.5. The .5 is for rounding - * purposes. */ - *p = ((*p - 128) * fade->factor + 8421367) >> 16; - p++; + if (fade->alpha) { + // alpha only + fade_luma( y, h, inlink->w, fade->factor, fade->black_level, fade->black_level_scaled, + fade->is_packed_rgb ? fade->rgba_map[3] : 0, fade->is_packed_rgb ? 4 : 1, 1, + outpic->data[fade->is_packed_rgb ? 0 : 3], outpic->linesize[fade->is_packed_rgb ? 0 : 3]); + } else { + /* luma or rgb plane */ + fade_luma( y, h, inlink->w, fade->factor, fade->black_level, fade->black_level_scaled, + 0, 1, fade->bpp, + outpic->data[0], outpic->linesize[0]); + if (outpic->data[1] && outpic->data[2]) { + /* chroma planes */ + for (plane = 1; plane < 3; plane++) { + for (i = 0; i < h; i++) { + p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane]; + for (j = 0; j < inlink->w >> fade->hsub; j++) { + /* 8421367 = ((128 << 1) + 1) << 15. It is an integer + * representation of 128.5. The .5 is for rounding + * purposes. */ + *p = ((*p - 128) * fade->factor + 8421367) >> 16; + p++; + } } } }