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