X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_overlay.c;h=ad292a61c199596fa78141526256937f615c155d;hb=12791ec5b0d3653ad2a453d20368229f53df65c4;hp=37b799fcae58d378b62416558109d1b4d813227c;hpb=bf0fde84d503280009e6f573ded2e43eae80901b;p=ffmpeg diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 37b799fcae5..ad292a61c19 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -104,6 +104,7 @@ enum OverlayFormat { OVERLAY_FORMAT_YUV444, OVERLAY_FORMAT_RGB, OVERLAY_FORMAT_GBRP, + OVERLAY_FORMAT_AUTO, OVERLAY_FORMAT_NB }; @@ -111,7 +112,6 @@ typedef struct OverlayContext { const AVClass *class; int x, y; ///< position of overlaid picture - int allow_packed_rgb; uint8_t main_is_packed_rgb; uint8_t main_rgba_map[4]; uint8_t main_has_alpha; @@ -211,6 +211,12 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar return ret; } +static const enum AVPixelFormat alpha_pix_fmts[] = { + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, + AV_PIX_FMT_BGRA, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE +}; + static int query_formats(AVFilterContext *ctx) { OverlayContext *s = ctx->priv; @@ -298,14 +304,26 @@ static int query_formats(AVFilterContext *ctx) goto fail; } break; + case OVERLAY_FORMAT_AUTO: + if (!(main_formats = ff_make_format_list(alpha_pix_fmts))) { + ret = AVERROR(ENOMEM); + goto fail; + } + break; default: av_assert0(0); } - if ((ret = ff_formats_ref(main_formats , &ctx->inputs[MAIN]->out_formats )) < 0 || - (ret = ff_formats_ref(overlay_formats, &ctx->inputs[OVERLAY]->out_formats)) < 0 || - (ret = ff_formats_ref(main_formats , &ctx->outputs[MAIN]->in_formats )) < 0) + if (s->format == OVERLAY_FORMAT_AUTO) { + ret = ff_set_common_formats(ctx, main_formats); + if (ret < 0) goto fail; + } else { + if ((ret = ff_formats_ref(main_formats , &ctx->inputs[MAIN]->out_formats )) < 0 || + (ret = ff_formats_ref(overlay_formats, &ctx->inputs[OVERLAY]->out_formats)) < 0 || + (ret = ff_formats_ref(main_formats , &ctx->outputs[MAIN]->in_formats )) < 0) + goto fail; + } return 0; fail: @@ -318,12 +336,6 @@ fail: return ret; } -static const enum AVPixelFormat alpha_pix_fmts[] = { - AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, - AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, - AV_PIX_FMT_BGRA, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE -}; - static int config_input_overlay(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -404,7 +416,7 @@ static int config_output(AVFilterLink *outlink) static void blend_image_packed_rgb(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, - int x, int y) + int main_has_alpha, int x, int y) { OverlayContext *s = ctx->priv; int i, imax, j, jmax; @@ -423,7 +435,6 @@ static void blend_image_packed_rgb(AVFilterContext *ctx, const int sb = s->overlay_rgba_map[B]; const int sa = s->overlay_rgba_map[A]; const int sstep = s->overlay_pix_step[0]; - const int main_has_alpha = s->main_has_alpha; uint8_t *S, *sp, *d, *dp; i = FFMAX(-y, 0); @@ -622,11 +633,11 @@ static av_always_inline void blend_image_yuv(AVFilterContext *ctx, s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step); } -static av_always_inline void blend_image_rgb(AVFilterContext *ctx, - AVFrame *dst, const AVFrame *src, - int hsub, int vsub, - int main_has_alpha, - int x, int y) +static av_always_inline void blend_image_planar_rgb(AVFilterContext *ctx, + AVFrame *dst, const AVFrame *src, + int hsub, int vsub, + int main_has_alpha, + int x, int y) { OverlayContext *s = ctx->priv; const int src_w = src->width; @@ -647,30 +658,52 @@ static av_always_inline void blend_image_rgb(AVFilterContext *ctx, static void blend_image_yuv420(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - OverlayContext *s = ctx->priv; + blend_image_yuv(ctx, dst, src, 1, 1, 0, x, y); +} - blend_image_yuv(ctx, dst, src, 1, 1, s->main_has_alpha, x, y); +static void blend_image_yuva420(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 1, 1, 1, x, y); } static void blend_image_yuv422(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - OverlayContext *s = ctx->priv; + blend_image_yuv(ctx, dst, src, 1, 0, 0, x, y); +} - blend_image_yuv(ctx, dst, src, 1, 0, s->main_has_alpha, x, y); +static void blend_image_yuva422(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 1, 0, 1, x, y); } static void blend_image_yuv444(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - OverlayContext *s = ctx->priv; + blend_image_yuv(ctx, dst, src, 0, 0, 0, x, y); +} - blend_image_yuv(ctx, dst, src, 0, 0, s->main_has_alpha, x, y); +static void blend_image_yuva444(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 0, 0, 1, x, y); } static void blend_image_gbrp(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - OverlayContext *s = ctx->priv; + blend_image_planar_rgb(ctx, dst, src, 0, 0, 0, x, y); +} + +static void blend_image_gbrap(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_planar_rgb(ctx, dst, src, 0, 0, 1, x, y); +} - blend_image_rgb(ctx, dst, src, 0, 0, s->main_has_alpha, x, y); +static void blend_image_rgb(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_packed_rgb(ctx, dst, src, 0, x, y); +} + +static void blend_image_rgba(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_packed_rgb(ctx, dst, src, 1, x, y); } static int config_input_main(AVFilterLink *inlink) @@ -690,19 +723,44 @@ static int config_input_main(AVFilterLink *inlink) s->main_has_alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts); switch (s->format) { case OVERLAY_FORMAT_YUV420: - s->blend_image = blend_image_yuv420; + s->blend_image = s->main_has_alpha ? blend_image_yuva420 : blend_image_yuv420; break; case OVERLAY_FORMAT_YUV422: - s->blend_image = blend_image_yuv422; + s->blend_image = s->main_has_alpha ? blend_image_yuva422 : blend_image_yuv422; break; case OVERLAY_FORMAT_YUV444: - s->blend_image = blend_image_yuv444; + s->blend_image = s->main_has_alpha ? blend_image_yuva444 : blend_image_yuv444; break; case OVERLAY_FORMAT_RGB: - s->blend_image = blend_image_packed_rgb; + s->blend_image = s->main_has_alpha ? blend_image_rgba : blend_image_rgb; break; case OVERLAY_FORMAT_GBRP: - s->blend_image = blend_image_gbrp; + s->blend_image = s->main_has_alpha ? blend_image_gbrap : blend_image_gbrp; + break; + case OVERLAY_FORMAT_AUTO: + switch (inlink->format) { + case AV_PIX_FMT_YUVA420P: + s->blend_image = blend_image_yuva420; + break; + case AV_PIX_FMT_YUVA422P: + s->blend_image = blend_image_yuva422; + break; + case AV_PIX_FMT_YUVA444P: + s->blend_image = blend_image_yuva444; + break; + case AV_PIX_FMT_ARGB: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_BGRA: + case AV_PIX_FMT_ABGR: + s->blend_image = blend_image_rgba; + break; + case AV_PIX_FMT_GBRAP: + s->blend_image = blend_image_gbrap; + break; + default: + av_assert0(0); + break; + } break; } return 0; @@ -757,11 +815,6 @@ static av_cold int init(AVFilterContext *ctx) { OverlayContext *s = ctx->priv; - if (s->allow_packed_rgb) { - av_log(ctx, AV_LOG_WARNING, - "The rgb option is deprecated and is overriding the format option, use format instead\n"); - s->format = OVERLAY_FORMAT_RGB; - } if (!s->dinput.repeatlast || s->eof_action == EOF_ACTION_PASS) { s->dinput.repeatlast = 0; s->eof_action = EOF_ACTION_PASS; @@ -790,7 +843,6 @@ static const AVOption overlay_options[] = { { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_FRAME}, 0, EVAL_MODE_NB-1, FLAGS, "eval" }, { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" }, { "frame", "eval expressions per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" }, - { "rgb", "force packed RGB in input and output (deprecated)", OFFSET(allow_packed_rgb), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "shortest", "force termination when the shortest input terminates", OFFSET(dinput.shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { "format", "set output format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=OVERLAY_FORMAT_YUV420}, 0, OVERLAY_FORMAT_NB-1, FLAGS, "format" }, { "yuv420", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV420}, .flags = FLAGS, .unit = "format" }, @@ -798,6 +850,7 @@ static const AVOption overlay_options[] = { { "yuv444", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV444}, .flags = FLAGS, .unit = "format" }, { "rgb", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_RGB}, .flags = FLAGS, .unit = "format" }, { "gbrp", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_GBRP}, .flags = FLAGS, .unit = "format" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_AUTO}, .flags = FLAGS, .unit = "format" }, { "repeatlast", "repeat overlay of the last overlay frame", OFFSET(dinput.repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { NULL } };