1/* 2 * Copyright (c) 2016 Alexandra Hájková 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with FFmpeg; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 21#include <string.h> 22 23#include "libavutil/common.h" 24#include "libavutil/intreadwrite.h" 25#include "libavutil/mem.h" 26 27#include "libavcodec/lossless_videodsp.h" 28 29#include "checkasm.h" 30 31#define randomize_buffers(buf, size) \ 32 do { \ 33 int j; \ 34 uint8_t *tmp_buf = (uint8_t *)buf;\ 35 for (j = 0; j < size; j++) \ 36 tmp_buf[j] = rnd() & 0xFF; \ 37 } while (0) 38 39#define init_buffer(a0, a1, type, width)\ 40 if (!a0 || !a1)\ 41 fail();\ 42 randomize_buffers(a0, width * sizeof(type));\ 43 memcpy(a1, a0, width*sizeof(type));\ 44 45static void check_add_bytes(LLVidDSPContext c, int width) 46{ 47 uint8_t *dst0 = av_mallocz(width); 48 uint8_t *dst1 = av_mallocz(width); 49 uint8_t *src0 = av_calloc(width, sizeof(*src0)); 50 uint8_t *src1 = av_calloc(width, sizeof(*src1)); 51 declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w); 52 53 init_buffer(src0, src1, uint8_t, width); 54 55 if (!dst0 || !dst1) 56 fail(); 57 58 59 if (check_func(c.add_bytes, "add_bytes")) { 60 call_ref(dst0, src0, width); 61 call_new(dst1, src1, width); 62 if (memcmp(dst0, dst1, width)) 63 fail(); 64 bench_new(dst1, src1, width); 65 } 66 67 av_free(src0); 68 av_free(src1); 69 av_free(dst0); 70 av_free(dst1); 71} 72 73static void check_add_median_pred(LLVidDSPContext c, int width) { 74 int A0, A1, B0, B1; 75 uint8_t *dst0 = av_mallocz(width); 76 uint8_t *dst1 = av_mallocz(width); 77 uint8_t *src0 = av_calloc(width, sizeof(*src0)); 78 uint8_t *src1 = av_calloc(width, sizeof(*src1)); 79 uint8_t *diff0 = av_calloc(width, sizeof(*diff0)); 80 uint8_t *diff1 = av_calloc(width, sizeof(*diff1)); 81 declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src1, 82 const uint8_t *diff, ptrdiff_t w, 83 int *left, int *left_top); 84 85 init_buffer(src0, src1, uint8_t, width); 86 init_buffer(diff0, diff1, uint8_t, width); 87 88 A0 = rnd() & 0xFF; 89 B0 = rnd() & 0xFF; 90 A1 = A0; 91 B1 = B0; 92 93 94 if (check_func(c.add_median_pred, "add_median_pred")) { 95 call_ref(dst0, src0, diff0, width, &A0, &B0); 96 call_new(dst1, src1, diff1, width, &A1, &B1); 97 if (memcmp(dst0, dst1, width) || (A0 != A1) || (B0 != B1)) 98 fail(); 99 bench_new(dst1, src1, diff1, width, &A1, &B1); 100 } 101 102 av_free(src0); 103 av_free(src1); 104 av_free(diff0); 105 av_free(diff1); 106 av_free(dst0); 107 av_free(dst1); 108} 109 110static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const char * report) 111{ 112 int res0, res1; 113 uint8_t *dst0 = av_mallocz(width); 114 uint8_t *dst1 = av_mallocz(width); 115 uint8_t *src0 = av_calloc(width, sizeof(*src0)); 116 uint8_t *src1 = av_calloc(width, sizeof(*src1)); 117 declare_func_emms(AV_CPU_FLAG_MMX, int, uint8_t *dst, uint8_t *src, ptrdiff_t w, int acc); 118 119 init_buffer(src0, src1, uint8_t, width); 120 121 if (!dst0 || !dst1) 122 fail(); 123 124 if (check_func(c.add_left_pred, "%s", report)) { 125 res0 = call_ref(dst0, src0, width, acc); 126 res1 = call_new(dst1, src1, width, acc); 127 if ((res0 & 0xFF) != (res1 & 0xFF)||\ 128 memcmp(dst0, dst1, width)) 129 fail(); 130 bench_new(dst1, src1, width, acc); 131 } 132 133 av_free(src0); 134 av_free(src1); 135 av_free(dst0); 136 av_free(dst1); 137} 138 139static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, unsigned acc, const char * report) 140{ 141 int res0, res1; 142 uint16_t *dst0 = av_calloc(width, sizeof(*dst0)); 143 uint16_t *dst1 = av_calloc(width, sizeof(*dst1)); 144 uint16_t *src0 = av_calloc(width, sizeof(*src0)); 145 uint16_t *src1 = av_calloc(width, sizeof(*src1)); 146 declare_func_emms(AV_CPU_FLAG_MMX, int, uint16_t *dst, uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); 147 148 init_buffer(src0, src1, uint16_t, width); 149 150 if (!dst0 || !dst1) 151 fail(); 152 153 if (check_func(c.add_left_pred_int16, "%s", report)) { 154 res0 = call_ref(dst0, src0, mask, width, acc); 155 res1 = call_new(dst1, src1, mask, width, acc); 156 if ((res0 &0xFFFF) != (res1 &0xFFFF)||\ 157 memcmp(dst0, dst1, width)) 158 fail(); 159 bench_new(dst1, src1, mask, width, acc); 160 } 161 162 av_free(src0); 163 av_free(src1); 164 av_free(dst0); 165 av_free(dst1); 166} 167 168static void check_add_gradient_pred(LLVidDSPContext c, int w) { 169 int src_size, stride; 170 uint8_t *src0, *src1; 171 declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *src, const ptrdiff_t stride, 172 const ptrdiff_t width); 173 174 stride = w + 32; 175 src_size = (stride + 32) * 2; /* dsp need previous line, and ignore the start of the line */ 176 src0 = av_mallocz(src_size); 177 src1 = av_mallocz(src_size); 178 179 init_buffer(src0, src1, uint8_t, src_size); 180 181 if (check_func(c.add_gradient_pred, "add_gradient_pred")) { 182 call_ref(src0 + stride + 32, stride, w); 183 call_new(src1 + stride + 32, stride, w); 184 if (memcmp(src0, src1, stride)||/* previous line doesn't change */ 185 memcmp(src0+stride, src1 + stride, w + 32)) { 186 fail(); 187 } 188 bench_new(src1 + stride + 32, stride, w); 189 } 190 191 av_free(src0); 192 av_free(src1); 193} 194 195void checkasm_check_llviddsp(void) 196{ 197 LLVidDSPContext c; 198 int width = 16 * av_clip(rnd(), 16, 128); 199 int accRnd = rnd() & 0xFF; 200 201 ff_llviddsp_init(&c); 202 203 check_add_bytes(c, width); 204 report("add_bytes"); 205 206 check_add_median_pred(c, width); 207 report("add_median_pred"); 208 209 check_add_left_pred(c, width, 0, "add_left_pred_zero"); 210 report("add_left_pred_zero"); 211 212 check_add_left_pred(c, width, accRnd, "add_left_pred_rnd_acc"); 213 report("add_left_pred_rnd_acc"); 214 215 check_add_left_pred_16(c, 255, width, accRnd, "add_left_pred_int16"); 216 report("add_left_pred_int16"); 217 218 check_add_gradient_pred(c, width); 219 report("add_gradient_pred"); 220} 221