23 #define _SVID_SOURCE // needed for MAP_ANONYMOUS
24 #define _DARWIN_C_SOURCE // needed for MAP_ANON
31 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
32 #define MAP_ANONYMOUS MAP_ANON
36 #define WIN32_LEAN_AND_MEAN
63 return FFMPEG_CONFIGURATION;
68 #define LICENSE_PREFIX "libswscale license: "
72 #define RET 0xC3 // near return opcode for x86
215 #if FF_API_SWS_FORMAT_NAME
222 return "Unknown format";
230 return ((d * dist + c) * dist + b) * dist +
a;
233 b + 2.0 * c + 3.0 * d,
235 -b - 3.0 * c - 6.0 * d,
240 int *outFilterSize,
int xInc,
int srcW,
int dstW,
250 int64_t *filter2 =
NULL;
251 const int64_t fone = 1LL << (54 -
FFMIN(
av_log2(srcW/dstW), 8));
259 if (
FFABS(xInc - 0x10000) < 10) {
263 dstW *
sizeof(*filter) * filterSize, fail);
265 for (i = 0; i < dstW; i++) {
266 filter[i * filterSize] = fone;
274 dstW *
sizeof(*filter) * filterSize, fail);
276 xDstInSrc = xInc / 2 - 0x8000;
277 for (i = 0; i < dstW; i++) {
278 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
280 (*filterPos)[i] = xx;
284 }
else if ((xInc <= (1 << 16) && (flags &
SWS_AREA)) ||
290 dstW *
sizeof(*filter) * filterSize, fail);
292 xDstInSrc = xInc / 2 - 0x8000;
293 for (i = 0; i < dstW; i++) {
294 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
297 (*filterPos)[i] = xx;
299 for (j = 0; j < filterSize; j++) {
300 int64_t
coeff= fone -
FFABS(((int64_t)xx<<16) - xDstInSrc)*(fone>>16);
303 filter[i * filterSize + j] =
coeff;
314 else if (flags &
SWS_X)
333 filterSize = 1 + sizeFactor;
335 filterSize = 1 + (sizeFactor * srcW + dstW - 1) / dstW;
337 filterSize =
FFMIN(filterSize, srcW - 2);
338 filterSize =
FFMAX(filterSize, 1);
341 dstW *
sizeof(*filter) * filterSize, fail);
343 xDstInSrc = xInc - 0x10000;
344 for (i = 0; i < dstW; i++) {
345 int xx = (xDstInSrc - ((filterSize - 2) << 16)) / (1 << 17);
347 (*filterPos)[i] = xx;
348 for (j = 0; j < filterSize; j++) {
349 int64_t d = (
FFABS(((int64_t)xx << 17) - xDstInSrc)) << 13;
355 floatd = d * (1.0 / (1 << 30));
357 if (flags & SWS_BICUBIC) {
361 if (d >= 1LL << 31) {
364 int64_t dd = (d * d) >> 30;
365 int64_t ddd = (dd * d) >> 30;
368 coeff = (12 * (1 << 24) - 9 * B - 6 * C) * ddd +
369 (-18 * (1 << 24) + 12 * B + 6 * C) * dd +
370 (6 * (1 << 24) - 2 * B) * (1 << 30);
372 coeff = (-B - 6 * C) * ddd +
373 (6 * B + 30 * C) * dd +
374 (-12 * B - 48 * C) * d +
375 (8 * B + 24 * C) * (1 << 30);
377 coeff /= (1LL<<54)/fone;
380 else if (flags & SWS_X) {
381 double p = param ? param * 0.01 : 0.3;
382 coeff = d ? sin(d *
M_PI) / (d *
M_PI) : 1.0;
383 coeff *= pow(2.0, -p * d * d);
386 else if (flags & SWS_X) {
391 c = cos(floatd *
M_PI);
398 coeff = (c * 0.5 + 0.5) * fone;
399 }
else if (flags & SWS_AREA) {
400 int64_t d2 = d - (1 << 29);
401 if (d2 * xInc < -(1LL << (29 + 16)))
402 coeff = 1.0 * (1LL << (30 + 16));
403 else if (d2 * xInc < (1LL << (29 + 16)))
404 coeff = -d2 * xInc + (1LL << (29 + 16));
407 coeff *= fone >> (30 + 16);
408 }
else if (flags & SWS_GAUSS) {
410 coeff = (pow(2.0, -p * floatd * floatd)) * fone;
411 }
else if (flags & SWS_SINC) {
412 coeff = (d ? sin(floatd *
M_PI) / (floatd *
M_PI) : 1.0) * fone;
413 }
else if (flags & SWS_LANCZOS) {
415 coeff = (d ? sin(floatd *
M_PI) * sin(floatd * M_PI / p) /
416 (floatd * floatd * M_PI * M_PI / p) : 1.0) * fone;
419 }
else if (flags & SWS_BILINEAR) {
420 coeff = (1 << 30) - d;
424 }
else if (flags & SWS_SPLINE) {
425 double p = -2.196152422706632;
431 filter[i * filterSize + j] =
coeff;
434 xDstInSrc += 2 * xInc;
442 filter2Size = filterSize;
444 filter2Size += srcFilter->
length - 1;
446 filter2Size += dstFilter->
length - 1;
450 for (i = 0; i < dstW; i++) {
454 for (k = 0; k < srcFilter->
length; k++) {
455 for (j = 0; j < filterSize; j++)
456 filter2[i * filter2Size + k + j] +=
457 srcFilter->
coeff[k] * filter[i * filterSize + j];
460 for (j = 0; j < filterSize; j++)
461 filter2[i * filter2Size + j] = filter[i * filterSize + j];
465 (*filterPos)[i] += (filterSize - 1) / 2 - (filter2Size - 1) / 2;
472 for (i = dstW - 1; i >= 0; i--) {
473 int min = filter2Size;
475 int64_t cutOff = 0.0;
478 for (j = 0; j < filter2Size; j++) {
480 cutOff +=
FFABS(filter2[i * filter2Size]);
487 if (i < dstW - 1 && (*filterPos)[i] >= (*filterPos)[i + 1])
491 for (k = 1; k < filter2Size; k++)
492 filter2[i * filter2Size + k - 1] = filter2[i * filter2Size + k];
493 filter2[i * filter2Size + k - 1] = 0;
499 for (j = filter2Size - 1; j > 0; j--) {
500 cutOff +=
FFABS(filter2[i * filter2Size + j]);
507 if (min > minFilterSize)
513 if (minFilterSize < 5)
519 if (minFilterSize < 3)
525 if (minFilterSize == 1 && filterAlign == 2)
530 filterSize = (minFilterSize + (filterAlign - 1)) & (~(filterAlign - 1));
532 filter =
av_malloc(filterSize * dstW *
sizeof(*filter));
535 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);
538 *outFilterSize = filterSize;
542 "SwScaler: reducing / aligning filtersize %d -> %d\n",
543 filter2Size, filterSize);
545 for (i = 0; i < dstW; i++) {
548 for (j = 0; j < filterSize; j++) {
549 if (j >= filter2Size)
550 filter[i * filterSize + j] = 0;
552 filter[i * filterSize + j] = filter2[i * filter2Size + j];
554 filter[i * filterSize + j] = 0;
561 for (i = 0; i < dstW; i++) {
563 if ((*filterPos)[i] < 0) {
565 for (j = 1; j < filterSize; j++) {
566 int left =
FFMAX(j + (*filterPos)[i], 0);
567 filter[i * filterSize + left] += filter[i * filterSize + j];
568 filter[i * filterSize + j] = 0;
573 if ((*filterPos)[i] + filterSize > srcW) {
574 int shift = (*filterPos)[i] + filterSize - srcW;
576 for (j = filterSize - 2; j >= 0; j--) {
577 int right =
FFMIN(j + shift, filterSize - 1);
578 filter[i * filterSize + right] += filter[i * filterSize + j];
579 filter[i * filterSize + j] = 0;
581 (*filterPos)[i]= srcW - filterSize;
588 *outFilterSize * (dstW + 3) *
sizeof(int16_t), fail);
591 for (i = 0; i < dstW; i++) {
596 for (j = 0; j < filterSize; j++) {
597 sum += filter[i * filterSize + j];
599 sum = (sum + one / 2) / one;
600 for (j = 0; j < *outFilterSize; j++) {
601 int64_t
v = filter[i * filterSize + j] + error;
603 (*outFilter)[i * (*outFilterSize) + j] = intV;
604 error = v - intV * sum;
608 (*filterPos)[dstW + 0] =
609 (*filterPos)[dstW + 1] =
610 (*filterPos)[dstW + 2] = (*filterPos)[dstW - 1];
612 for (i = 0; i < *outFilterSize; i++) {
613 int k = (dstW - 1) * (*outFilterSize) + i;
614 (*outFilter)[k + 1 * (*outFilterSize)] =
615 (*outFilter)[k + 2 * (*outFilterSize)] =
616 (*outFilter)[k + 3 * (*outFilterSize)] = (*outFilter)[k];
629 #if HAVE_MMXEXT_INLINE
630 static int init_hscaler_mmxext(
int dstW,
int xInc,
uint8_t *filterCode,
659 "movq (%%"REG_d
", %%"REG_a
"), %%mm3 \n\t"
660 "movd (%%"REG_c
", %%"REG_S
"), %%mm0 \n\t"
661 "movd 1(%%"REG_c
", %%"REG_S
"), %%mm1 \n\t"
662 "punpcklbw %%mm7, %%mm1 \n\t"
663 "punpcklbw %%mm7, %%mm0 \n\t"
664 "pshufw $0xFF, %%mm1, %%mm1 \n\t"
666 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
668 "psubw %%mm1, %%mm0 \n\t"
669 "movl 8(%%"REG_b
", %%"REG_a
"), %%esi \n\t"
670 "pmullw %%mm3, %%mm0 \n\t"
671 "psllw $7, %%mm1 \n\t"
672 "paddw %%mm1, %%mm0 \n\t"
674 "movq %%mm0, (%%"REG_D
", %%"REG_a
") \n\t"
676 "add $8, %%"REG_a
" \n\t"
691 :
"=r" (fragmentA),
"=r" (imm8OfPShufW1A),
"=r" (imm8OfPShufW2A),
692 "=r" (fragmentLengthA)
699 "movq (%%"REG_d
", %%"REG_a
"), %%mm3 \n\t"
700 "movd (%%"REG_c
", %%"REG_S
"), %%mm0 \n\t"
701 "punpcklbw %%mm7, %%mm0 \n\t"
702 "pshufw $0xFF, %%mm0, %%mm1 \n\t"
704 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
706 "psubw %%mm1, %%mm0 \n\t"
707 "movl 8(%%"REG_b
", %%"REG_a
"), %%esi \n\t"
708 "pmullw %%mm3, %%mm0 \n\t"
709 "psllw $7, %%mm1 \n\t"
710 "paddw %%mm1, %%mm0 \n\t"
712 "movq %%mm0, (%%"REG_D
", %%"REG_a
") \n\t"
714 "add $8, %%"REG_a
" \n\t"
729 :
"=r" (fragmentB),
"=r" (imm8OfPShufW1B),
"=r" (imm8OfPShufW2B),
730 "=r" (fragmentLengthB)
736 for (i = 0; i < dstW / numSplits; i++) {
741 int b = ((xpos + xInc) >> 16) - xx;
742 int c = ((xpos + xInc * 2) >> 16) - xx;
743 int d = ((xpos + xInc * 3) >> 16) - xx;
744 int inc = (d + 1 < 4);
745 uint8_t *fragment = (d + 1 < 4) ? fragmentB : fragmentA;
746 x86_reg imm8OfPShufW1 = (d + 1 < 4) ? imm8OfPShufW1B : imm8OfPShufW1A;
747 x86_reg imm8OfPShufW2 = (d + 1 < 4) ? imm8OfPShufW2B : imm8OfPShufW2A;
748 x86_reg fragmentLength = (d + 1 < 4) ? fragmentLengthB : fragmentLengthA;
749 int maxShift = 3 - (d + inc);
753 filter[i] = ((xpos & 0xFFFF) ^ 0xFFFF) >> 9;
754 filter[i + 1] = (((xpos + xInc) & 0xFFFF) ^ 0xFFFF) >> 9;
755 filter[i + 2] = (((xpos + xInc * 2) & 0xFFFF) ^ 0xFFFF) >> 9;
756 filter[i + 3] = (((xpos + xInc * 3) & 0xFFFF) ^ 0xFFFF) >> 9;
757 filterPos[i / 2] = xx;
759 memcpy(filterCode + fragmentPos, fragment, fragmentLength);
761 filterCode[fragmentPos + imm8OfPShufW1] = (a + inc) |
765 filterCode[fragmentPos + imm8OfPShufW2] = a | (b << 2) |
769 if (i + 4 - inc >= dstW)
771 else if ((filterPos[i / 2] & 3) <= maxShift)
772 shift = filterPos[i / 2] & 3;
774 if (shift && i >= shift) {
775 filterCode[fragmentPos + imm8OfPShufW1] += 0x55 *
shift;
776 filterCode[fragmentPos + imm8OfPShufW2] += 0x55 *
shift;
777 filterPos[i / 2] -=
shift;
781 fragmentPos += fragmentLength;
784 filterCode[fragmentPos] =
RET;
789 filterPos[((i / 2) + 1) & (~1)] = xpos >> 16;
791 return fragmentPos + 1;
803 int srcRange,
const int table[4],
int dstRange,
804 int brightness,
int contrast,
int saturation)
829 contrast, saturation);
834 contrast, saturation);
839 int *srcRange,
int **
table,
int *dstRange,
840 int *brightness,
int *contrast,
int *saturation)
903 int usesVFilter, usesHFilter;
910 int dst_stride =
FFALIGN(dstW *
sizeof(int16_t) + 66, 16);
923 unscaled = (srcW == dstW && srcH == dstH);
931 av_log(c,
AV_LOG_WARNING,
"deprecated pixel format used, make sure you did set range correctly\n");
958 if (!i || (i & (i - 1))) {
963 if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
967 srcW, srcH, dstW, dstH);
972 dstFilter = &dummyFilter;
974 srcFilter = &dummyFilter;
976 c->
lumXInc = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;
977 c->
lumYInc = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;
980 c->
vRounder = 4 * 0x0001000100010001ULL;
1008 "Error diffusion dither is only supported in full chroma interpolation for destination format '%s'\n",
1015 "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
1022 if (!(flags & SWS_FULL_CHR_H_INT)) {
1024 "%s output is not supported with half chroma resolution, switching to full\n",
1033 if (flags & SWS_FULL_CHR_H_INT &&
1048 "full chroma interpolation for destination format '%s' not yet implemented\n",
1050 flags &= ~SWS_FULL_CHR_H_INT;
1053 if (
isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
1085 if (unscaled && !usesHFilter && !usesVFilter &&
1092 "using unscaled %s -> %s special converter\n",
1111 (srcW & 15) == 0) ? 1 : 0;
1117 "output width is not a multiple of 32 -> no MMXEXT scaler\n");
1134 if (flags & SWS_FAST_BILINEAR) {
1141 c->
lumXInc = ((int64_t)(srcW - 2) << 16) / (dstW - 2) - 20;
1146 #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
1150 #if HAVE_MMXEXT_INLINE
1160 PROT_READ | PROT_WRITE,
1161 MAP_PRIVATE | MAP_ANONYMOUS,
1164 PROT_READ | PROT_WRITE,
1165 MAP_PRIVATE | MAP_ANONYMOUS,
1167 #elif HAVE_VIRTUALALLOC
1171 PAGE_EXECUTE_READWRITE);
1175 PAGE_EXECUTE_READWRITE);
1181 #ifdef MAP_ANONYMOUS
1208 const int filterAlign =
1215 srcW, dstW, filterAlign, 1 << 14,
1217 cpu_flags, srcFilter->
lumH, dstFilter->
lumH,
1223 (flags & SWS_BICUBLIN) ? (flags |
SWS_BILINEAR) : flags,
1224 cpu_flags, srcFilter->
chrH, dstFilter->
chrH,
1232 const int filterAlign =
1238 c->
lumYInc, srcH, dstH, filterAlign, (1 << 12),
1245 filterAlign, (1 << 12),
1257 short *p = (
short *)&c->vYCoeffsBank[i];
1258 for (j = 0; j < 8; j++)
1264 short *p = (
short *)&c->vCCoeffsBank[i];
1265 for (j = 0; j < 8; j++)
1274 for (i = 0; i < dstH; i++) {
1275 int chrI = (int64_t)i * c->
chrDstH / dstH;
1290 for (i = 0; i < 4; i++)
1305 dst_stride + 16, fail);
1313 dst_stride * 2 + 32, fail);
1318 if (CONFIG_SWSCALE_ALPHA && c->
alpPixBuf)
1321 dst_stride + 16, fail);
1329 for(j=0; j<dst_stride/2+1; j++)
1332 for(j=0; j<dst_stride+1; j++)
1338 if (flags & SWS_FAST_BILINEAR)
1344 else if (flags &
SWS_X)
1388 "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1391 "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1402 #if FF_API_SWS_GETCONTEXT
1406 SwsFilter *dstFilter,
const double *param)
1426 c->
param[0] = param[0];
1427 c->
param[1] = param[1];
1443 float lumaSharpen,
float chromaSharpen,
1444 float chromaHShift,
float chromaVShift,
1451 if (lumaGBlur != 0.0) {
1459 if (chromaGBlur != 0.0) {
1467 if (chromaSharpen != 0.0) {
1476 if (lumaSharpen != 0.0) {
1485 if (chromaHShift != 0.0)
1488 if (chromaVShift != 0.0)
1508 if(length <= 0 || length > INT_MAX/
sizeof(
double))
1523 const int length = (int)(variance * quality + 0.5) | 1;
1525 double middle = (length - 1) * 0.5;
1528 if(variance < 0 || quality < 0)
1536 for (i = 0; i < length; i++) {
1537 double dist = i - middle;
1538 vec->
coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
1539 sqrt(2 * variance *
M_PI);
1555 for (i = 0; i < length; i++)
1571 for (i = 0; i < a->
length; i++)
1581 for (i = 0; i < a->
length; i++)
1582 a->
coeff[i] *= scalar;
1599 for (i = 0; i < a->
length; i++) {
1600 for (j = 0; j < b->
length; j++) {
1617 for (i = 0; i < a->
length; i++)
1634 for (i = 0; i < a->
length; i++)
1652 for (i = 0; i < a->
length; i++) {
1653 vec->
coeff[i + (length - 1) / 2 -
1704 for (i = 0; i < a->
length; i++)
1717 for (i = 0; i < a->
length; i++)
1718 if (a->
coeff[i] > max)
1721 for (i = 0; i < a->
length; i++)
1722 if (a->
coeff[i] < min)
1727 for (i = 0; i < a->
length; i++) {
1728 int x = (int)((a->
coeff[i] - min) * 60.0 / range + 0.5);
1729 av_log(log_ctx, log_level,
"%1.3f ", a->
coeff[i]);
1731 av_log(log_ctx, log_level,
" ");
1732 av_log(log_ctx, log_level,
"|\n");
1780 if (CONFIG_SWSCALE_ALPHA && c->
alpPixBuf) {
1786 for (i = 0; i < 4; i++)
1809 #elif HAVE_VIRTUALALLOC
1834 const double *
param)
1840 param = default_param;
1843 (context->
srcW != srcW ||
1844 context->
srcH != srcH ||
1846 context->
dstW != dstW ||
1847 context->
dstH != dstH ||
1849 context->
flags != flags ||
1850 context->
param[0] != param[0] ||
1851 context->
param[1] != param[1])) {
1870 context->
param[0] = param[0];
1871 context->
param[1] = param[1];
1875 context->
dstRange, 0, 1 << 16, 1 << 16);