00001 /* 00002 * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at> 00003 * 00004 * This file is part of FFmpeg. 00005 * 00006 * FFmpeg is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * FFmpeg is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with FFmpeg; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <stdio.h> 00022 #include <stdlib.h> 00023 #include <string.h> 00024 #include <inttypes.h> 00025 #include <stdarg.h> 00026 00027 #undef HAVE_AV_CONFIG_H 00028 #include "libavutil/avutil.h" 00029 #include "swscale.h" 00030 #include "swscale_internal.h" 00031 00032 static uint64_t getSSD(uint8_t *src1, uint8_t *src2, int stride1, int stride2, int w, int h){ 00033 int x,y; 00034 uint64_t ssd=0; 00035 00036 //printf("%d %d\n", w, h); 00037 00038 for (y=0; y<h; y++){ 00039 for (x=0; x<w; x++){ 00040 int d= src1[x + y*stride1] - src2[x + y*stride2]; 00041 ssd+= d*d; 00042 //printf("%d", abs(src1[x + y*stride1] - src2[x + y*stride2])/26 ); 00043 } 00044 //printf("\n"); 00045 } 00046 return ssd; 00047 } 00048 00049 // test by ref -> src -> dst -> out & compare out against ref 00050 // ref & out are YV12 00051 static int doTest(uint8_t *ref[3], int refStride[3], int w, int h, int srcFormat, int dstFormat, 00052 int srcW, int srcH, int dstW, int dstH, int flags){ 00053 uint8_t *src[3]; 00054 uint8_t *dst[3]; 00055 uint8_t *out[3]; 00056 int srcStride[3], dstStride[3]; 00057 int i; 00058 uint64_t ssdY, ssdU, ssdV; 00059 struct SwsContext *srcContext, *dstContext, *outContext; 00060 int res; 00061 00062 res = 0; 00063 for (i=0; i<3; i++){ 00064 // avoid stride % bpp != 0 00065 if (srcFormat==PIX_FMT_RGB24 || srcFormat==PIX_FMT_BGR24) 00066 srcStride[i]= srcW*3; 00067 else 00068 srcStride[i]= srcW*4; 00069 00070 if (dstFormat==PIX_FMT_RGB24 || dstFormat==PIX_FMT_BGR24) 00071 dstStride[i]= dstW*3; 00072 else 00073 dstStride[i]= dstW*4; 00074 00075 src[i]= (uint8_t*) malloc(srcStride[i]*srcH); 00076 dst[i]= (uint8_t*) malloc(dstStride[i]*dstH); 00077 out[i]= (uint8_t*) malloc(refStride[i]*h); 00078 if (!src[i] || !dst[i] || !out[i]) { 00079 perror("Malloc"); 00080 res = -1; 00081 00082 goto end; 00083 } 00084 } 00085 00086 dstContext = outContext = NULL; 00087 srcContext= sws_getContext(w, h, PIX_FMT_YUV420P, srcW, srcH, srcFormat, flags, NULL, NULL, NULL); 00088 if (!srcContext) { 00089 fprintf(stderr, "Failed to get %s ---> %s\n", 00090 sws_format_name(PIX_FMT_YUV420P), 00091 sws_format_name(srcFormat)); 00092 res = -1; 00093 00094 goto end; 00095 } 00096 dstContext= sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, NULL, NULL, NULL); 00097 if (!dstContext) { 00098 fprintf(stderr, "Failed to get %s ---> %s\n", 00099 sws_format_name(srcFormat), 00100 sws_format_name(dstFormat)); 00101 res = -1; 00102 00103 goto end; 00104 } 00105 outContext= sws_getContext(dstW, dstH, dstFormat, w, h, PIX_FMT_YUV420P, flags, NULL, NULL, NULL); 00106 if (!outContext) { 00107 fprintf(stderr, "Failed to get %s ---> %s\n", 00108 sws_format_name(dstFormat), 00109 sws_format_name(PIX_FMT_YUV420P)); 00110 res = -1; 00111 00112 goto end; 00113 } 00114 // printf("test %X %X %X -> %X %X %X\n", (int)ref[0], (int)ref[1], (int)ref[2], 00115 // (int)src[0], (int)src[1], (int)src[2]); 00116 00117 sws_scale(srcContext, ref, refStride, 0, h , src, srcStride); 00118 sws_scale(dstContext, src, srcStride, 0, srcH, dst, dstStride); 00119 sws_scale(outContext, dst, dstStride, 0, dstH, out, refStride); 00120 00121 ssdY= getSSD(ref[0], out[0], refStride[0], refStride[0], w, h); 00122 ssdU= getSSD(ref[1], out[1], refStride[1], refStride[1], (w+1)>>1, (h+1)>>1); 00123 ssdV= getSSD(ref[2], out[2], refStride[2], refStride[2], (w+1)>>1, (h+1)>>1); 00124 00125 if (srcFormat == PIX_FMT_GRAY8 || dstFormat==PIX_FMT_GRAY8) ssdU=ssdV=0; //FIXME check that output is really gray 00126 00127 ssdY/= w*h; 00128 ssdU/= w*h/4; 00129 ssdV/= w*h/4; 00130 00131 printf(" %s %dx%d -> %s %4dx%4d flags=%2d SSD=%5lld,%5lld,%5lld\n", 00132 sws_format_name(srcFormat), srcW, srcH, 00133 sws_format_name(dstFormat), dstW, dstH, 00134 flags, ssdY, ssdU, ssdV); 00135 fflush(stdout); 00136 00137 end: 00138 00139 sws_freeContext(srcContext); 00140 sws_freeContext(dstContext); 00141 sws_freeContext(outContext); 00142 00143 for (i=0; i<3; i++){ 00144 free(src[i]); 00145 free(dst[i]); 00146 free(out[i]); 00147 } 00148 00149 return res; 00150 } 00151 00152 static void selfTest(uint8_t *src[3], int stride[3], int w, int h){ 00153 enum PixelFormat srcFormat, dstFormat; 00154 int srcW, srcH, dstW, dstH; 00155 int flags; 00156 00157 for (srcFormat = 0; srcFormat < PIX_FMT_NB; srcFormat++) { 00158 for (dstFormat = 0; dstFormat < PIX_FMT_NB; dstFormat++) { 00159 printf("%s -> %s\n", 00160 sws_format_name(srcFormat), 00161 sws_format_name(dstFormat)); 00162 fflush(stdout); 00163 00164 srcW= w; 00165 srcH= h; 00166 for (dstW=w - w/3; dstW<= 4*w/3; dstW+= w/3){ 00167 for (dstH=h - h/3; dstH<= 4*h/3; dstH+= h/3){ 00168 for (flags=1; flags<33; flags*=2) { 00169 int res; 00170 00171 res = doTest(src, stride, w, h, srcFormat, dstFormat, 00172 srcW, srcH, dstW, dstH, flags); 00173 if (res < 0) { 00174 dstW = 4 * w / 3; 00175 dstH = 4 * h / 3; 00176 flags = 33; 00177 } 00178 } 00179 } 00180 } 00181 } 00182 } 00183 } 00184 00185 #define W 96 00186 #define H 96 00187 00188 int main(int argc, char **argv){ 00189 uint8_t *rgb_data = malloc (W*H*4); 00190 uint8_t *rgb_src[3]= {rgb_data, NULL, NULL}; 00191 int rgb_stride[3]={4*W, 0, 0}; 00192 uint8_t *data = malloc (3*W*H); 00193 uint8_t *src[3]= {data, data+W*H, data+W*H*2}; 00194 int stride[3]={W, W, W}; 00195 int x, y; 00196 struct SwsContext *sws; 00197 00198 sws= sws_getContext(W/12, H/12, PIX_FMT_RGB32, W, H, PIX_FMT_YUV420P, 2, NULL, NULL, NULL); 00199 00200 for (y=0; y<H; y++){ 00201 for (x=0; x<W*4; x++){ 00202 rgb_data[ x + y*4*W]= random(); 00203 } 00204 } 00205 sws_scale(sws, rgb_src, rgb_stride, 0, H, src, stride); 00206 00207 selfTest(src, stride, W, H); 00208 00209 return 123; 00210 }