1/* 2 * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at> 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (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 GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <inttypes.h> 25#include <stdarg.h> 26 27#undef HAVE_AV_CONFIG_H 28#include "libavutil/avutil.h" 29#include "swscale.h" 30#include "swscale_internal.h" 31 32static uint64_t getSSD(uint8_t *src1, uint8_t *src2, int stride1, int stride2, int w, int h){ 33 int x,y; 34 uint64_t ssd=0; 35 36//printf("%d %d\n", w, h); 37 38 for (y=0; y<h; y++){ 39 for (x=0; x<w; x++){ 40 int d= src1[x + y*stride1] - src2[x + y*stride2]; 41 ssd+= d*d; 42//printf("%d", abs(src1[x + y*stride1] - src2[x + y*stride2])/26 ); 43 } 44//printf("\n"); 45 } 46 return ssd; 47} 48 49// test by ref -> src -> dst -> out & compare out against ref 50// ref & out are YV12 51static int doTest(uint8_t *ref[3], int refStride[3], int w, int h, int srcFormat, int dstFormat, 52 int srcW, int srcH, int dstW, int dstH, int flags){ 53 uint8_t *src[3]; 54 uint8_t *dst[3]; 55 uint8_t *out[3]; 56 int srcStride[3], dstStride[3]; 57 int i; 58 uint64_t ssdY, ssdU, ssdV; 59 struct SwsContext *srcContext, *dstContext, *outContext; 60 int res; 61 62 res = 0; 63 for (i=0; i<3; i++){ 64 // avoid stride % bpp != 0 65 if (srcFormat==PIX_FMT_RGB24 || srcFormat==PIX_FMT_BGR24) 66 srcStride[i]= srcW*3; 67 else 68 srcStride[i]= srcW*4; 69 70 if (dstFormat==PIX_FMT_RGB24 || dstFormat==PIX_FMT_BGR24) 71 dstStride[i]= dstW*3; 72 else 73 dstStride[i]= dstW*4; 74 75 src[i]= (uint8_t*) malloc(srcStride[i]*srcH); 76 dst[i]= (uint8_t*) malloc(dstStride[i]*dstH); 77 out[i]= (uint8_t*) malloc(refStride[i]*h); 78 if (!src[i] || !dst[i] || !out[i]) { 79 perror("Malloc"); 80 res = -1; 81 82 goto end; 83 } 84 } 85 86 dstContext = outContext = NULL; 87 srcContext= sws_getContext(w, h, PIX_FMT_YUV420P, srcW, srcH, srcFormat, flags, NULL, NULL, NULL); 88 if (!srcContext) { 89 fprintf(stderr, "Failed to get %s ---> %s\n", 90 sws_format_name(PIX_FMT_YUV420P), 91 sws_format_name(srcFormat)); 92 res = -1; 93 94 goto end; 95 } 96 dstContext= sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, NULL, NULL, NULL); 97 if (!dstContext) { 98 fprintf(stderr, "Failed to get %s ---> %s\n", 99 sws_format_name(srcFormat), 100 sws_format_name(dstFormat)); 101 res = -1; 102 103 goto end; 104 } 105 outContext= sws_getContext(dstW, dstH, dstFormat, w, h, PIX_FMT_YUV420P, flags, NULL, NULL, NULL); 106 if (!outContext) { 107 fprintf(stderr, "Failed to get %s ---> %s\n", 108 sws_format_name(dstFormat), 109 sws_format_name(PIX_FMT_YUV420P)); 110 res = -1; 111 112 goto end; 113 } 114// printf("test %X %X %X -> %X %X %X\n", (int)ref[0], (int)ref[1], (int)ref[2], 115// (int)src[0], (int)src[1], (int)src[2]); 116 117 sws_scale(srcContext, ref, refStride, 0, h , src, srcStride); 118 sws_scale(dstContext, src, srcStride, 0, srcH, dst, dstStride); 119 sws_scale(outContext, dst, dstStride, 0, dstH, out, refStride); 120 121 ssdY= getSSD(ref[0], out[0], refStride[0], refStride[0], w, h); 122 ssdU= getSSD(ref[1], out[1], refStride[1], refStride[1], (w+1)>>1, (h+1)>>1); 123 ssdV= getSSD(ref[2], out[2], refStride[2], refStride[2], (w+1)>>1, (h+1)>>1); 124 125 if (srcFormat == PIX_FMT_GRAY8 || dstFormat==PIX_FMT_GRAY8) ssdU=ssdV=0; //FIXME check that output is really gray 126 127 ssdY/= w*h; 128 ssdU/= w*h/4; 129 ssdV/= w*h/4; 130 131 printf(" %s %dx%d -> %s %4dx%4d flags=%2d SSD=%5lld,%5lld,%5lld\n", 132 sws_format_name(srcFormat), srcW, srcH, 133 sws_format_name(dstFormat), dstW, dstH, 134 flags, ssdY, ssdU, ssdV); 135 fflush(stdout); 136 137 end: 138 139 sws_freeContext(srcContext); 140 sws_freeContext(dstContext); 141 sws_freeContext(outContext); 142 143 for (i=0; i<3; i++){ 144 free(src[i]); 145 free(dst[i]); 146 free(out[i]); 147 } 148 149 return res; 150} 151 152static void selfTest(uint8_t *src[3], int stride[3], int w, int h){ 153 enum PixelFormat srcFormat, dstFormat; 154 int srcW, srcH, dstW, dstH; 155 int flags; 156 157 for (srcFormat = 0; srcFormat < PIX_FMT_NB; srcFormat++) { 158 for (dstFormat = 0; dstFormat < PIX_FMT_NB; dstFormat++) { 159 printf("%s -> %s\n", 160 sws_format_name(srcFormat), 161 sws_format_name(dstFormat)); 162 fflush(stdout); 163 164 srcW= w; 165 srcH= h; 166 for (dstW=w - w/3; dstW<= 4*w/3; dstW+= w/3){ 167 for (dstH=h - h/3; dstH<= 4*h/3; dstH+= h/3){ 168 for (flags=1; flags<33; flags*=2) { 169 int res; 170 171 res = doTest(src, stride, w, h, srcFormat, dstFormat, 172 srcW, srcH, dstW, dstH, flags); 173 if (res < 0) { 174 dstW = 4 * w / 3; 175 dstH = 4 * h / 3; 176 flags = 33; 177 } 178 } 179 } 180 } 181 } 182 } 183} 184 185#define W 96 186#define H 96 187 188int main(int argc, char **argv){ 189 uint8_t *rgb_data = malloc (W*H*4); 190 uint8_t *rgb_src[3]= {rgb_data, NULL, NULL}; 191 int rgb_stride[3]={4*W, 0, 0}; 192 uint8_t *data = malloc (3*W*H); 193 uint8_t *src[3]= {data, data+W*H, data+W*H*2}; 194 int stride[3]={W, W, W}; 195 int x, y; 196 struct SwsContext *sws; 197 198 sws= sws_getContext(W/12, H/12, PIX_FMT_RGB32, W, H, PIX_FMT_YUV420P, 2, NULL, NULL, NULL); 199 200 for (y=0; y<H; y++){ 201 for (x=0; x<W*4; x++){ 202 rgb_data[ x + y*4*W]= random(); 203 } 204 } 205 sws_scale(sws, rgb_src, rgb_stride, 0, H, src, stride); 206 207 selfTest(src, stride, W, H); 208 209 return 123; 210} 211