avfilter/vf_neighbor: rewrite without using temp memory
authorPaul B Mahol <onemda@gmail.com>
Tue, 1 May 2018 11:12:50 +0000 (13:12 +0200)
committerPaul B Mahol <onemda@gmail.com>
Tue, 1 May 2018 11:12:50 +0000 (13:12 +0200)
Signed-off-by: Paul B Mahol <onemda@gmail.com>
libavfilter/vf_neighbor.c

index de4a12f..bd69c9e 100644 (file)
@@ -34,7 +34,6 @@ typedef struct NContext {
     int nb_planes;
     int threshold[4];
     int coordinates;
-    uint8_t *buffer;
 
     void (*filter)(uint8_t *dst, const uint8_t *p1, int width,
                    int threshold, const uint8_t *coordinates[], int coord);
@@ -52,25 +51,6 @@ static int query_formats(AVFilterContext *ctx)
     return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
 }
 
-static av_cold void uninit(AVFilterContext *ctx)
-{
-    NContext *s = ctx->priv;
-
-    av_freep(&s->buffer);
-}
-
-static inline void line_copy8(uint8_t *line, const uint8_t *srcp, int width, int mergin)
-{
-    int i;
-
-    memcpy(line, srcp, width);
-
-    for (i = mergin; i > 0; i--) {
-        line[-i] = line[i];
-        line[width - 1 + i] = line[width - 1 - i];
-    }
-}
-
 static void erosion(uint8_t *dst, const uint8_t *p1, int width,
                     int threshold, const uint8_t *coordinates[], int coord)
 {
@@ -155,9 +135,6 @@ static int config_input(AVFilterLink *inlink)
     s->planeheight[0] = s->planeheight[3] = inlink->h;
 
     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
-    s->buffer = av_malloc(3 * (s->planewidth[0] + 32));
-    if (!s->buffer)
-        return AVERROR(ENOMEM);
 
     if (!strcmp(ctx->filter->name, "erosion"))
         s->filter = erosion;
@@ -190,32 +167,34 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         const int threshold = s->threshold[plane];
 
         if (threshold) {
+            const int stride = in->linesize[plane];
+            const int dstride = out->linesize[plane];
             const uint8_t *src = in->data[plane];
             uint8_t *dst = out->data[plane];
-            int stride = in->linesize[plane];
-            int height = s->planeheight[plane];
-            int width  = s->planewidth[plane];
-            uint8_t *p0 = s->buffer + 16;
-            uint8_t *p1 = p0 + s->planewidth[0];
-            uint8_t *p2 = p1 + s->planewidth[0];
-            uint8_t *orig = p0, *end = p2;
-
-            line_copy8(p0, src + stride, width, 1);
-            line_copy8(p1, src, width, 1);
+            const int height = s->planeheight[plane];
+            const int width  = s->planewidth[plane];
 
             for (y = 0; y < height; y++) {
-                const uint8_t *coordinates[] = { p0 - 1, p0, p0 + 1,
-                                                 p1 - 1,     p1 + 1,
-                                                 p2 - 1, p2, p2 + 1};
-                src += stride * (y < height - 1 ? 1 : -1);
-                line_copy8(p2, src, width, 1);
-
-                s->filter(dst, p1, width, threshold, coordinates, s->coordinates);
-
-                p0 = p1;
-                p1 = p2;
-                p2 = (p2 == end) ? orig: p2 + s->planewidth[0];
-                dst += out->linesize[plane];
+                const int nh = y > 0;
+                const int ph = y < height - 1;
+                const uint8_t *coordinates[] = { src - nh * stride, src + 1 - nh * stride, src + 2 - nh * stride,
+                                                 src,                                      src + 2,
+                                                 src + ph * stride, src + 1 + ph * stride, src + 2 + ph * stride};
+
+                const uint8_t *coordinateslb[] = { src - nh * stride, src - nh * stride, src + 1 - nh * stride,
+                                                   src,                                  src + 1,
+                                                   src + ph * stride, src + ph * stride, src + 1 + ph * stride};
+
+                const uint8_t *coordinatesrb[] = { src + width - 2 - nh * stride, src + width - 1 - nh * stride, src + width - 1 - nh * stride,
+                                                   src + width - 2,                                              src + width - 1,
+                                                   src + width - 2 + ph * stride, src + width - 1 + ph * stride, src + width - 1 + ph * stride};
+
+                s->filter(dst,             src,             1,         threshold, coordinateslb, s->coordinates);
+                s->filter(dst         + 1, src         + 1, width - 2, threshold, coordinates,   s->coordinates);
+                s->filter(dst + width - 1, src + width - 1, 1,         threshold, coordinatesrb, s->coordinates);
+
+                src += stride;
+                dst += dstride;
             }
         } else {
             av_image_copy_plane(out->data[plane], out->linesize[plane],
@@ -257,7 +236,6 @@ AVFilter ff_vf_##name_ = {                                   \
     .description   = NULL_IF_CONFIG_SMALL(description_),     \
     .priv_size     = sizeof(NContext),                       \
     .priv_class    = &name_##_class,                         \
-    .uninit        = uninit,                                 \
     .query_formats = query_formats,                          \
     .inputs        = neighbor_inputs,                        \
     .outputs       = neighbor_outputs,                       \