Libav 0.7.1
|
00001 /* 00002 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> 00003 * 00004 * This file is part of Libav. 00005 * 00006 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <inttypes.h> 00022 #include <string.h> 00023 #include <math.h> 00024 #include <stdio.h> 00025 #include "config.h" 00026 #include <assert.h> 00027 #if HAVE_SYS_MMAN_H 00028 #include <sys/mman.h> 00029 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) 00030 #define MAP_ANONYMOUS MAP_ANON 00031 #endif 00032 #endif 00033 #if HAVE_VIRTUALALLOC 00034 #define WIN32_LEAN_AND_MEAN 00035 #include <windows.h> 00036 #endif 00037 #include "swscale.h" 00038 #include "swscale_internal.h" 00039 #include "rgb2rgb.h" 00040 #include "libavutil/intreadwrite.h" 00041 #include "libavutil/x86_cpu.h" 00042 #include "libavutil/cpu.h" 00043 #include "libavutil/avutil.h" 00044 #include "libavutil/bswap.h" 00045 #include "libavutil/opt.h" 00046 #include "libavutil/pixdesc.h" 00047 00048 unsigned swscale_version(void) 00049 { 00050 return LIBSWSCALE_VERSION_INT; 00051 } 00052 00053 const char *swscale_configuration(void) 00054 { 00055 return LIBAV_CONFIGURATION; 00056 } 00057 00058 const char *swscale_license(void) 00059 { 00060 #define LICENSE_PREFIX "libswscale license: " 00061 return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; 00062 } 00063 00064 #define RET 0xC3 //near return opcode for x86 00065 00066 #define isSupportedIn(x) ( \ 00067 (x)==PIX_FMT_YUV420P \ 00068 || (x)==PIX_FMT_YUVA420P \ 00069 || (x)==PIX_FMT_YUYV422 \ 00070 || (x)==PIX_FMT_UYVY422 \ 00071 || (x)==PIX_FMT_RGB48BE \ 00072 || (x)==PIX_FMT_RGB48LE \ 00073 || (x)==PIX_FMT_RGB32 \ 00074 || (x)==PIX_FMT_RGB32_1 \ 00075 || (x)==PIX_FMT_BGR48BE \ 00076 || (x)==PIX_FMT_BGR48LE \ 00077 || (x)==PIX_FMT_BGR24 \ 00078 || (x)==PIX_FMT_BGR565LE \ 00079 || (x)==PIX_FMT_BGR565BE \ 00080 || (x)==PIX_FMT_BGR555LE \ 00081 || (x)==PIX_FMT_BGR555BE \ 00082 || (x)==PIX_FMT_BGR32 \ 00083 || (x)==PIX_FMT_BGR32_1 \ 00084 || (x)==PIX_FMT_RGB24 \ 00085 || (x)==PIX_FMT_RGB565LE \ 00086 || (x)==PIX_FMT_RGB565BE \ 00087 || (x)==PIX_FMT_RGB555LE \ 00088 || (x)==PIX_FMT_RGB555BE \ 00089 || (x)==PIX_FMT_GRAY8 \ 00090 || (x)==PIX_FMT_Y400A \ 00091 || (x)==PIX_FMT_YUV410P \ 00092 || (x)==PIX_FMT_YUV440P \ 00093 || (x)==PIX_FMT_NV12 \ 00094 || (x)==PIX_FMT_NV21 \ 00095 || (x)==PIX_FMT_GRAY16BE \ 00096 || (x)==PIX_FMT_GRAY16LE \ 00097 || (x)==PIX_FMT_YUV444P \ 00098 || (x)==PIX_FMT_YUV422P \ 00099 || (x)==PIX_FMT_YUV411P \ 00100 || (x)==PIX_FMT_YUVJ420P \ 00101 || (x)==PIX_FMT_YUVJ422P \ 00102 || (x)==PIX_FMT_YUVJ440P \ 00103 || (x)==PIX_FMT_YUVJ444P \ 00104 || (x)==PIX_FMT_PAL8 \ 00105 || (x)==PIX_FMT_BGR8 \ 00106 || (x)==PIX_FMT_RGB8 \ 00107 || (x)==PIX_FMT_BGR4_BYTE \ 00108 || (x)==PIX_FMT_RGB4_BYTE \ 00109 || (x)==PIX_FMT_YUV440P \ 00110 || (x)==PIX_FMT_MONOWHITE \ 00111 || (x)==PIX_FMT_MONOBLACK \ 00112 || (x)==PIX_FMT_YUV420P9LE \ 00113 || (x)==PIX_FMT_YUV444P9LE \ 00114 || (x)==PIX_FMT_YUV420P10LE \ 00115 || (x)==PIX_FMT_YUV422P10LE \ 00116 || (x)==PIX_FMT_YUV444P10LE \ 00117 || (x)==PIX_FMT_YUV420P16LE \ 00118 || (x)==PIX_FMT_YUV422P16LE \ 00119 || (x)==PIX_FMT_YUV444P16LE \ 00120 || (x)==PIX_FMT_YUV420P9BE \ 00121 || (x)==PIX_FMT_YUV444P9BE \ 00122 || (x)==PIX_FMT_YUV420P10BE \ 00123 || (x)==PIX_FMT_YUV444P10BE \ 00124 || (x)==PIX_FMT_YUV422P10BE \ 00125 || (x)==PIX_FMT_YUV420P16BE \ 00126 || (x)==PIX_FMT_YUV422P16BE \ 00127 || (x)==PIX_FMT_YUV444P16BE \ 00128 ) 00129 00130 int sws_isSupportedInput(enum PixelFormat pix_fmt) 00131 { 00132 return isSupportedIn(pix_fmt); 00133 } 00134 00135 #define isSupportedOut(x) ( \ 00136 (x)==PIX_FMT_YUV420P \ 00137 || (x)==PIX_FMT_YUVA420P \ 00138 || (x)==PIX_FMT_YUYV422 \ 00139 || (x)==PIX_FMT_UYVY422 \ 00140 || (x)==PIX_FMT_YUV444P \ 00141 || (x)==PIX_FMT_YUV422P \ 00142 || (x)==PIX_FMT_YUV411P \ 00143 || (x)==PIX_FMT_YUVJ420P \ 00144 || (x)==PIX_FMT_YUVJ422P \ 00145 || (x)==PIX_FMT_YUVJ440P \ 00146 || (x)==PIX_FMT_YUVJ444P \ 00147 || isRGBinBytes(x) \ 00148 || isBGRinBytes(x) \ 00149 || (x)==PIX_FMT_RGB565 \ 00150 || (x)==PIX_FMT_RGB555 \ 00151 || (x)==PIX_FMT_RGB444 \ 00152 || (x)==PIX_FMT_BGR565 \ 00153 || (x)==PIX_FMT_BGR555 \ 00154 || (x)==PIX_FMT_BGR444 \ 00155 || (x)==PIX_FMT_RGB8 \ 00156 || (x)==PIX_FMT_BGR8 \ 00157 || (x)==PIX_FMT_RGB4_BYTE \ 00158 || (x)==PIX_FMT_BGR4_BYTE \ 00159 || (x)==PIX_FMT_RGB4 \ 00160 || (x)==PIX_FMT_BGR4 \ 00161 || (x)==PIX_FMT_MONOBLACK \ 00162 || (x)==PIX_FMT_MONOWHITE \ 00163 || (x)==PIX_FMT_NV12 \ 00164 || (x)==PIX_FMT_NV21 \ 00165 || (x)==PIX_FMT_GRAY16BE \ 00166 || (x)==PIX_FMT_GRAY16LE \ 00167 || (x)==PIX_FMT_GRAY8 \ 00168 || (x)==PIX_FMT_YUV410P \ 00169 || (x)==PIX_FMT_YUV440P \ 00170 || (x)==PIX_FMT_YUV420P9LE \ 00171 || (x)==PIX_FMT_YUV420P10LE \ 00172 || (x)==PIX_FMT_YUV420P16LE \ 00173 || (x)==PIX_FMT_YUV422P16LE \ 00174 || (x)==PIX_FMT_YUV444P16LE \ 00175 || (x)==PIX_FMT_YUV420P9BE \ 00176 || (x)==PIX_FMT_YUV420P10BE \ 00177 || (x)==PIX_FMT_YUV420P16BE \ 00178 || (x)==PIX_FMT_YUV422P16BE \ 00179 || (x)==PIX_FMT_YUV444P16BE \ 00180 ) 00181 00182 int sws_isSupportedOutput(enum PixelFormat pix_fmt) 00183 { 00184 return isSupportedOut(pix_fmt); 00185 } 00186 00187 extern const int32_t ff_yuv2rgb_coeffs[8][4]; 00188 00189 const char *sws_format_name(enum PixelFormat format) 00190 { 00191 if ((unsigned)format < PIX_FMT_NB && av_pix_fmt_descriptors[format].name) 00192 return av_pix_fmt_descriptors[format].name; 00193 else 00194 return "Unknown format"; 00195 } 00196 00197 static double getSplineCoeff(double a, double b, double c, double d, double dist) 00198 { 00199 if (dist<=1.0) return ((d*dist + c)*dist + b)*dist +a; 00200 else return getSplineCoeff( 0.0, 00201 b+ 2.0*c + 3.0*d, 00202 c + 3.0*d, 00203 -b- 3.0*c - 6.0*d, 00204 dist-1.0); 00205 } 00206 00207 static int initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc, 00208 int srcW, int dstW, int filterAlign, int one, int flags, int cpu_flags, 00209 SwsVector *srcFilter, SwsVector *dstFilter, double param[2]) 00210 { 00211 int i; 00212 int filterSize; 00213 int filter2Size; 00214 int minFilterSize; 00215 int64_t *filter=NULL; 00216 int64_t *filter2=NULL; 00217 const int64_t fone= 1LL<<54; 00218 int ret= -1; 00219 00220 emms_c(); //FIXME this should not be required but it IS (even for non-MMX versions) 00221 00222 // NOTE: the +1 is for the MMX scaler which reads over the end 00223 FF_ALLOC_OR_GOTO(NULL, *filterPos, (dstW+1)*sizeof(int16_t), fail); 00224 00225 if (FFABS(xInc - 0x10000) <10) { // unscaled 00226 int i; 00227 filterSize= 1; 00228 FF_ALLOCZ_OR_GOTO(NULL, filter, dstW*sizeof(*filter)*filterSize, fail); 00229 00230 for (i=0; i<dstW; i++) { 00231 filter[i*filterSize]= fone; 00232 (*filterPos)[i]=i; 00233 } 00234 00235 } else if (flags&SWS_POINT) { // lame looking point sampling mode 00236 int i; 00237 int xDstInSrc; 00238 filterSize= 1; 00239 FF_ALLOC_OR_GOTO(NULL, filter, dstW*sizeof(*filter)*filterSize, fail); 00240 00241 xDstInSrc= xInc/2 - 0x8000; 00242 for (i=0; i<dstW; i++) { 00243 int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16; 00244 00245 (*filterPos)[i]= xx; 00246 filter[i]= fone; 00247 xDstInSrc+= xInc; 00248 } 00249 } else if ((xInc <= (1<<16) && (flags&SWS_AREA)) || (flags&SWS_FAST_BILINEAR)) { // bilinear upscale 00250 int i; 00251 int xDstInSrc; 00252 filterSize= 2; 00253 FF_ALLOC_OR_GOTO(NULL, filter, dstW*sizeof(*filter)*filterSize, fail); 00254 00255 xDstInSrc= xInc/2 - 0x8000; 00256 for (i=0; i<dstW; i++) { 00257 int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16; 00258 int j; 00259 00260 (*filterPos)[i]= xx; 00261 //bilinear upscale / linear interpolate / area averaging 00262 for (j=0; j<filterSize; j++) { 00263 int64_t coeff= fone - FFABS((xx<<16) - xDstInSrc)*(fone>>16); 00264 if (coeff<0) coeff=0; 00265 filter[i*filterSize + j]= coeff; 00266 xx++; 00267 } 00268 xDstInSrc+= xInc; 00269 } 00270 } else { 00271 int xDstInSrc; 00272 int sizeFactor; 00273 00274 if (flags&SWS_BICUBIC) sizeFactor= 4; 00275 else if (flags&SWS_X) sizeFactor= 8; 00276 else if (flags&SWS_AREA) sizeFactor= 1; //downscale only, for upscale it is bilinear 00277 else if (flags&SWS_GAUSS) sizeFactor= 8; // infinite ;) 00278 else if (flags&SWS_LANCZOS) sizeFactor= param[0] != SWS_PARAM_DEFAULT ? ceil(2*param[0]) : 6; 00279 else if (flags&SWS_SINC) sizeFactor= 20; // infinite ;) 00280 else if (flags&SWS_SPLINE) sizeFactor= 20; // infinite ;) 00281 else if (flags&SWS_BILINEAR) sizeFactor= 2; 00282 else { 00283 sizeFactor= 0; //GCC warning killer 00284 assert(0); 00285 } 00286 00287 if (xInc <= 1<<16) filterSize= 1 + sizeFactor; // upscale 00288 else filterSize= 1 + (sizeFactor*srcW + dstW - 1)/ dstW; 00289 00290 if (filterSize > srcW-2) filterSize=srcW-2; 00291 00292 FF_ALLOC_OR_GOTO(NULL, filter, dstW*sizeof(*filter)*filterSize, fail); 00293 00294 xDstInSrc= xInc - 0x10000; 00295 for (i=0; i<dstW; i++) { 00296 int xx= (xDstInSrc - ((filterSize-2)<<16)) / (1<<17); 00297 int j; 00298 (*filterPos)[i]= xx; 00299 for (j=0; j<filterSize; j++) { 00300 int64_t d= ((int64_t)FFABS((xx<<17) - xDstInSrc))<<13; 00301 double floatd; 00302 int64_t coeff; 00303 00304 if (xInc > 1<<16) 00305 d= d*dstW/srcW; 00306 floatd= d * (1.0/(1<<30)); 00307 00308 if (flags & SWS_BICUBIC) { 00309 int64_t B= (param[0] != SWS_PARAM_DEFAULT ? param[0] : 0) * (1<<24); 00310 int64_t C= (param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6) * (1<<24); 00311 int64_t dd = ( d*d)>>30; 00312 int64_t ddd= (dd*d)>>30; 00313 00314 if (d < 1LL<<30) 00315 coeff = (12*(1<<24)-9*B-6*C)*ddd + (-18*(1<<24)+12*B+6*C)*dd + (6*(1<<24)-2*B)*(1<<30); 00316 else if (d < 1LL<<31) 00317 coeff = (-B-6*C)*ddd + (6*B+30*C)*dd + (-12*B-48*C)*d + (8*B+24*C)*(1<<30); 00318 else 00319 coeff=0.0; 00320 coeff *= fone>>(30+24); 00321 } 00322 /* else if (flags & SWS_X) { 00323 double p= param ? param*0.01 : 0.3; 00324 coeff = d ? sin(d*M_PI)/(d*M_PI) : 1.0; 00325 coeff*= pow(2.0, - p*d*d); 00326 }*/ 00327 else if (flags & SWS_X) { 00328 double A= param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0; 00329 double c; 00330 00331 if (floatd<1.0) 00332 c = cos(floatd*M_PI); 00333 else 00334 c=-1.0; 00335 if (c<0.0) c= -pow(-c, A); 00336 else c= pow( c, A); 00337 coeff= (c*0.5 + 0.5)*fone; 00338 } else if (flags & SWS_AREA) { 00339 int64_t d2= d - (1<<29); 00340 if (d2*xInc < -(1LL<<(29+16))) coeff= 1.0 * (1LL<<(30+16)); 00341 else if (d2*xInc < (1LL<<(29+16))) coeff= -d2*xInc + (1LL<<(29+16)); 00342 else coeff=0.0; 00343 coeff *= fone>>(30+16); 00344 } else if (flags & SWS_GAUSS) { 00345 double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0; 00346 coeff = (pow(2.0, - p*floatd*floatd))*fone; 00347 } else if (flags & SWS_SINC) { 00348 coeff = (d ? sin(floatd*M_PI)/(floatd*M_PI) : 1.0)*fone; 00349 } else if (flags & SWS_LANCZOS) { 00350 double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0; 00351 coeff = (d ? sin(floatd*M_PI)*sin(floatd*M_PI/p)/(floatd*floatd*M_PI*M_PI/p) : 1.0)*fone; 00352 if (floatd>p) coeff=0; 00353 } else if (flags & SWS_BILINEAR) { 00354 coeff= (1<<30) - d; 00355 if (coeff<0) coeff=0; 00356 coeff *= fone >> 30; 00357 } else if (flags & SWS_SPLINE) { 00358 double p=-2.196152422706632; 00359 coeff = getSplineCoeff(1.0, 0.0, p, -p-1.0, floatd) * fone; 00360 } else { 00361 coeff= 0.0; //GCC warning killer 00362 assert(0); 00363 } 00364 00365 filter[i*filterSize + j]= coeff; 00366 xx++; 00367 } 00368 xDstInSrc+= 2*xInc; 00369 } 00370 } 00371 00372 /* apply src & dst Filter to filter -> filter2 00373 av_free(filter); 00374 */ 00375 assert(filterSize>0); 00376 filter2Size= filterSize; 00377 if (srcFilter) filter2Size+= srcFilter->length - 1; 00378 if (dstFilter) filter2Size+= dstFilter->length - 1; 00379 assert(filter2Size>0); 00380 FF_ALLOCZ_OR_GOTO(NULL, filter2, filter2Size*dstW*sizeof(*filter2), fail); 00381 00382 for (i=0; i<dstW; i++) { 00383 int j, k; 00384 00385 if(srcFilter) { 00386 for (k=0; k<srcFilter->length; k++) { 00387 for (j=0; j<filterSize; j++) 00388 filter2[i*filter2Size + k + j] += srcFilter->coeff[k]*filter[i*filterSize + j]; 00389 } 00390 } else { 00391 for (j=0; j<filterSize; j++) 00392 filter2[i*filter2Size + j]= filter[i*filterSize + j]; 00393 } 00394 //FIXME dstFilter 00395 00396 (*filterPos)[i]+= (filterSize-1)/2 - (filter2Size-1)/2; 00397 } 00398 av_freep(&filter); 00399 00400 /* try to reduce the filter-size (step1 find size and shift left) */ 00401 // Assume it is near normalized (*0.5 or *2.0 is OK but * 0.001 is not). 00402 minFilterSize= 0; 00403 for (i=dstW-1; i>=0; i--) { 00404 int min= filter2Size; 00405 int j; 00406 int64_t cutOff=0.0; 00407 00408 /* get rid of near zero elements on the left by shifting left */ 00409 for (j=0; j<filter2Size; j++) { 00410 int k; 00411 cutOff += FFABS(filter2[i*filter2Size]); 00412 00413 if (cutOff > SWS_MAX_REDUCE_CUTOFF*fone) break; 00414 00415 /* preserve monotonicity because the core can't handle the filter otherwise */ 00416 if (i<dstW-1 && (*filterPos)[i] >= (*filterPos)[i+1]) break; 00417 00418 // move filter coefficients left 00419 for (k=1; k<filter2Size; k++) 00420 filter2[i*filter2Size + k - 1]= filter2[i*filter2Size + k]; 00421 filter2[i*filter2Size + k - 1]= 0; 00422 (*filterPos)[i]++; 00423 } 00424 00425 cutOff=0; 00426 /* count near zeros on the right */ 00427 for (j=filter2Size-1; j>0; j--) { 00428 cutOff += FFABS(filter2[i*filter2Size + j]); 00429 00430 if (cutOff > SWS_MAX_REDUCE_CUTOFF*fone) break; 00431 min--; 00432 } 00433 00434 if (min>minFilterSize) minFilterSize= min; 00435 } 00436 00437 if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) { 00438 // we can handle the special case 4, 00439 // so we don't want to go to the full 8 00440 if (minFilterSize < 5) 00441 filterAlign = 4; 00442 00443 // We really don't want to waste our time 00444 // doing useless computation, so fall back on 00445 // the scalar C code for very small filters. 00446 // Vectorizing is worth it only if you have a 00447 // decent-sized vector. 00448 if (minFilterSize < 3) 00449 filterAlign = 1; 00450 } 00451 00452 if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) { 00453 // special case for unscaled vertical filtering 00454 if (minFilterSize == 1 && filterAlign == 2) 00455 filterAlign= 1; 00456 } 00457 00458 assert(minFilterSize > 0); 00459 filterSize= (minFilterSize +(filterAlign-1)) & (~(filterAlign-1)); 00460 assert(filterSize > 0); 00461 filter= av_malloc(filterSize*dstW*sizeof(*filter)); 00462 if (filterSize >= MAX_FILTER_SIZE*16/((flags&SWS_ACCURATE_RND) ? APCK_SIZE : 16) || !filter) 00463 goto fail; 00464 *outFilterSize= filterSize; 00465 00466 if (flags&SWS_PRINT_INFO) 00467 av_log(NULL, AV_LOG_VERBOSE, "SwScaler: reducing / aligning filtersize %d -> %d\n", filter2Size, filterSize); 00468 /* try to reduce the filter-size (step2 reduce it) */ 00469 for (i=0; i<dstW; i++) { 00470 int j; 00471 00472 for (j=0; j<filterSize; j++) { 00473 if (j>=filter2Size) filter[i*filterSize + j]= 0; 00474 else filter[i*filterSize + j]= filter2[i*filter2Size + j]; 00475 if((flags & SWS_BITEXACT) && j>=minFilterSize) 00476 filter[i*filterSize + j]= 0; 00477 } 00478 } 00479 00480 //FIXME try to align filterPos if possible 00481 00482 //fix borders 00483 for (i=0; i<dstW; i++) { 00484 int j; 00485 if ((*filterPos)[i] < 0) { 00486 // move filter coefficients left to compensate for filterPos 00487 for (j=1; j<filterSize; j++) { 00488 int left= FFMAX(j + (*filterPos)[i], 0); 00489 filter[i*filterSize + left] += filter[i*filterSize + j]; 00490 filter[i*filterSize + j]=0; 00491 } 00492 (*filterPos)[i]= 0; 00493 } 00494 00495 if ((*filterPos)[i] + filterSize > srcW) { 00496 int shift= (*filterPos)[i] + filterSize - srcW; 00497 // move filter coefficients right to compensate for filterPos 00498 for (j=filterSize-2; j>=0; j--) { 00499 int right= FFMIN(j + shift, filterSize-1); 00500 filter[i*filterSize +right] += filter[i*filterSize +j]; 00501 filter[i*filterSize +j]=0; 00502 } 00503 (*filterPos)[i]= srcW - filterSize; 00504 } 00505 } 00506 00507 // Note the +1 is for the MMX scaler which reads over the end 00508 /* align at 16 for AltiVec (needed by hScale_altivec_real) */ 00509 FF_ALLOCZ_OR_GOTO(NULL, *outFilter, *outFilterSize*(dstW+1)*sizeof(int16_t), fail); 00510 00511 /* normalize & store in outFilter */ 00512 for (i=0; i<dstW; i++) { 00513 int j; 00514 int64_t error=0; 00515 int64_t sum=0; 00516 00517 for (j=0; j<filterSize; j++) { 00518 sum+= filter[i*filterSize + j]; 00519 } 00520 sum= (sum + one/2)/ one; 00521 for (j=0; j<*outFilterSize; j++) { 00522 int64_t v= filter[i*filterSize + j] + error; 00523 int intV= ROUNDED_DIV(v, sum); 00524 (*outFilter)[i*(*outFilterSize) + j]= intV; 00525 error= v - intV*sum; 00526 } 00527 } 00528 00529 (*filterPos)[dstW]= (*filterPos)[dstW-1]; // the MMX scaler will read over the end 00530 for (i=0; i<*outFilterSize; i++) { 00531 int j= dstW*(*outFilterSize); 00532 (*outFilter)[j + i]= (*outFilter)[j + i - (*outFilterSize)]; 00533 } 00534 00535 ret=0; 00536 fail: 00537 av_free(filter); 00538 av_free(filter2); 00539 return ret; 00540 } 00541 00542 #if HAVE_MMX2 00543 static int initMMX2HScaler(int dstW, int xInc, uint8_t *filterCode, int16_t *filter, int32_t *filterPos, int numSplits) 00544 { 00545 uint8_t *fragmentA; 00546 x86_reg imm8OfPShufW1A; 00547 x86_reg imm8OfPShufW2A; 00548 x86_reg fragmentLengthA; 00549 uint8_t *fragmentB; 00550 x86_reg imm8OfPShufW1B; 00551 x86_reg imm8OfPShufW2B; 00552 x86_reg fragmentLengthB; 00553 int fragmentPos; 00554 00555 int xpos, i; 00556 00557 // create an optimized horizontal scaling routine 00558 /* This scaler is made of runtime-generated MMX2 code using specially 00559 * tuned pshufw instructions. For every four output pixels, if four 00560 * input pixels are enough for the fast bilinear scaling, then a chunk 00561 * of fragmentB is used. If five input pixels are needed, then a chunk 00562 * of fragmentA is used. 00563 */ 00564 00565 //code fragment 00566 00567 __asm__ volatile( 00568 "jmp 9f \n\t" 00569 // Begin 00570 "0: \n\t" 00571 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t" 00572 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t" 00573 "movd 1(%%"REG_c", %%"REG_S"), %%mm1 \n\t" 00574 "punpcklbw %%mm7, %%mm1 \n\t" 00575 "punpcklbw %%mm7, %%mm0 \n\t" 00576 "pshufw $0xFF, %%mm1, %%mm1 \n\t" 00577 "1: \n\t" 00578 "pshufw $0xFF, %%mm0, %%mm0 \n\t" 00579 "2: \n\t" 00580 "psubw %%mm1, %%mm0 \n\t" 00581 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t" 00582 "pmullw %%mm3, %%mm0 \n\t" 00583 "psllw $7, %%mm1 \n\t" 00584 "paddw %%mm1, %%mm0 \n\t" 00585 00586 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t" 00587 00588 "add $8, %%"REG_a" \n\t" 00589 // End 00590 "9: \n\t" 00591 // "int $3 \n\t" 00592 "lea " LOCAL_MANGLE(0b) ", %0 \n\t" 00593 "lea " LOCAL_MANGLE(1b) ", %1 \n\t" 00594 "lea " LOCAL_MANGLE(2b) ", %2 \n\t" 00595 "dec %1 \n\t" 00596 "dec %2 \n\t" 00597 "sub %0, %1 \n\t" 00598 "sub %0, %2 \n\t" 00599 "lea " LOCAL_MANGLE(9b) ", %3 \n\t" 00600 "sub %0, %3 \n\t" 00601 00602 00603 :"=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A), 00604 "=r" (fragmentLengthA) 00605 ); 00606 00607 __asm__ volatile( 00608 "jmp 9f \n\t" 00609 // Begin 00610 "0: \n\t" 00611 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t" 00612 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t" 00613 "punpcklbw %%mm7, %%mm0 \n\t" 00614 "pshufw $0xFF, %%mm0, %%mm1 \n\t" 00615 "1: \n\t" 00616 "pshufw $0xFF, %%mm0, %%mm0 \n\t" 00617 "2: \n\t" 00618 "psubw %%mm1, %%mm0 \n\t" 00619 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t" 00620 "pmullw %%mm3, %%mm0 \n\t" 00621 "psllw $7, %%mm1 \n\t" 00622 "paddw %%mm1, %%mm0 \n\t" 00623 00624 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t" 00625 00626 "add $8, %%"REG_a" \n\t" 00627 // End 00628 "9: \n\t" 00629 // "int $3 \n\t" 00630 "lea " LOCAL_MANGLE(0b) ", %0 \n\t" 00631 "lea " LOCAL_MANGLE(1b) ", %1 \n\t" 00632 "lea " LOCAL_MANGLE(2b) ", %2 \n\t" 00633 "dec %1 \n\t" 00634 "dec %2 \n\t" 00635 "sub %0, %1 \n\t" 00636 "sub %0, %2 \n\t" 00637 "lea " LOCAL_MANGLE(9b) ", %3 \n\t" 00638 "sub %0, %3 \n\t" 00639 00640 00641 :"=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B), 00642 "=r" (fragmentLengthB) 00643 ); 00644 00645 xpos= 0; //lumXInc/2 - 0x8000; // difference between pixel centers 00646 fragmentPos=0; 00647 00648 for (i=0; i<dstW/numSplits; i++) { 00649 int xx=xpos>>16; 00650 00651 if ((i&3) == 0) { 00652 int a=0; 00653 int b=((xpos+xInc)>>16) - xx; 00654 int c=((xpos+xInc*2)>>16) - xx; 00655 int d=((xpos+xInc*3)>>16) - xx; 00656 int inc = (d+1<4); 00657 uint8_t *fragment = (d+1<4) ? fragmentB : fragmentA; 00658 x86_reg imm8OfPShufW1 = (d+1<4) ? imm8OfPShufW1B : imm8OfPShufW1A; 00659 x86_reg imm8OfPShufW2 = (d+1<4) ? imm8OfPShufW2B : imm8OfPShufW2A; 00660 x86_reg fragmentLength = (d+1<4) ? fragmentLengthB : fragmentLengthA; 00661 int maxShift= 3-(d+inc); 00662 int shift=0; 00663 00664 if (filterCode) { 00665 filter[i ] = (( xpos & 0xFFFF) ^ 0xFFFF)>>9; 00666 filter[i+1] = (((xpos+xInc ) & 0xFFFF) ^ 0xFFFF)>>9; 00667 filter[i+2] = (((xpos+xInc*2) & 0xFFFF) ^ 0xFFFF)>>9; 00668 filter[i+3] = (((xpos+xInc*3) & 0xFFFF) ^ 0xFFFF)>>9; 00669 filterPos[i/2]= xx; 00670 00671 memcpy(filterCode + fragmentPos, fragment, fragmentLength); 00672 00673 filterCode[fragmentPos + imm8OfPShufW1]= 00674 (a+inc) | ((b+inc)<<2) | ((c+inc)<<4) | ((d+inc)<<6); 00675 filterCode[fragmentPos + imm8OfPShufW2]= 00676 a | (b<<2) | (c<<4) | (d<<6); 00677 00678 if (i+4-inc>=dstW) shift=maxShift; //avoid overread 00679 else if ((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3; //Align 00680 00681 if (shift && i>=shift) { 00682 filterCode[fragmentPos + imm8OfPShufW1]+= 0x55*shift; 00683 filterCode[fragmentPos + imm8OfPShufW2]+= 0x55*shift; 00684 filterPos[i/2]-=shift; 00685 } 00686 } 00687 00688 fragmentPos+= fragmentLength; 00689 00690 if (filterCode) 00691 filterCode[fragmentPos]= RET; 00692 } 00693 xpos+=xInc; 00694 } 00695 if (filterCode) 00696 filterPos[((i/2)+1)&(~1)]= xpos>>16; // needed to jump to the next part 00697 00698 return fragmentPos + 1; 00699 } 00700 #endif /* HAVE_MMX2 */ 00701 00702 static void getSubSampleFactors(int *h, int *v, enum PixelFormat format) 00703 { 00704 *h = av_pix_fmt_descriptors[format].log2_chroma_w; 00705 *v = av_pix_fmt_descriptors[format].log2_chroma_h; 00706 } 00707 00708 int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation) 00709 { 00710 memcpy(c->srcColorspaceTable, inv_table, sizeof(int)*4); 00711 memcpy(c->dstColorspaceTable, table, sizeof(int)*4); 00712 00713 c->brightness= brightness; 00714 c->contrast = contrast; 00715 c->saturation= saturation; 00716 c->srcRange = srcRange; 00717 c->dstRange = dstRange; 00718 if (isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1; 00719 00720 c->dstFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[c->dstFormat]); 00721 c->srcFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[c->srcFormat]); 00722 00723 ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation); 00724 //FIXME factorize 00725 00726 if (HAVE_ALTIVEC && av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) 00727 ff_yuv2rgb_init_tables_altivec(c, inv_table, brightness, contrast, saturation); 00728 return 0; 00729 } 00730 00731 int sws_getColorspaceDetails(SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation) 00732 { 00733 if (isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1; 00734 00735 *inv_table = c->srcColorspaceTable; 00736 *table = c->dstColorspaceTable; 00737 *srcRange = c->srcRange; 00738 *dstRange = c->dstRange; 00739 *brightness= c->brightness; 00740 *contrast = c->contrast; 00741 *saturation= c->saturation; 00742 00743 return 0; 00744 } 00745 00746 static int handle_jpeg(enum PixelFormat *format) 00747 { 00748 switch (*format) { 00749 case PIX_FMT_YUVJ420P: *format = PIX_FMT_YUV420P; return 1; 00750 case PIX_FMT_YUVJ422P: *format = PIX_FMT_YUV422P; return 1; 00751 case PIX_FMT_YUVJ444P: *format = PIX_FMT_YUV444P; return 1; 00752 case PIX_FMT_YUVJ440P: *format = PIX_FMT_YUV440P; return 1; 00753 default: return 0; 00754 } 00755 } 00756 00757 SwsContext *sws_alloc_context(void) 00758 { 00759 SwsContext *c= av_mallocz(sizeof(SwsContext)); 00760 00761 c->av_class = &sws_context_class; 00762 av_opt_set_defaults(c); 00763 00764 return c; 00765 } 00766 00767 int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter) 00768 { 00769 int i; 00770 int usesVFilter, usesHFilter; 00771 int unscaled; 00772 SwsFilter dummyFilter= {NULL, NULL, NULL, NULL}; 00773 int srcW= c->srcW; 00774 int srcH= c->srcH; 00775 int dstW= c->dstW; 00776 int dstH= c->dstH; 00777 int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 16, 16), dst_stride_px = dst_stride >> 1; 00778 int flags, cpu_flags; 00779 enum PixelFormat srcFormat= c->srcFormat; 00780 enum PixelFormat dstFormat= c->dstFormat; 00781 00782 cpu_flags = av_get_cpu_flags(); 00783 flags = c->flags; 00784 emms_c(); 00785 if (!rgb15to16) sws_rgb2rgb_init(); 00786 00787 unscaled = (srcW == dstW && srcH == dstH); 00788 00789 if (!isSupportedIn(srcFormat)) { 00790 av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n", sws_format_name(srcFormat)); 00791 return AVERROR(EINVAL); 00792 } 00793 if (!isSupportedOut(dstFormat)) { 00794 av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n", sws_format_name(dstFormat)); 00795 return AVERROR(EINVAL); 00796 } 00797 00798 i= flags & ( SWS_POINT 00799 |SWS_AREA 00800 |SWS_BILINEAR 00801 |SWS_FAST_BILINEAR 00802 |SWS_BICUBIC 00803 |SWS_X 00804 |SWS_GAUSS 00805 |SWS_LANCZOS 00806 |SWS_SINC 00807 |SWS_SPLINE 00808 |SWS_BICUBLIN); 00809 if(!i || (i & (i-1))) { 00810 av_log(c, AV_LOG_ERROR, "Exactly one scaler algorithm must be chosen\n"); 00811 return AVERROR(EINVAL); 00812 } 00813 /* sanity check */ 00814 if (srcW<4 || srcH<1 || dstW<8 || dstH<1) { //FIXME check if these are enough and try to lowwer them after fixing the relevant parts of the code 00815 av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n", 00816 srcW, srcH, dstW, dstH); 00817 return AVERROR(EINVAL); 00818 } 00819 00820 if (!dstFilter) dstFilter= &dummyFilter; 00821 if (!srcFilter) srcFilter= &dummyFilter; 00822 00823 c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW; 00824 c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH; 00825 c->dstFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[dstFormat]); 00826 c->srcFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[srcFormat]); 00827 c->vRounder= 4* 0x0001000100010001ULL; 00828 00829 usesVFilter = (srcFilter->lumV && srcFilter->lumV->length>1) || 00830 (srcFilter->chrV && srcFilter->chrV->length>1) || 00831 (dstFilter->lumV && dstFilter->lumV->length>1) || 00832 (dstFilter->chrV && dstFilter->chrV->length>1); 00833 usesHFilter = (srcFilter->lumH && srcFilter->lumH->length>1) || 00834 (srcFilter->chrH && srcFilter->chrH->length>1) || 00835 (dstFilter->lumH && dstFilter->lumH->length>1) || 00836 (dstFilter->chrH && dstFilter->chrH->length>1); 00837 00838 getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat); 00839 getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat); 00840 00841 // reuse chroma for 2 pixels RGB/BGR unless user wants full chroma interpolation 00842 if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1; 00843 00844 // drop some chroma lines if the user wants it 00845 c->vChrDrop= (flags&SWS_SRC_V_CHR_DROP_MASK)>>SWS_SRC_V_CHR_DROP_SHIFT; 00846 c->chrSrcVSubSample+= c->vChrDrop; 00847 00848 // drop every other pixel for chroma calculation unless user wants full chroma 00849 if (isAnyRGB(srcFormat) && !(flags&SWS_FULL_CHR_H_INP) 00850 && srcFormat!=PIX_FMT_RGB8 && srcFormat!=PIX_FMT_BGR8 00851 && srcFormat!=PIX_FMT_RGB4 && srcFormat!=PIX_FMT_BGR4 00852 && srcFormat!=PIX_FMT_RGB4_BYTE && srcFormat!=PIX_FMT_BGR4_BYTE 00853 && ((dstW>>c->chrDstHSubSample) <= (srcW>>1) || (flags&SWS_FAST_BILINEAR))) 00854 c->chrSrcHSubSample=1; 00855 00856 // Note the -((-x)>>y) is so that we always round toward +inf. 00857 c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample); 00858 c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample); 00859 c->chrDstW= -((-dstW) >> c->chrDstHSubSample); 00860 c->chrDstH= -((-dstH) >> c->chrDstVSubSample); 00861 00862 /* unscaled special cases */ 00863 if (unscaled && !usesHFilter && !usesVFilter && (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) { 00864 ff_get_unscaled_swscale(c); 00865 00866 if (c->swScale) { 00867 if (flags&SWS_PRINT_INFO) 00868 av_log(c, AV_LOG_INFO, "using unscaled %s -> %s special converter\n", 00869 sws_format_name(srcFormat), sws_format_name(dstFormat)); 00870 return 0; 00871 } 00872 } 00873 00874 FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW, 16) * 2, fail); 00875 if (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2) { 00876 c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0; 00877 if (!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR)) { 00878 if (flags&SWS_PRINT_INFO) 00879 av_log(c, AV_LOG_INFO, "output width is not a multiple of 32 -> no MMX2 scaler\n"); 00880 } 00881 if (usesHFilter) c->canMMX2BeUsed=0; 00882 } 00883 else 00884 c->canMMX2BeUsed=0; 00885 00886 c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW; 00887 c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH; 00888 00889 // match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst 00890 // but only for the FAST_BILINEAR mode otherwise do correct scaling 00891 // n-2 is the last chrominance sample available 00892 // this is not perfect, but no one should notice the difference, the more correct variant 00893 // would be like the vertical one, but that would require some special code for the 00894 // first and last pixel 00895 if (flags&SWS_FAST_BILINEAR) { 00896 if (c->canMMX2BeUsed) { 00897 c->lumXInc+= 20; 00898 c->chrXInc+= 20; 00899 } 00900 //we don't use the x86 asm scaler if MMX is available 00901 else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) { 00902 c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20; 00903 c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20; 00904 } 00905 } 00906 00907 /* precalculate horizontal scaler filter coefficients */ 00908 { 00909 #if HAVE_MMX2 00910 // can't downscale !!! 00911 if (c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR)) { 00912 c->lumMmx2FilterCodeSize = initMMX2HScaler( dstW, c->lumXInc, NULL, NULL, NULL, 8); 00913 c->chrMmx2FilterCodeSize = initMMX2HScaler(c->chrDstW, c->chrXInc, NULL, NULL, NULL, 4); 00914 00915 #ifdef MAP_ANONYMOUS 00916 c->lumMmx2FilterCode = mmap(NULL, c->lumMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 00917 c->chrMmx2FilterCode = mmap(NULL, c->chrMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 00918 #elif HAVE_VIRTUALALLOC 00919 c->lumMmx2FilterCode = VirtualAlloc(NULL, c->lumMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 00920 c->chrMmx2FilterCode = VirtualAlloc(NULL, c->chrMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 00921 #else 00922 c->lumMmx2FilterCode = av_malloc(c->lumMmx2FilterCodeSize); 00923 c->chrMmx2FilterCode = av_malloc(c->chrMmx2FilterCodeSize); 00924 #endif 00925 00926 if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode) 00927 return AVERROR(ENOMEM); 00928 FF_ALLOCZ_OR_GOTO(c, c->hLumFilter , (dstW /8+8)*sizeof(int16_t), fail); 00929 FF_ALLOCZ_OR_GOTO(c, c->hChrFilter , (c->chrDstW /4+8)*sizeof(int16_t), fail); 00930 FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW /2/8+8)*sizeof(int32_t), fail); 00931 FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW/2/4+8)*sizeof(int32_t), fail); 00932 00933 initMMX2HScaler( dstW, c->lumXInc, c->lumMmx2FilterCode, c->hLumFilter, c->hLumFilterPos, 8); 00934 initMMX2HScaler(c->chrDstW, c->chrXInc, c->chrMmx2FilterCode, c->hChrFilter, c->hChrFilterPos, 4); 00935 00936 #ifdef MAP_ANONYMOUS 00937 mprotect(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize, PROT_EXEC | PROT_READ); 00938 mprotect(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize, PROT_EXEC | PROT_READ); 00939 #endif 00940 } else 00941 #endif /* HAVE_MMX2 */ 00942 { 00943 const int filterAlign= 00944 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 4 : 00945 (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 : 00946 1; 00947 00948 if (initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc, 00949 srcW , dstW, filterAlign, 1<<14, 00950 (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags, cpu_flags, 00951 srcFilter->lumH, dstFilter->lumH, c->param) < 0) 00952 goto fail; 00953 if (initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc, 00954 c->chrSrcW, c->chrDstW, filterAlign, 1<<14, 00955 (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags, cpu_flags, 00956 srcFilter->chrH, dstFilter->chrH, c->param) < 0) 00957 goto fail; 00958 } 00959 } // initialize horizontal stuff 00960 00961 /* precalculate vertical scaler filter coefficients */ 00962 { 00963 const int filterAlign= 00964 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) && (flags & SWS_ACCURATE_RND) ? 2 : 00965 (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 : 00966 1; 00967 00968 if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize, c->lumYInc, 00969 srcH , dstH, filterAlign, (1<<12), 00970 (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags, cpu_flags, 00971 srcFilter->lumV, dstFilter->lumV, c->param) < 0) 00972 goto fail; 00973 if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc, 00974 c->chrSrcH, c->chrDstH, filterAlign, (1<<12), 00975 (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags, cpu_flags, 00976 srcFilter->chrV, dstFilter->chrV, c->param) < 0) 00977 goto fail; 00978 00979 #if HAVE_ALTIVEC 00980 FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof (vector signed short)*c->vLumFilterSize*c->dstH, fail); 00981 FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof (vector signed short)*c->vChrFilterSize*c->chrDstH, fail); 00982 00983 for (i=0;i<c->vLumFilterSize*c->dstH;i++) { 00984 int j; 00985 short *p = (short *)&c->vYCoeffsBank[i]; 00986 for (j=0;j<8;j++) 00987 p[j] = c->vLumFilter[i]; 00988 } 00989 00990 for (i=0;i<c->vChrFilterSize*c->chrDstH;i++) { 00991 int j; 00992 short *p = (short *)&c->vCCoeffsBank[i]; 00993 for (j=0;j<8;j++) 00994 p[j] = c->vChrFilter[i]; 00995 } 00996 #endif 00997 } 00998 00999 // calculate buffer sizes so that they won't run out while handling these damn slices 01000 c->vLumBufSize= c->vLumFilterSize; 01001 c->vChrBufSize= c->vChrFilterSize; 01002 for (i=0; i<dstH; i++) { 01003 int chrI= i*c->chrDstH / dstH; 01004 int nextSlice= FFMAX(c->vLumFilterPos[i ] + c->vLumFilterSize - 1, 01005 ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample)); 01006 01007 nextSlice>>= c->chrSrcVSubSample; 01008 nextSlice<<= c->chrSrcVSubSample; 01009 if (c->vLumFilterPos[i ] + c->vLumBufSize < nextSlice) 01010 c->vLumBufSize= nextSlice - c->vLumFilterPos[i]; 01011 if (c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>c->chrSrcVSubSample)) 01012 c->vChrBufSize= (nextSlice>>c->chrSrcVSubSample) - c->vChrFilterPos[chrI]; 01013 } 01014 01015 // allocate pixbufs (we use dynamic allocation because otherwise we would need to 01016 // allocate several megabytes to handle all possible cases) 01017 FF_ALLOC_OR_GOTO(c, c->lumPixBuf, c->vLumBufSize*2*sizeof(int16_t*), fail); 01018 FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize*2*sizeof(int16_t*), fail); 01019 FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize*2*sizeof(int16_t*), fail); 01020 if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) 01021 FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize*2*sizeof(int16_t*), fail); 01022 //Note we need at least one pixel more at the end because of the MMX code (just in case someone wanna replace the 4000/8000) 01023 /* align at 16 bytes for AltiVec */ 01024 for (i=0; i<c->vLumBufSize; i++) { 01025 FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i+c->vLumBufSize], dst_stride+1, fail); 01026 c->lumPixBuf[i] = c->lumPixBuf[i+c->vLumBufSize]; 01027 } 01028 c->uv_off = dst_stride_px; 01029 c->uv_offx2 = dst_stride; 01030 for (i=0; i<c->vChrBufSize; i++) { 01031 FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i+c->vChrBufSize], dst_stride*2+1, fail); 01032 c->chrUPixBuf[i] = c->chrUPixBuf[i+c->vChrBufSize]; 01033 c->chrVPixBuf[i] = c->chrVPixBuf[i+c->vChrBufSize] = c->chrUPixBuf[i] + dst_stride_px; 01034 } 01035 if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) 01036 for (i=0; i<c->vLumBufSize; i++) { 01037 FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i+c->vLumBufSize], dst_stride+1, fail); 01038 c->alpPixBuf[i] = c->alpPixBuf[i+c->vLumBufSize]; 01039 } 01040 01041 //try to avoid drawing green stuff between the right end and the stride end 01042 for (i=0; i<c->vChrBufSize; i++) 01043 memset(c->chrUPixBuf[i], 64, dst_stride*2+1); 01044 01045 assert(c->chrDstH <= dstH); 01046 01047 if (flags&SWS_PRINT_INFO) { 01048 if (flags&SWS_FAST_BILINEAR) av_log(c, AV_LOG_INFO, "FAST_BILINEAR scaler, "); 01049 else if (flags&SWS_BILINEAR) av_log(c, AV_LOG_INFO, "BILINEAR scaler, "); 01050 else if (flags&SWS_BICUBIC) av_log(c, AV_LOG_INFO, "BICUBIC scaler, "); 01051 else if (flags&SWS_X) av_log(c, AV_LOG_INFO, "Experimental scaler, "); 01052 else if (flags&SWS_POINT) av_log(c, AV_LOG_INFO, "Nearest Neighbor / POINT scaler, "); 01053 else if (flags&SWS_AREA) av_log(c, AV_LOG_INFO, "Area Averaging scaler, "); 01054 else if (flags&SWS_BICUBLIN) av_log(c, AV_LOG_INFO, "luma BICUBIC / chroma BILINEAR scaler, "); 01055 else if (flags&SWS_GAUSS) av_log(c, AV_LOG_INFO, "Gaussian scaler, "); 01056 else if (flags&SWS_SINC) av_log(c, AV_LOG_INFO, "Sinc scaler, "); 01057 else if (flags&SWS_LANCZOS) av_log(c, AV_LOG_INFO, "Lanczos scaler, "); 01058 else if (flags&SWS_SPLINE) av_log(c, AV_LOG_INFO, "Bicubic spline scaler, "); 01059 else av_log(c, AV_LOG_INFO, "ehh flags invalid?! "); 01060 01061 av_log(c, AV_LOG_INFO, "from %s to %s%s ", 01062 sws_format_name(srcFormat), 01063 #ifdef DITHER1XBPP 01064 dstFormat == PIX_FMT_BGR555 || dstFormat == PIX_FMT_BGR565 || 01065 dstFormat == PIX_FMT_RGB444BE || dstFormat == PIX_FMT_RGB444LE || 01066 dstFormat == PIX_FMT_BGR444BE || dstFormat == PIX_FMT_BGR444LE ? "dithered " : "", 01067 #else 01068 "", 01069 #endif 01070 sws_format_name(dstFormat)); 01071 01072 if (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2) av_log(c, AV_LOG_INFO, "using MMX2\n"); 01073 else if (HAVE_AMD3DNOW && cpu_flags & AV_CPU_FLAG_3DNOW) av_log(c, AV_LOG_INFO, "using 3DNOW\n"); 01074 else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) av_log(c, AV_LOG_INFO, "using MMX\n"); 01075 else if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) av_log(c, AV_LOG_INFO, "using AltiVec\n"); 01076 else av_log(c, AV_LOG_INFO, "using C\n"); 01077 01078 if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) { 01079 if (c->canMMX2BeUsed && (flags&SWS_FAST_BILINEAR)) 01080 av_log(c, AV_LOG_VERBOSE, "using FAST_BILINEAR MMX2 scaler for horizontal scaling\n"); 01081 else { 01082 if (c->hLumFilterSize==4) 01083 av_log(c, AV_LOG_VERBOSE, "using 4-tap MMX scaler for horizontal luminance scaling\n"); 01084 else if (c->hLumFilterSize==8) 01085 av_log(c, AV_LOG_VERBOSE, "using 8-tap MMX scaler for horizontal luminance scaling\n"); 01086 else 01087 av_log(c, AV_LOG_VERBOSE, "using n-tap MMX scaler for horizontal luminance scaling\n"); 01088 01089 if (c->hChrFilterSize==4) 01090 av_log(c, AV_LOG_VERBOSE, "using 4-tap MMX scaler for horizontal chrominance scaling\n"); 01091 else if (c->hChrFilterSize==8) 01092 av_log(c, AV_LOG_VERBOSE, "using 8-tap MMX scaler for horizontal chrominance scaling\n"); 01093 else 01094 av_log(c, AV_LOG_VERBOSE, "using n-tap MMX scaler for horizontal chrominance scaling\n"); 01095 } 01096 } else { 01097 #if HAVE_MMX 01098 av_log(c, AV_LOG_VERBOSE, "using x86 asm scaler for horizontal scaling\n"); 01099 #else 01100 if (flags & SWS_FAST_BILINEAR) 01101 av_log(c, AV_LOG_VERBOSE, "using FAST_BILINEAR C scaler for horizontal scaling\n"); 01102 else 01103 av_log(c, AV_LOG_VERBOSE, "using C scaler for horizontal scaling\n"); 01104 #endif 01105 } 01106 if (isPlanarYUV(dstFormat)) { 01107 if (c->vLumFilterSize==1) 01108 av_log(c, AV_LOG_VERBOSE, "using 1-tap %s \"scaler\" for vertical scaling (YV12 like)\n", 01109 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01110 else 01111 av_log(c, AV_LOG_VERBOSE, "using n-tap %s scaler for vertical scaling (YV12 like)\n", 01112 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01113 } else { 01114 if (c->vLumFilterSize==1 && c->vChrFilterSize==2) 01115 av_log(c, AV_LOG_VERBOSE, "using 1-tap %s \"scaler\" for vertical luminance scaling (BGR)\n" 01116 " 2-tap scaler for vertical chrominance scaling (BGR)\n", 01117 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01118 else if (c->vLumFilterSize==2 && c->vChrFilterSize==2) 01119 av_log(c, AV_LOG_VERBOSE, "using 2-tap linear %s scaler for vertical scaling (BGR)\n", 01120 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01121 else 01122 av_log(c, AV_LOG_VERBOSE, "using n-tap %s scaler for vertical scaling (BGR)\n", 01123 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01124 } 01125 01126 if (dstFormat==PIX_FMT_BGR24) 01127 av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR24 converter\n", 01128 (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2) ? "MMX2" : 01129 ((HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C")); 01130 else if (dstFormat==PIX_FMT_RGB32) 01131 av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR32 converter\n", 01132 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01133 else if (dstFormat==PIX_FMT_BGR565) 01134 av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR16 converter\n", 01135 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01136 else if (dstFormat==PIX_FMT_BGR555) 01137 av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR15 converter\n", 01138 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01139 else if (dstFormat == PIX_FMT_RGB444BE || dstFormat == PIX_FMT_RGB444LE || 01140 dstFormat == PIX_FMT_BGR444BE || dstFormat == PIX_FMT_BGR444LE) 01141 av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR12 converter\n", 01142 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"); 01143 01144 av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH); 01145 av_log(c, AV_LOG_DEBUG, "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", 01146 c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc); 01147 av_log(c, AV_LOG_DEBUG, "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", 01148 c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, c->chrXInc, c->chrYInc); 01149 } 01150 01151 c->swScale= ff_getSwsFunc(c); 01152 return 0; 01153 fail: //FIXME replace things by appropriate error codes 01154 return -1; 01155 } 01156 01157 #if FF_API_SWS_GETCONTEXT 01158 SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, 01159 int dstW, int dstH, enum PixelFormat dstFormat, int flags, 01160 SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param) 01161 { 01162 SwsContext *c; 01163 01164 if(!(c=sws_alloc_context())) 01165 return NULL; 01166 01167 c->flags= flags; 01168 c->srcW= srcW; 01169 c->srcH= srcH; 01170 c->dstW= dstW; 01171 c->dstH= dstH; 01172 c->srcRange = handle_jpeg(&srcFormat); 01173 c->dstRange = handle_jpeg(&dstFormat); 01174 c->srcFormat= srcFormat; 01175 c->dstFormat= dstFormat; 01176 01177 if (param) { 01178 c->param[0] = param[0]; 01179 c->param[1] = param[1]; 01180 } 01181 sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/, c->dstRange, 0, 1<<16, 1<<16); 01182 01183 if(sws_init_context(c, srcFilter, dstFilter) < 0){ 01184 sws_freeContext(c); 01185 return NULL; 01186 } 01187 01188 return c; 01189 } 01190 #endif 01191 01192 SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, 01193 float lumaSharpen, float chromaSharpen, 01194 float chromaHShift, float chromaVShift, 01195 int verbose) 01196 { 01197 SwsFilter *filter= av_malloc(sizeof(SwsFilter)); 01198 if (!filter) 01199 return NULL; 01200 01201 if (lumaGBlur!=0.0) { 01202 filter->lumH= sws_getGaussianVec(lumaGBlur, 3.0); 01203 filter->lumV= sws_getGaussianVec(lumaGBlur, 3.0); 01204 } else { 01205 filter->lumH= sws_getIdentityVec(); 01206 filter->lumV= sws_getIdentityVec(); 01207 } 01208 01209 if (chromaGBlur!=0.0) { 01210 filter->chrH= sws_getGaussianVec(chromaGBlur, 3.0); 01211 filter->chrV= sws_getGaussianVec(chromaGBlur, 3.0); 01212 } else { 01213 filter->chrH= sws_getIdentityVec(); 01214 filter->chrV= sws_getIdentityVec(); 01215 } 01216 01217 if (chromaSharpen!=0.0) { 01218 SwsVector *id= sws_getIdentityVec(); 01219 sws_scaleVec(filter->chrH, -chromaSharpen); 01220 sws_scaleVec(filter->chrV, -chromaSharpen); 01221 sws_addVec(filter->chrH, id); 01222 sws_addVec(filter->chrV, id); 01223 sws_freeVec(id); 01224 } 01225 01226 if (lumaSharpen!=0.0) { 01227 SwsVector *id= sws_getIdentityVec(); 01228 sws_scaleVec(filter->lumH, -lumaSharpen); 01229 sws_scaleVec(filter->lumV, -lumaSharpen); 01230 sws_addVec(filter->lumH, id); 01231 sws_addVec(filter->lumV, id); 01232 sws_freeVec(id); 01233 } 01234 01235 if (chromaHShift != 0.0) 01236 sws_shiftVec(filter->chrH, (int)(chromaHShift+0.5)); 01237 01238 if (chromaVShift != 0.0) 01239 sws_shiftVec(filter->chrV, (int)(chromaVShift+0.5)); 01240 01241 sws_normalizeVec(filter->chrH, 1.0); 01242 sws_normalizeVec(filter->chrV, 1.0); 01243 sws_normalizeVec(filter->lumH, 1.0); 01244 sws_normalizeVec(filter->lumV, 1.0); 01245 01246 if (verbose) sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG); 01247 if (verbose) sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG); 01248 01249 return filter; 01250 } 01251 01252 SwsVector *sws_allocVec(int length) 01253 { 01254 SwsVector *vec = av_malloc(sizeof(SwsVector)); 01255 if (!vec) 01256 return NULL; 01257 vec->length = length; 01258 vec->coeff = av_malloc(sizeof(double) * length); 01259 if (!vec->coeff) 01260 av_freep(&vec); 01261 return vec; 01262 } 01263 01264 SwsVector *sws_getGaussianVec(double variance, double quality) 01265 { 01266 const int length= (int)(variance*quality + 0.5) | 1; 01267 int i; 01268 double middle= (length-1)*0.5; 01269 SwsVector *vec= sws_allocVec(length); 01270 01271 if (!vec) 01272 return NULL; 01273 01274 for (i=0; i<length; i++) { 01275 double dist= i-middle; 01276 vec->coeff[i]= exp(-dist*dist/(2*variance*variance)) / sqrt(2*variance*M_PI); 01277 } 01278 01279 sws_normalizeVec(vec, 1.0); 01280 01281 return vec; 01282 } 01283 01284 SwsVector *sws_getConstVec(double c, int length) 01285 { 01286 int i; 01287 SwsVector *vec= sws_allocVec(length); 01288 01289 if (!vec) 01290 return NULL; 01291 01292 for (i=0; i<length; i++) 01293 vec->coeff[i]= c; 01294 01295 return vec; 01296 } 01297 01298 SwsVector *sws_getIdentityVec(void) 01299 { 01300 return sws_getConstVec(1.0, 1); 01301 } 01302 01303 static double sws_dcVec(SwsVector *a) 01304 { 01305 int i; 01306 double sum=0; 01307 01308 for (i=0; i<a->length; i++) 01309 sum+= a->coeff[i]; 01310 01311 return sum; 01312 } 01313 01314 void sws_scaleVec(SwsVector *a, double scalar) 01315 { 01316 int i; 01317 01318 for (i=0; i<a->length; i++) 01319 a->coeff[i]*= scalar; 01320 } 01321 01322 void sws_normalizeVec(SwsVector *a, double height) 01323 { 01324 sws_scaleVec(a, height/sws_dcVec(a)); 01325 } 01326 01327 static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b) 01328 { 01329 int length= a->length + b->length - 1; 01330 int i, j; 01331 SwsVector *vec= sws_getConstVec(0.0, length); 01332 01333 if (!vec) 01334 return NULL; 01335 01336 for (i=0; i<a->length; i++) { 01337 for (j=0; j<b->length; j++) { 01338 vec->coeff[i+j]+= a->coeff[i]*b->coeff[j]; 01339 } 01340 } 01341 01342 return vec; 01343 } 01344 01345 static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b) 01346 { 01347 int length= FFMAX(a->length, b->length); 01348 int i; 01349 SwsVector *vec= sws_getConstVec(0.0, length); 01350 01351 if (!vec) 01352 return NULL; 01353 01354 for (i=0; i<a->length; i++) vec->coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i]; 01355 for (i=0; i<b->length; i++) vec->coeff[i + (length-1)/2 - (b->length-1)/2]+= b->coeff[i]; 01356 01357 return vec; 01358 } 01359 01360 static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b) 01361 { 01362 int length= FFMAX(a->length, b->length); 01363 int i; 01364 SwsVector *vec= sws_getConstVec(0.0, length); 01365 01366 if (!vec) 01367 return NULL; 01368 01369 for (i=0; i<a->length; i++) vec->coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i]; 01370 for (i=0; i<b->length; i++) vec->coeff[i + (length-1)/2 - (b->length-1)/2]-= b->coeff[i]; 01371 01372 return vec; 01373 } 01374 01375 /* shift left / or right if "shift" is negative */ 01376 static SwsVector *sws_getShiftedVec(SwsVector *a, int shift) 01377 { 01378 int length= a->length + FFABS(shift)*2; 01379 int i; 01380 SwsVector *vec= sws_getConstVec(0.0, length); 01381 01382 if (!vec) 01383 return NULL; 01384 01385 for (i=0; i<a->length; i++) { 01386 vec->coeff[i + (length-1)/2 - (a->length-1)/2 - shift]= a->coeff[i]; 01387 } 01388 01389 return vec; 01390 } 01391 01392 void sws_shiftVec(SwsVector *a, int shift) 01393 { 01394 SwsVector *shifted= sws_getShiftedVec(a, shift); 01395 av_free(a->coeff); 01396 a->coeff= shifted->coeff; 01397 a->length= shifted->length; 01398 av_free(shifted); 01399 } 01400 01401 void sws_addVec(SwsVector *a, SwsVector *b) 01402 { 01403 SwsVector *sum= sws_sumVec(a, b); 01404 av_free(a->coeff); 01405 a->coeff= sum->coeff; 01406 a->length= sum->length; 01407 av_free(sum); 01408 } 01409 01410 void sws_subVec(SwsVector *a, SwsVector *b) 01411 { 01412 SwsVector *diff= sws_diffVec(a, b); 01413 av_free(a->coeff); 01414 a->coeff= diff->coeff; 01415 a->length= diff->length; 01416 av_free(diff); 01417 } 01418 01419 void sws_convVec(SwsVector *a, SwsVector *b) 01420 { 01421 SwsVector *conv= sws_getConvVec(a, b); 01422 av_free(a->coeff); 01423 a->coeff= conv->coeff; 01424 a->length= conv->length; 01425 av_free(conv); 01426 } 01427 01428 SwsVector *sws_cloneVec(SwsVector *a) 01429 { 01430 int i; 01431 SwsVector *vec= sws_allocVec(a->length); 01432 01433 if (!vec) 01434 return NULL; 01435 01436 for (i=0; i<a->length; i++) vec->coeff[i]= a->coeff[i]; 01437 01438 return vec; 01439 } 01440 01441 void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level) 01442 { 01443 int i; 01444 double max=0; 01445 double min=0; 01446 double range; 01447 01448 for (i=0; i<a->length; i++) 01449 if (a->coeff[i]>max) max= a->coeff[i]; 01450 01451 for (i=0; i<a->length; i++) 01452 if (a->coeff[i]<min) min= a->coeff[i]; 01453 01454 range= max - min; 01455 01456 for (i=0; i<a->length; i++) { 01457 int x= (int)((a->coeff[i]-min)*60.0/range +0.5); 01458 av_log(log_ctx, log_level, "%1.3f ", a->coeff[i]); 01459 for (;x>0; x--) av_log(log_ctx, log_level, " "); 01460 av_log(log_ctx, log_level, "|\n"); 01461 } 01462 } 01463 01464 void sws_freeVec(SwsVector *a) 01465 { 01466 if (!a) return; 01467 av_freep(&a->coeff); 01468 a->length=0; 01469 av_free(a); 01470 } 01471 01472 void sws_freeFilter(SwsFilter *filter) 01473 { 01474 if (!filter) return; 01475 01476 if (filter->lumH) sws_freeVec(filter->lumH); 01477 if (filter->lumV) sws_freeVec(filter->lumV); 01478 if (filter->chrH) sws_freeVec(filter->chrH); 01479 if (filter->chrV) sws_freeVec(filter->chrV); 01480 av_free(filter); 01481 } 01482 01483 void sws_freeContext(SwsContext *c) 01484 { 01485 int i; 01486 if (!c) return; 01487 01488 if (c->lumPixBuf) { 01489 for (i=0; i<c->vLumBufSize; i++) 01490 av_freep(&c->lumPixBuf[i]); 01491 av_freep(&c->lumPixBuf); 01492 } 01493 01494 if (c->chrUPixBuf) { 01495 for (i=0; i<c->vChrBufSize; i++) 01496 av_freep(&c->chrUPixBuf[i]); 01497 av_freep(&c->chrUPixBuf); 01498 av_freep(&c->chrVPixBuf); 01499 } 01500 01501 if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) { 01502 for (i=0; i<c->vLumBufSize; i++) 01503 av_freep(&c->alpPixBuf[i]); 01504 av_freep(&c->alpPixBuf); 01505 } 01506 01507 av_freep(&c->vLumFilter); 01508 av_freep(&c->vChrFilter); 01509 av_freep(&c->hLumFilter); 01510 av_freep(&c->hChrFilter); 01511 #if HAVE_ALTIVEC 01512 av_freep(&c->vYCoeffsBank); 01513 av_freep(&c->vCCoeffsBank); 01514 #endif 01515 01516 av_freep(&c->vLumFilterPos); 01517 av_freep(&c->vChrFilterPos); 01518 av_freep(&c->hLumFilterPos); 01519 av_freep(&c->hChrFilterPos); 01520 01521 #if HAVE_MMX 01522 #ifdef MAP_ANONYMOUS 01523 if (c->lumMmx2FilterCode) munmap(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize); 01524 if (c->chrMmx2FilterCode) munmap(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize); 01525 #elif HAVE_VIRTUALALLOC 01526 if (c->lumMmx2FilterCode) VirtualFree(c->lumMmx2FilterCode, 0, MEM_RELEASE); 01527 if (c->chrMmx2FilterCode) VirtualFree(c->chrMmx2FilterCode, 0, MEM_RELEASE); 01528 #else 01529 av_free(c->lumMmx2FilterCode); 01530 av_free(c->chrMmx2FilterCode); 01531 #endif 01532 c->lumMmx2FilterCode=NULL; 01533 c->chrMmx2FilterCode=NULL; 01534 #endif /* HAVE_MMX */ 01535 01536 av_freep(&c->yuvTable); 01537 av_free(c->formatConvBuffer); 01538 01539 av_free(c); 01540 } 01541 01542 struct SwsContext *sws_getCachedContext(struct SwsContext *context, 01543 int srcW, int srcH, enum PixelFormat srcFormat, 01544 int dstW, int dstH, enum PixelFormat dstFormat, int flags, 01545 SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param) 01546 { 01547 static const double default_param[2] = {SWS_PARAM_DEFAULT, SWS_PARAM_DEFAULT}; 01548 01549 if (!param) 01550 param = default_param; 01551 01552 if (context && 01553 (context->srcW != srcW || 01554 context->srcH != srcH || 01555 context->srcFormat != srcFormat || 01556 context->dstW != dstW || 01557 context->dstH != dstH || 01558 context->dstFormat != dstFormat || 01559 context->flags != flags || 01560 context->param[0] != param[0] || 01561 context->param[1] != param[1])) { 01562 sws_freeContext(context); 01563 context = NULL; 01564 } 01565 01566 if (!context) { 01567 if (!(context = sws_alloc_context())) 01568 return NULL; 01569 context->srcW = srcW; 01570 context->srcH = srcH; 01571 context->srcRange = handle_jpeg(&srcFormat); 01572 context->srcFormat = srcFormat; 01573 context->dstW = dstW; 01574 context->dstH = dstH; 01575 context->dstRange = handle_jpeg(&dstFormat); 01576 context->dstFormat = dstFormat; 01577 context->flags = flags; 01578 context->param[0] = param[0]; 01579 context->param[1] = param[1]; 01580 sws_setColorspaceDetails(context, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], context->srcRange, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/, context->dstRange, 0, 1<<16, 1<<16); 01581 if (sws_init_context(context, srcFilter, dstFilter) < 0) { 01582 sws_freeContext(context); 01583 return NULL; 01584 } 01585 } 01586 return context; 01587 } 01588