00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <inttypes.h>
00058 #include <string.h>
00059 #include <math.h>
00060 #include <stdio.h>
00061 #include <unistd.h>
00062 #include "config.h"
00063 #include <assert.h>
00064 #ifdef HAVE_SYS_MMAN_H
00065 #include <sys/mman.h>
00066 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
00067 #define MAP_ANONYMOUS MAP_ANON
00068 #endif
00069 #endif
00070 #include "swscale.h"
00071 #include "swscale_internal.h"
00072 #include "x86_cpu.h"
00073 #include "bswap.h"
00074 #include "rgb2rgb.h"
00075 #include "libavcodec/opt.h"
00076
00077 #undef MOVNTQ
00078 #undef PAVGB
00079
00080
00081
00082
00083
00084
00085 #define DITHER1XBPP
00086
00087 #define FAST_BGR2YV12 // use 7 bit coeffs instead of 15bit
00088
00089 #define RET 0xC3 //near return opcode for X86
00090
00091 #ifdef MP_DEBUG
00092 #define ASSERT(x) assert(x);
00093 #else
00094 #define ASSERT(x) ;
00095 #endif
00096
00097 #ifdef M_PI
00098 #define PI M_PI
00099 #else
00100 #define PI 3.14159265358979323846
00101 #endif
00102
00103 #define isSupportedIn(x) ( \
00104 (x)==PIX_FMT_YUV420P \
00105 || (x)==PIX_FMT_YUVA420P \
00106 || (x)==PIX_FMT_YUYV422 \
00107 || (x)==PIX_FMT_UYVY422 \
00108 || (x)==PIX_FMT_RGB32 \
00109 || (x)==PIX_FMT_BGR24 \
00110 || (x)==PIX_FMT_BGR565 \
00111 || (x)==PIX_FMT_BGR555 \
00112 || (x)==PIX_FMT_BGR32 \
00113 || (x)==PIX_FMT_RGB24 \
00114 || (x)==PIX_FMT_RGB565 \
00115 || (x)==PIX_FMT_RGB555 \
00116 || (x)==PIX_FMT_GRAY8 \
00117 || (x)==PIX_FMT_YUV410P \
00118 || (x)==PIX_FMT_GRAY16BE \
00119 || (x)==PIX_FMT_GRAY16LE \
00120 || (x)==PIX_FMT_YUV444P \
00121 || (x)==PIX_FMT_YUV422P \
00122 || (x)==PIX_FMT_YUV411P \
00123 || (x)==PIX_FMT_PAL8 \
00124 || (x)==PIX_FMT_BGR8 \
00125 || (x)==PIX_FMT_RGB8 \
00126 || (x)==PIX_FMT_BGR4_BYTE \
00127 || (x)==PIX_FMT_RGB4_BYTE \
00128 || (x)==PIX_FMT_YUV440P \
00129 )
00130 #define isSupportedOut(x) ( \
00131 (x)==PIX_FMT_YUV420P \
00132 || (x)==PIX_FMT_YUYV422 \
00133 || (x)==PIX_FMT_UYVY422 \
00134 || (x)==PIX_FMT_YUV444P \
00135 || (x)==PIX_FMT_YUV422P \
00136 || (x)==PIX_FMT_YUV411P \
00137 || isRGB(x) \
00138 || isBGR(x) \
00139 || (x)==PIX_FMT_NV12 \
00140 || (x)==PIX_FMT_NV21 \
00141 || (x)==PIX_FMT_GRAY16BE \
00142 || (x)==PIX_FMT_GRAY16LE \
00143 || (x)==PIX_FMT_GRAY8 \
00144 || (x)==PIX_FMT_YUV410P \
00145 )
00146 #define isPacked(x) ( \
00147 (x)==PIX_FMT_PAL8 \
00148 || (x)==PIX_FMT_YUYV422 \
00149 || (x)==PIX_FMT_UYVY422 \
00150 || isRGB(x) \
00151 || isBGR(x) \
00152 )
00153
00154 #define RGB2YUV_SHIFT 16
00155 #define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
00156 #define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
00157 #define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
00158 #define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
00159 #define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
00160 #define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
00161 #define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
00162 #define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
00163 #define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
00164
00165 extern const int32_t Inverse_Table_6_9[8][4];
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 #if defined(ARCH_X86) && defined (CONFIG_GPL)
00183 DECLARE_ASM_CONST(8, uint64_t, bF8)= 0xF8F8F8F8F8F8F8F8LL;
00184 DECLARE_ASM_CONST(8, uint64_t, bFC)= 0xFCFCFCFCFCFCFCFCLL;
00185 DECLARE_ASM_CONST(8, uint64_t, w10)= 0x0010001000100010LL;
00186 DECLARE_ASM_CONST(8, uint64_t, w02)= 0x0002000200020002LL;
00187 DECLARE_ASM_CONST(8, uint64_t, bm00001111)=0x00000000FFFFFFFFLL;
00188 DECLARE_ASM_CONST(8, uint64_t, bm00000111)=0x0000000000FFFFFFLL;
00189 DECLARE_ASM_CONST(8, uint64_t, bm11111000)=0xFFFFFFFFFF000000LL;
00190 DECLARE_ASM_CONST(8, uint64_t, bm01010101)=0x00FF00FF00FF00FFLL;
00191
00192 static volatile uint64_t attribute_used __attribute__((aligned(8))) b5Dither;
00193 static volatile uint64_t attribute_used __attribute__((aligned(8))) g5Dither;
00194 static volatile uint64_t attribute_used __attribute__((aligned(8))) g6Dither;
00195 static volatile uint64_t attribute_used __attribute__((aligned(8))) r5Dither;
00196
00197 static uint64_t __attribute__((aligned(8))) dither4[2]={
00198 0x0103010301030103LL,
00199 0x0200020002000200LL,};
00200
00201 static uint64_t __attribute__((aligned(8))) dither8[2]={
00202 0x0602060206020602LL,
00203 0x0004000400040004LL,};
00204
00205 DECLARE_ASM_CONST(8, uint64_t, b16Mask)= 0x001F001F001F001FLL;
00206 DECLARE_ASM_CONST(8, uint64_t, g16Mask)= 0x07E007E007E007E0LL;
00207 DECLARE_ASM_CONST(8, uint64_t, r16Mask)= 0xF800F800F800F800LL;
00208 DECLARE_ASM_CONST(8, uint64_t, b15Mask)= 0x001F001F001F001FLL;
00209 DECLARE_ASM_CONST(8, uint64_t, g15Mask)= 0x03E003E003E003E0LL;
00210 DECLARE_ASM_CONST(8, uint64_t, r15Mask)= 0x7C007C007C007C00LL;
00211
00212 DECLARE_ALIGNED(8, const uint64_t, ff_M24A) = 0x00FF0000FF0000FFLL;
00213 DECLARE_ALIGNED(8, const uint64_t, ff_M24B) = 0xFF0000FF0000FF00LL;
00214 DECLARE_ALIGNED(8, const uint64_t, ff_M24C) = 0x0000FF0000FF0000LL;
00215
00216 #ifdef FAST_BGR2YV12
00217 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YCoeff) = 0x000000210041000DULL;
00218 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UCoeff) = 0x0000FFEEFFDC0038ULL;
00219 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2VCoeff) = 0x00000038FFD2FFF8ULL;
00220 #else
00221 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YCoeff) = 0x000020E540830C8BULL;
00222 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UCoeff) = 0x0000ED0FDAC23831ULL;
00223 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2VCoeff) = 0x00003831D0E6F6EAULL;
00224 #endif
00225 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YOffset) = 0x1010101010101010ULL;
00226 DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UVOffset) = 0x8080808080808080ULL;
00227 DECLARE_ALIGNED(8, const uint64_t, ff_w1111) = 0x0001000100010001ULL;
00228 #endif
00229
00230
00231 static unsigned char clip_table[768];
00232
00233 static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b);
00234
00235 extern const uint8_t dither_2x2_4[2][8];
00236 extern const uint8_t dither_2x2_8[2][8];
00237 extern const uint8_t dither_8x8_32[8][8];
00238 extern const uint8_t dither_8x8_73[8][8];
00239 extern const uint8_t dither_8x8_220[8][8];
00240
00241 static const char * sws_context_to_name(void * ptr) {
00242 return "swscaler";
00243 }
00244
00245 #define OFFSET(x) offsetof(SwsContext, x)
00246 #define DEFAULT 0
00247 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
00248
00249 static const AVOption options[] = {
00250 { "sws_flags", "scaler/cpu flags", OFFSET(flags), FF_OPT_TYPE_FLAGS, DEFAULT, INT_MIN, INT_MAX, VE, "sws_flags" },
00251 { "fast_bilinear", "fast bilinear", 0, FF_OPT_TYPE_CONST, SWS_FAST_BILINEAR, INT_MIN, INT_MAX, VE, "sws_flags" },
00252 { "bilinear", "bilinear", 0, FF_OPT_TYPE_CONST, SWS_BILINEAR, INT_MIN, INT_MAX, VE, "sws_flags" },
00253 { "bicubic", "bicubic", 0, FF_OPT_TYPE_CONST, SWS_BICUBIC, INT_MIN, INT_MAX, VE, "sws_flags" },
00254 { "experimental", "experimental", 0, FF_OPT_TYPE_CONST, SWS_X, INT_MIN, INT_MAX, VE, "sws_flags" },
00255 { "neighbor", "nearest neighbor", 0, FF_OPT_TYPE_CONST, SWS_POINT, INT_MIN, INT_MAX, VE, "sws_flags" },
00256 { "area", "averaging area", 0, FF_OPT_TYPE_CONST, SWS_AREA, INT_MIN, INT_MAX, VE, "sws_flags" },
00257 { "bicublin", "luma bicubic, chroma bilinear", 0, FF_OPT_TYPE_CONST, SWS_BICUBLIN, INT_MIN, INT_MAX, VE, "sws_flags" },
00258 { "gauss", "gaussian", 0, FF_OPT_TYPE_CONST, SWS_GAUSS, INT_MIN, INT_MAX, VE, "sws_flags" },
00259 { "sinc", "sinc", 0, FF_OPT_TYPE_CONST, SWS_SINC, INT_MIN, INT_MAX, VE, "sws_flags" },
00260 { "lanczos", "lanczos", 0, FF_OPT_TYPE_CONST, SWS_LANCZOS, INT_MIN, INT_MAX, VE, "sws_flags" },
00261 { "spline", "natural bicubic spline", 0, FF_OPT_TYPE_CONST, SWS_SPLINE, INT_MIN, INT_MAX, VE, "sws_flags" },
00262 { "print_info", "print info", 0, FF_OPT_TYPE_CONST, SWS_PRINT_INFO, INT_MIN, INT_MAX, VE, "sws_flags" },
00263 { "accurate_rnd", "accurate rounding", 0, FF_OPT_TYPE_CONST, SWS_ACCURATE_RND, INT_MIN, INT_MAX, VE, "sws_flags" },
00264 { "mmx", "MMX SIMD acceleration", 0, FF_OPT_TYPE_CONST, SWS_CPU_CAPS_MMX, INT_MIN, INT_MAX, VE, "sws_flags" },
00265 { "mmx2", "MMX2 SIMD acceleration", 0, FF_OPT_TYPE_CONST, SWS_CPU_CAPS_MMX2, INT_MIN, INT_MAX, VE, "sws_flags" },
00266 { "3dnow", "3DNOW SIMD acceleration", 0, FF_OPT_TYPE_CONST, SWS_CPU_CAPS_3DNOW, INT_MIN, INT_MAX, VE, "sws_flags" },
00267 { "altivec", "AltiVec SIMD acceleration", 0, FF_OPT_TYPE_CONST, SWS_CPU_CAPS_ALTIVEC, INT_MIN, INT_MAX, VE, "sws_flags" },
00268 { "bfin", "Blackfin SIMD acceleration", 0, FF_OPT_TYPE_CONST, SWS_CPU_CAPS_BFIN, INT_MIN, INT_MAX, VE, "sws_flags" },
00269 { "full_chroma_int", "full chroma interpolation", 0 , FF_OPT_TYPE_CONST, SWS_FULL_CHR_H_INT, INT_MIN, INT_MAX, VE, "sws_flags" },
00270 { "full_chroma_inp", "full chroma input", 0 , FF_OPT_TYPE_CONST, SWS_FULL_CHR_H_INP, INT_MIN, INT_MAX, VE, "sws_flags" },
00271 { NULL }
00272 };
00273
00274 #undef VE
00275 #undef DEFAULT
00276
00277 static AVClass sws_context_class = { "SWScaler", sws_context_to_name, options };
00278
00279 char *sws_format_name(enum PixelFormat format)
00280 {
00281 switch (format) {
00282 case PIX_FMT_YUV420P:
00283 return "yuv420p";
00284 case PIX_FMT_YUVA420P:
00285 return "yuva420p";
00286 case PIX_FMT_YUYV422:
00287 return "yuyv422";
00288 case PIX_FMT_RGB24:
00289 return "rgb24";
00290 case PIX_FMT_BGR24:
00291 return "bgr24";
00292 case PIX_FMT_YUV422P:
00293 return "yuv422p";
00294 case PIX_FMT_YUV444P:
00295 return "yuv444p";
00296 case PIX_FMT_RGB32:
00297 return "rgb32";
00298 case PIX_FMT_YUV410P:
00299 return "yuv410p";
00300 case PIX_FMT_YUV411P:
00301 return "yuv411p";
00302 case PIX_FMT_RGB565:
00303 return "rgb565";
00304 case PIX_FMT_RGB555:
00305 return "rgb555";
00306 case PIX_FMT_GRAY16BE:
00307 return "gray16be";
00308 case PIX_FMT_GRAY16LE:
00309 return "gray16le";
00310 case PIX_FMT_GRAY8:
00311 return "gray8";
00312 case PIX_FMT_MONOWHITE:
00313 return "mono white";
00314 case PIX_FMT_MONOBLACK:
00315 return "mono black";
00316 case PIX_FMT_PAL8:
00317 return "Palette";
00318 case PIX_FMT_YUVJ420P:
00319 return "yuvj420p";
00320 case PIX_FMT_YUVJ422P:
00321 return "yuvj422p";
00322 case PIX_FMT_YUVJ444P:
00323 return "yuvj444p";
00324 case PIX_FMT_XVMC_MPEG2_MC:
00325 return "xvmc_mpeg2_mc";
00326 case PIX_FMT_XVMC_MPEG2_IDCT:
00327 return "xvmc_mpeg2_idct";
00328 case PIX_FMT_UYVY422:
00329 return "uyvy422";
00330 case PIX_FMT_UYYVYY411:
00331 return "uyyvyy411";
00332 case PIX_FMT_RGB32_1:
00333 return "rgb32x";
00334 case PIX_FMT_BGR32_1:
00335 return "bgr32x";
00336 case PIX_FMT_BGR32:
00337 return "bgr32";
00338 case PIX_FMT_BGR565:
00339 return "bgr565";
00340 case PIX_FMT_BGR555:
00341 return "bgr555";
00342 case PIX_FMT_BGR8:
00343 return "bgr8";
00344 case PIX_FMT_BGR4:
00345 return "bgr4";
00346 case PIX_FMT_BGR4_BYTE:
00347 return "bgr4 byte";
00348 case PIX_FMT_RGB8:
00349 return "rgb8";
00350 case PIX_FMT_RGB4:
00351 return "rgb4";
00352 case PIX_FMT_RGB4_BYTE:
00353 return "rgb4 byte";
00354 case PIX_FMT_NV12:
00355 return "nv12";
00356 case PIX_FMT_NV21:
00357 return "nv21";
00358 case PIX_FMT_YUV440P:
00359 return "yuv440p";
00360 default:
00361 return "Unknown format";
00362 }
00363 }
00364
00365 #if defined(ARCH_X86) && defined (CONFIG_GPL)
00366 void in_asm_used_var_warning_killer()
00367 {
00368 volatile int i= bF8+bFC+w10+
00369 bm00001111+bm00000111+bm11111000+b16Mask+g16Mask+r16Mask+b15Mask+g15Mask+r15Mask+
00370 ff_M24A+ff_M24B+ff_M24C+w02 + b5Dither+g5Dither+r5Dither+g6Dither+dither4[0]+dither8[0]+bm01010101;
00371 if (i) i=0;
00372 }
00373 #endif
00374
00375 static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
00376 int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
00377 uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW)
00378 {
00379
00380 int i;
00381 for (i=0; i<dstW; i++)
00382 {
00383 int val=1<<18;
00384 int j;
00385 for (j=0; j<lumFilterSize; j++)
00386 val += lumSrc[j][i] * lumFilter[j];
00387
00388 dest[i]= av_clip_uint8(val>>19);
00389 }
00390
00391 if (uDest)
00392 for (i=0; i<chrDstW; i++)
00393 {
00394 int u=1<<18;
00395 int v=1<<18;
00396 int j;
00397 for (j=0; j<chrFilterSize; j++)
00398 {
00399 u += chrSrc[j][i] * chrFilter[j];
00400 v += chrSrc[j][i + 2048] * chrFilter[j];
00401 }
00402
00403 uDest[i]= av_clip_uint8(u>>19);
00404 vDest[i]= av_clip_uint8(v>>19);
00405 }
00406 }
00407
00408 static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
00409 int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
00410 uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat)
00411 {
00412
00413 int i;
00414 for (i=0; i<dstW; i++)
00415 {
00416 int val=1<<18;
00417 int j;
00418 for (j=0; j<lumFilterSize; j++)
00419 val += lumSrc[j][i] * lumFilter[j];
00420
00421 dest[i]= av_clip_uint8(val>>19);
00422 }
00423
00424 if (!uDest)
00425 return;
00426
00427 if (dstFormat == PIX_FMT_NV12)
00428 for (i=0; i<chrDstW; i++)
00429 {
00430 int u=1<<18;
00431 int v=1<<18;
00432 int j;
00433 for (j=0; j<chrFilterSize; j++)
00434 {
00435 u += chrSrc[j][i] * chrFilter[j];
00436 v += chrSrc[j][i + 2048] * chrFilter[j];
00437 }
00438
00439 uDest[2*i]= av_clip_uint8(u>>19);
00440 uDest[2*i+1]= av_clip_uint8(v>>19);
00441 }
00442 else
00443 for (i=0; i<chrDstW; i++)
00444 {
00445 int u=1<<18;
00446 int v=1<<18;
00447 int j;
00448 for (j=0; j<chrFilterSize; j++)
00449 {
00450 u += chrSrc[j][i] * chrFilter[j];
00451 v += chrSrc[j][i + 2048] * chrFilter[j];
00452 }
00453
00454 uDest[2*i]= av_clip_uint8(v>>19);
00455 uDest[2*i+1]= av_clip_uint8(u>>19);
00456 }
00457 }
00458
00459 #define YSCALE_YUV_2_PACKEDX_C(type) \
00460 for (i=0; i<(dstW>>1); i++){\
00461 int j;\
00462 int Y1 = 1<<18;\
00463 int Y2 = 1<<18;\
00464 int U = 1<<18;\
00465 int V = 1<<18;\
00466 type av_unused *r, *b, *g;\
00467 const int i2= 2*i;\
00468 \
00469 for (j=0; j<lumFilterSize; j++)\
00470 {\
00471 Y1 += lumSrc[j][i2] * lumFilter[j];\
00472 Y2 += lumSrc[j][i2+1] * lumFilter[j];\
00473 }\
00474 for (j=0; j<chrFilterSize; j++)\
00475 {\
00476 U += chrSrc[j][i] * chrFilter[j];\
00477 V += chrSrc[j][i+2048] * chrFilter[j];\
00478 }\
00479 Y1>>=19;\
00480 Y2>>=19;\
00481 U >>=19;\
00482 V >>=19;\
00483 if ((Y1|Y2|U|V)&256)\
00484 {\
00485 if (Y1>255) Y1=255; \
00486 else if (Y1<0)Y1=0; \
00487 if (Y2>255) Y2=255; \
00488 else if (Y2<0)Y2=0; \
00489 if (U>255) U=255; \
00490 else if (U<0) U=0; \
00491 if (V>255) V=255; \
00492 else if (V<0) V=0; \
00493 }
00494
00495 #define YSCALE_YUV_2_RGBX_C(type) \
00496 YSCALE_YUV_2_PACKEDX_C(type) \
00497 r = (type *)c->table_rV[V]; \
00498 g = (type *)(c->table_gU[U] + c->table_gV[V]); \
00499 b = (type *)c->table_bU[U]; \
00500
00501 #define YSCALE_YUV_2_PACKED2_C \
00502 for (i=0; i<(dstW>>1); i++){ \
00503 const int i2= 2*i; \
00504 int Y1= (buf0[i2 ]*yalpha1+buf1[i2 ]*yalpha)>>19; \
00505 int Y2= (buf0[i2+1]*yalpha1+buf1[i2+1]*yalpha)>>19; \
00506 int U= (uvbuf0[i ]*uvalpha1+uvbuf1[i ]*uvalpha)>>19; \
00507 int V= (uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19; \
00508
00509 #define YSCALE_YUV_2_RGB2_C(type) \
00510 YSCALE_YUV_2_PACKED2_C\
00511 type *r, *b, *g;\
00512 r = (type *)c->table_rV[V];\
00513 g = (type *)(c->table_gU[U] + c->table_gV[V]);\
00514 b = (type *)c->table_bU[U];\
00515
00516 #define YSCALE_YUV_2_PACKED1_C \
00517 for (i=0; i<(dstW>>1); i++){\
00518 const int i2= 2*i;\
00519 int Y1= buf0[i2 ]>>7;\
00520 int Y2= buf0[i2+1]>>7;\
00521 int U= (uvbuf1[i ])>>7;\
00522 int V= (uvbuf1[i+2048])>>7;\
00523
00524 #define YSCALE_YUV_2_RGB1_C(type) \
00525 YSCALE_YUV_2_PACKED1_C\
00526 type *r, *b, *g;\
00527 r = (type *)c->table_rV[V];\
00528 g = (type *)(c->table_gU[U] + c->table_gV[V]);\
00529 b = (type *)c->table_bU[U];\
00530
00531 #define YSCALE_YUV_2_PACKED1B_C \
00532 for (i=0; i<(dstW>>1); i++){\
00533 const int i2= 2*i;\
00534 int Y1= buf0[i2 ]>>7;\
00535 int Y2= buf0[i2+1]>>7;\
00536 int U= (uvbuf0[i ] + uvbuf1[i ])>>8;\
00537 int V= (uvbuf0[i+2048] + uvbuf1[i+2048])>>8;\
00538
00539 #define YSCALE_YUV_2_RGB1B_C(type) \
00540 YSCALE_YUV_2_PACKED1B_C\
00541 type *r, *b, *g;\
00542 r = (type *)c->table_rV[V];\
00543 g = (type *)(c->table_gU[U] + c->table_gV[V]);\
00544 b = (type *)c->table_bU[U];\
00545
00546 #define YSCALE_YUV_2_ANYRGB_C(func, func2)\
00547 switch(c->dstFormat)\
00548 {\
00549 case PIX_FMT_RGB32:\
00550 case PIX_FMT_BGR32:\
00551 func(uint32_t)\
00552 ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
00553 ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
00554 } \
00555 break;\
00556 case PIX_FMT_RGB24:\
00557 func(uint8_t)\
00558 ((uint8_t*)dest)[0]= r[Y1];\
00559 ((uint8_t*)dest)[1]= g[Y1];\
00560 ((uint8_t*)dest)[2]= b[Y1];\
00561 ((uint8_t*)dest)[3]= r[Y2];\
00562 ((uint8_t*)dest)[4]= g[Y2];\
00563 ((uint8_t*)dest)[5]= b[Y2];\
00564 dest+=6;\
00565 }\
00566 break;\
00567 case PIX_FMT_BGR24:\
00568 func(uint8_t)\
00569 ((uint8_t*)dest)[0]= b[Y1];\
00570 ((uint8_t*)dest)[1]= g[Y1];\
00571 ((uint8_t*)dest)[2]= r[Y1];\
00572 ((uint8_t*)dest)[3]= b[Y2];\
00573 ((uint8_t*)dest)[4]= g[Y2];\
00574 ((uint8_t*)dest)[5]= r[Y2];\
00575 dest+=6;\
00576 }\
00577 break;\
00578 case PIX_FMT_RGB565:\
00579 case PIX_FMT_BGR565:\
00580 {\
00581 const int dr1= dither_2x2_8[y&1 ][0];\
00582 const int dg1= dither_2x2_4[y&1 ][0];\
00583 const int db1= dither_2x2_8[(y&1)^1][0];\
00584 const int dr2= dither_2x2_8[y&1 ][1];\
00585 const int dg2= dither_2x2_4[y&1 ][1];\
00586 const int db2= dither_2x2_8[(y&1)^1][1];\
00587 func(uint16_t)\
00588 ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
00589 ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
00590 }\
00591 }\
00592 break;\
00593 case PIX_FMT_RGB555:\
00594 case PIX_FMT_BGR555:\
00595 {\
00596 const int dr1= dither_2x2_8[y&1 ][0];\
00597 const int dg1= dither_2x2_8[y&1 ][1];\
00598 const int db1= dither_2x2_8[(y&1)^1][0];\
00599 const int dr2= dither_2x2_8[y&1 ][1];\
00600 const int dg2= dither_2x2_8[y&1 ][0];\
00601 const int db2= dither_2x2_8[(y&1)^1][1];\
00602 func(uint16_t)\
00603 ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
00604 ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
00605 }\
00606 }\
00607 break;\
00608 case PIX_FMT_RGB8:\
00609 case PIX_FMT_BGR8:\
00610 {\
00611 const uint8_t * const d64= dither_8x8_73[y&7];\
00612 const uint8_t * const d32= dither_8x8_32[y&7];\
00613 func(uint8_t)\
00614 ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]];\
00615 ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]];\
00616 }\
00617 }\
00618 break;\
00619 case PIX_FMT_RGB4:\
00620 case PIX_FMT_BGR4:\
00621 {\
00622 const uint8_t * const d64= dither_8x8_73 [y&7];\
00623 const uint8_t * const d128=dither_8x8_220[y&7];\
00624 func(uint8_t)\
00625 ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]\
00626 + ((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4);\
00627 }\
00628 }\
00629 break;\
00630 case PIX_FMT_RGB4_BYTE:\
00631 case PIX_FMT_BGR4_BYTE:\
00632 {\
00633 const uint8_t * const d64= dither_8x8_73 [y&7];\
00634 const uint8_t * const d128=dither_8x8_220[y&7];\
00635 func(uint8_t)\
00636 ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]];\
00637 ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]];\
00638 }\
00639 }\
00640 break;\
00641 case PIX_FMT_MONOBLACK:\
00642 {\
00643 const uint8_t * const d128=dither_8x8_220[y&7];\
00644 uint8_t *g= c->table_gU[128] + c->table_gV[128];\
00645 for (i=0; i<dstW-7; i+=8){\
00646 int acc;\
00647 acc = g[((buf0[i ]*yalpha1+buf1[i ]*yalpha)>>19) + d128[0]];\
00648 acc+= acc + g[((buf0[i+1]*yalpha1+buf1[i+1]*yalpha)>>19) + d128[1]];\
00649 acc+= acc + g[((buf0[i+2]*yalpha1+buf1[i+2]*yalpha)>>19) + d128[2]];\
00650 acc+= acc + g[((buf0[i+3]*yalpha1+buf1[i+3]*yalpha)>>19) + d128[3]];\
00651 acc+= acc + g[((buf0[i+4]*yalpha1+buf1[i+4]*yalpha)>>19) + d128[4]];\
00652 acc+= acc + g[((buf0[i+5]*yalpha1+buf1[i+5]*yalpha)>>19) + d128[5]];\
00653 acc+= acc + g[((buf0[i+6]*yalpha1+buf1[i+6]*yalpha)>>19) + d128[6]];\
00654 acc+= acc + g[((buf0[i+7]*yalpha1+buf1[i+7]*yalpha)>>19) + d128[7]];\
00655 ((uint8_t*)dest)[0]= acc;\
00656 dest++;\
00657 }\
00658 \
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 \
00703 }\
00704 break;\
00705 case PIX_FMT_YUYV422:\
00706 func2\
00707 ((uint8_t*)dest)[2*i2+0]= Y1;\
00708 ((uint8_t*)dest)[2*i2+1]= U;\
00709 ((uint8_t*)dest)[2*i2+2]= Y2;\
00710 ((uint8_t*)dest)[2*i2+3]= V;\
00711 } \
00712 break;\
00713 case PIX_FMT_UYVY422:\
00714 func2\
00715 ((uint8_t*)dest)[2*i2+0]= U;\
00716 ((uint8_t*)dest)[2*i2+1]= Y1;\
00717 ((uint8_t*)dest)[2*i2+2]= V;\
00718 ((uint8_t*)dest)[2*i2+3]= Y2;\
00719 } \
00720 break;\
00721 }\
00722
00723
00724 static inline void yuv2packedXinC(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
00725 int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
00726 uint8_t *dest, int dstW, int y)
00727 {
00728 int i;
00729 switch(c->dstFormat)
00730 {
00731 case PIX_FMT_BGR32:
00732 case PIX_FMT_RGB32:
00733 YSCALE_YUV_2_RGBX_C(uint32_t)
00734 ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];
00735 ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];
00736 }
00737 break;
00738 case PIX_FMT_RGB24:
00739 YSCALE_YUV_2_RGBX_C(uint8_t)
00740 ((uint8_t*)dest)[0]= r[Y1];
00741 ((uint8_t*)dest)[1]= g[Y1];
00742 ((uint8_t*)dest)[2]= b[Y1];
00743 ((uint8_t*)dest)[3]= r[Y2];
00744 ((uint8_t*)dest)[4]= g[Y2];
00745 ((uint8_t*)dest)[5]= b[Y2];
00746 dest+=6;
00747 }
00748 break;
00749 case PIX_FMT_BGR24:
00750 YSCALE_YUV_2_RGBX_C(uint8_t)
00751 ((uint8_t*)dest)[0]= b[Y1];
00752 ((uint8_t*)dest)[1]= g[Y1];
00753 ((uint8_t*)dest)[2]= r[Y1];
00754 ((uint8_t*)dest)[3]= b[Y2];
00755 ((uint8_t*)dest)[4]= g[Y2];
00756 ((uint8_t*)dest)[5]= r[Y2];
00757 dest+=6;
00758 }
00759 break;
00760 case PIX_FMT_RGB565:
00761 case PIX_FMT_BGR565:
00762 {
00763 const int dr1= dither_2x2_8[y&1 ][0];
00764 const int dg1= dither_2x2_4[y&1 ][0];
00765 const int db1= dither_2x2_8[(y&1)^1][0];
00766 const int dr2= dither_2x2_8[y&1 ][1];
00767 const int dg2= dither_2x2_4[y&1 ][1];
00768 const int db2= dither_2x2_8[(y&1)^1][1];
00769 YSCALE_YUV_2_RGBX_C(uint16_t)
00770 ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];
00771 ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];
00772 }
00773 }
00774 break;
00775 case PIX_FMT_RGB555:
00776 case PIX_FMT_BGR555:
00777 {
00778 const int dr1= dither_2x2_8[y&1 ][0];
00779 const int dg1= dither_2x2_8[y&1 ][1];
00780 const int db1= dither_2x2_8[(y&1)^1][0];
00781 const int dr2= dither_2x2_8[y&1 ][1];
00782 const int dg2= dither_2x2_8[y&1 ][0];
00783 const int db2= dither_2x2_8[(y&1)^1][1];
00784 YSCALE_YUV_2_RGBX_C(uint16_t)
00785 ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];
00786 ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];
00787 }
00788 }
00789 break;
00790 case PIX_FMT_RGB8:
00791 case PIX_FMT_BGR8:
00792 {
00793 const uint8_t * const d64= dither_8x8_73[y&7];
00794 const uint8_t * const d32= dither_8x8_32[y&7];
00795 YSCALE_YUV_2_RGBX_C(uint8_t)
00796 ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]];
00797 ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]];
00798 }
00799 }
00800 break;
00801 case PIX_FMT_RGB4:
00802 case PIX_FMT_BGR4:
00803 {
00804 const uint8_t * const d64= dither_8x8_73 [y&7];
00805 const uint8_t * const d128=dither_8x8_220[y&7];
00806 YSCALE_YUV_2_RGBX_C(uint8_t)
00807 ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]
00808 +((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4);
00809 }
00810 }
00811 break;
00812 case PIX_FMT_RGB4_BYTE:
00813 case PIX_FMT_BGR4_BYTE:
00814 {
00815 const uint8_t * const d64= dither_8x8_73 [y&7];
00816 const uint8_t * const d128=dither_8x8_220[y&7];
00817 YSCALE_YUV_2_RGBX_C(uint8_t)
00818 ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]];
00819 ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]];
00820 }
00821 }
00822 break;
00823 case PIX_FMT_MONOBLACK:
00824 {
00825 const uint8_t * const d128=dither_8x8_220[y&7];
00826 uint8_t *g= c->table_gU[128] + c->table_gV[128];
00827 int acc=0;
00828 for (i=0; i<dstW-1; i+=2){
00829 int j;
00830 int Y1=1<<18;
00831 int Y2=1<<18;
00832
00833 for (j=0; j<lumFilterSize; j++)
00834 {
00835 Y1 += lumSrc[j][i] * lumFilter[j];
00836 Y2 += lumSrc[j][i+1] * lumFilter[j];
00837 }
00838 Y1>>=19;
00839 Y2>>=19;
00840 if ((Y1|Y2)&256)
00841 {
00842 if (Y1>255) Y1=255;
00843 else if (Y1<0)Y1=0;
00844 if (Y2>255) Y2=255;
00845 else if (Y2<0)Y2=0;
00846 }
00847 acc+= acc + g[Y1+d128[(i+0)&7]];
00848 acc+= acc + g[Y2+d128[(i+1)&7]];
00849 if ((i&7)==6){
00850 ((uint8_t*)dest)[0]= acc;
00851 dest++;
00852 }
00853 }
00854 }
00855 break;
00856 case PIX_FMT_YUYV422:
00857 YSCALE_YUV_2_PACKEDX_C(void)
00858 ((uint8_t*)dest)[2*i2+0]= Y1;
00859 ((uint8_t*)dest)[2*i2+1]= U;
00860 ((uint8_t*)dest)[2*i2+2]= Y2;
00861 ((uint8_t*)dest)[2*i2+3]= V;
00862 }
00863 break;
00864 case PIX_FMT_UYVY422:
00865 YSCALE_YUV_2_PACKEDX_C(void)
00866 ((uint8_t*)dest)[2*i2+0]= U;
00867 ((uint8_t*)dest)[2*i2+1]= Y1;
00868 ((uint8_t*)dest)[2*i2+2]= V;
00869 ((uint8_t*)dest)[2*i2+3]= Y2;
00870 }
00871 break;
00872 }
00873 }
00874
00875
00876
00877
00878 #if !defined (HAVE_MMX) || defined (RUNTIME_CPUDETECT) || !defined(CONFIG_GPL)
00879 #define COMPILE_C
00880 #endif
00881
00882 #ifdef ARCH_POWERPC
00883 #if (defined (HAVE_ALTIVEC) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL)
00884 #define COMPILE_ALTIVEC
00885 #endif //HAVE_ALTIVEC
00886 #endif //ARCH_POWERPC
00887
00888 #if defined(ARCH_X86)
00889
00890 #if ((defined (HAVE_MMX) && !defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL)
00891 #define COMPILE_MMX
00892 #endif
00893
00894 #if (defined (HAVE_MMX2) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL)
00895 #define COMPILE_MMX2
00896 #endif
00897
00898 #if ((defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL)
00899 #define COMPILE_3DNOW
00900 #endif
00901 #endif //ARCH_X86 || ARCH_X86_64
00902
00903 #undef HAVE_MMX
00904 #undef HAVE_MMX2
00905 #undef HAVE_3DNOW
00906
00907 #ifdef COMPILE_C
00908 #undef HAVE_MMX
00909 #undef HAVE_MMX2
00910 #undef HAVE_3DNOW
00911 #undef HAVE_ALTIVEC
00912 #define RENAME(a) a ## _C
00913 #include "swscale_template.c"
00914 #endif
00915
00916 #ifdef ARCH_POWERPC
00917 #ifdef COMPILE_ALTIVEC
00918 #undef RENAME
00919 #define HAVE_ALTIVEC
00920 #define RENAME(a) a ## _altivec
00921 #include "swscale_template.c"
00922 #endif
00923 #endif //ARCH_POWERPC
00924
00925 #if defined(ARCH_X86)
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 #ifdef COMPILE_MMX
00939 #undef RENAME
00940 #define HAVE_MMX
00941 #undef HAVE_MMX2
00942 #undef HAVE_3DNOW
00943 #define RENAME(a) a ## _MMX
00944 #include "swscale_template.c"
00945 #endif
00946
00947
00948 #ifdef COMPILE_MMX2
00949 #undef RENAME
00950 #define HAVE_MMX
00951 #define HAVE_MMX2
00952 #undef HAVE_3DNOW
00953 #define RENAME(a) a ## _MMX2
00954 #include "swscale_template.c"
00955 #endif
00956
00957
00958 #ifdef COMPILE_3DNOW
00959 #undef RENAME
00960 #define HAVE_MMX
00961 #undef HAVE_MMX2
00962 #define HAVE_3DNOW
00963 #define RENAME(a) a ## _3DNow
00964 #include "swscale_template.c"
00965 #endif
00966
00967 #endif //ARCH_X86 || ARCH_X86_64
00968
00969
00970
00971 static double getSplineCoeff(double a, double b, double c, double d, double dist)
00972 {
00973
00974 if (dist<=1.0) return ((d*dist + c)*dist + b)*dist +a;
00975 else return getSplineCoeff( 0.0,
00976 b+ 2.0*c + 3.0*d,
00977 c + 3.0*d,
00978 -b- 3.0*c - 6.0*d,
00979 dist-1.0);
00980 }
00981
00982 static inline int initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc,
00983 int srcW, int dstW, int filterAlign, int one, int flags,
00984 SwsVector *srcFilter, SwsVector *dstFilter, double param[2])
00985 {
00986 int i;
00987 int filterSize;
00988 int filter2Size;
00989 int minFilterSize;
00990 double *filter=NULL;
00991 double *filter2=NULL;
00992 #if defined(ARCH_X86)
00993 if (flags & SWS_CPU_CAPS_MMX)
00994 asm volatile("emms\n\t"::: "memory");
00995 #endif
00996
00997
00998 *filterPos = av_malloc((dstW+1)*sizeof(int16_t));
00999
01000 if (FFABS(xInc - 0x10000) <10)
01001 {
01002 int i;
01003 filterSize= 1;
01004 filter= av_malloc(dstW*sizeof(double)*filterSize);
01005 for (i=0; i<dstW*filterSize; i++) filter[i]=0;
01006
01007 for (i=0; i<dstW; i++)
01008 {
01009 filter[i*filterSize]=1;
01010 (*filterPos)[i]=i;
01011 }
01012
01013 }
01014 else if (flags&SWS_POINT)
01015 {
01016 int i;
01017 int xDstInSrc;
01018 filterSize= 1;
01019 filter= av_malloc(dstW*sizeof(double)*filterSize);
01020
01021 xDstInSrc= xInc/2 - 0x8000;
01022 for (i=0; i<dstW; i++)
01023 {
01024 int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16;
01025
01026 (*filterPos)[i]= xx;
01027 filter[i]= 1.0;
01028 xDstInSrc+= xInc;
01029 }
01030 }
01031 else if ((xInc <= (1<<16) && (flags&SWS_AREA)) || (flags&SWS_FAST_BILINEAR))
01032 {
01033 int i;
01034 int xDstInSrc;
01035 if (flags&SWS_BICUBIC) filterSize= 4;
01036 else if (flags&SWS_X ) filterSize= 4;
01037 else filterSize= 2;
01038 filter= av_malloc(dstW*sizeof(double)*filterSize);
01039
01040 xDstInSrc= xInc/2 - 0x8000;
01041 for (i=0; i<dstW; i++)
01042 {
01043 int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16;
01044 int j;
01045
01046 (*filterPos)[i]= xx;
01047
01048 for (j=0; j<filterSize; j++)
01049 {
01050 double d= FFABS((xx<<16) - xDstInSrc)/(double)(1<<16);
01051 double coeff= 1.0 - d;
01052 if (coeff<0) coeff=0;
01053 filter[i*filterSize + j]= coeff;
01054 xx++;
01055 }
01056 xDstInSrc+= xInc;
01057 }
01058 }
01059 else
01060 {
01061 double xDstInSrc;
01062 double sizeFactor, filterSizeInSrc;
01063 const double xInc1= (double)xInc / (double)(1<<16);
01064
01065 if (flags&SWS_BICUBIC) sizeFactor= 4.0;
01066 else if (flags&SWS_X) sizeFactor= 8.0;
01067 else if (flags&SWS_AREA) sizeFactor= 1.0;
01068 else if (flags&SWS_GAUSS) sizeFactor= 8.0;
01069 else if (flags&SWS_LANCZOS) sizeFactor= param[0] != SWS_PARAM_DEFAULT ? 2.0*param[0] : 6.0;
01070 else if (flags&SWS_SINC) sizeFactor= 20.0;
01071 else if (flags&SWS_SPLINE) sizeFactor= 20.0;
01072 else if (flags&SWS_BILINEAR) sizeFactor= 2.0;
01073 else {
01074 sizeFactor= 0.0;
01075 ASSERT(0)
01076 }
01077
01078 if (xInc1 <= 1.0) filterSizeInSrc= sizeFactor;
01079 else filterSizeInSrc= sizeFactor*srcW / (double)dstW;
01080
01081 filterSize= (int)ceil(1 + filterSizeInSrc);
01082 if (filterSize > srcW-2) filterSize=srcW-2;
01083
01084 filter= av_malloc(dstW*sizeof(double)*filterSize);
01085
01086 xDstInSrc= xInc1 / 2.0 - 0.5;
01087 for (i=0; i<dstW; i++)
01088 {
01089 int xx= (int)(xDstInSrc - (filterSize-1)*0.5 + 0.5);
01090 int j;
01091 (*filterPos)[i]= xx;
01092 for (j=0; j<filterSize; j++)
01093 {
01094 double d= FFABS(xx - xDstInSrc)/filterSizeInSrc*sizeFactor;
01095 double coeff;
01096 if (flags & SWS_BICUBIC)
01097 {
01098 double B= param[0] != SWS_PARAM_DEFAULT ? param[0] : 0.0;
01099 double C= param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6;
01100
01101 if (d<1.0)
01102 coeff = (12-9*B-6*C)*d*d*d + (-18+12*B+6*C)*d*d + 6-2*B;
01103 else if (d<2.0)
01104 coeff = (-B-6*C)*d*d*d + (6*B+30*C)*d*d + (-12*B-48*C)*d +8*B+24*C;
01105 else
01106 coeff=0.0;
01107 }
01108
01109
01110
01111
01112
01113
01114 else if (flags & SWS_X)
01115 {
01116 double A= param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0;
01117
01118 if (d<1.0)
01119 coeff = cos(d*PI);
01120 else
01121 coeff=-1.0;
01122 if (coeff<0.0) coeff= -pow(-coeff, A);
01123 else coeff= pow( coeff, A);
01124 coeff= coeff*0.5 + 0.5;
01125 }
01126 else if (flags & SWS_AREA)
01127 {
01128 double srcPixelSize= 1.0/xInc1;
01129 if (d + srcPixelSize/2 < 0.5) coeff= 1.0;
01130 else if (d - srcPixelSize/2 < 0.5) coeff= (0.5-d)/srcPixelSize + 0.5;
01131 else coeff=0.0;
01132 }
01133 else if (flags & SWS_GAUSS)
01134 {
01135 double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
01136 coeff = pow(2.0, - p*d*d);
01137 }
01138 else if (flags & SWS_SINC)
01139 {
01140 coeff = d ? sin(d*PI)/(d*PI) : 1.0;
01141 }
01142 else if (flags & SWS_LANCZOS)
01143 {
01144 double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
01145 coeff = d ? sin(d*PI)*sin(d*PI/p)/(d*d*PI*PI/p) : 1.0;
01146 if (d>p) coeff=0;
01147 }
01148 else if (flags & SWS_BILINEAR)
01149 {
01150 coeff= 1.0 - d;
01151 if (coeff<0) coeff=0;
01152 }
01153 else if (flags & SWS_SPLINE)
01154 {
01155 double p=-2.196152422706632;
01156 coeff = getSplineCoeff(1.0, 0.0, p, -p-1.0, d);
01157 }
01158 else {
01159 coeff= 0.0;
01160 ASSERT(0)
01161 }
01162
01163 filter[i*filterSize + j]= coeff;
01164 xx++;
01165 }
01166 xDstInSrc+= xInc1;
01167 }
01168 }
01169
01170
01171
01172
01173 ASSERT(filterSize>0)
01174 filter2Size= filterSize;
01175 if (srcFilter) filter2Size+= srcFilter->length - 1;
01176 if (dstFilter) filter2Size+= dstFilter->length - 1;
01177 ASSERT(filter2Size>0)
01178 filter2= av_malloc(filter2Size*dstW*sizeof(double));
01179
01180 for (i=0; i<dstW; i++)
01181 {
01182 int j;
01183 SwsVector scaleFilter;
01184 SwsVector *outVec;
01185
01186 scaleFilter.coeff= filter + i*filterSize;
01187 scaleFilter.length= filterSize;
01188
01189 if (srcFilter) outVec= sws_getConvVec(srcFilter, &scaleFilter);
01190 else outVec= &scaleFilter;
01191
01192 ASSERT(outVec->length == filter2Size)
01193
01194
01195 for (j=0; j<outVec->length; j++)
01196 {
01197 filter2[i*filter2Size + j]= outVec->coeff[j];
01198 }
01199
01200 (*filterPos)[i]+= (filterSize-1)/2 - (filter2Size-1)/2;
01201
01202 if (outVec != &scaleFilter) sws_freeVec(outVec);
01203 }
01204 av_free(filter); filter=NULL;
01205
01206
01207
01208 minFilterSize= 0;
01209 for (i=dstW-1; i>=0; i--)
01210 {
01211 int min= filter2Size;
01212 int j;
01213 double cutOff=0.0;
01214
01215
01216 for (j=0; j<filter2Size; j++)
01217 {
01218 int k;
01219 cutOff += FFABS(filter2[i*filter2Size]);
01220
01221 if (cutOff > SWS_MAX_REDUCE_CUTOFF) break;
01222
01223
01224 if (i<dstW-1 && (*filterPos)[i] >= (*filterPos)[i+1]) break;
01225
01226
01227 for (k=1; k<filter2Size; k++)
01228 filter2[i*filter2Size + k - 1]= filter2[i*filter2Size + k];
01229 filter2[i*filter2Size + k - 1]= 0.0;
01230 (*filterPos)[i]++;
01231 }
01232
01233 cutOff=0.0;
01234
01235 for (j=filter2Size-1; j>0; j--)
01236 {
01237 cutOff += FFABS(filter2[i*filter2Size + j]);
01238
01239 if (cutOff > SWS_MAX_REDUCE_CUTOFF) break;
01240 min--;
01241 }
01242
01243 if (min>minFilterSize) minFilterSize= min;
01244 }
01245
01246 if (flags & SWS_CPU_CAPS_ALTIVEC) {
01247
01248
01249 if (minFilterSize < 5)
01250 filterAlign = 4;
01251
01252
01253
01254
01255
01256
01257 if (minFilterSize < 3)
01258 filterAlign = 1;
01259 }
01260
01261 if (flags & SWS_CPU_CAPS_MMX) {
01262
01263 if (minFilterSize == 1 && filterAlign == 2)
01264 filterAlign= 1;
01265 }
01266
01267 ASSERT(minFilterSize > 0)
01268 filterSize= (minFilterSize +(filterAlign-1)) & (~(filterAlign-1));
01269 ASSERT(filterSize > 0)
01270 filter= av_malloc(filterSize*dstW*sizeof(double));
01271 if (filterSize >= MAX_FILTER_SIZE)
01272 return -1;
01273 *outFilterSize= filterSize;
01274
01275 if (flags&SWS_PRINT_INFO)
01276 av_log(NULL, AV_LOG_VERBOSE, "SwScaler: reducing / aligning filtersize %d -> %d\n", filter2Size, filterSize);
01277
01278 for (i=0; i<dstW; i++)
01279 {
01280 int j;
01281
01282 for (j=0; j<filterSize; j++)
01283 {
01284 if (j>=filter2Size) filter[i*filterSize + j]= 0.0;
01285 else filter[i*filterSize + j]= filter2[i*filter2Size + j];
01286 }
01287 }
01288 av_free(filter2); filter2=NULL;
01289
01290
01291
01292
01293
01294 for (i=0; i<dstW; i++)
01295 {
01296 int j;
01297 if ((*filterPos)[i] < 0)
01298 {
01299
01300 for (j=1; j<filterSize; j++)
01301 {
01302 int left= FFMAX(j + (*filterPos)[i], 0);
01303 filter[i*filterSize + left] += filter[i*filterSize + j];
01304 filter[i*filterSize + j]=0;
01305 }
01306 (*filterPos)[i]= 0;
01307 }
01308
01309 if ((*filterPos)[i] + filterSize > srcW)
01310 {
01311 int shift= (*filterPos)[i] + filterSize - srcW;
01312
01313 for (j=filterSize-2; j>=0; j--)
01314 {
01315 int right= FFMIN(j + shift, filterSize-1);
01316 filter[i*filterSize +right] += filter[i*filterSize +j];
01317 filter[i*filterSize +j]=0;
01318 }
01319 (*filterPos)[i]= srcW - filterSize;
01320 }
01321 }
01322
01323
01324
01325 *outFilter= av_mallocz(*outFilterSize*(dstW+1)*sizeof(int16_t));
01326
01327
01328 for (i=0; i<dstW; i++)
01329 {
01330 int j;
01331 double error=0;
01332 double sum=0;
01333 double scale= one;
01334
01335 for (j=0; j<filterSize; j++)
01336 {
01337 sum+= filter[i*filterSize + j];
01338 }
01339 scale/= sum;
01340 for (j=0; j<*outFilterSize; j++)
01341 {
01342 double v= filter[i*filterSize + j]*scale + error;
01343 int intV= floor(v + 0.5);
01344 (*outFilter)[i*(*outFilterSize) + j]= intV;
01345 error = v - intV;
01346 }
01347 }
01348
01349 (*filterPos)[dstW]= (*filterPos)[dstW-1];
01350 for (i=0; i<*outFilterSize; i++)
01351 {
01352 int j= dstW*(*outFilterSize);
01353 (*outFilter)[j + i]= (*outFilter)[j + i - (*outFilterSize)];
01354 }
01355
01356 av_free(filter);
01357 return 0;
01358 }
01359
01360 #if defined (COMPILE_MMX2) && !defined(ARCH_X86_64)
01361 static void initMMX2HScaler(int dstW, int xInc, uint8_t *funnyCode, int16_t *filter, int32_t *filterPos, int numSplits)
01362 {
01363 uint8_t *fragmentA;
01364 long imm8OfPShufW1A;
01365 long imm8OfPShufW2A;
01366 long fragmentLengthA;
01367 uint8_t *fragmentB;
01368 long imm8OfPShufW1B;
01369 long imm8OfPShufW2B;
01370 long fragmentLengthB;
01371 int fragmentPos;
01372
01373 int xpos, i;
01374
01375
01376
01377
01378
01379 asm volatile(
01380 "jmp 9f \n\t"
01381
01382 "0: \n\t"
01383 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
01384 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
01385 "movd 1(%%"REG_c", %%"REG_S"), %%mm1 \n\t"
01386 "punpcklbw %%mm7, %%mm1 \n\t"
01387 "punpcklbw %%mm7, %%mm0 \n\t"
01388 "pshufw $0xFF, %%mm1, %%mm1 \n\t"
01389 "1: \n\t"
01390 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
01391 "2: \n\t"
01392 "psubw %%mm1, %%mm0 \n\t"
01393 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
01394 "pmullw %%mm3, %%mm0 \n\t"
01395 "psllw $7, %%mm1 \n\t"
01396 "paddw %%mm1, %%mm0 \n\t"
01397
01398 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
01399
01400 "add $8, %%"REG_a" \n\t"
01401
01402 "9: \n\t"
01403
01404 "lea 0b, %0 \n\t"
01405 "lea 1b, %1 \n\t"
01406 "lea 2b, %2 \n\t"
01407 "dec %1 \n\t"
01408 "dec %2 \n\t"
01409 "sub %0, %1 \n\t"
01410 "sub %0, %2 \n\t"
01411 "lea 9b, %3 \n\t"
01412 "sub %0, %3 \n\t"
01413
01414
01415 :"=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A),
01416 "=r" (fragmentLengthA)
01417 );
01418
01419 asm volatile(
01420 "jmp 9f \n\t"
01421
01422 "0: \n\t"
01423 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
01424 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
01425 "punpcklbw %%mm7, %%mm0 \n\t"
01426 "pshufw $0xFF, %%mm0, %%mm1 \n\t"
01427 "1: \n\t"
01428 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
01429 "2: \n\t"
01430 "psubw %%mm1, %%mm0 \n\t"
01431 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
01432 "pmullw %%mm3, %%mm0 \n\t"
01433 "psllw $7, %%mm1 \n\t"
01434 "paddw %%mm1, %%mm0 \n\t"
01435
01436 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
01437
01438 "add $8, %%"REG_a" \n\t"
01439
01440 "9: \n\t"
01441
01442 "lea 0b, %0 \n\t"
01443 "lea 1b, %1 \n\t"
01444 "lea 2b, %2 \n\t"
01445 "dec %1 \n\t"
01446 "dec %2 \n\t"
01447 "sub %0, %1 \n\t"
01448 "sub %0, %2 \n\t"
01449 "lea 9b, %3 \n\t"
01450 "sub %0, %3 \n\t"
01451
01452
01453 :"=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B),
01454 "=r" (fragmentLengthB)
01455 );
01456
01457 xpos= 0;
01458 fragmentPos=0;
01459
01460 for (i=0; i<dstW/numSplits; i++)
01461 {
01462 int xx=xpos>>16;
01463
01464 if ((i&3) == 0)
01465 {
01466 int a=0;
01467 int b=((xpos+xInc)>>16) - xx;
01468 int c=((xpos+xInc*2)>>16) - xx;
01469 int d=((xpos+xInc*3)>>16) - xx;
01470
01471 filter[i ] = (( xpos & 0xFFFF) ^ 0xFFFF)>>9;
01472 filter[i+1] = (((xpos+xInc ) & 0xFFFF) ^ 0xFFFF)>>9;
01473 filter[i+2] = (((xpos+xInc*2) & 0xFFFF) ^ 0xFFFF)>>9;
01474 filter[i+3] = (((xpos+xInc*3) & 0xFFFF) ^ 0xFFFF)>>9;
01475 filterPos[i/2]= xx;
01476
01477 if (d+1<4)
01478 {
01479 int maxShift= 3-(d+1);
01480 int shift=0;
01481
01482 memcpy(funnyCode + fragmentPos, fragmentB, fragmentLengthB);
01483
01484 funnyCode[fragmentPos + imm8OfPShufW1B]=
01485 (a+1) | ((b+1)<<2) | ((c+1)<<4) | ((d+1)<<6);
01486 funnyCode[fragmentPos + imm8OfPShufW2B]=
01487 a | (b<<2) | (c<<4) | (d<<6);
01488
01489 if (i+3>=dstW) shift=maxShift;
01490 else if ((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3;
01491
01492 if (shift && i>=shift)
01493 {
01494 funnyCode[fragmentPos + imm8OfPShufW1B]+= 0x55*shift;
01495 funnyCode[fragmentPos + imm8OfPShufW2B]+= 0x55*shift;
01496 filterPos[i/2]-=shift;
01497 }
01498
01499 fragmentPos+= fragmentLengthB;
01500 }
01501 else
01502 {
01503 int maxShift= 3-d;
01504 int shift=0;
01505
01506 memcpy(funnyCode + fragmentPos, fragmentA, fragmentLengthA);
01507
01508 funnyCode[fragmentPos + imm8OfPShufW1A]=
01509 funnyCode[fragmentPos + imm8OfPShufW2A]=
01510 a | (b<<2) | (c<<4) | (d<<6);
01511
01512 if (i+4>=dstW) shift=maxShift;
01513 else if ((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3;
01514
01515 if (shift && i>=shift)
01516 {
01517 funnyCode[fragmentPos + imm8OfPShufW1A]+= 0x55*shift;
01518 funnyCode[fragmentPos + imm8OfPShufW2A]+= 0x55*shift;
01519 filterPos[i/2]-=shift;
01520 }
01521
01522 fragmentPos+= fragmentLengthA;
01523 }
01524
01525 funnyCode[fragmentPos]= RET;
01526 }
01527 xpos+=xInc;
01528 }
01529 filterPos[i/2]= xpos>>16;
01530 }
01531 #endif
01532
01533 static void globalInit(void){
01534
01535 int i;
01536 for (i=0; i<768; i++){
01537 int c= av_clip_uint8(i-256);
01538 clip_table[i]=c;
01539 }
01540 }
01541
01542 static SwsFunc getSwsFunc(int flags){
01543
01544 #if defined(RUNTIME_CPUDETECT) && defined (CONFIG_GPL)
01545 #if defined(ARCH_X86)
01546
01547 if (flags & SWS_CPU_CAPS_MMX2)
01548 return swScale_MMX2;
01549 else if (flags & SWS_CPU_CAPS_3DNOW)
01550 return swScale_3DNow;
01551 else if (flags & SWS_CPU_CAPS_MMX)
01552 return swScale_MMX;
01553 else
01554 return swScale_C;
01555
01556 #else
01557 #ifdef ARCH_POWERPC
01558 if (flags & SWS_CPU_CAPS_ALTIVEC)
01559 return swScale_altivec;
01560 else
01561 return swScale_C;
01562 #endif
01563 return swScale_C;
01564 #endif
01565 #else //RUNTIME_CPUDETECT
01566 #ifdef HAVE_MMX2
01567 return swScale_MMX2;
01568 #elif defined (HAVE_3DNOW)
01569 return swScale_3DNow;
01570 #elif defined (HAVE_MMX)
01571 return swScale_MMX;
01572 #elif defined (HAVE_ALTIVEC)
01573 return swScale_altivec;
01574 #else
01575 return swScale_C;
01576 #endif
01577 #endif
01578 }
01579
01580 static int PlanarToNV12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01581 int srcSliceH, uint8_t* dstParam[], int dstStride[]){
01582 uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
01583
01584 if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
01585 memcpy(dst, src[0], srcSliceH*dstStride[0]);
01586 else
01587 {
01588 int i;
01589 uint8_t *srcPtr= src[0];
01590 uint8_t *dstPtr= dst;
01591 for (i=0; i<srcSliceH; i++)
01592 {
01593 memcpy(dstPtr, srcPtr, c->srcW);
01594 srcPtr+= srcStride[0];
01595 dstPtr+= dstStride[0];
01596 }
01597 }
01598 dst = dstParam[1] + dstStride[1]*srcSliceY/2;
01599 if (c->dstFormat == PIX_FMT_NV12)
01600 interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]);
01601 else
01602 interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]);
01603
01604 return srcSliceH;
01605 }
01606
01607 static int PlanarToYuy2Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01608 int srcSliceH, uint8_t* dstParam[], int dstStride[]){
01609 uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
01610
01611 yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
01612
01613 return srcSliceH;
01614 }
01615
01616 static int PlanarToUyvyWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01617 int srcSliceH, uint8_t* dstParam[], int dstStride[]){
01618 uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
01619
01620 yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
01621
01622 return srcSliceH;
01623 }
01624
01625
01626 static int rgb2rgbWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01627 int srcSliceH, uint8_t* dst[], int dstStride[]){
01628 const int srcFormat= c->srcFormat;
01629 const int dstFormat= c->dstFormat;
01630 const int srcBpp= (fmt_depth(srcFormat) + 7) >> 3;
01631 const int dstBpp= (fmt_depth(dstFormat) + 7) >> 3;
01632 const int srcId= fmt_depth(srcFormat) >> 2;
01633 const int dstId= fmt_depth(dstFormat) >> 2;
01634 void (*conv)(const uint8_t *src, uint8_t *dst, long src_size)=NULL;
01635
01636
01637 if ( (isBGR(srcFormat) && isBGR(dstFormat))
01638 || (isRGB(srcFormat) && isRGB(dstFormat))){
01639 switch(srcId | (dstId<<4)){
01640 case 0x34: conv= rgb16to15; break;
01641 case 0x36: conv= rgb24to15; break;
01642 case 0x38: conv= rgb32to15; break;
01643 case 0x43: conv= rgb15to16; break;
01644 case 0x46: conv= rgb24to16; break;
01645 case 0x48: conv= rgb32to16; break;
01646 case 0x63: conv= rgb15to24; break;
01647 case 0x64: conv= rgb16to24; break;
01648 case 0x68: conv= rgb32to24; break;
01649 case 0x83: conv= rgb15to32; break;
01650 case 0x84: conv= rgb16to32; break;
01651 case 0x86: conv= rgb24to32; break;
01652 default: av_log(c, AV_LOG_ERROR, "swScaler: internal error %s -> %s converter\n",
01653 sws_format_name(srcFormat), sws_format_name(dstFormat)); break;
01654 }
01655 }else if ( (isBGR(srcFormat) && isRGB(dstFormat))
01656 || (isRGB(srcFormat) && isBGR(dstFormat))){
01657 switch(srcId | (dstId<<4)){
01658 case 0x33: conv= rgb15tobgr15; break;
01659 case 0x34: conv= rgb16tobgr15; break;
01660 case 0x36: conv= rgb24tobgr15; break;
01661 case 0x38: conv= rgb32tobgr15; break;
01662 case 0x43: conv= rgb15tobgr16; break;
01663 case 0x44: conv= rgb16tobgr16; break;
01664 case 0x46: conv= rgb24tobgr16; break;
01665 case 0x48: conv= rgb32tobgr16; break;
01666 case 0x63: conv= rgb15tobgr24; break;
01667 case 0x64: conv= rgb16tobgr24; break;
01668 case 0x66: conv= rgb24tobgr24; break;
01669 case 0x68: conv= rgb32tobgr24; break;
01670 case 0x83: conv= rgb15tobgr32; break;
01671 case 0x84: conv= rgb16tobgr32; break;
01672 case 0x86: conv= rgb24tobgr32; break;
01673 case 0x88: conv= rgb32tobgr32; break;
01674 default: av_log(c, AV_LOG_ERROR, "swScaler: internal error %s -> %s converter\n",
01675 sws_format_name(srcFormat), sws_format_name(dstFormat)); break;
01676 }
01677 }else{
01678 av_log(c, AV_LOG_ERROR, "swScaler: internal error %s -> %s converter\n",
01679 sws_format_name(srcFormat), sws_format_name(dstFormat));
01680 }
01681
01682 if(conv)
01683 {
01684 if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0)
01685 conv(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
01686 else
01687 {
01688 int i;
01689 uint8_t *srcPtr= src[0];
01690 uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
01691
01692 for (i=0; i<srcSliceH; i++)
01693 {
01694 conv(srcPtr, dstPtr, c->srcW*srcBpp);
01695 srcPtr+= srcStride[0];
01696 dstPtr+= dstStride[0];
01697 }
01698 }
01699 }
01700 return srcSliceH;
01701 }
01702
01703 static int bgr24toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01704 int srcSliceH, uint8_t* dst[], int dstStride[]){
01705
01706 rgb24toyv12(
01707 src[0],
01708 dst[0]+ srcSliceY *dstStride[0],
01709 dst[1]+(srcSliceY>>1)*dstStride[1],
01710 dst[2]+(srcSliceY>>1)*dstStride[2],
01711 c->srcW, srcSliceH,
01712 dstStride[0], dstStride[1], srcStride[0]);
01713 return srcSliceH;
01714 }
01715
01716 static int yvu9toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01717 int srcSliceH, uint8_t* dst[], int dstStride[]){
01718 int i;
01719
01720
01721 if (srcStride[0]==dstStride[0] && srcStride[0] > 0)
01722 memcpy(dst[0]+ srcSliceY*dstStride[0], src[0], srcStride[0]*srcSliceH);
01723 else{
01724 uint8_t *srcPtr= src[0];
01725 uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
01726
01727 for (i=0; i<srcSliceH; i++)
01728 {
01729 memcpy(dstPtr, srcPtr, c->srcW);
01730 srcPtr+= srcStride[0];
01731 dstPtr+= dstStride[0];
01732 }
01733 }
01734
01735 if (c->dstFormat==PIX_FMT_YUV420P){
01736 planar2x(src[1], dst[1], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[1]);
01737 planar2x(src[2], dst[2], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[2]);
01738 }else{
01739 planar2x(src[1], dst[2], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[2]);
01740 planar2x(src[2], dst[1], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[1]);
01741 }
01742 return srcSliceH;
01743 }
01744
01745
01746 static int simpleCopy(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01747 int srcSliceH, uint8_t* dst[], int dstStride[]){
01748
01749 if (isPacked(c->srcFormat))
01750 {
01751 if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
01752 memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
01753 else
01754 {
01755 int i;
01756 uint8_t *srcPtr= src[0];
01757 uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
01758 int length=0;
01759
01760
01761 while(length+c->srcW <= FFABS(dstStride[0])
01762 && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW;
01763 ASSERT(length!=0);
01764
01765 for (i=0; i<srcSliceH; i++)
01766 {
01767 memcpy(dstPtr, srcPtr, length);
01768 srcPtr+= srcStride[0];
01769 dstPtr+= dstStride[0];
01770 }
01771 }
01772 }
01773 else
01774 {
01775 int plane;
01776 for (plane=0; plane<3; plane++)
01777 {
01778 int length= plane==0 ? c->srcW : -((-c->srcW )>>c->chrDstHSubSample);
01779 int y= plane==0 ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
01780 int height= plane==0 ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
01781
01782 if ((isGray(c->srcFormat) || isGray(c->dstFormat)) && plane>0)
01783 {
01784 if (!isGray(c->dstFormat))
01785 memset(dst[plane], 128, dstStride[plane]*height);
01786 }
01787 else
01788 {
01789 if (dstStride[plane]==srcStride[plane] && srcStride[plane] > 0)
01790 memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]);
01791 else
01792 {
01793 int i;
01794 uint8_t *srcPtr= src[plane];
01795 uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
01796 for (i=0; i<height; i++)
01797 {
01798 memcpy(dstPtr, srcPtr, length);
01799 srcPtr+= srcStride[plane];
01800 dstPtr+= dstStride[plane];
01801 }
01802 }
01803 }
01804 }
01805 }
01806 return srcSliceH;
01807 }
01808
01809 static int gray16togray(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01810 int srcSliceH, uint8_t* dst[], int dstStride[]){
01811
01812 int length= c->srcW;
01813 int y= srcSliceY;
01814 int height= srcSliceH;
01815 int i, j;
01816 uint8_t *srcPtr= src[0];
01817 uint8_t *dstPtr= dst[0] + dstStride[0]*y;
01818
01819 if (!isGray(c->dstFormat)){
01820 int height= -((-srcSliceH)>>c->chrDstVSubSample);
01821 memset(dst[1], 128, dstStride[1]*height);
01822 memset(dst[2], 128, dstStride[2]*height);
01823 }
01824 if (c->srcFormat == PIX_FMT_GRAY16LE) srcPtr++;
01825 for (i=0; i<height; i++)
01826 {
01827 for (j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1];
01828 srcPtr+= srcStride[0];
01829 dstPtr+= dstStride[0];
01830 }
01831 return srcSliceH;
01832 }
01833
01834 static int graytogray16(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01835 int srcSliceH, uint8_t* dst[], int dstStride[]){
01836
01837 int length= c->srcW;
01838 int y= srcSliceY;
01839 int height= srcSliceH;
01840 int i, j;
01841 uint8_t *srcPtr= src[0];
01842 uint8_t *dstPtr= dst[0] + dstStride[0]*y;
01843 for (i=0; i<height; i++)
01844 {
01845 for (j=0; j<length; j++)
01846 {
01847 dstPtr[j<<1] = srcPtr[j];
01848 dstPtr[(j<<1)+1] = srcPtr[j];
01849 }
01850 srcPtr+= srcStride[0];
01851 dstPtr+= dstStride[0];
01852 }
01853 return srcSliceH;
01854 }
01855
01856 static int gray16swap(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
01857 int srcSliceH, uint8_t* dst[], int dstStride[]){
01858
01859 int length= c->srcW;
01860 int y= srcSliceY;
01861 int height= srcSliceH;
01862 int i, j;
01863 uint16_t *srcPtr= src[0];
01864 uint16_t *dstPtr= dst[0] + dstStride[0]*y/2;
01865 for (i=0; i<height; i++)
01866 {
01867 for (j=0; j<length; j++) dstPtr[j] = bswap_16(srcPtr[j]);
01868 srcPtr+= srcStride[0]/2;
01869 dstPtr+= dstStride[0]/2;
01870 }
01871 return srcSliceH;
01872 }
01873
01874
01875 static void getSubSampleFactors(int *h, int *v, int format){
01876 switch(format){
01877 case PIX_FMT_UYVY422:
01878 case PIX_FMT_YUYV422:
01879 *h=1;
01880 *v=0;
01881 break;
01882 case PIX_FMT_YUV420P:
01883 case PIX_FMT_YUVA420P:
01884 case PIX_FMT_GRAY16BE:
01885 case PIX_FMT_GRAY16LE:
01886 case PIX_FMT_GRAY8:
01887 case PIX_FMT_NV12:
01888 case PIX_FMT_NV21:
01889 *h=1;
01890 *v=1;
01891 break;
01892 case PIX_FMT_YUV440P:
01893 *h=0;
01894 *v=1;
01895 break;
01896 case PIX_FMT_YUV410P:
01897 *h=2;
01898 *v=2;
01899 break;
01900 case PIX_FMT_YUV444P:
01901 *h=0;
01902 *v=0;
01903 break;
01904 case PIX_FMT_YUV422P:
01905 *h=1;
01906 *v=0;
01907 break;
01908 case PIX_FMT_YUV411P:
01909 *h=2;
01910 *v=0;
01911 break;
01912 default:
01913 *h=0;
01914 *v=0;
01915 break;
01916 }
01917 }
01918
01919 static uint16_t roundToInt16(int64_t f){
01920 int r= (f + (1<<15))>>16;
01921 if (r<-0x7FFF) return 0x8000;
01922 else if (r> 0x7FFF) return 0x7FFF;
01923 else return r;
01924 }
01925
01931 int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation){
01932 int64_t crv = inv_table[0];
01933 int64_t cbu = inv_table[1];
01934 int64_t cgu = -inv_table[2];
01935 int64_t cgv = -inv_table[3];
01936 int64_t cy = 1<<16;
01937 int64_t oy = 0;
01938
01939 if (isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
01940 memcpy(c->srcColorspaceTable, inv_table, sizeof(int)*4);
01941 memcpy(c->dstColorspaceTable, table, sizeof(int)*4);
01942
01943 c->brightness= brightness;
01944 c->contrast = contrast;
01945 c->saturation= saturation;
01946 c->srcRange = srcRange;
01947 c->dstRange = dstRange;
01948
01949 c->uOffset= 0x0400040004000400LL;
01950 c->vOffset= 0x0400040004000400LL;
01951
01952 if (!srcRange){
01953 cy= (cy*255) / 219;
01954 oy= 16<<16;
01955 }else{
01956 crv= (crv*224) / 255;
01957 cbu= (cbu*224) / 255;
01958 cgu= (cgu*224) / 255;
01959 cgv= (cgv*224) / 255;
01960 }
01961
01962 cy = (cy *contrast )>>16;
01963 crv= (crv*contrast * saturation)>>32;
01964 cbu= (cbu*contrast * saturation)>>32;
01965 cgu= (cgu*contrast * saturation)>>32;
01966 cgv= (cgv*contrast * saturation)>>32;
01967
01968 oy -= 256*brightness;
01969
01970 c->yCoeff= roundToInt16(cy *8192) * 0x0001000100010001ULL;
01971 c->vrCoeff= roundToInt16(crv*8192) * 0x0001000100010001ULL;
01972 c->ubCoeff= roundToInt16(cbu*8192) * 0x0001000100010001ULL;
01973 c->vgCoeff= roundToInt16(cgv*8192) * 0x0001000100010001ULL;
01974 c->ugCoeff= roundToInt16(cgu*8192) * 0x0001000100010001ULL;
01975 c->yOffset= roundToInt16(oy * 8) * 0x0001000100010001ULL;
01976
01977 yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation);
01978
01979
01980 #ifdef COMPILE_ALTIVEC
01981 if (c->flags & SWS_CPU_CAPS_ALTIVEC)
01982 yuv2rgb_altivec_init_tables (c, inv_table, brightness, contrast, saturation);
01983 #endif
01984 return 0;
01985 }
01986
01990 int sws_getColorspaceDetails(SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation){
01991 if (isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
01992
01993 *inv_table = c->srcColorspaceTable;
01994 *table = c->dstColorspaceTable;
01995 *srcRange = c->srcRange;
01996 *dstRange = c->dstRange;
01997 *brightness= c->brightness;
01998 *contrast = c->contrast;
01999 *saturation= c->saturation;
02000
02001 return 0;
02002 }
02003
02004 static int handle_jpeg(int *format)
02005 {
02006 switch (*format) {
02007 case PIX_FMT_YUVJ420P:
02008 *format = PIX_FMT_YUV420P;
02009 return 1;
02010 case PIX_FMT_YUVJ422P:
02011 *format = PIX_FMT_YUV422P;
02012 return 1;
02013 case PIX_FMT_YUVJ444P:
02014 *format = PIX_FMT_YUV444P;
02015 return 1;
02016 case PIX_FMT_YUVJ440P:
02017 *format = PIX_FMT_YUV440P;
02018 return 1;
02019 default:
02020 return 0;
02021 }
02022 }
02023
02024 SwsContext *sws_getContext(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags,
02025 SwsFilter *srcFilter, SwsFilter *dstFilter, double *param){
02026
02027 SwsContext *c;
02028 int i;
02029 int usesVFilter, usesHFilter;
02030 int unscaled, needsDither;
02031 int srcRange, dstRange;
02032 SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
02033 #if defined(ARCH_X86)
02034 if (flags & SWS_CPU_CAPS_MMX)
02035 asm volatile("emms\n\t"::: "memory");
02036 #endif
02037
02038 #if !defined(RUNTIME_CPUDETECT) || !defined (CONFIG_GPL) //ensure that the flags match the compiled variant if cpudetect is off
02039 flags &= ~(SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2|SWS_CPU_CAPS_3DNOW|SWS_CPU_CAPS_ALTIVEC|SWS_CPU_CAPS_BFIN);
02040 #ifdef HAVE_MMX2
02041 flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2;
02042 #elif defined (HAVE_3DNOW)
02043 flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_3DNOW;
02044 #elif defined (HAVE_MMX)
02045 flags |= SWS_CPU_CAPS_MMX;
02046 #elif defined (HAVE_ALTIVEC)
02047 flags |= SWS_CPU_CAPS_ALTIVEC;
02048 #elif defined (ARCH_BFIN)
02049 flags |= SWS_CPU_CAPS_BFIN;
02050 #endif
02051 #endif
02052 if (clip_table[512] != 255) globalInit();
02053 if (!rgb15to16) sws_rgb2rgb_init(flags);
02054
02055 unscaled = (srcW == dstW && srcH == dstH);
02056 needsDither= (isBGR(dstFormat) || isRGB(dstFormat))
02057 && (fmt_depth(dstFormat))<24
02058 && ((fmt_depth(dstFormat))<(fmt_depth(srcFormat)) || (!(isRGB(srcFormat) || isBGR(srcFormat))));
02059
02060 srcRange = handle_jpeg(&srcFormat);
02061 dstRange = handle_jpeg(&dstFormat);
02062
02063 if (!isSupportedIn(srcFormat))
02064 {
02065 av_log(NULL, AV_LOG_ERROR, "swScaler: %s is not supported as input format\n", sws_format_name(srcFormat));
02066 return NULL;
02067 }
02068 if (!isSupportedOut(dstFormat))
02069 {
02070 av_log(NULL, AV_LOG_ERROR, "swScaler: %s is not supported as output format\n", sws_format_name(dstFormat));
02071 return NULL;
02072 }
02073
02074
02075 if (srcW<4 || srcH<1 || dstW<8 || dstH<1)
02076 {
02077 av_log(NULL, AV_LOG_ERROR, "swScaler: %dx%d -> %dx%d is invalid scaling dimension\n",
02078 srcW, srcH, dstW, dstH);
02079 return NULL;
02080 }
02081
02082 if (!dstFilter) dstFilter= &dummyFilter;
02083 if (!srcFilter) srcFilter= &dummyFilter;
02084
02085 c= av_mallocz(sizeof(SwsContext));
02086
02087 c->av_class = &sws_context_class;
02088 c->srcW= srcW;
02089 c->srcH= srcH;
02090 c->dstW= dstW;
02091 c->dstH= dstH;
02092 c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW;
02093 c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH;
02094 c->flags= flags;
02095 c->dstFormat= dstFormat;
02096 c->srcFormat= srcFormat;
02097 c->vRounder= 4* 0x0001000100010001ULL;
02098
02099 usesHFilter= usesVFilter= 0;
02100 if (dstFilter->lumV && dstFilter->lumV->length>1) usesVFilter=1;
02101 if (dstFilter->lumH && dstFilter->lumH->length>1) usesHFilter=1;
02102 if (dstFilter->chrV && dstFilter->chrV->length>1) usesVFilter=1;
02103 if (dstFilter->chrH && dstFilter->chrH->length>1) usesHFilter=1;
02104 if (srcFilter->lumV && srcFilter->lumV->length>1) usesVFilter=1;
02105 if (srcFilter->lumH && srcFilter->lumH->length>1) usesHFilter=1;
02106 if (srcFilter->chrV && srcFilter->chrV->length>1) usesVFilter=1;
02107 if (srcFilter->chrH && srcFilter->chrH->length>1) usesHFilter=1;
02108
02109 getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
02110 getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
02111
02112
02113 if ((isBGR(dstFormat) || isRGB(dstFormat)) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;
02114
02115
02116 c->vChrDrop= (flags&SWS_SRC_V_CHR_DROP_MASK)>>SWS_SRC_V_CHR_DROP_SHIFT;
02117 c->chrSrcVSubSample+= c->vChrDrop;
02118
02119
02120 if ((isBGR(srcFormat) || isRGB(srcFormat)) && !(flags&SWS_FULL_CHR_H_INP)
02121 && srcFormat!=PIX_FMT_RGB8 && srcFormat!=PIX_FMT_BGR8
02122 && srcFormat!=PIX_FMT_RGB4 && srcFormat!=PIX_FMT_BGR4
02123 && srcFormat!=PIX_FMT_RGB4_BYTE && srcFormat!=PIX_FMT_BGR4_BYTE)
02124 c->chrSrcHSubSample=1;
02125
02126 if (param){
02127 c->param[0] = param[0];
02128 c->param[1] = param[1];
02129 }else{
02130 c->param[0] =
02131 c->param[1] = SWS_PARAM_DEFAULT;
02132 }
02133
02134 c->chrIntHSubSample= c->chrDstHSubSample;
02135 c->chrIntVSubSample= c->chrSrcVSubSample;
02136
02137
02138 c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample);
02139 c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample);
02140 c->chrDstW= -((-dstW) >> c->chrDstHSubSample);
02141 c->chrDstH= -((-dstH) >> c->chrDstVSubSample);
02142
02143 sws_setColorspaceDetails(c, Inverse_Table_6_9[SWS_CS_DEFAULT], srcRange, Inverse_Table_6_9[SWS_CS_DEFAULT] , dstRange, 0, 1<<16, 1<<16);
02144
02145
02146 if (unscaled && !usesHFilter && !usesVFilter)
02147 {
02148
02149 if (srcFormat == PIX_FMT_YUV420P && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21))
02150 {
02151 c->swScale= PlanarToNV12Wrapper;
02152 }
02153 #ifdef CONFIG_GPL
02154
02155 if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P) && (isBGR(dstFormat) || isRGB(dstFormat)))
02156 {
02157 c->swScale= yuv2rgb_get_func_ptr(c);
02158 }
02159 #endif
02160
02161 if (srcFormat==PIX_FMT_YUV410P && dstFormat==PIX_FMT_YUV420P)
02162 {
02163 c->swScale= yvu9toyv12Wrapper;
02164 }
02165
02166
02167 if (srcFormat==PIX_FMT_BGR24 && dstFormat==PIX_FMT_YUV420P)
02168 c->swScale= bgr24toyv12Wrapper;
02169
02170
02171 if ( (isBGR(srcFormat) || isRGB(srcFormat))
02172 && (isBGR(dstFormat) || isRGB(dstFormat))
02173 && srcFormat != PIX_FMT_BGR8 && dstFormat != PIX_FMT_BGR8
02174 && srcFormat != PIX_FMT_RGB8 && dstFormat != PIX_FMT_RGB8
02175 && srcFormat != PIX_FMT_BGR4 && dstFormat != PIX_FMT_BGR4
02176 && srcFormat != PIX_FMT_RGB4 && dstFormat != PIX_FMT_RGB4
02177 && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
02178 && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
02179 && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
02180 && !needsDither)
02181 c->swScale= rgb2rgbWrapper;
02182
02183
02184 if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)){
02185
02186 if ( (isBGR(srcFormat) || isRGB(srcFormat))
02187 && (isBGR(dstFormat) || isRGB(dstFormat))
02188 && needsDither)
02189 c->swScale= rgb2rgbWrapper;
02190
02191
02192 if (srcFormat == PIX_FMT_YUV420P &&
02193 (dstFormat == PIX_FMT_YUYV422 || dstFormat == PIX_FMT_UYVY422))
02194 {
02195 if (dstFormat == PIX_FMT_YUYV422)
02196 c->swScale= PlanarToYuy2Wrapper;
02197 else
02198 c->swScale= PlanarToUyvyWrapper;
02199 }
02200 }
02201
02202 #ifdef COMPILE_ALTIVEC
02203 if ((c->flags & SWS_CPU_CAPS_ALTIVEC) &&
02204 ((srcFormat == PIX_FMT_YUV420P &&
02205 (dstFormat == PIX_FMT_YUYV422 || dstFormat == PIX_FMT_UYVY422)))) {
02206
02207 if (dstFormat == PIX_FMT_YUYV422)
02208 c->swScale= yv12toyuy2_unscaled_altivec;
02209 else
02210 c->swScale= yv12touyvy_unscaled_altivec;
02211 }
02212 #endif
02213
02214
02215 if ( srcFormat == dstFormat
02216 || (isPlanarYUV(srcFormat) && isGray(dstFormat))
02217 || (isPlanarYUV(dstFormat) && isGray(srcFormat)))
02218 {
02219 c->swScale= simpleCopy;
02220 }
02221
02222
02223 if (isGray16(srcFormat) && (isPlanarYUV(dstFormat) || (dstFormat == PIX_FMT_GRAY8)))
02224 {
02225 c->swScale= gray16togray;
02226 }
02227 if ((isPlanarYUV(srcFormat) || (srcFormat == PIX_FMT_GRAY8)) && isGray16(dstFormat))
02228 {
02229 c->swScale= graytogray16;
02230 }
02231 if (srcFormat != dstFormat && isGray16(srcFormat) && isGray16(dstFormat))
02232 {
02233 c->swScale= gray16swap;
02234 }
02235
02236 #ifdef ARCH_BFIN
02237 if (flags & SWS_CPU_CAPS_BFIN)
02238 ff_bfin_get_unscaled_swscale (c);
02239 #endif
02240
02241 if (c->swScale){
02242 if (flags&SWS_PRINT_INFO)
02243 av_log(c, AV_LOG_INFO, "SwScaler: using unscaled %s -> %s special converter\n",
02244 sws_format_name(srcFormat), sws_format_name(dstFormat));
02245 return c;
02246 }
02247 }
02248
02249 if (flags & SWS_CPU_CAPS_MMX2)
02250 {
02251 c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0;
02252 if (!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR))
02253 {
02254 if (flags&SWS_PRINT_INFO)
02255 av_log(c, AV_LOG_INFO, "SwScaler: output Width is not a multiple of 32 -> no MMX2 scaler\n");
02256 }
02257 if (usesHFilter) c->canMMX2BeUsed=0;
02258 }
02259 else
02260 c->canMMX2BeUsed=0;
02261
02262 c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW;
02263 c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH;
02264
02265
02266
02267
02268
02269
02270
02271 if (flags&SWS_FAST_BILINEAR)
02272 {
02273 if (c->canMMX2BeUsed)
02274 {
02275 c->lumXInc+= 20;
02276 c->chrXInc+= 20;
02277 }
02278
02279 else if (flags & SWS_CPU_CAPS_MMX)
02280 {
02281 c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20;
02282 c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20;
02283 }
02284 }
02285
02286
02287 {
02288 const int filterAlign=
02289 (flags & SWS_CPU_CAPS_MMX) ? 4 :
02290 (flags & SWS_CPU_CAPS_ALTIVEC) ? 8 :
02291 1;
02292
02293 initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc,
02294 srcW , dstW, filterAlign, 1<<14,
02295 (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags,
02296 srcFilter->lumH, dstFilter->lumH, c->param);
02297 initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc,
02298 c->chrSrcW, c->chrDstW, filterAlign, 1<<14,
02299 (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags,
02300 srcFilter->chrH, dstFilter->chrH, c->param);
02301
02302 #define MAX_FUNNY_CODE_SIZE 10000
02303 #if defined (COMPILE_MMX2) && !defined(ARCH_X86_64)
02304
02305 if (c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR))
02306 {
02307 #ifdef MAP_ANONYMOUS
02308 c->funnyYCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
02309 c->funnyUVCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
02310 #else
02311 c->funnyYCode = av_malloc(MAX_FUNNY_CODE_SIZE);
02312 c->funnyUVCode = av_malloc(MAX_FUNNY_CODE_SIZE);
02313 #endif
02314
02315 c->lumMmx2Filter = av_malloc((dstW /8+8)*sizeof(int16_t));
02316 c->chrMmx2Filter = av_malloc((c->chrDstW /4+8)*sizeof(int16_t));
02317 c->lumMmx2FilterPos= av_malloc((dstW /2/8+8)*sizeof(int32_t));
02318 c->chrMmx2FilterPos= av_malloc((c->chrDstW/2/4+8)*sizeof(int32_t));
02319
02320 initMMX2HScaler( dstW, c->lumXInc, c->funnyYCode , c->lumMmx2Filter, c->lumMmx2FilterPos, 8);
02321 initMMX2HScaler(c->chrDstW, c->chrXInc, c->funnyUVCode, c->chrMmx2Filter, c->chrMmx2FilterPos, 4);
02322 }
02323 #endif
02324 }
02325
02326
02327
02328
02329 {
02330 const int filterAlign=
02331 (flags & SWS_CPU_CAPS_MMX) && (flags & SWS_ACCURATE_RND) ? 2 :
02332 (flags & SWS_CPU_CAPS_ALTIVEC) ? 8 :
02333 1;
02334
02335 initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize, c->lumYInc,
02336 srcH , dstH, filterAlign, (1<<12)-4,
02337 (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags,
02338 srcFilter->lumV, dstFilter->lumV, c->param);
02339 initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc,
02340 c->chrSrcH, c->chrDstH, filterAlign, (1<<12)-4,
02341 (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags,
02342 srcFilter->chrV, dstFilter->chrV, c->param);
02343
02344 #ifdef HAVE_ALTIVEC
02345 c->vYCoeffsBank = av_malloc(sizeof (vector signed short)*c->vLumFilterSize*c->dstH);
02346 c->vCCoeffsBank = av_malloc(sizeof (vector signed short)*c->vChrFilterSize*c->chrDstH);
02347
02348 for (i=0;i<c->vLumFilterSize*c->dstH;i++) {
02349 int j;
02350 short *p = (short *)&c->vYCoeffsBank[i];
02351 for (j=0;j<8;j++)
02352 p[j] = c->vLumFilter[i];
02353 }
02354
02355 for (i=0;i<c->vChrFilterSize*c->chrDstH;i++) {
02356 int j;
02357 short *p = (short *)&c->vCCoeffsBank[i];
02358 for (j=0;j<8;j++)
02359 p[j] = c->vChrFilter[i];
02360 }
02361 #endif
02362 }
02363
02364
02365 c->vLumBufSize= c->vLumFilterSize;
02366 c->vChrBufSize= c->vChrFilterSize;
02367 for (i=0; i<dstH; i++)
02368 {
02369 int chrI= i*c->chrDstH / dstH;
02370 int nextSlice= FFMAX(c->vLumFilterPos[i ] + c->vLumFilterSize - 1,
02371 ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample));
02372
02373 nextSlice>>= c->chrSrcVSubSample;
02374 nextSlice<<= c->chrSrcVSubSample;
02375 if (c->vLumFilterPos[i ] + c->vLumBufSize < nextSlice)
02376 c->vLumBufSize= nextSlice - c->vLumFilterPos[i];
02377 if (c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>c->chrSrcVSubSample))
02378 c->vChrBufSize= (nextSlice>>c->chrSrcVSubSample) - c->vChrFilterPos[chrI];
02379 }
02380
02381
02382 c->lumPixBuf= av_malloc(c->vLumBufSize*2*sizeof(int16_t*));
02383 c->chrPixBuf= av_malloc(c->vChrBufSize*2*sizeof(int16_t*));
02384
02385
02386 for (i=0; i<c->vLumBufSize; i++)
02387 c->lumPixBuf[i]= c->lumPixBuf[i+c->vLumBufSize]= av_mallocz(4000);
02388 for (i=0; i<c->vChrBufSize; i++)
02389 c->chrPixBuf[i]= c->chrPixBuf[i+c->vChrBufSize]= av_malloc(8000);
02390
02391
02392 for (i=0; i<c->vChrBufSize; i++) memset(c->chrPixBuf[i], 64, 8000);
02393
02394 ASSERT(c->chrDstH <= dstH)
02395
02396 if (flags&SWS_PRINT_INFO)
02397 {
02398 #ifdef DITHER1XBPP
02399 char *dither= " dithered";
02400 #else
02401 char *dither= "";
02402 #endif
02403 if (flags&SWS_FAST_BILINEAR)
02404 av_log(c, AV_LOG_INFO, "SwScaler: FAST_BILINEAR scaler, ");
02405 else if (flags&SWS_BILINEAR)
02406 av_log(c, AV_LOG_INFO, "SwScaler: BILINEAR scaler, ");
02407 else if (flags&SWS_BICUBIC)
02408 av_log(c, AV_LOG_INFO, "SwScaler: BICUBIC scaler, ");
02409 else if (flags&SWS_X)
02410 av_log(c, AV_LOG_INFO, "SwScaler: Experimental scaler, ");
02411 else if (flags&SWS_POINT)
02412 av_log(c, AV_LOG_INFO, "SwScaler: Nearest Neighbor / POINT scaler, ");
02413 else if (flags&SWS_AREA)
02414 av_log(c, AV_LOG_INFO, "SwScaler: Area Averageing scaler, ");
02415 else if (flags&SWS_BICUBLIN)
02416 av_log(c, AV_LOG_INFO, "SwScaler: luma BICUBIC / chroma BILINEAR scaler, ");
02417 else if (flags&SWS_GAUSS)
02418 av_log(c, AV_LOG_INFO, "SwScaler: Gaussian scaler, ");
02419 else if (flags&SWS_SINC)
02420 av_log(c, AV_LOG_INFO, "SwScaler: Sinc scaler, ");
02421 else if (flags&SWS_LANCZOS)
02422 av_log(c, AV_LOG_INFO, "SwScaler: Lanczos scaler, ");
02423 else if (flags&SWS_SPLINE)
02424 av_log(c, AV_LOG_INFO, "SwScaler: Bicubic spline scaler, ");
02425 else
02426 av_log(c, AV_LOG_INFO, "SwScaler: ehh flags invalid?! ");
02427
02428 if (dstFormat==PIX_FMT_BGR555 || dstFormat==PIX_FMT_BGR565)
02429 av_log(c, AV_LOG_INFO, "from %s to%s %s ",
02430 sws_format_name(srcFormat), dither, sws_format_name(dstFormat));
02431 else
02432 av_log(c, AV_LOG_INFO, "from %s to %s ",
02433 sws_format_name(srcFormat), sws_format_name(dstFormat));
02434
02435 if (flags & SWS_CPU_CAPS_MMX2)
02436 av_log(c, AV_LOG_INFO, "using MMX2\n");
02437 else if (flags & SWS_CPU_CAPS_3DNOW)
02438 av_log(c, AV_LOG_INFO, "using 3DNOW\n");
02439 else if (flags & SWS_CPU_CAPS_MMX)
02440 av_log(c, AV_LOG_INFO, "using MMX\n");
02441 else if (flags & SWS_CPU_CAPS_ALTIVEC)
02442 av_log(c, AV_LOG_INFO, "using AltiVec\n");
02443 else
02444 av_log(c, AV_LOG_INFO, "using C\n");
02445 }
02446
02447 if (flags & SWS_PRINT_INFO)
02448 {
02449 if (flags & SWS_CPU_CAPS_MMX)
02450 {
02451 if (c->canMMX2BeUsed && (flags&SWS_FAST_BILINEAR))
02452 av_log(c, AV_LOG_VERBOSE, "SwScaler: using FAST_BILINEAR MMX2 scaler for horizontal scaling\n");
02453 else
02454 {
02455 if (c->hLumFilterSize==4)
02456 av_log(c, AV_LOG_VERBOSE, "SwScaler: using 4-tap MMX scaler for horizontal luminance scaling\n");
02457 else if (c->hLumFilterSize==8)
02458 av_log(c, AV_LOG_VERBOSE, "SwScaler: using 8-tap MMX scaler for horizontal luminance scaling\n");
02459 else
02460 av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap MMX scaler for horizontal luminance scaling\n");
02461
02462 if (c->hChrFilterSize==4)
02463 av_log(c, AV_LOG_VERBOSE, "SwScaler: using 4-tap MMX scaler for horizontal chrominance scaling\n");
02464 else if (c->hChrFilterSize==8)
02465 av_log(c, AV_LOG_VERBOSE, "SwScaler: using 8-tap MMX scaler for horizontal chrominance scaling\n");
02466 else
02467 av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap MMX scaler for horizontal chrominance scaling\n");
02468 }
02469 }
02470 else
02471 {
02472 #if defined(ARCH_X86)
02473 av_log(c, AV_LOG_VERBOSE, "SwScaler: using X86-Asm scaler for horizontal scaling\n");
02474 #else
02475 if (flags & SWS_FAST_BILINEAR)
02476 av_log(c, AV_LOG_VERBOSE, "SwScaler: using FAST_BILINEAR C scaler for horizontal scaling\n");
02477 else
02478 av_log(c, AV_LOG_VERBOSE, "SwScaler: using C scaler for horizontal scaling\n");
02479 #endif
02480 }
02481 if (isPlanarYUV(dstFormat))
02482 {
02483 if (c->vLumFilterSize==1)
02484 av_log(c, AV_LOG_VERBOSE, "SwScaler: using 1-tap %s \"scaler\" for vertical scaling (YV12 like)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02485 else
02486 av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap %s scaler for vertical scaling (YV12 like)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02487 }
02488 else
02489 {
02490 if (c->vLumFilterSize==1 && c->vChrFilterSize==2)
02491 av_log(c, AV_LOG_VERBOSE, "SwScaler: using 1-tap %s \"scaler\" for vertical luminance scaling (BGR)\n"
02492 "SwScaler: 2-tap scaler for vertical chrominance scaling (BGR)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02493 else if (c->vLumFilterSize==2 && c->vChrFilterSize==2)
02494 av_log(c, AV_LOG_VERBOSE, "SwScaler: using 2-tap linear %s scaler for vertical scaling (BGR)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02495 else
02496 av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap %s scaler for vertical scaling (BGR)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02497 }
02498
02499 if (dstFormat==PIX_FMT_BGR24)
02500 av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR24 Converter\n",
02501 (flags & SWS_CPU_CAPS_MMX2) ? "MMX2" : ((flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"));
02502 else if (dstFormat==PIX_FMT_RGB32)
02503 av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR32 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02504 else if (dstFormat==PIX_FMT_BGR565)
02505 av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR16 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02506 else if (dstFormat==PIX_FMT_BGR555)
02507 av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR15 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
02508
02509 av_log(c, AV_LOG_VERBOSE, "SwScaler: %dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
02510 }
02511 if (flags & SWS_PRINT_INFO)
02512 {
02513 av_log(c, AV_LOG_DEBUG, "SwScaler:Lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
02514 c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
02515 av_log(c, AV_LOG_DEBUG, "SwScaler:Chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
02516 c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, c->chrXInc, c->chrYInc);
02517 }
02518
02519 c->swScale= getSwsFunc(flags);
02520 return c;
02521 }
02522
02527 int sws_scale(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
02528 int srcSliceH, uint8_t* dst[], int dstStride[]){
02529 int i;
02530 uint8_t* src2[4]= {src[0], src[1], src[2]};
02531 uint32_t pal[256];
02532 if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
02533 av_log(c, AV_LOG_ERROR, "swScaler: slices start in the middle!\n");
02534 return 0;
02535 }
02536 if (c->sliceDir == 0) {
02537 if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
02538 }
02539
02540 if (c->srcFormat == PIX_FMT_PAL8){
02541 for (i=0; i<256; i++){
02542 int p= ((uint32_t*)(src[1]))[i];
02543 int r= (p>>16)&0xFF;
02544 int g= (p>> 8)&0xFF;
02545 int b= p &0xFF;
02546 int y= av_clip_uint8(((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16 );
02547 int u= av_clip_uint8(((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128);
02548 int v= av_clip_uint8(((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128);
02549 pal[i]= y + (u<<8) + (v<<16);
02550 }
02551 src2[1]= pal;
02552 }
02553
02554
02555 if (c->sliceDir == 1) {
02556
02557 int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2]};
02558 int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2]};
02559 return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst, dstStride2);
02560 } else {
02561
02562 uint8_t* dst2[4]= {dst[0] + (c->dstH-1)*dstStride[0],
02563 dst[1] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1],
02564 dst[2] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2]};
02565 int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2]};
02566 int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2]};
02567
02568 src2[0] += (srcSliceH-1)*srcStride[0];
02569 if (c->srcFormat != PIX_FMT_PAL8)
02570 src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1];
02571 src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2];
02572
02573 return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
02574 }
02575 }
02576
02580 int sws_scale_ordered(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
02581 int srcSliceH, uint8_t* dst[], int dstStride[]){
02582 return sws_scale(c, src, srcStride, srcSliceY, srcSliceH, dst, dstStride);
02583 }
02584
02585 SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
02586 float lumaSharpen, float chromaSharpen,
02587 float chromaHShift, float chromaVShift,
02588 int verbose)
02589 {
02590 SwsFilter *filter= av_malloc(sizeof(SwsFilter));
02591
02592 if (lumaGBlur!=0.0){
02593 filter->lumH= sws_getGaussianVec(lumaGBlur, 3.0);
02594 filter->lumV= sws_getGaussianVec(lumaGBlur, 3.0);
02595 }else{
02596 filter->lumH= sws_getIdentityVec();
02597 filter->lumV= sws_getIdentityVec();
02598 }
02599
02600 if (chromaGBlur!=0.0){
02601 filter->chrH= sws_getGaussianVec(chromaGBlur, 3.0);
02602 filter->chrV= sws_getGaussianVec(chromaGBlur, 3.0);
02603 }else{
02604 filter->chrH= sws_getIdentityVec();
02605 filter->chrV= sws_getIdentityVec();
02606 }
02607
02608 if (chromaSharpen!=0.0){
02609 SwsVector *id= sws_getIdentityVec();
02610 sws_scaleVec(filter->chrH, -chromaSharpen);
02611 sws_scaleVec(filter->chrV, -chromaSharpen);
02612 sws_addVec(filter->chrH, id);
02613 sws_addVec(filter->chrV, id);
02614 sws_freeVec(id);
02615 }
02616
02617 if (lumaSharpen!=0.0){
02618 SwsVector *id= sws_getIdentityVec();
02619 sws_scaleVec(filter->lumH, -lumaSharpen);
02620 sws_scaleVec(filter->lumV, -lumaSharpen);
02621 sws_addVec(filter->lumH, id);
02622 sws_addVec(filter->lumV, id);
02623 sws_freeVec(id);
02624 }
02625
02626 if (chromaHShift != 0.0)
02627 sws_shiftVec(filter->chrH, (int)(chromaHShift+0.5));
02628
02629 if (chromaVShift != 0.0)
02630 sws_shiftVec(filter->chrV, (int)(chromaVShift+0.5));
02631
02632 sws_normalizeVec(filter->chrH, 1.0);
02633 sws_normalizeVec(filter->chrV, 1.0);
02634 sws_normalizeVec(filter->lumH, 1.0);
02635 sws_normalizeVec(filter->lumV, 1.0);
02636
02637 if (verbose) sws_printVec(filter->chrH);
02638 if (verbose) sws_printVec(filter->lumH);
02639
02640 return filter;
02641 }
02642
02647 SwsVector *sws_getGaussianVec(double variance, double quality){
02648 const int length= (int)(variance*quality + 0.5) | 1;
02649 int i;
02650 double *coeff= av_malloc(length*sizeof(double));
02651 double middle= (length-1)*0.5;
02652 SwsVector *vec= av_malloc(sizeof(SwsVector));
02653
02654 vec->coeff= coeff;
02655 vec->length= length;
02656
02657 for (i=0; i<length; i++)
02658 {
02659 double dist= i-middle;
02660 coeff[i]= exp(-dist*dist/(2*variance*variance)) / sqrt(2*variance*PI);
02661 }
02662
02663 sws_normalizeVec(vec, 1.0);
02664
02665 return vec;
02666 }
02667
02668 SwsVector *sws_getConstVec(double c, int length){
02669 int i;
02670 double *coeff= av_malloc(length*sizeof(double));
02671 SwsVector *vec= av_malloc(sizeof(SwsVector));
02672
02673 vec->coeff= coeff;
02674 vec->length= length;
02675
02676 for (i=0; i<length; i++)
02677 coeff[i]= c;
02678
02679 return vec;
02680 }
02681
02682
02683 SwsVector *sws_getIdentityVec(void){
02684 return sws_getConstVec(1.0, 1);
02685 }
02686
02687 double sws_dcVec(SwsVector *a){
02688 int i;
02689 double sum=0;
02690
02691 for (i=0; i<a->length; i++)
02692 sum+= a->coeff[i];
02693
02694 return sum;
02695 }
02696
02697 void sws_scaleVec(SwsVector *a, double scalar){
02698 int i;
02699
02700 for (i=0; i<a->length; i++)
02701 a->coeff[i]*= scalar;
02702 }
02703
02704 void sws_normalizeVec(SwsVector *a, double height){
02705 sws_scaleVec(a, height/sws_dcVec(a));
02706 }
02707
02708 static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b){
02709 int length= a->length + b->length - 1;
02710 double *coeff= av_malloc(length*sizeof(double));
02711 int i, j;
02712 SwsVector *vec= av_malloc(sizeof(SwsVector));
02713
02714 vec->coeff= coeff;
02715 vec->length= length;
02716
02717 for (i=0; i<length; i++) coeff[i]= 0.0;
02718
02719 for (i=0; i<a->length; i++)
02720 {
02721 for (j=0; j<b->length; j++)
02722 {
02723 coeff[i+j]+= a->coeff[i]*b->coeff[j];
02724 }
02725 }
02726
02727 return vec;
02728 }
02729
02730 static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b){
02731 int length= FFMAX(a->length, b->length);
02732 double *coeff= av_malloc(length*sizeof(double));
02733 int i;
02734 SwsVector *vec= av_malloc(sizeof(SwsVector));
02735
02736 vec->coeff= coeff;
02737 vec->length= length;
02738
02739 for (i=0; i<length; i++) coeff[i]= 0.0;
02740
02741 for (i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i];
02742 for (i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]+= b->coeff[i];
02743
02744 return vec;
02745 }
02746
02747 static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b){
02748 int length= FFMAX(a->length, b->length);
02749 double *coeff= av_malloc(length*sizeof(double));
02750 int i;
02751 SwsVector *vec= av_malloc(sizeof(SwsVector));
02752
02753 vec->coeff= coeff;
02754 vec->length= length;
02755
02756 for (i=0; i<length; i++) coeff[i]= 0.0;
02757
02758 for (i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i];
02759 for (i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]-= b->coeff[i];
02760
02761 return vec;
02762 }
02763
02764
02765 static SwsVector *sws_getShiftedVec(SwsVector *a, int shift){
02766 int length= a->length + FFABS(shift)*2;
02767 double *coeff= av_malloc(length*sizeof(double));
02768 int i;
02769 SwsVector *vec= av_malloc(sizeof(SwsVector));
02770
02771 vec->coeff= coeff;
02772 vec->length= length;
02773
02774 for (i=0; i<length; i++) coeff[i]= 0.0;
02775
02776 for (i=0; i<a->length; i++)
02777 {
02778 coeff[i + (length-1)/2 - (a->length-1)/2 - shift]= a->coeff[i];
02779 }
02780
02781 return vec;
02782 }
02783
02784 void sws_shiftVec(SwsVector *a, int shift){
02785 SwsVector *shifted= sws_getShiftedVec(a, shift);
02786 av_free(a->coeff);
02787 a->coeff= shifted->coeff;
02788 a->length= shifted->length;
02789 av_free(shifted);
02790 }
02791
02792 void sws_addVec(SwsVector *a, SwsVector *b){
02793 SwsVector *sum= sws_sumVec(a, b);
02794 av_free(a->coeff);
02795 a->coeff= sum->coeff;
02796 a->length= sum->length;
02797 av_free(sum);
02798 }
02799
02800 void sws_subVec(SwsVector *a, SwsVector *b){
02801 SwsVector *diff= sws_diffVec(a, b);
02802 av_free(a->coeff);
02803 a->coeff= diff->coeff;
02804 a->length= diff->length;
02805 av_free(diff);
02806 }
02807
02808 void sws_convVec(SwsVector *a, SwsVector *b){
02809 SwsVector *conv= sws_getConvVec(a, b);
02810 av_free(a->coeff);
02811 a->coeff= conv->coeff;
02812 a->length= conv->length;
02813 av_free(conv);
02814 }
02815
02816 SwsVector *sws_cloneVec(SwsVector *a){
02817 double *coeff= av_malloc(a->length*sizeof(double));
02818 int i;
02819 SwsVector *vec= av_malloc(sizeof(SwsVector));
02820
02821 vec->coeff= coeff;
02822 vec->length= a->length;
02823
02824 for (i=0; i<a->length; i++) coeff[i]= a->coeff[i];
02825
02826 return vec;
02827 }
02828
02829 void sws_printVec(SwsVector *a){
02830 int i;
02831 double max=0;
02832 double min=0;
02833 double range;
02834
02835 for (i=0; i<a->length; i++)
02836 if (a->coeff[i]>max) max= a->coeff[i];
02837
02838 for (i=0; i<a->length; i++)
02839 if (a->coeff[i]<min) min= a->coeff[i];
02840
02841 range= max - min;
02842
02843 for (i=0; i<a->length; i++)
02844 {
02845 int x= (int)((a->coeff[i]-min)*60.0/range +0.5);
02846 av_log(NULL, AV_LOG_DEBUG, "%1.3f ", a->coeff[i]);
02847 for (;x>0; x--) av_log(NULL, AV_LOG_DEBUG, " ");
02848 av_log(NULL, AV_LOG_DEBUG, "|\n");
02849 }
02850 }
02851
02852 void sws_freeVec(SwsVector *a){
02853 if (!a) return;
02854 av_free(a->coeff);
02855 a->coeff=NULL;
02856 a->length=0;
02857 av_free(a);
02858 }
02859
02860 void sws_freeFilter(SwsFilter *filter){
02861 if (!filter) return;
02862
02863 if (filter->lumH) sws_freeVec(filter->lumH);
02864 if (filter->lumV) sws_freeVec(filter->lumV);
02865 if (filter->chrH) sws_freeVec(filter->chrH);
02866 if (filter->chrV) sws_freeVec(filter->chrV);
02867 av_free(filter);
02868 }
02869
02870
02871 void sws_freeContext(SwsContext *c){
02872 int i;
02873 if (!c) return;
02874
02875 if (c->lumPixBuf)
02876 {
02877 for (i=0; i<c->vLumBufSize; i++)
02878 {
02879 av_free(c->lumPixBuf[i]);
02880 c->lumPixBuf[i]=NULL;
02881 }
02882 av_free(c->lumPixBuf);
02883 c->lumPixBuf=NULL;
02884 }
02885
02886 if (c->chrPixBuf)
02887 {
02888 for (i=0; i<c->vChrBufSize; i++)
02889 {
02890 av_free(c->chrPixBuf[i]);
02891 c->chrPixBuf[i]=NULL;
02892 }
02893 av_free(c->chrPixBuf);
02894 c->chrPixBuf=NULL;
02895 }
02896
02897 av_free(c->vLumFilter);
02898 c->vLumFilter = NULL;
02899 av_free(c->vChrFilter);
02900 c->vChrFilter = NULL;
02901 av_free(c->hLumFilter);
02902 c->hLumFilter = NULL;
02903 av_free(c->hChrFilter);
02904 c->hChrFilter = NULL;
02905 #ifdef HAVE_ALTIVEC
02906 av_free(c->vYCoeffsBank);
02907 c->vYCoeffsBank = NULL;
02908 av_free(c->vCCoeffsBank);
02909 c->vCCoeffsBank = NULL;
02910 #endif
02911
02912 av_free(c->vLumFilterPos);
02913 c->vLumFilterPos = NULL;
02914 av_free(c->vChrFilterPos);
02915 c->vChrFilterPos = NULL;
02916 av_free(c->hLumFilterPos);
02917 c->hLumFilterPos = NULL;
02918 av_free(c->hChrFilterPos);
02919 c->hChrFilterPos = NULL;
02920
02921 #if defined(ARCH_X86) && defined(CONFIG_GPL)
02922 #ifdef MAP_ANONYMOUS
02923 if (c->funnyYCode) munmap(c->funnyYCode, MAX_FUNNY_CODE_SIZE);
02924 if (c->funnyUVCode) munmap(c->funnyUVCode, MAX_FUNNY_CODE_SIZE);
02925 #else
02926 av_free(c->funnyYCode);
02927 av_free(c->funnyUVCode);
02928 #endif
02929 c->funnyYCode=NULL;
02930 c->funnyUVCode=NULL;
02931 #endif
02932
02933 av_free(c->lumMmx2Filter);
02934 c->lumMmx2Filter=NULL;
02935 av_free(c->chrMmx2Filter);
02936 c->chrMmx2Filter=NULL;
02937 av_free(c->lumMmx2FilterPos);
02938 c->lumMmx2FilterPos=NULL;
02939 av_free(c->chrMmx2FilterPos);
02940 c->chrMmx2FilterPos=NULL;
02941 av_free(c->yuvTable);
02942 c->yuvTable=NULL;
02943
02944 av_free(c);
02945 }
02946
02957 struct SwsContext *sws_getCachedContext(struct SwsContext *context,
02958 int srcW, int srcH, int srcFormat,
02959 int dstW, int dstH, int dstFormat, int flags,
02960 SwsFilter *srcFilter, SwsFilter *dstFilter, double *param)
02961 {
02962 static const double default_param[2] = {SWS_PARAM_DEFAULT, SWS_PARAM_DEFAULT};
02963
02964 if (!param)
02965 param = default_param;
02966
02967 if (context) {
02968 if (context->srcW != srcW || context->srcH != srcH ||
02969 context->srcFormat != srcFormat ||
02970 context->dstW != dstW || context->dstH != dstH ||
02971 context->dstFormat != dstFormat || context->flags != flags ||
02972 context->param[0] != param[0] || context->param[1] != param[1])
02973 {
02974 sws_freeContext(context);
02975 context = NULL;
02976 }
02977 }
02978 if (!context) {
02979 return sws_getContext(srcW, srcH, srcFormat,
02980 dstW, dstH, dstFormat, flags,
02981 srcFilter, dstFilter, param);
02982 }
02983 return context;
02984 }
02985