[FFmpeg-cvslog] avfilter/vf_xmedian: refactor slice function

Paul B Mahol git at videolan.org
Fri Feb 18 18:14:24 EET 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Fri Feb 18 16:00:55 2022 +0100| [cca6fe7fe0482d06391fb34858aa9e3d59b590b2] | committer: Paul B Mahol

avfilter/vf_xmedian: refactor slice function

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=cca6fe7fe0482d06391fb34858aa9e3d59b590b2
---

 libavfilter/vf_xmedian.c | 145 +++++++++++++++++++----------------------------
 1 file changed, 57 insertions(+), 88 deletions(-)

diff --git a/libavfilter/vf_xmedian.c b/libavfilter/vf_xmedian.c
index f9dc0f7ecf..28d8e6d4e9 100644
--- a/libavfilter/vf_xmedian.c
+++ b/libavfilter/vf_xmedian.c
@@ -45,7 +45,7 @@ typedef struct XMedianContext {
     int depth;
     int max;
     int nb_planes;
-    int linesize[4];
+    int linesizes[4];
     int width[4];
     int height[4];
 
@@ -107,101 +107,70 @@ typedef struct ThreadData {
     AVFrame **in, *out;
 } ThreadData;
 
-static int comparei(const void *p1, const void *p2)
+static int compare8(const void *p1, const void *p2)
 {
-    int left  = *(const int *)p1;
-    int right = *(const int *)p2;
+    int left  = *(const uint8_t *)p1;
+    int right = *(const uint8_t *)p2;
     return FFDIFFSIGN(left, right);
 }
 
-static int median_frames16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+static int compare16(const void *p1, const void *p2)
 {
-    XMedianContext *s = ctx->priv;
-    ThreadData *td = arg;
-    AVFrame **in = td->in;
-    AVFrame *out = td->out;
-    const int nb_inputs = s->nb_inputs;
-    const int radius = s->radius;
-    const int index = s->index;
-    int values[256];
-
-    for (int p = 0; p < s->nb_planes; p++) {
-        const int slice_start = (s->height[p] * jobnr) / nb_jobs;
-        const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
-        uint16_t *dst = (uint16_t *)(out->data[p] + slice_start * out->linesize[p]);
-
-        if (!((1 << p) & s->planes)) {
-            av_image_copy_plane((uint8_t *)dst, out->linesize[p],
-                                in[radius]->data[p] + slice_start * in[radius]->linesize[p],
-                                in[radius]->linesize[p],
-                                s->linesize[p], slice_end - slice_start);
-            continue;
-        }
-
-        for (int y = slice_start; y < slice_end; y++) {
-            for (int x = 0; x < s->width[p]; x++) {
-                for (int i = 0; i < nb_inputs; i++) {
-                    const uint16_t *src = (const uint16_t *)(in[i]->data[p] + y * in[i]->linesize[p]);
-                    values[i] = src[x];
-                }
-
-                AV_QSORT(values, nb_inputs, int, comparei);
-                if (nb_inputs & 1)
-                    dst[x] = values[index];
-                else
-                    dst[x] = (values[index] + values[index - 1]) >> 1;
-            }
-
-            dst += out->linesize[p] / 2;
-        }
-    }
-
-    return 0;
+    int left  = *(const uint16_t *)p1;
+    int right = *(const uint16_t *)p2;
+    return FFDIFFSIGN(left, right);
 }
 
-static int median_frames8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
-{
-    XMedianContext *s = ctx->priv;
-    ThreadData *td = arg;
-    AVFrame **in = td->in;
-    AVFrame *out = td->out;
-    const int nb_inputs = s->nb_inputs;
-    const int radius = s->radius;
-    const int index = s->index;
-    int values[256];
-
-    for (int p = 0; p < s->nb_planes; p++) {
-        const int slice_start = (s->height[p] * jobnr) / nb_jobs;
-        const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
-        uint8_t *dst = out->data[p] + slice_start * out->linesize[p];
-
-        if (!((1 << p) & s->planes)) {
-            av_image_copy_plane(dst, out->linesize[p],
-                                in[radius]->data[p] + slice_start * in[radius]->linesize[p],
-                                in[radius]->linesize[p],
-                                s->linesize[p], slice_end - slice_start);
-            continue;
-        }
-
-        for (int y = slice_start; y < slice_end; y++) {
-            for (int x = 0; x < s->width[p]; x++) {
-                for (int i = 0; i < nb_inputs; i++)
-                    values[i] = in[i]->data[p][y * in[i]->linesize[p] + x];
-
-                AV_QSORT(values, nb_inputs, int, comparei);
-                if (nb_inputs & 1)
-                    dst[x] = values[index];
-                else
-                    dst[x] = (values[index] + values[index - 1]) >> 1;
-            }
-
-            dst += out->linesize[p];
-        }
-    }
-
-    return 0;
+#define MEDIAN_SLICE(name, type, comparei)                                                      \
+static int median_frames ## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)       \
+{                                                                                               \
+    XMedianContext *s = ctx->priv;                                                              \
+    ThreadData *td = arg;                                                                       \
+    AVFrame **in = td->in;                                                                      \
+    AVFrame *out = td->out;                                                                     \
+    const int nb_inputs = s->nb_inputs;                                                         \
+    const int radius = s->radius;                                                               \
+    const int index = s->index;                                                                 \
+    type values[256];                                                                           \
+                                                                                                \
+    for (int p = 0; p < s->nb_planes; p++) {                                                    \
+        const int slice_start = (s->height[p] * jobnr) / nb_jobs;                               \
+        const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;                             \
+        type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]);                    \
+        ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type);                               \
+                                                                                                \
+        if (!((1 << p) & s->planes)) {                                                          \
+            av_image_copy_plane((uint8_t *)dst, out->linesize[p],                               \
+                                in[radius]->data[p] + slice_start * in[radius]->linesize[p],    \
+                                in[radius]->linesize[p],                                        \
+                                s->linesizes[p], slice_end - slice_start);                      \
+            continue;                                                                           \
+        }                                                                                       \
+                                                                                                \
+        for (int y = slice_start; y < slice_end; y++) {                                         \
+            for (int x = 0; x < s->width[p]; x++) {                                             \
+                for (int i = 0; i < nb_inputs; i++) {                                           \
+                    const type *src = (const type *)(in[i]->data[p] + y * in[i]->linesize[p]);  \
+                    values[i] = src[x];                                                         \
+                }                                                                               \
+                                                                                                \
+                AV_QSORT(values, nb_inputs, type, comparei);                                    \
+                if (nb_inputs & 1)                                                              \
+                    dst[x] = values[index];                                                     \
+                else                                                                            \
+                    dst[x] = (values[index] + values[index - 1]) >> 1;                          \
+            }                                                                                   \
+                                                                                                \
+            dst += dst_linesize;                                                                \
+        }                                                                                       \
+    }                                                                                           \
+                                                                                                \
+    return 0;                                                                                   \
 }
 
+MEDIAN_SLICE(8, uint8_t, compare8)
+MEDIAN_SLICE(16, uint16_t, compare16)
+
 static int process_frame(FFFrameSync *fs)
 {
     AVFilterContext *ctx = fs->parent;
@@ -267,7 +236,7 @@ static int config_output(AVFilterLink *outlink)
     else
         s->median_frames = median_frames16;
 
-    if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
+    if ((ret = av_image_fill_linesizes(s->linesizes, inlink->format, inlink->w)) < 0)
         return ret;
 
     s->width[1] = s->width[2] = AV_CEIL_RSHIFT(inlink->w, s->desc->log2_chroma_w);



More information about the ffmpeg-cvslog mailing list