[FFmpeg-devel] [PATCH] vf_fade: fade alpha

Stefano Sabatini stefasab at gmail.com
Mon Nov 7 18:01:58 CET 2011


On date Sunday 2011-11-06 16:56:09 +0000, Mark Himsley encoded:
> On 06/11/2011 16:54, Mark Himsley wrote:
> >Add alpha fading.
> >
> >On 06/11/2011 00:40, Stefano Sabatini wrote:
> >>On date Saturday 2011-11-05 21:53:35 +0000, Mark Himsley encoded:
> >>>On 05/11/2011 14:26, Stefano Sabatini wrote:
> >>>>On date Saturday 2011-11-05 02:01:02 +0000, Mark Himsley encoded:
> >>>>>add alpha fading
> >>[...]
> >>>
> >>>Thanks for the review.
> >>
> >>Thanks for the patch ;-).
> >>
> >>>
> >>>I'll send updated patches.
> >
> >Including all suggested changes, including removing spurious double
> >alpha_expr variable, simplifying black_level determination, changing new
> >function name, meaningful names for variables, reformatting function
> >call and adding comments in function call.
> >
> >I also added macros for R G B A Y U V, although currently only 'A' is
> >ever used...
> 
> ...attached...
> 
> -- 
> Mark
> 

> diff --git a/doc/filters.texi b/doc/filters.texi
> index fec9a87..abfca59 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -1169,6 +1169,9 @@ See @var{start_frame}
>  @item duration, d
>  See @var{nb_frames}
>  
> + at item alpha
> +If set to 1, fade only alpha channel, if one exists on the input.
> +Default value is 0.
>  @end table
>  
>  A few usage examples follow, usable too as test scenarios.
> @@ -1184,6 +1187,9 @@ fade=in:0:25, fade=out:975:25
>  
>  # make first 5 frames black, then fade in from frame 5-24
>  fade=in:5:20
> +
> +# fade in alpha over first 25 frames of video
> +fade=in:0:25:alpha=1
>  @end example
>  
>  @section fieldorder
> diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
> index 7a2b4e1..4f74449 100644
> --- a/libavfilter/vf_fade.c
> +++ b/libavfilter/vf_fade.c
> @@ -30,14 +30,27 @@
>  #include "libavutil/opt.h"
>  #include "libavutil/pixdesc.h"
>  #include "avfilter.h"
> +#include "drawutils.h"
>  #include "internal.h"
>  
> +#define R 0
> +#define G 1
> +#define B 2
> +#define A 3
> +
> +#define Y 0
> +#define U 1
> +#define V 2
> +
>  typedef struct {
>      const AVClass *class;
>      int factor, fade_per_frame;
>      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];
> +    int alpha;
>  
>      char *type, *start_expr, *count_expr;
>  } FadeContext;
> @@ -51,6 +64,7 @@ static const AVOption fade_options[] = {
>      { "i",        "set expression of frame to start fading",    OFFSET(start_expr), AV_OPT_TYPE_STRING, {.str = "0"  }, CHAR_MIN, CHAR_MAX },
>      { "duration", "set expression for fade duration in frames", OFFSET(count_expr), AV_OPT_TYPE_STRING, {.str = "25" }, CHAR_MIN, CHAR_MAX },
>      { "d",        "set expression for fade duration in frames", OFFSET(count_expr), AV_OPT_TYPE_STRING, {.str = "25" }, CHAR_MIN, CHAR_MAX },
> +    { "alpha",    "fade alpha if it's available on the input",  OFFSET(alpha),      AV_OPT_TYPE_INT,    {.dbl = 0    },        0,        1 },
>      {NULL},
>  };
>  
> @@ -125,10 +139,11 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
>          goto fail;
>      }
>      fade->stop_frame = fade->start_frame + nb_frames;

> +    fade->alpha = !!fade->alpha;

this is not needed, as fade->alpha can only be 1 or 0.

>  
>      av_log(ctx, AV_LOG_INFO,
> -           "type:%s start_frame:%d nb_frames:%d\n",
> -           fade->type, fade->start_frame, nb_frames);
> +           "type:%s start_frame:%d nb_frames:%d alpha:%d\n",
> +           fade->type, fade->start_frame, nb_frames, fade->alpha);
>  
>  end:
>      av_free(args1);
> @@ -157,7 +172,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
>      };
>  
> @@ -172,6 +190,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;
> @@ -181,14 +206,37 @@ static int config_props(AVFilterLink *inlink)
>      fade->vsub = pixdesc->log2_chroma_h;
>  
>      fade->bpp = av_get_bits_per_pixel(pixdesc) >> 3;
> +    fade->alpha = fade->alpha ? ff_fmt_is_in(inlink->format, alpha_pix_fmts) : 0;
> +    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;
>      /* 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_plane(int y, int h, int w,
> +        int fade_factor, int black_level, int black_level_scaled,
> +        uint8_t offset, uint8_t step, int bytes_per_plane,
> +        uint8_t *data, int line_size)
> +{
> +    uint8_t *p;
> +    int i, j;
> +
> +    /* luma, alpha or rgb plane */
> +    for (i = 0; i < h; i++) {
> +        p = data + offset + (y+i) * line_size;
> +        for (j = 0; j < w * bytes_per_plane; j++) {
> +            /* fade->factor is using 16 lower-order bits for decimal places. */
> +            *p = ((*p - black_level) * fade_factor + black_level_scaled) >> 16;
> +            p+=step;
> +        }
> +    }
> +}
> +
>  static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
>  {
>      FadeContext *fade = inlink->dst->priv;
> @@ -197,16 +245,21 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
>      int i, j, plane;
>  
>      if (fade->factor < UINT16_MAX) {
> +        if (fade->alpha) {
> +            // alpha only
> +            plane = fade->is_packed_rgb ? 0 : A; // alpha is on plane 0 for packed formats
> +                                                 // or plane 3 for planar formats
> +            fade_plane(y, h, inlink->w,
> +                    fade->factor, fade->black_level, fade->black_level_scaled,
> +                    fade->is_packed_rgb ? fade->rgba_map[A] : 0, // alpha offset for packed formats
> +                    fade->is_packed_rgb ? 4 : 1,                 // pixstep for 8 bit packed formats
> +                    1, outpic->data[plane], outpic->linesize[plane]);
> +        } else {
>          /* 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++;
> -            }
> -        }
> -
> +        fade_plane(y, h, inlink->w,
> +                fade->factor, fade->black_level, fade->black_level_scaled,
> +                0, 1, // offset & pixstep for Y plane or RGB packed format
> +                fade->bpp, outpic->data[0], outpic->linesize[0]);

weird indent (no need to post a new patch for this)

>          if (outpic->data[1] && outpic->data[2]) {
>              /* chroma planes */
>              for (plane = 1; plane < 3; plane++) {
> @@ -222,6 +275,7 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
>                  }
>              }
>          }
> +        }
>      }

Looks fine to me, I'll post in a day or so if I read no more comments.
-- 
FFmpeg = Fancy & Frightening Magnificient Plastic Epic Gargoyle


More information about the ffmpeg-devel mailing list