[FFmpeg-devel] [PATCH] vf_fade: fade alpha
Stefano Sabatini
stefasab at gmail.com
Sat Nov 5 15:26:02 CET 2011
On date Saturday 2011-11-05 02:01:02 +0000, Mark Himsley encoded:
> add alpha fading
>
> --
> Mark
> diff --git a/doc/filters.texi b/doc/filters.texi
> index a6110e4..70fbea7 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -1105,6 +1105,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.
> @@ -1120,6 +1123,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 6f750b4..8b7e70e 100644
> --- a/libavfilter/vf_fade.c
> +++ b/libavfilter/vf_fade.c
> @@ -39,8 +39,12 @@ 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;
>
> char *type, *start_expr, *count_expr;
> + double alpha_expr;
double alpha_expr => int alpha
> } FadeContext;
>
> #define OFFSET(x) offsetof(FadeContext, x)
> @@ -52,6 +56,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_expr), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, 1 },
> {NULL},
> };
>
> @@ -126,10 +131,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_expr;
>
> 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);
> @@ -158,7 +164,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
> };
>
> @@ -173,6 +182,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;
> @@ -182,14 +198,36 @@ 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 : 0;
simpler:
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_luma(int y, int h, int w, int ff, int bl, int bls,
please more meaningful names or doxygen them
the function may be renamed fade_plane()
> + 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;
> @@ -198,16 +236,15 @@ 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
> + 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]);
slightly more readable:
plane = fade->is_packed_rgb ? 0 : 3;
fade_luma(y, h, inlink->w, fade->factor, fade->black_level, fade->black_level_scaled,
fade->is_packed_rgb ? fade->rgba_map[3] : 0, // offset
fade->is_packed_rgb ? 4 : 1, // pixstep
1, outpic->data[plane], outpic->linesize[plane]);
maybe you can define R G B A Y macros and use them in place of 0 1 2 3 0.
> + } 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_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++) {
> @@ -223,6 +260,7 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
> }
> }
> }
> + }
> }
--
FFmpeg = Fascinating and Frightening Minimalistic Practical Eager Generator
More information about the ffmpeg-devel
mailing list