]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_overlay.c
avfilter/vf_gblur: add support for commands
[ffmpeg] / libavfilter / vf_overlay.c
index a90540f45c2421eb27086876d8bd77298985384d..0a8f089c0d57d05d89844e479a45892114b76e7e 100644 (file)
@@ -39,6 +39,7 @@
 #include "drawutils.h"
 #include "framesync.h"
 #include "video.h"
+#include "vf_overlay.h"
 
 typedef struct ThreadData {
     AVFrame *dst, *src;
@@ -59,21 +60,6 @@ static const char *const var_names[] = {
     NULL
 };
 
-enum var_name {
-    VAR_MAIN_W,    VAR_MW,
-    VAR_MAIN_H,    VAR_MH,
-    VAR_OVERLAY_W, VAR_OW,
-    VAR_OVERLAY_H, VAR_OH,
-    VAR_HSUB,
-    VAR_VSUB,
-    VAR_X,
-    VAR_Y,
-    VAR_N,
-    VAR_POS,
-    VAR_T,
-    VAR_VARS_NB
-};
-
 #define MAIN    0
 #define OVERLAY 1
 
@@ -92,45 +78,6 @@ enum EvalMode {
     EVAL_MODE_NB
 };
 
-enum OverlayFormat {
-    OVERLAY_FORMAT_YUV420,
-    OVERLAY_FORMAT_YUV422,
-    OVERLAY_FORMAT_YUV444,
-    OVERLAY_FORMAT_RGB,
-    OVERLAY_FORMAT_GBRP,
-    OVERLAY_FORMAT_AUTO,
-    OVERLAY_FORMAT_NB
-};
-
-typedef struct OverlayContext {
-    const AVClass *class;
-    int x, y;                   ///< position of overlaid picture
-
-    uint8_t main_is_packed_rgb;
-    uint8_t main_rgba_map[4];
-    uint8_t main_has_alpha;
-    uint8_t overlay_is_packed_rgb;
-    uint8_t overlay_rgba_map[4];
-    uint8_t overlay_has_alpha;
-    int format;                 ///< OverlayFormat
-    int alpha_format;
-    int eval_mode;              ///< EvalMode
-
-    FFFrameSync fs;
-
-    int main_pix_step[4];       ///< steps per pixel for each plane of the main output
-    int overlay_pix_step[4];    ///< steps per pixel for each plane of the overlay
-    int hsub, vsub;             ///< chroma subsampling values
-    const AVPixFmtDescriptor *main_desc; ///< format descriptor for main input
-
-    double var_values[VAR_VARS_NB];
-    char *x_expr, *y_expr;
-
-    AVExpr *x_pexpr, *y_pexpr;
-
-    int (*blend_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
-} OverlayContext;
-
 static av_cold void uninit(AVFilterContext *ctx)
 {
     OverlayContext *s = ctx->priv;
@@ -433,15 +380,15 @@ static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx,
     uint8_t *S, *sp, *d, *dp;
 
     i = FFMAX(-y, 0);
-    imax = FFMIN(-y + dst_h, src_h);
+    imax = FFMIN3(-y + dst_h, FFMIN(src_h, dst_h), y + src_h);
 
-    slice_start = (imax * jobnr) / nb_jobs;
-    slice_end = (imax * (jobnr+1)) / nb_jobs;
+    slice_start = i + (imax * jobnr) / nb_jobs;
+    slice_end = i + (imax * (jobnr+1)) / nb_jobs;
 
-    sp = src->data[0] + (i + slice_start)     * src->linesize[0];
-    dp = dst->data[0] + (y + i + slice_start) * dst->linesize[0];
+    sp = src->data[0] + (slice_start)     * src->linesize[0];
+    dp = dst->data[0] + (y + slice_start) * dst->linesize[0];
 
-    for (i = i + slice_start; i < slice_end; i++) {
+    for (i = slice_start; i < slice_end; i++) {
         j = FFMAX(-x, 0);
         S = sp + j     * sstep;
         d = dp + (x+j) * dstep;
@@ -509,6 +456,7 @@ static av_always_inline void blend_plane(AVFilterContext *ctx,
                                          int jobnr,
                                          int nb_jobs)
 {
+    OverlayContext *octx = ctx->priv;
     int src_wp = AV_CEIL_RSHIFT(src_w, hsub);
     int src_hp = AV_CEIL_RSHIFT(src_h, vsub);
     int dst_wp = AV_CEIL_RSHIFT(dst_w, hsub);
@@ -520,26 +468,36 @@ static av_always_inline void blend_plane(AVFilterContext *ctx,
     int slice_start, slice_end;
 
     j = FFMAX(-yp, 0);
-    jmax = FFMIN(-yp + dst_hp, src_hp);
+    jmax = FFMIN3(-yp + dst_hp, FFMIN(src_hp, dst_hp), yp + src_hp);
 
-    slice_start = (jmax * jobnr) / nb_jobs;
-    slice_end = (jmax * (jobnr+1)) / nb_jobs;
+    slice_start = j + (jmax * jobnr) / nb_jobs;
+    slice_end = j + (jmax * (jobnr+1)) / nb_jobs;
 
-    sp = src->data[i] + slice_start * src->linesize[i];
+    sp = src->data[i] + (slice_start) * src->linesize[i];
     dp = dst->data[dst_plane]
                       + (yp + slice_start) * dst->linesize[dst_plane]
                       + dst_offset;
     ap = src->data[3] + (slice_start << vsub) * src->linesize[3];
     dap = dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3];
 
-    for (j = j + slice_start; j < slice_end; j++) {
+    for (j = slice_start; j < slice_end; j++) {
         k = FFMAX(-xp, 0);
         d = dp + (xp+k) * dst_step;
         s = sp + k;
         a = ap + (k<<hsub);
         da = dap + ((xp+k) << hsub);
+        kmax = FFMIN(-xp + dst_wp, src_wp);
+
+        if (((vsub && j+1 < src_hp) || !vsub) && octx->blend_row[i]) {
+            int c = octx->blend_row[i](d, da, s, a, kmax - k, src->linesize[3]);
 
-        for (kmax = FFMIN(-xp + dst_wp, src_wp); k < kmax; k++) {
+            s += c;
+            d += dst_step * c;
+            da += (1 << hsub) * c;
+            a += (1 << hsub) * c;
+            k += c;
+        }
+        for (; k < kmax; k++) {
             int alpha_v, alpha_h, alpha;
 
             // average alpha for color components, improve quality
@@ -611,7 +569,7 @@ static inline void alpha_composite(const AVFrame *src, const AVFrame *dst,
     sa = src->data[3] + (i + slice_start) * src->linesize[3];
     da = dst->data[3] + (y + i + slice_start) * dst->linesize[3];
 
-    for (i = i + slice_start; i < imax; i++) {
+    for (i = i + slice_start; i < slice_end; i++) {
         j = FFMAX(-x, 0);
         s = sa + j;
         d = da + x+j;
@@ -916,7 +874,7 @@ static int config_input_main(AVFilterLink *inlink)
     }
 
     if (!s->alpha_format)
-        return 0;
+        goto end;
 
     switch (s->format) {
     case OVERLAY_FORMAT_YUV420:
@@ -960,6 +918,12 @@ static int config_input_main(AVFilterLink *inlink)
         }
         break;
     }
+
+end:
+    if (ARCH_X86)
+        ff_overlay_init_x86(s, s->format, inlink->format,
+                            s->alpha_format, s->main_has_alpha);
+
     return 0;
 }
 
@@ -997,13 +961,13 @@ static int do_blend(FFFrameSync *fs)
                s->var_values[VAR_Y], s->y);
     }
 
-    if (s->x < mainpic->width  && s->x + second->width  >= 0 ||
+    if (s->x < mainpic->width  && s->x + second->width  >= 0 &&
         s->y < mainpic->height && s->y + second->height >= 0) {
         ThreadData td;
 
         td.dst = mainpic;
         td.src = second;
-        ctx->internal->execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMIN(mainpic->height - s->y, second->height),
+        ctx->internal->execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMAX(1, FFMIN3(s->y + second->height, FFMIN(second->height, mainpic->height), mainpic->height - s->y)),
                                                                      ff_filter_get_nb_threads(ctx)));
     }
     return ff_filter_frame(ctx->outputs[0], mainpic);