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