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