annotate ffmpeg/libswscale/swscale-test.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Copyright (C) 2003-2011 Michael Niedermayer <michaelni@gmx.at>
yading@11 3 *
yading@11 4 * This file is part of FFmpeg.
yading@11 5 *
yading@11 6 * FFmpeg is free software; you can redistribute it and/or
yading@11 7 * modify it under the terms of the GNU Lesser General Public
yading@11 8 * License as published by the Free Software Foundation; either
yading@11 9 * version 2.1 of the License, or (at your option) any later version.
yading@11 10 *
yading@11 11 * FFmpeg is distributed in the hope that it will be useful,
yading@11 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 14 * Lesser General Public License for more details.
yading@11 15 *
yading@11 16 * You should have received a copy of the GNU Lesser General Public
yading@11 17 * License along with FFmpeg; if not, write to the Free Software
yading@11 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 19 */
yading@11 20
yading@11 21 #include <stdio.h>
yading@11 22 #include <stdlib.h>
yading@11 23 #include <string.h>
yading@11 24 #include <inttypes.h>
yading@11 25 #include <stdarg.h>
yading@11 26
yading@11 27 #undef HAVE_AV_CONFIG_H
yading@11 28 #include "libavutil/imgutils.h"
yading@11 29 #include "libavutil/mem.h"
yading@11 30 #include "libavutil/avutil.h"
yading@11 31 #include "libavutil/crc.h"
yading@11 32 #include "libavutil/pixdesc.h"
yading@11 33 #include "libavutil/lfg.h"
yading@11 34 #include "swscale.h"
yading@11 35
yading@11 36 /* HACK Duplicated from swscale_internal.h.
yading@11 37 * Should be removed when a cleaner pixel format system exists. */
yading@11 38 #define isGray(x) \
yading@11 39 ((x) == AV_PIX_FMT_GRAY8 || \
yading@11 40 (x) == AV_PIX_FMT_Y400A || \
yading@11 41 (x) == AV_PIX_FMT_GRAY16BE || \
yading@11 42 (x) == AV_PIX_FMT_GRAY16LE)
yading@11 43 #define hasChroma(x) \
yading@11 44 (!(isGray(x) || \
yading@11 45 (x) == AV_PIX_FMT_MONOBLACK || \
yading@11 46 (x) == AV_PIX_FMT_MONOWHITE))
yading@11 47 #define isALPHA(x) \
yading@11 48 ((x) == AV_PIX_FMT_BGR32 || \
yading@11 49 (x) == AV_PIX_FMT_BGR32_1 || \
yading@11 50 (x) == AV_PIX_FMT_RGB32 || \
yading@11 51 (x) == AV_PIX_FMT_RGB32_1 || \
yading@11 52 (x) == AV_PIX_FMT_YUVA420P)
yading@11 53
yading@11 54 static uint64_t getSSD(const uint8_t *src1, const uint8_t *src2, int stride1,
yading@11 55 int stride2, int w, int h)
yading@11 56 {
yading@11 57 int x, y;
yading@11 58 uint64_t ssd = 0;
yading@11 59
yading@11 60 for (y = 0; y < h; y++) {
yading@11 61 for (x = 0; x < w; x++) {
yading@11 62 int d = src1[x + y * stride1] - src2[x + y * stride2];
yading@11 63 ssd += d * d;
yading@11 64 }
yading@11 65 }
yading@11 66 return ssd;
yading@11 67 }
yading@11 68
yading@11 69 struct Results {
yading@11 70 uint64_t ssdY;
yading@11 71 uint64_t ssdU;
yading@11 72 uint64_t ssdV;
yading@11 73 uint64_t ssdA;
yading@11 74 uint32_t crc;
yading@11 75 };
yading@11 76
yading@11 77 // test by ref -> src -> dst -> out & compare out against ref
yading@11 78 // ref & out are YV12
yading@11 79 static int doTest(uint8_t *ref[4], int refStride[4], int w, int h,
yading@11 80 enum AVPixelFormat srcFormat, enum AVPixelFormat dstFormat,
yading@11 81 int srcW, int srcH, int dstW, int dstH, int flags,
yading@11 82 struct Results *r)
yading@11 83 {
yading@11 84 const AVPixFmtDescriptor *desc_yuva420p = av_pix_fmt_desc_get(AV_PIX_FMT_YUVA420P);
yading@11 85 const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat);
yading@11 86 const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat);
yading@11 87 static enum AVPixelFormat cur_srcFormat;
yading@11 88 static int cur_srcW, cur_srcH;
yading@11 89 static uint8_t *src[4];
yading@11 90 static int srcStride[4];
yading@11 91 uint8_t *dst[4] = { 0 };
yading@11 92 uint8_t *out[4] = { 0 };
yading@11 93 int dstStride[4] = {0};
yading@11 94 int i;
yading@11 95 uint64_t ssdY, ssdU = 0, ssdV = 0, ssdA = 0;
yading@11 96 struct SwsContext *dstContext = NULL, *outContext = NULL;
yading@11 97 uint32_t crc = 0;
yading@11 98 int res = 0;
yading@11 99
yading@11 100 if (cur_srcFormat != srcFormat || cur_srcW != srcW || cur_srcH != srcH) {
yading@11 101 struct SwsContext *srcContext = NULL;
yading@11 102 int p;
yading@11 103
yading@11 104 for (p = 0; p < 4; p++)
yading@11 105 av_freep(&src[p]);
yading@11 106
yading@11 107 av_image_fill_linesizes(srcStride, srcFormat, srcW);
yading@11 108 for (p = 0; p < 4; p++) {
yading@11 109 srcStride[p] = FFALIGN(srcStride[p], 16);
yading@11 110 if (srcStride[p])
yading@11 111 src[p] = av_mallocz(srcStride[p] * srcH + 16);
yading@11 112 if (srcStride[p] && !src[p]) {
yading@11 113 perror("Malloc");
yading@11 114 res = -1;
yading@11 115 goto end;
yading@11 116 }
yading@11 117 }
yading@11 118 srcContext = sws_getContext(w, h, AV_PIX_FMT_YUVA420P, srcW, srcH,
yading@11 119 srcFormat, SWS_BILINEAR, NULL, NULL, NULL);
yading@11 120 if (!srcContext) {
yading@11 121 fprintf(stderr, "Failed to get %s ---> %s\n",
yading@11 122 desc_yuva420p->name,
yading@11 123 desc_src->name);
yading@11 124 res = -1;
yading@11 125 goto end;
yading@11 126 }
yading@11 127 sws_scale(srcContext, (const uint8_t * const*)ref, refStride, 0, h, src, srcStride);
yading@11 128 sws_freeContext(srcContext);
yading@11 129
yading@11 130 cur_srcFormat = srcFormat;
yading@11 131 cur_srcW = srcW;
yading@11 132 cur_srcH = srcH;
yading@11 133 }
yading@11 134
yading@11 135 av_image_fill_linesizes(dstStride, dstFormat, dstW);
yading@11 136 for (i = 0; i < 4; i++) {
yading@11 137 /* Image buffers passed into libswscale can be allocated any way you
yading@11 138 * prefer, as long as they're aligned enough for the architecture, and
yading@11 139 * they're freed appropriately (such as using av_free for buffers
yading@11 140 * allocated with av_malloc). */
yading@11 141 /* An extra 16 bytes is being allocated because some scalers may write
yading@11 142 * out of bounds. */
yading@11 143 dstStride[i] = FFALIGN(dstStride[i], 16);
yading@11 144 if (dstStride[i])
yading@11 145 dst[i] = av_mallocz(dstStride[i] * dstH + 16);
yading@11 146 if (dstStride[i] && !dst[i]) {
yading@11 147 perror("Malloc");
yading@11 148 res = -1;
yading@11 149
yading@11 150 goto end;
yading@11 151 }
yading@11 152 }
yading@11 153
yading@11 154 dstContext = sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat,
yading@11 155 flags, NULL, NULL, NULL);
yading@11 156 if (!dstContext) {
yading@11 157 fprintf(stderr, "Failed to get %s ---> %s\n",
yading@11 158 desc_src->name, desc_dst->name);
yading@11 159 res = -1;
yading@11 160 goto end;
yading@11 161 }
yading@11 162
yading@11 163 printf(" %s %dx%d -> %s %3dx%3d flags=%2d",
yading@11 164 desc_src->name, srcW, srcH,
yading@11 165 desc_dst->name, dstW, dstH,
yading@11 166 flags);
yading@11 167 fflush(stdout);
yading@11 168
yading@11 169 sws_scale(dstContext, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride);
yading@11 170
yading@11 171 for (i = 0; i < 4 && dstStride[i]; i++)
yading@11 172 crc = av_crc(av_crc_get_table(AV_CRC_32_IEEE), crc, dst[i],
yading@11 173 dstStride[i] * dstH);
yading@11 174
yading@11 175 if (r && crc == r->crc) {
yading@11 176 ssdY = r->ssdY;
yading@11 177 ssdU = r->ssdU;
yading@11 178 ssdV = r->ssdV;
yading@11 179 ssdA = r->ssdA;
yading@11 180 } else {
yading@11 181 for (i = 0; i < 4; i++) {
yading@11 182 refStride[i] = FFALIGN(refStride[i], 16);
yading@11 183 if (refStride[i])
yading@11 184 out[i] = av_mallocz(refStride[i] * h);
yading@11 185 if (refStride[i] && !out[i]) {
yading@11 186 perror("Malloc");
yading@11 187 res = -1;
yading@11 188 goto end;
yading@11 189 }
yading@11 190 }
yading@11 191 outContext = sws_getContext(dstW, dstH, dstFormat, w, h,
yading@11 192 AV_PIX_FMT_YUVA420P, SWS_BILINEAR,
yading@11 193 NULL, NULL, NULL);
yading@11 194 if (!outContext) {
yading@11 195 fprintf(stderr, "Failed to get %s ---> %s\n",
yading@11 196 desc_dst->name,
yading@11 197 desc_yuva420p->name);
yading@11 198 res = -1;
yading@11 199 goto end;
yading@11 200 }
yading@11 201 sws_scale(outContext, (const uint8_t * const*)dst, dstStride, 0, dstH, out, refStride);
yading@11 202
yading@11 203 ssdY = getSSD(ref[0], out[0], refStride[0], refStride[0], w, h);
yading@11 204 if (hasChroma(srcFormat) && hasChroma(dstFormat)) {
yading@11 205 //FIXME check that output is really gray
yading@11 206 ssdU = getSSD(ref[1], out[1], refStride[1], refStride[1],
yading@11 207 (w + 1) >> 1, (h + 1) >> 1);
yading@11 208 ssdV = getSSD(ref[2], out[2], refStride[2], refStride[2],
yading@11 209 (w + 1) >> 1, (h + 1) >> 1);
yading@11 210 }
yading@11 211 if (isALPHA(srcFormat) && isALPHA(dstFormat))
yading@11 212 ssdA = getSSD(ref[3], out[3], refStride[3], refStride[3], w, h);
yading@11 213
yading@11 214 ssdY /= w * h;
yading@11 215 ssdU /= w * h / 4;
yading@11 216 ssdV /= w * h / 4;
yading@11 217 ssdA /= w * h;
yading@11 218
yading@11 219 sws_freeContext(outContext);
yading@11 220
yading@11 221 for (i = 0; i < 4; i++)
yading@11 222 if (refStride[i])
yading@11 223 av_free(out[i]);
yading@11 224 }
yading@11 225
yading@11 226 printf(" CRC=%08x SSD=%5"PRId64 ",%5"PRId64 ",%5"PRId64 ",%5"PRId64 "\n",
yading@11 227 crc, ssdY, ssdU, ssdV, ssdA);
yading@11 228
yading@11 229 end:
yading@11 230 sws_freeContext(dstContext);
yading@11 231
yading@11 232 for (i = 0; i < 4; i++)
yading@11 233 if (dstStride[i])
yading@11 234 av_free(dst[i]);
yading@11 235
yading@11 236 return res;
yading@11 237 }
yading@11 238
yading@11 239 static void selfTest(uint8_t *ref[4], int refStride[4], int w, int h,
yading@11 240 enum AVPixelFormat srcFormat_in,
yading@11 241 enum AVPixelFormat dstFormat_in)
yading@11 242 {
yading@11 243 const int flags[] = { SWS_FAST_BILINEAR, SWS_BILINEAR, SWS_BICUBIC,
yading@11 244 SWS_X, SWS_POINT, SWS_AREA, 0 };
yading@11 245 const int srcW = w;
yading@11 246 const int srcH = h;
yading@11 247 const int dstW[] = { srcW - srcW / 3, srcW, srcW + srcW / 3, 0 };
yading@11 248 const int dstH[] = { srcH - srcH / 3, srcH, srcH + srcH / 3, 0 };
yading@11 249 enum AVPixelFormat srcFormat, dstFormat;
yading@11 250 const AVPixFmtDescriptor *desc_src, *desc_dst;
yading@11 251
yading@11 252 for (srcFormat = srcFormat_in != AV_PIX_FMT_NONE ? srcFormat_in : 0;
yading@11 253 srcFormat < AV_PIX_FMT_NB; srcFormat++) {
yading@11 254 if (!sws_isSupportedInput(srcFormat) ||
yading@11 255 !sws_isSupportedOutput(srcFormat))
yading@11 256 continue;
yading@11 257
yading@11 258 desc_src = av_pix_fmt_desc_get(srcFormat);
yading@11 259
yading@11 260 for (dstFormat = dstFormat_in != AV_PIX_FMT_NONE ? dstFormat_in : 0;
yading@11 261 dstFormat < AV_PIX_FMT_NB; dstFormat++) {
yading@11 262 int i, j, k;
yading@11 263 int res = 0;
yading@11 264
yading@11 265 if (!sws_isSupportedInput(dstFormat) ||
yading@11 266 !sws_isSupportedOutput(dstFormat))
yading@11 267 continue;
yading@11 268
yading@11 269 desc_dst = av_pix_fmt_desc_get(dstFormat);
yading@11 270
yading@11 271 printf("%s -> %s\n", desc_src->name, desc_dst->name);
yading@11 272 fflush(stdout);
yading@11 273
yading@11 274 for (k = 0; flags[k] && !res; k++)
yading@11 275 for (i = 0; dstW[i] && !res; i++)
yading@11 276 for (j = 0; dstH[j] && !res; j++)
yading@11 277 res = doTest(ref, refStride, w, h,
yading@11 278 srcFormat, dstFormat,
yading@11 279 srcW, srcH, dstW[i], dstH[j], flags[k],
yading@11 280 NULL);
yading@11 281 if (dstFormat_in != AV_PIX_FMT_NONE)
yading@11 282 break;
yading@11 283 }
yading@11 284 if (srcFormat_in != AV_PIX_FMT_NONE)
yading@11 285 break;
yading@11 286 }
yading@11 287 }
yading@11 288
yading@11 289 static int fileTest(uint8_t *ref[4], int refStride[4], int w, int h, FILE *fp,
yading@11 290 enum AVPixelFormat srcFormat_in,
yading@11 291 enum AVPixelFormat dstFormat_in)
yading@11 292 {
yading@11 293 char buf[256];
yading@11 294
yading@11 295 while (fgets(buf, sizeof(buf), fp)) {
yading@11 296 struct Results r;
yading@11 297 enum AVPixelFormat srcFormat;
yading@11 298 char srcStr[12];
yading@11 299 int srcW, srcH;
yading@11 300 enum AVPixelFormat dstFormat;
yading@11 301 char dstStr[12];
yading@11 302 int dstW, dstH;
yading@11 303 int flags;
yading@11 304 int ret;
yading@11 305
yading@11 306 ret = sscanf(buf,
yading@11 307 " %12s %dx%d -> %12s %dx%d flags=%d CRC=%x"
yading@11 308 " SSD=%"SCNd64 ", %"SCNd64 ", %"SCNd64 ", %"SCNd64 "\n",
yading@11 309 srcStr, &srcW, &srcH, dstStr, &dstW, &dstH,
yading@11 310 &flags, &r.crc, &r.ssdY, &r.ssdU, &r.ssdV, &r.ssdA);
yading@11 311 if (ret != 12) {
yading@11 312 srcStr[0] = dstStr[0] = 0;
yading@11 313 ret = sscanf(buf, "%12s -> %12s\n", srcStr, dstStr);
yading@11 314 }
yading@11 315
yading@11 316 srcFormat = av_get_pix_fmt(srcStr);
yading@11 317 dstFormat = av_get_pix_fmt(dstStr);
yading@11 318
yading@11 319 if (srcFormat == AV_PIX_FMT_NONE || dstFormat == AV_PIX_FMT_NONE ||
yading@11 320 srcW > 8192U || srcH > 8192U || dstW > 8192U || dstH > 8192U) {
yading@11 321 fprintf(stderr, "malformed input file\n");
yading@11 322 return -1;
yading@11 323 }
yading@11 324 if ((srcFormat_in != AV_PIX_FMT_NONE && srcFormat_in != srcFormat) ||
yading@11 325 (dstFormat_in != AV_PIX_FMT_NONE && dstFormat_in != dstFormat))
yading@11 326 continue;
yading@11 327 if (ret != 12) {
yading@11 328 printf("%s", buf);
yading@11 329 continue;
yading@11 330 }
yading@11 331
yading@11 332 doTest(ref, refStride, w, h,
yading@11 333 srcFormat, dstFormat,
yading@11 334 srcW, srcH, dstW, dstH, flags,
yading@11 335 &r);
yading@11 336 }
yading@11 337
yading@11 338 return 0;
yading@11 339 }
yading@11 340
yading@11 341 #define W 96
yading@11 342 #define H 96
yading@11 343
yading@11 344 int main(int argc, char **argv)
yading@11 345 {
yading@11 346 enum AVPixelFormat srcFormat = AV_PIX_FMT_NONE;
yading@11 347 enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE;
yading@11 348 uint8_t *rgb_data = av_malloc(W * H * 4);
yading@11 349 const uint8_t * const rgb_src[4] = { rgb_data, NULL, NULL, NULL };
yading@11 350 int rgb_stride[4] = { 4 * W, 0, 0, 0 };
yading@11 351 uint8_t *data = av_malloc(4 * W * H);
yading@11 352 uint8_t *src[4] = { data, data + W * H, data + W * H * 2, data + W * H * 3 };
yading@11 353 int stride[4] = { W, W, W, W };
yading@11 354 int x, y;
yading@11 355 struct SwsContext *sws;
yading@11 356 AVLFG rand;
yading@11 357 int res = -1;
yading@11 358 int i;
yading@11 359 FILE *fp = NULL;
yading@11 360
yading@11 361 if (!rgb_data || !data)
yading@11 362 return -1;
yading@11 363
yading@11 364 for (i = 1; i < argc; i += 2) {
yading@11 365 if (argv[i][0] != '-' || i + 1 == argc)
yading@11 366 goto bad_option;
yading@11 367 if (!strcmp(argv[i], "-ref")) {
yading@11 368 fp = fopen(argv[i + 1], "r");
yading@11 369 if (!fp) {
yading@11 370 fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
yading@11 371 goto error;
yading@11 372 }
yading@11 373 } else if (!strcmp(argv[i], "-src")) {
yading@11 374 srcFormat = av_get_pix_fmt(argv[i + 1]);
yading@11 375 if (srcFormat == AV_PIX_FMT_NONE) {
yading@11 376 fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
yading@11 377 return -1;
yading@11 378 }
yading@11 379 } else if (!strcmp(argv[i], "-dst")) {
yading@11 380 dstFormat = av_get_pix_fmt(argv[i + 1]);
yading@11 381 if (dstFormat == AV_PIX_FMT_NONE) {
yading@11 382 fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
yading@11 383 return -1;
yading@11 384 }
yading@11 385 } else {
yading@11 386 bad_option:
yading@11 387 fprintf(stderr, "bad option or argument missing (%s)\n", argv[i]);
yading@11 388 goto error;
yading@11 389 }
yading@11 390 }
yading@11 391
yading@11 392 sws = sws_getContext(W / 12, H / 12, AV_PIX_FMT_RGB32, W, H,
yading@11 393 AV_PIX_FMT_YUVA420P, SWS_BILINEAR, NULL, NULL, NULL);
yading@11 394
yading@11 395 av_lfg_init(&rand, 1);
yading@11 396
yading@11 397 for (y = 0; y < H; y++)
yading@11 398 for (x = 0; x < W * 4; x++)
yading@11 399 rgb_data[ x + y * 4 * W] = av_lfg_get(&rand);
yading@11 400 sws_scale(sws, rgb_src, rgb_stride, 0, H, src, stride);
yading@11 401 sws_freeContext(sws);
yading@11 402 av_free(rgb_data);
yading@11 403
yading@11 404 if(fp) {
yading@11 405 res = fileTest(src, stride, W, H, fp, srcFormat, dstFormat);
yading@11 406 fclose(fp);
yading@11 407 } else {
yading@11 408 selfTest(src, stride, W, H, srcFormat, dstFormat);
yading@11 409 res = 0;
yading@11 410 }
yading@11 411 error:
yading@11 412 av_free(data);
yading@11 413
yading@11 414 return res;
yading@11 415 }