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