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