diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index d339b755a19eead254046d2d0e3484e4eba93685..8d3d03aa8c3b102ea3f9cbbcaa69bb558af53b93 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -11,6 +11,7 @@ AVCODECOBJS-$(CONFIG_VP8DSP) += vp8dsp.o AVCODECOBJS-$(CONFIG_DCA_DECODER) += dcadsp.o synth_filter.o AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_mc.o hevc_idct.o AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o +AVCODECOBJS-$(CONFIG_VP9_DECODER) += vp9dsp.o CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 34f49c0b3711c6d636c875f1f7703ab771f2f4bf..86d3bab30aaadc183bf67e0f10c3472e5f7f0b81 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -92,6 +92,9 @@ static const struct { #endif #if CONFIG_VP8DSP { "vp8dsp", checkasm_check_vp8dsp }, +#endif +#if CONFIG_VP9_DECODER + { "vp9dsp", checkasm_check_vp9dsp }, #endif { NULL } }; diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 73109c3afa2ca0545dd4014b4199eb393f021b4d..5e67b7d75a8df81a38dfc329bbd637e5b9455838 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -42,6 +42,7 @@ void checkasm_check_hevc_mc(void); void checkasm_check_synth_filter(void); void checkasm_check_v210enc(void); void checkasm_check_vp8dsp(void); +void checkasm_check_vp9dsp(void); void *checkasm_check_func(void *func, const char *name, ...) av_printf_format(2, 3); int checkasm_bench_func(void); diff --git a/tests/checkasm/vp9dsp.c b/tests/checkasm/vp9dsp.c new file mode 100644 index 0000000000000000000000000000000000000000..dd37077adf6f5272d9d0ff7ca49f86568c92f5e6 --- /dev/null +++ b/tests/checkasm/vp9dsp.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015 Ronald S. Bultje + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +#include "libavcodec/vp9.h" + +#include "checkasm.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; + +#define BIT_DEPTH 8 +#define SIZEOF_PIXEL ((BIT_DEPTH + 7) / 8) +#define DST_BUF_SIZE (size * size * SIZEOF_PIXEL) +#define SRC_BUF_STRIDE 72 +#define SRC_BUF_SIZE ((size + 7) * SRC_BUF_STRIDE * SIZEOF_PIXEL) +#define src (buf + 3 * SIZEOF_PIXEL * (SRC_BUF_STRIDE + 1)) + +#define randomize_buffers() \ + do { \ + uint32_t mask = pixel_mask[(BIT_DEPTH - 8) >> 1]; \ + int k; \ + for (k = 0; k < SRC_BUF_SIZE; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf + k, r); \ + } \ + if (op == 1) { \ + for (k = 0; k < DST_BUF_SIZE; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(dst0 + k, r); \ + AV_WN32A(dst1 + k, r); \ + } \ + } \ + } while (0) + +static void check_mc(void) +{ + static const char *const filter_names[4] = { + "8tap_smooth", "8tap_regular", "8tap_sharp", "bilin" + }; + static const char *const subpel_names[2][2] = { { "", "h" }, { "v", "hv" } }; + static const char *const op_names[2] = { "put", "avg" }; + + LOCAL_ALIGNED_32(uint8_t, buf, [72 * 72 * 2]); + LOCAL_ALIGNED_32(uint8_t, dst0, [64 * 64 * 2]); + LOCAL_ALIGNED_32(uint8_t, dst1, [64 * 64 * 2]); + char str[256]; + VP9DSPContext dsp; + int op, hsize, filter, dx, dy; + + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, + void, uint8_t *dst, const uint8_t *ref, + ptrdiff_t dst_stride, ptrdiff_t ref_stride, + int h, int mx, int my); + + for (op = 0; op < 2; op++) { + ff_vp9dsp_init(&dsp); + for (hsize = 0; hsize < 5; hsize++) { + int size = 64 >> hsize; + + for (filter = 0; filter < 4; filter++) { + for (dx = 0; dx < 2; dx++) { + for (dy = 0; dy < 2; dy++) { + if (dx || dy) { + snprintf(str, sizeof(str), "%s_%s_%d%s", op_names[op], + filter_names[filter], size, + subpel_names[dy][dx]); + } else { + snprintf(str, sizeof(str), "%s%d", op_names[op], size); + } + if (check_func(dsp.mc[hsize][filter][op][dx][dy], + "vp9_%s", str)) { + int mx = dx ? 1 + (rnd() % 14) : 0; + int my = dy ? 1 + (rnd() % 14) : 0; + randomize_buffers(); + call_ref(dst0, src, + size * SIZEOF_PIXEL, + SRC_BUF_STRIDE * SIZEOF_PIXEL, + size, mx, my); + call_new(dst1, src, + size * SIZEOF_PIXEL, + SRC_BUF_STRIDE * SIZEOF_PIXEL, + size, mx, my); + if (memcmp(dst0, dst1, DST_BUF_SIZE)) + fail(); + + // SIMD implementations for each filter of subpel + // functions are identical + if (filter >= 1 && filter <= 2) continue; + + bench_new(dst1, src, size * SIZEOF_PIXEL, + SRC_BUF_STRIDE * SIZEOF_PIXEL, + size, mx, my); + } + } + } + } + } + } + report("mc"); +} + +void checkasm_check_vp9dsp(void) +{ + check_mc(); +}