[vlc-devel] [PATCH 18/25] deinterlace: add tests for SIMD optimized implementations
Victorien Le Couviour--Tuffet
victorien.lecouviour.tuffet at gmail.com
Tue Apr 14 12:40:29 CEST 2020
---
test/Makefile.am | 6 +
test/modules/video_filter/deinterlace.c | 187 ++++++++++++++++++++++++
2 files changed, 193 insertions(+)
create mode 100644 test/modules/video_filter/deinterlace.c
diff --git a/test/Makefile.am b/test/Makefile.am
index eafe46f5e1..94c8ba495b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -47,6 +47,7 @@ check_PROGRAMS = \
test_modules_demux_dashuri \
test_modules_demux_timestamps_filter \
test_modules_demux_ts_pes \
+ test_modules_vfilter_deinterlace_simd \
$(NULL)
if ENABLE_SOUT
@@ -171,6 +172,11 @@ test_modules_demux_ts_pes_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_modules_demux_ts_pes_SOURCES = modules/demux/ts_pes.c \
../modules/demux/mpeg/ts_pes.c \
../modules/demux/mpeg/ts_pes.h
+test_modules_vfilter_deinterlace_simd_SOURCES = \
+ modules/video_filter/deinterlace.c \
+ $(top_srcdir)/modules/video_filter/deinterlace/algo_basic.c \
+ $(top_srcdir)/modules/video_filter/deinterlace/merge.c
+test_modules_vfilter_deinterlace_simd_LDADD = $(LIBVLCCORE)
test_bench_asm_SOURCES = bench_asm/main.c \
bench_asm/startcode_annexb.c \
diff --git a/test/modules/video_filter/deinterlace.c b/test/modules/video_filter/deinterlace.c
new file mode 100644
index 0000000000..65a00d3ad0
--- /dev/null
+++ b/test/modules/video_filter/deinterlace.c
@@ -0,0 +1,187 @@
+/*****************************************************************************
+ * deinterlace.c : tests for the SIMD optimized deinterlacers
+ *****************************************************************************
+ * Copyright (C) 2019 VideoLAN
+ *
+ * Author: Victorien Le Couviour--Tuffet victorien at videolan.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <vlc_common.h>
+#include <vlc_cpu.h>
+#include <vlc_picture.h>
+#include "../../modules/video_filter/deinterlace/deinterlace.h"
+
+static struct cpu_feature
+{
+ char const *name;
+ int flag;
+} const cpu_features[] =
+{
+#if defined(__i386__) || defined(__x86_64__)
+ { "SSE2", VLC_CPU_SSE2 },
+ { "SSSE3", VLC_CPU_SSSE3 },
+#endif
+#ifdef __x86_64__
+ { "AVX2", VLC_CPU_AVX2 },
+#endif
+ { 0 }
+};
+
+static inline void
+setup_iovfmt(video_format_t *ifmt, video_format_t *ofmt,
+ bool half_height, int bpc)
+{
+ vlc_fourcc_t chroma = bpc == 8 ? VLC_CODEC_I420 : VLC_CODEC_I420_10L;
+ unsigned w = rand() % (128 - 1 + 1) + 1;
+ unsigned h = rand() % (128 - 4 + 1) + 4;
+ video_format_Setup(ifmt, chroma, w, h, w, h, w, h);
+ *ofmt = *ifmt;
+ if (half_height)
+ {
+ ofmt->i_height /= 2;
+ ofmt->i_visible_height /= 2;
+ ofmt->i_y_offset /= 2;
+ ofmt->i_sar_den /= 2;
+ }
+}
+
+static inline picture_t *
+create_picture(video_format_t *fmt, bool initialize)
+{
+ picture_t *pic = picture_NewFromFormat(fmt);
+ if (!pic)
+ return NULL;
+
+ for (int plane = 0; plane < pic->i_planes; ++plane)
+ for (int i = 0; i < pic->p[plane].i_lines; ++i)
+ {
+ ptrdiff_t const stride = pic->p[plane].i_pitch;
+ for (int j = 0; j < stride; j += sizeof(int))
+ {
+ int *ptr = (int *)(pic->p[plane].p_pixels + i * stride + j);
+ *ptr = 0xDEADBEEF;
+ }
+ if (initialize && i < pic->p[plane].i_visible_lines)
+ for (int j = 0; j < pic->p[plane].i_visible_pitch; ++j)
+ pic->p[plane].p_pixels[i * stride + j] = rand() % 256;
+ }
+ return pic;
+}
+
+static int
+init_deinterlacer(picture_t **srcpic_ptr,
+ picture_t **cdstpic_ptr, picture_t **adstpic_ptr,
+ bool half_height, int bpc)
+{
+ video_format_t in_fmt, out_fmt;
+ setup_iovfmt(&in_fmt, &out_fmt, half_height, bpc);
+ *srcpic_ptr = create_picture(&in_fmt, true);
+ if (*srcpic_ptr == NULL) goto error;
+ *cdstpic_ptr = create_picture(&out_fmt, false);
+ if (*cdstpic_ptr == NULL) goto error;
+ *adstpic_ptr = create_picture(&out_fmt, false);
+ if (*adstpic_ptr == NULL) goto error;
+ return VLC_SUCCESS;
+error:
+ if (*cdstpic_ptr)
+ picture_Release(*cdstpic_ptr);
+ if (*srcpic_ptr)
+ picture_Release(*srcpic_ptr);
+ return VLC_EGENERIC;
+}
+
+static void
+destroy_deinterlacer(picture_t *srcpic, picture_t *cdstpic, picture_t *adstpic)
+{
+ picture_Release(srcpic);
+ picture_Release(cdstpic);
+ picture_Release(adstpic);
+}
+
+int main(void)
+{
+ int ret = 0;
+ srand(time(NULL));
+
+#define TEST_DEINTERLACER(type, mode, Mode, half_height, bpc, ...) \
+ puts("deinterlace " #mode " " #bpc "-bit:"); \
+ vlc_CPU_mask(~0); \
+ type##_renderer_t render_##mode##bpc##_cref = Mode##Renderer(bpc / 8); \
+ assert(render_##mode##bpc##_cref); \
+ for (struct cpu_feature const *feature = cpu_features; \
+ feature->name; ++feature) \
+ { \
+ vlc_CPU_unmask(feature->flag); \
+ type##_renderer_t render_##mode##bpc##_simd = Mode##Renderer(bpc / 8);\
+ vlc_CPU_mask(feature->flag); \
+ int has_impl = render_##mode##bpc##_simd != Mode##Renderer(bpc / 8);\
+ vlc_CPU_unmask(feature->flag); \
+ if (!has_impl) \
+ continue; \
+ \
+ printf(" - %-5s : ", feature->name); \
+ bool fail = false; \
+ for (int i = 0; i < 256; ++i) \
+ { \
+ picture_t *src; \
+ picture_t *cdst; \
+ picture_t *adst; \
+ if (init_deinterlacer(&src, &cdst, &adst, half_height, bpc)) \
+ { \
+ puts("CANNOT EXECUTE"); \
+ break; \
+ } \
+ \
+ render_##mode##bpc##_cref(NULL, cdst, src, ##__VA_ARGS__); \
+ render_##mode##bpc##_simd(NULL, adst, src, ##__VA_ARGS__); \
+ \
+ for (int plane = 0; !fail && plane < cdst->i_planes; ++plane) \
+ { \
+ size_t plane_size = \
+ cdst->p[plane].i_lines * cdst->p[plane].i_pitch; \
+ if (memcmp(cdst->p[plane].p_pixels, \
+ adst->p[plane].p_pixels, plane_size)) \
+ fail = true; \
+ } \
+ \
+ destroy_deinterlacer(src, cdst, adst); \
+ if (fail) \
+ { \
+ ret = 1; \
+ break; \
+ } \
+ } \
+ printf("%s\n", !fail ? "OK" : "KO"); \
+ }
+
+ TEST_DEINTERLACER(ordered, linear, Linear, false, 8, 0, i & 1)
+ TEST_DEINTERLACER(ordered, linear, Linear, false, 16, 0, i & 1)
+ TEST_DEINTERLACER(single_pic, mean, Mean, true, 8)
+ TEST_DEINTERLACER(single_pic, mean, Mean, true, 16)
+ TEST_DEINTERLACER(single_pic, blend, Blend, false, 8)
+ TEST_DEINTERLACER(single_pic, blend, Blend, false, 16)
+
+ return ret;
+}
--
2.24.1
More information about the vlc-devel
mailing list