From 8201c51ced164efdcee292f71cc94d0a7ab38b18 Mon Sep 17 00:00:00 2001
From: Ulf Zibis <Ulf.Zibis@CoSoCo.de>
Date: 19.03.2019, 02:52:44

avfilter/fillborders: avoid needless calculations for performance; added ffmpeg-p2 and rgba64le-lzw.tif to benchmark

diff --git a/debug/fillborders.sh b/debug/fillborders.sh
index 671032b..1bd7e12 100755
--- a/debug/fillborders.sh
+++ b/debug/fillborders.sh
@@ -1,8 +1,9 @@
 #!/bin/bash
 i=0
-test[i++]="3-plane 8-bit YUV-colour:    CYD_1005.jpg"
-test[i++]="4-plane 8-bit RGB-colour:    8.jpg"
-test[i++]="4-plane 16-bit RGB-colour:   16.jpg"
+test[i++]="3-plane 8-bit  YUV-420:   CYD_1005.jpg"
+#test[i++]="1-plane 8-bit  Y-400:     8.jpg"
+#test[i++]="1-plane 16-bit Y-400:     16.jpg"
+#test[i++]="4-plane 16-bit RGB-444:   rgba64le-lzw.tif"
 
 for ((i=0;i<${#test[@]};i++))
 do
@@ -13,10 +14,10 @@
     for borders in "0:0:5:5" "5:5:0:0" "5:5:5:5"
     do
         output="ZZ_${input%.*}_${mode%:*}-${borders//:/-}.${input##*.}"
-        for patch in "ffmpeg     " "./ffmpeg-p1"
+        for patch in "./ffmpeg-p1" "./ffmpeg-p2"
         do
-            echo "${patch} ${input} --> ${output}"
-            for ((benchmark=0;benchmark<3;benchmark++))
+            echo "${patch} : ${input} --> ${output}"
+            for ((benchmark=0;benchmark<6;benchmark++))
             do
                  ${patch} -y -v error -i debug/${input} -vf fillborders=${borders}:${mode} debug/${output}
             done
diff --git a/libavfilter/vf_fillborders.c b/libavfilter/vf_fillborders.c
index e06b8e8..15cf5d9 100644
--- a/libavfilter/vf_fillborders.c
+++ b/libavfilter/vf_fillborders.c
@@ -93,14 +93,16 @@
         int linesize = frame->linesize[p];
 
         /* fill left and right borders from top to bottom border */
-        for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
-            memset(data + y * linesize,
-                    *(data + y * linesize + s->borders[p].left),
-                    s->borders[p].left);
-            memset(data + y * linesize + s->planewidth[p] - s->borders[p].right,
-                    *(data + y * linesize + s->planewidth[p] - s->borders[p].right - 1),
-                    s->borders[p].right);
-        }
+        if (s->borders[p].left != 0 ||
+                s->borders[p].right != s->planewidth[p]) // in case skip for performance
+            for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
+                memset(data + y * linesize,
+                        *(data + y * linesize + s->borders[p].left),
+                        s->borders[p].left);
+                memset(data + y * linesize + s->planewidth[p] - s->borders[p].right,
+                        *(data + y * linesize + s->planewidth[p] - s->borders[p].right - 1),
+                        s->borders[p].right);
+            }
 
         /* fill top and bottom borders */
         for (y = 0; y < s->borders[p].top; y++) {
@@ -124,15 +126,17 @@
         int linesize = frame->linesize[p] / sizeof(uint16_t);
 
         /* fill left and right borders from top to bottom border */
-        for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
-            for (x = 0; x < s->borders[p].left; x++) {
-                data[y * linesize + x] = *(data + y * linesize + s->borders[p].left);
+        if (s->borders[p].left != 0 ||
+                s->borders[p].right != s->planewidth[p]) // in case skip for performance
+            for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
+                for (x = 0; x < s->borders[p].left; x++) {
+                    data[y * linesize + x] = *(data + y * linesize + s->borders[p].left);
+                }
+                for (x = 0; x < s->borders[p].right; x++) {
+                    data[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
+                            *(data + y * linesize + s->planewidth[p] - s->borders[p].right - 1);
+                }
             }
-            for (x = 0; x < s->borders[p].right; x++) {
-                data[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
-                    *(data + y * linesize + s->planewidth[p] - s->borders[p].right - 1);
-            }
-        }
 
         /* fill top and bottom borders */
         for (y = 0; y < s->borders[p].top; y++) {
@@ -156,15 +160,17 @@
         int linesize = frame->linesize[p];
 
         /* fill left and right borders from top to bottom border */
-        for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
-            for (x = 0; x < s->borders[p].left; x++) {
-                data[y * linesize + x] = data[y * linesize + s->borders[p].left * 2 - 1 - x];
+        if (s->borders[p].left != 0 ||
+                s->borders[p].right != s->planewidth[p]) // in case skip for performance
+            for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
+                for (x = 0; x < s->borders[p].left; x++) {
+                    data[y * linesize + x] = data[y * linesize + s->borders[p].left * 2 - 1 - x];
+                }
+                for (x = 0; x < s->borders[p].right; x++) {
+                    data[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
+                            data[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
+                }
             }
-            for (x = 0; x < s->borders[p].right; x++) {
-                data[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
-                    data[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
-            }
-        }
 
         /* fill top and bottom borders */
         for (y = 0; y < s->borders[p].top; y++) {
@@ -189,16 +195,18 @@
         int linesize = frame->linesize[p] / sizeof(uint16_t);
 
         /* fill left and right borders from top to bottom border */
-        for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
-            for (x = 0; x < s->borders[p].left; x++) {
-                data[y * linesize + x] = data[y * linesize + s->borders[p].left * 2 - 1 - x];
-            }
+        if (s->borders[p].left != 0 ||
+                s->borders[p].right != s->planewidth[p]) // in case skip for performance
+            for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
+                for (x = 0; x < s->borders[p].left; x++) {
+                    data[y * linesize + x] = data[y * linesize + s->borders[p].left * 2 - 1 - x];
+                }
 
-            for (x = 0; x < s->borders[p].right; x++) {
-                data[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
-                    data[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
+                for (x = 0; x < s->borders[p].right; x++) {
+                    data[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
+                            data[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
+                }
             }
-        }
 
         /* fill top and bottom borders */
         for (y = 0; y < s->borders[p].top; y++) {
@@ -224,11 +232,13 @@
         int linesize = frame->linesize[p];
 
         /* fill left and right borders from top to bottom border */
-        for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
-            memset(data + y * linesize, fill, s->borders[p].left);
-            memset(data + y * linesize + s->planewidth[p] - s->borders[p].right, fill,
-                    s->borders[p].right);
-        }
+        if (s->borders[p].left != 0 ||
+                s->borders[p].right != s->planewidth[p]) // in case skip for performance
+            for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
+                memset(data + y * linesize, fill, s->borders[p].left);
+                memset(data + y * linesize + s->planewidth[p] - s->borders[p].right, fill,
+                        s->borders[p].right);
+            }
 
         /* fill top and bottom borders */
         for (y = 0; y < s->borders[p].top; y++) {
@@ -250,14 +260,16 @@
         int linesize = frame->linesize[p] / sizeof(uint16_t);
 
         /* fill left and right borders from top to bottom border */
-        for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
-            for (x = 0; x < s->borders[p].left; x++) {
-                data[y * linesize + x] = fill;
+        if (s->borders[p].left != 0 ||
+                s->borders[p].right != s->planewidth[p]) // in case skip for performance
+            for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
+                for (x = 0; x < s->borders[p].left; x++) {
+                    data[y * linesize + x] = fill;
+                }
+                for (x = 0; x < s->borders[p].right; x++) {
+                    data[y * linesize + s->planewidth[p] - s->borders[p].right + x] = fill;
+                }
             }
-            for (x = 0; x < s->borders[p].right; x++) {
-                data[y * linesize + s->planewidth[p] - s->borders[p].right + x] = fill;
-            }
-        }
 
         /* fill top and bottom borders */
         for (y = 0; y < s->borders[p].top; y++) {
@@ -303,6 +315,20 @@
     FillBordersContext *s = ctx->priv;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
 
+    if (inlink->w < s->left + s->right ||
+            inlink->w <= s->left ||
+            inlink->w <= s->right ||
+            inlink->h < s->top + s->bottom ||
+            inlink->h <= s->top ||
+            inlink->h <= s->bottom ||
+            inlink->w < s->left * 2 ||
+            inlink->w < s->right * 2 ||
+            inlink->h < s->top * 2 ||
+            inlink->h < s->bottom * 2) {
+        av_log(ctx, AV_LOG_ERROR, "Borders are bigger than input frame size.\n");
+        return AVERROR(EINVAL);
+    }
+
     s->nb_planes = desc->nb_components;
     s->depth = desc->comp[0].depth;
 
@@ -326,40 +352,23 @@
     s->borders[2].top    = s->top >> desc->log2_chroma_h;
     s->borders[2].bottom = s->bottom >> desc->log2_chroma_h;
 
-    if (inlink->w < s->left + s->right ||
-            inlink->w <= s->left ||
-            inlink->w <= s->right ||
-            inlink->h < s->top + s->bottom ||
-            inlink->h <= s->top ||
-            inlink->h <= s->bottom ||
-            inlink->w < s->left * 2 ||
-            inlink->w < s->right * 2 ||
-            inlink->h < s->top * 2 ||
-            inlink->h < s->bottom * 2) {
-        av_log(ctx, AV_LOG_ERROR, "Borders are bigger than input frame size.\n");
-        return AVERROR(EINVAL);
-    }
-
     switch (s->mode) {
         case FM_SMEAR:  s->fillborders = s->depth <= 8 ? smear_borders8  : smear_borders16;  break;
         case FM_MIRROR: s->fillborders = s->depth <= 8 ? mirror_borders8 : mirror_borders16; break;
-        case FM_FIXED:  s->fillborders = s->depth <= 8 ? fixed_borders8  : fixed_borders16;  break;
-    }
-
-    s->yuv_color[Y] = RGB_TO_Y_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B]);
-    s->yuv_color[U] = RGB_TO_U_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
-    s->yuv_color[V] = RGB_TO_V_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
-    s->yuv_color[A] = s->rgba_color[A];
-
-    if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
-        uint8_t rgba_map[4];
-        int i;
-
-        ff_fill_rgba_map(rgba_map, inlink->format);
-        for (i = 0; i < sizeof(rgba_map); i++)
-            s->fill[rgba_map[i]] = s->rgba_color[i];
-    } else {
-        memcpy(s->fill, s->yuv_color, sizeof(s->yuv_color));
+        case FM_FIXED:  s->fillborders = s->depth <= 8 ? fixed_borders8  : fixed_borders16;
+            if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
+                uint8_t rgba_map[4];
+                int i;
+                ff_fill_rgba_map(rgba_map, inlink->format);
+                for (i = 0; i < sizeof(rgba_map); i++)
+                    s->fill[rgba_map[i]] = s->rgba_color[i];
+            } else {
+                s->yuv_color[Y] = RGB_TO_Y_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B]);
+                s->yuv_color[U] = RGB_TO_U_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
+                s->yuv_color[V] = RGB_TO_V_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
+                s->yuv_color[A] = s->rgba_color[A];
+                memcpy(s->fill, s->yuv_color, sizeof(s->yuv_color));
+            } break;
     }
 
     return 0;
