]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_overlay.c
avfilter/af_astats: measure dynamic range
[ffmpeg] / libavfilter / vf_overlay.c
index 37b799fcae58d378b62416558109d1b4d813227c..ad292a61c199596fa78141526256937f615c155d 100644 (file)
@@ -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 }
 };