1 /*
2 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "config.h"
22
23 #define _SVID_SOURCE // needed for MAP_ANONYMOUS
24 #define _DARWIN_C_SOURCE // needed for MAP_ANON
25 #include <inttypes.h>
26 #include <math.h>
27 #include <stdio.h>
28 #include <string.h>
29 #if HAVE_SYS_MMAN_H
30 #include <sys/mman.h>
31 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
32 #define MAP_ANONYMOUS MAP_ANON
33 #endif
34 #endif
35 #if HAVE_VIRTUALALLOC
36 #define WIN32_LEAN_AND_MEAN
37 #include <windows.h>
38 #endif
39
54
56 {
59 }
60
62 {
63 return FFMPEG_CONFIGURATION;
64 }
65
67 {
68 #define LICENSE_PREFIX "libswscale license: "
70 }
71
72 #define RET 0xC3 // near return opcode for x86
73
79
207 };
208
210 {
213 }
214
216 {
219 }
220
222 {
225 }
226
228
229 #if FF_API_SWS_FORMAT_NAME
231 {
233 if (desc)
235 else
236 return "Unknown format";
237 }
238 #endif
239
241 double dist)
242 {
243 if (dist <= 1.0)
244 return ((d * dist + c) * dist + b) * dist +
a;
245 else
247 b + 2.0 * c + 3.0 * d,
248 c + 3.0 * d,
249 -b - 3.0 * c - 6.0 * d,
250 dist - 1.0);
251 }
252
254 int *outFilterSize, int xInc, int srcW,
255 int dstW, int filterAlign, int one,
258 double param[2])
259 {
260 int i;
261 int filterSize;
262 int filter2Size;
263 int minFilterSize;
265 int64_t *filter2 = NULL;
266 const int64_t fone = 1LL << (54 -
FFMIN(
av_log2(srcW/dstW), 8));
268
269 emms_c();
// FIXME should not be required but IS (even for non-MMX versions)
270
271 // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end
273
274 if (
FFABS(xInc - 0x10000) < 10) {
// unscaled
275 int i;
276 filterSize = 1;
278 dstW * sizeof(*filter) * filterSize, fail);
279
280 for (i = 0; i < dstW; i++) {
281 filter[i * filterSize] = fone;
282 (*filterPos)[i] = i;
283 }
284 }
else if (flags &
SWS_POINT) {
// lame looking point sampling mode
285 int i;
286 int64_t xDstInSrc;
287 filterSize = 1;
289 dstW * sizeof(*filter) * filterSize, fail);
290
291 xDstInSrc = xInc / 2 - 0x8000;
292 for (i = 0; i < dstW; i++) {
293 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
294
295 (*filterPos)[i] = xx;
296 filter[i] = fone;
297 xDstInSrc += xInc;
298 }
299 }
else if ((xInc <= (1 << 16) && (flags &
SWS_AREA)) ||
301 int i;
302 int64_t xDstInSrc;
303 filterSize = 2;
305 dstW * sizeof(*filter) * filterSize, fail);
306
307 xDstInSrc = xInc / 2 - 0x8000;
308 for (i = 0; i < dstW; i++) {
309 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
310 int j;
311
312 (*filterPos)[i] = xx;
313 // bilinear upscale / linear interpolate / area averaging
314 for (j = 0; j < filterSize; j++) {
315 int64_t
coeff= fone -
FFABS(((int64_t)xx<<16) - xDstInSrc)*(fone>>16);
316 if (coeff < 0)
317 coeff = 0;
318 filter[i * filterSize + j] =
coeff;
319 xx++;
320 }
321 xDstInSrc += xInc;
322 }
323 } else {
324 int64_t xDstInSrc;
325 int sizeFactor;
326
328 sizeFactor = 4;
329 else if (flags &
SWS_X)
330 sizeFactor = 8;
332 sizeFactor = 1; // downscale only, for upscale it is bilinear
334 sizeFactor = 8; // infinite ;)
338 sizeFactor = 20; // infinite ;)
340 sizeFactor = 20; // infinite ;)
342 sizeFactor = 2;
343 else {
345 }
346
347 if (xInc <= 1 << 16)
348 filterSize = 1 + sizeFactor; // upscale
349 else
350 filterSize = 1 + (sizeFactor * srcW + dstW - 1) / dstW;
351
352 filterSize =
FFMIN(filterSize, srcW - 2);
353 filterSize =
FFMAX(filterSize, 1);
354
356 dstW * sizeof(*filter) * filterSize, fail);
357
358 xDstInSrc = xInc - 0x10000;
359 for (i = 0; i < dstW; i++) {
360 int xx = (xDstInSrc - ((filterSize - 2) << 16)) / (1 << 17);
361 int j;
362 (*filterPos)[i] = xx;
363 for (j = 0; j < filterSize; j++) {
364 int64_t d = (
FFABS(((int64_t)xx << 17) - xDstInSrc)) << 13;
365 double floatd;
367
368 if (xInc > 1 << 16)
369 d = d * dstW / srcW;
370 floatd = d * (1.0 / (1 << 30));
371
372 if (flags & SWS_BICUBIC) {
375
376 if (d >= 1LL << 31) {
377 coeff = 0.0;
378 } else {
379 int64_t dd = (d * d) >> 30;
380 int64_t ddd = (dd * d) >> 30;
381
382 if (d < 1LL << 30)
383 coeff = (12 * (1 << 24) - 9 * B - 6 * C) * ddd +
384 (-18 * (1 << 24) + 12 * B + 6 * C) * dd +
385 (6 * (1 << 24) - 2 * B) * (1 << 30);
386 else
387 coeff = (-B - 6 * C) * ddd +
388 (6 * B + 30 * C) * dd +
389 (-12 * B - 48 * C) * d +
390 (8 * B + 24 * C) * (1 << 30);
391 }
392 coeff /= (1LL<<54)/fone;
393 }
394 #if 0
395 else if (flags & SWS_X) {
396 double p = param ? param * 0.01 : 0.3;
397 coeff = d ? sin(d *
M_PI) / (d *
M_PI) : 1.0;
398 coeff *= pow(2.0, -p * d * d);
399 }
400 #endif
401 else if (flags & SWS_X) {
404
405 if (floatd < 1.0)
406 c = cos(floatd *
M_PI);
407 else
408 c = -1.0;
409 if (c < 0.0)
410 c = -pow(-c, A);
411 else
412 c = pow(c, A);
413 coeff = (c * 0.5 + 0.5) * fone;
414 } else if (flags & SWS_AREA) {
415 int64_t d2 = d - (1 << 29);
416 if (d2 * xInc < -(1LL << (29 + 16)))
417 coeff = 1.0 * (1LL << (30 + 16));
418 else if (d2 * xInc < (1LL << (29 + 16)))
419 coeff = -d2 * xInc + (1LL << (29 + 16));
420 else
421 coeff = 0.0;
422 coeff *= fone >> (30 + 16);
423 } else if (flags & SWS_GAUSS) {
425 coeff = (pow(2.0, -p * floatd * floatd)) * fone;
426 } else if (flags & SWS_SINC) {
427 coeff = (d ? sin(floatd *
M_PI) / (floatd *
M_PI) : 1.0) * fone;
428 } else if (flags & SWS_LANCZOS) {
430 coeff = (d ? sin(floatd *
M_PI) * sin(floatd * M_PI / p) /
431 (floatd * floatd * M_PI * M_PI / p) : 1.0) * fone;
432 if (floatd > p)
433 coeff = 0;
434 } else if (flags & SWS_BILINEAR) {
435 coeff = (1 << 30) - d;
436 if (coeff < 0)
437 coeff = 0;
438 coeff *= fone >> 30;
439 } else if (flags & SWS_SPLINE) {
440 double p = -2.196152422706632;
442 } else {
444 }
445
446 filter[i * filterSize + j] =
coeff;
447 xx++;
448 }
449 xDstInSrc += 2 * xInc;
450 }
451 }
452
453 /* apply src & dst Filter to filter -> filter2
454 * av_free(filter);
455 */
457 filter2Size = filterSize;
458 if (srcFilter)
459 filter2Size += srcFilter->
length - 1;
460 if (dstFilter)
461 filter2Size += dstFilter->
length - 1;
464
465 for (i = 0; i < dstW; i++) {
466 int j, k;
467
468 if (srcFilter) {
469 for (k = 0; k < srcFilter->
length; k++) {
470 for (j = 0; j < filterSize; j++)
471 filter2[i * filter2Size + k + j] +=
472 srcFilter->
coeff[k] * filter[i * filterSize + j];
473 }
474 } else {
475 for (j = 0; j < filterSize; j++)
476 filter2[i * filter2Size + j] = filter[i * filterSize + j];
477 }
478 // FIXME dstFilter
479
480 (*filterPos)[i] += (filterSize - 1) / 2 - (filter2Size - 1) / 2;
481 }
483
484 /* try to reduce the filter-size (step1 find size and shift left) */
485 // Assume it is near normalized (*0.5 or *2.0 is OK but * 0.001 is not).
486 minFilterSize = 0;
487 for (i = dstW - 1; i >= 0; i--) {
488 int min = filter2Size;
489 int j;
490 int64_t cutOff = 0.0;
491
492 /* get rid of near zero elements on the left by shifting left */
493 for (j = 0; j < filter2Size; j++) {
494 int k;
495 cutOff +=
FFABS(filter2[i * filter2Size]);
496
498 break;
499
500 /* preserve monotonicity because the core can't handle the
501 * filter otherwise */
502 if (i < dstW - 1 && (*filterPos)[i] >= (*filterPos)[i + 1])
503 break;
504
505 // move filter coefficients left
506 for (k = 1; k < filter2Size; k++)
507 filter2[i * filter2Size + k - 1] = filter2[i * filter2Size + k];
508 filter2[i * filter2Size + k - 1] = 0;
509 (*filterPos)[i]++;
510 }
511
512 cutOff = 0;
513 /* count near zeros on the right */
514 for (j = filter2Size - 1; j > 0; j--) {
515 cutOff +=
FFABS(filter2[i * filter2Size + j]);
516
518 break;
519 min--;
520 }
521
522 if (min > minFilterSize)
524 }
525
527 // we can handle the special case 4, so we don't want to go the full 8
528 if (minFilterSize < 5)
529 filterAlign = 4;
530
531 /* We really don't want to waste our time doing useless computation, so
532 * fall back on the scalar C code for very small filters.
533 * Vectorizing is worth it only if you have a decent-sized vector. */
534 if (minFilterSize < 3)
535 filterAlign = 1;
536 }
537
539 // special case for unscaled vertical filtering
540 if (minFilterSize == 1 && filterAlign == 2)
541 filterAlign = 1;
542 }
543
545 filterSize = (minFilterSize + (filterAlign - 1)) & (~(filterAlign - 1));
547 filter =
av_malloc(filterSize * dstW *
sizeof(*filter));
550 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);
551 goto fail;
552 }
553 *outFilterSize = filterSize;
554
557 "SwScaler: reducing / aligning filtersize %d -> %d\n",
558 filter2Size, filterSize);
559 /* try to reduce the filter-size (step2 reduce it) */
560 for (i = 0; i < dstW; i++) {
561 int j;
562
563 for (j = 0; j < filterSize; j++) {
564 if (j >= filter2Size)
565 filter[i * filterSize + j] = 0;
566 else
567 filter[i * filterSize + j] = filter2[i * filter2Size + j];
569 filter[i * filterSize + j] = 0;
570 }
571 }
572
573 // FIXME try to align filterPos if possible
574
575 // fix borders
576 for (i = 0; i < dstW; i++) {
577 int j;
578 if ((*filterPos)[i] < 0) {
579 // move filter coefficients left to compensate for filterPos
580 for (j = 1; j < filterSize; j++) {
581 int left =
FFMAX(j + (*filterPos)[i], 0);
582 filter[i * filterSize + left] += filter[i * filterSize + j];
583 filter[i * filterSize + j] = 0;
584 }
585 (*filterPos)[i]= 0;
586 }
587
588 if ((*filterPos)[i] + filterSize > srcW) {
589 int shift = (*filterPos)[i] + filterSize - srcW;
590 // move filter coefficients right to compensate for filterPos
591 for (j = filterSize - 2; j >= 0; j--) {
592 int right =
FFMIN(j + shift, filterSize - 1);
593 filter[i * filterSize + right] += filter[i * filterSize + j];
594 filter[i * filterSize + j] = 0;
595 }
596 (*filterPos)[i]= srcW - filterSize;
597 }
598 }
599
600 // Note the +1 is for the MMX scaler which reads over the end
601 /* align at 16 for AltiVec (needed by hScale_altivec_real) */
603 *outFilterSize * (dstW + 3) * sizeof(int16_t), fail);
604
605 /* normalize & store in outFilter */
606 for (i = 0; i < dstW; i++) {
607 int j;
608 int64_t error = 0;
609 int64_t sum = 0;
610
611 for (j = 0; j < filterSize; j++) {
612 sum += filter[i * filterSize + j];
613 }
614 sum = (sum + one / 2) / one;
615 for (j = 0; j < *outFilterSize; j++) {
616 int64_t
v = filter[i * filterSize + j] + error;
618 (*outFilter)[i * (*outFilterSize) + j] = intV;
619 error = v - intV * sum;
620 }
621 }
622
623 (*filterPos)[dstW + 0] =
624 (*filterPos)[dstW + 1] =
625 (*filterPos)[dstW + 2] = (*filterPos)[dstW - 1]; /* the MMX/SSE scaler will
626 * read over the end */
627 for (i = 0; i < *outFilterSize; i++) {
628 int k = (dstW - 1) * (*outFilterSize) + i;
629 (*outFilter)[k + 1 * (*outFilterSize)] =
630 (*outFilter)[k + 2 * (*outFilterSize)] =
631 (*outFilter)[k + 3 * (*outFilterSize)] = (*outFilter)[k];
632 }
633
634 ret = 0;
635
636 fail:
637 if(ret < 0)
642 }
643
644 #if HAVE_MMXEXT_INLINE
645 static av_cold int init_hscaler_mmxext(
int dstW,
int xInc,
uint8_t *filterCode,
647 int numSplits)
648 {
657 int fragmentPos;
658
659 int xpos, i;
660
661 // create an optimized horizontal scaling routine
662 /* This scaler is made of runtime-generated MMXEXT code using specially tuned
663 * pshufw instructions. For every four output pixels, if four input pixels
664 * are enough for the fast bilinear scaling, then a chunk of fragmentB is
665 * used. If five input pixels are needed, then a chunk of fragmentA is used.
666 */
667
668 // code fragment
669
670 __asm__ volatile (
671 "jmp 9f \n\t"
672 // Begin
673 "0: \n\t"
674 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
675 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
676 "movd 1(%%"REG_c", %%"REG_S"), %%mm1 \n\t"
677 "punpcklbw %%mm7, %%mm1 \n\t"
678 "punpcklbw %%mm7, %%mm0 \n\t"
679 "pshufw 0ドルxFF, %%mm1, %%mm1 \n\t"
680 "1: \n\t"
681 "pshufw 0ドルxFF, %%mm0, %%mm0 \n\t"
682 "2: \n\t"
683 "psubw %%mm1, %%mm0 \n\t"
684 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
685 "pmullw %%mm3, %%mm0 \n\t"
686 "psllw 7,ドル %%mm1 \n\t"
687 "paddw %%mm1, %%mm0 \n\t"
688
689 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
690
691 "add 8,ドル %%"REG_a" \n\t"
692 // End
693 "9: \n\t"
694 // "int 3ドル \n\t"
698 "dec %1 \n\t"
699 "dec %2 \n\t"
700 "sub %0, %1 \n\t"
701 "sub %0, %2 \n\t"
703 "sub %0, %3 \n\t"
704
705
706 : "=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A),
707 "=r" (fragmentLengthA)
708 );
709
710 __asm__ volatile (
711 "jmp 9f \n\t"
712 // Begin
713 "0: \n\t"
714 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
715 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
716 "punpcklbw %%mm7, %%mm0 \n\t"
717 "pshufw 0ドルxFF, %%mm0, %%mm1 \n\t"
718 "1: \n\t"
719 "pshufw 0ドルxFF, %%mm0, %%mm0 \n\t"
720 "2: \n\t"
721 "psubw %%mm1, %%mm0 \n\t"
722 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
723 "pmullw %%mm3, %%mm0 \n\t"
724 "psllw 7,ドル %%mm1 \n\t"
725 "paddw %%mm1, %%mm0 \n\t"
726
727 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
728
729 "add 8,ドル %%"REG_a" \n\t"
730 // End
731 "9: \n\t"
732 // "int 3ドル \n\t"
736 "dec %1 \n\t"
737 "dec %2 \n\t"
738 "sub %0, %1 \n\t"
739 "sub %0, %2 \n\t"
741 "sub %0, %3 \n\t"
742
743
744 : "=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B),
745 "=r" (fragmentLengthB)
746 );
747
748 xpos = 0; // lumXInc/2 - 0x8000; // difference between pixel centers
749 fragmentPos = 0;
750
751 for (i = 0; i < dstW / numSplits; i++) {
752 int xx = xpos >> 16;
753
754 if ((i & 3) == 0) {
756 int b = ((xpos + xInc) >> 16) - xx;
757 int c = ((xpos + xInc * 2) >> 16) - xx;
758 int d = ((xpos + xInc * 3) >> 16) - xx;
759 int inc = (d + 1 < 4);
760 uint8_t *fragment = (d + 1 < 4) ? fragmentB : fragmentA;
761 x86_reg imm8OfPShufW1 = (d + 1 < 4) ? imm8OfPShufW1B : imm8OfPShufW1A;
762 x86_reg imm8OfPShufW2 = (d + 1 < 4) ? imm8OfPShufW2B : imm8OfPShufW2A;
763 x86_reg fragmentLength = (d + 1 < 4) ? fragmentLengthB : fragmentLengthA;
764 int maxShift = 3 - (d + inc);
766
767 if (filterCode) {
768 filter[i] = ((xpos & 0xFFFF) ^ 0xFFFF) >> 9;
769 filter[i + 1] = (((xpos + xInc) & 0xFFFF) ^ 0xFFFF) >> 9;
770 filter[i + 2] = (((xpos + xInc * 2) & 0xFFFF) ^ 0xFFFF) >> 9;
771 filter[i + 3] = (((xpos + xInc * 3) & 0xFFFF) ^ 0xFFFF) >> 9;
772 filterPos[i / 2] = xx;
773
774 memcpy(filterCode + fragmentPos, fragment, fragmentLength);
775
776 filterCode[fragmentPos + imm8OfPShufW1] = (a + inc) |
777 ((b + inc) << 2) |
778 ((c + inc) << 4) |
779 ((d + inc) << 6);
780 filterCode[fragmentPos + imm8OfPShufW2] = a | (b << 2) |
781 (c << 4) |
782 (d << 6);
783
784 if (i + 4 - inc >= dstW)
785 shift = maxShift; // avoid overread
786 else if ((filterPos[i / 2] & 3) <= maxShift)
787 shift = filterPos[i / 2] & 3; // align
788
789 if (shift && i >= shift) {
790 filterCode[fragmentPos + imm8OfPShufW1] += 0x55 *
shift;
791 filterCode[fragmentPos + imm8OfPShufW2] += 0x55 *
shift;
792 filterPos[i / 2] -=
shift;
793 }
794 }
795
796 fragmentPos += fragmentLength;
797
798 if (filterCode)
799 filterCode[fragmentPos] =
RET;
800 }
801 xpos += xInc;
802 }
803 if (filterCode)
804 filterPos[((i / 2) + 1) & (~1)] = xpos >> 16; // needed to jump to the next part
805
806 return fragmentPos + 1;
807 }
808 #endif /* HAVE_MMXEXT_INLINE */
809
811 {
815 }
816
818 {
819 int64_t
W,
V, Z, Cy, Cu, Cv;
820 int64_t vr = table[0];
821 int64_t ub = table[1];
822 int64_t ug = -table[2];
823 int64_t vg = -table[3];
827 int i;
828 static const int8_t map[] = {
853 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //24
854 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //25
855 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //26
856 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //27
857 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //28
858 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //29
859 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //30
860 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //31
864 };
865
866 dstRange = 0; //FIXME range = 1 is handled elsewhere
867
868 if (!dstRange) {
869 cy = cy * 255 / 219;
870 } else {
871 vr = vr * 224 / 255;
872 ub = ub * 224 / 255;
873 ug = ug * 224 / 255;
874 vg = vg * 224 / 255;
875 }
879
883
887
891
895
897 c->input_rgb2yuv_table[
BY_IDX] = ((int)(0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
898 c->input_rgb2yuv_table[
BV_IDX] = (-(int)(0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
899 c->input_rgb2yuv_table[
BU_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
900 c->input_rgb2yuv_table[
GY_IDX] = ((int)(0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
901 c->input_rgb2yuv_table[
GV_IDX] = (-(int)(0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
902 c->input_rgb2yuv_table[
GU_IDX] = (-(int)(0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
903 c->input_rgb2yuv_table[
RY_IDX] = ((int)(0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
904 c->input_rgb2yuv_table[
RV_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
905 c->input_rgb2yuv_table[
RU_IDX] = (-(int)(0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
906 }
908 AV_WL16(p + 16*4 + 2*i, map[i] >= 0 ? c->input_rgb2yuv_table[map[i]] : 0);
909 }
910
912 {
913 int i;
916 static const int16_t xyz2rgb_matrix[3][4] = {
917 {13270, -6295, -2041},
918 {-3969, 7682, 170},
919 { 228, -835, 4329} };
920 static int16_t xyzgamma_tab[4096], rgbgamma_tab[4096];
921
925
926 if (rgbgamma_tab[4095])
927 return;
928
929 /* set gamma vectors */
930 for (i = 0; i < 4096; i++) {
931 xyzgamma_tab[i] =
lrint(pow(i / 4095.0, xyzgamma) * 4095.0);
932 rgbgamma_tab[i] =
lrint(pow(i / 4095.0, rgbgamma) * 4095.0);
933 }
934 }
935
937 int srcRange,
const int table[4],
int dstRange,
938 int brightness, int contrast, int saturation)
939 {
944
946 dstRange = 0;
948 srcRange = 0;
949
955
957
959 return -1;
960
963
966 contrast, saturation);
967 // FIXME factorize
968
971 contrast, saturation);
972 }
973
975
976 return 0;
977 }
978
980 int *srcRange,
int **
table,
int *dstRange,
981 int *brightness, int *contrast, int *saturation)
982 {
984 return -1;
985
993
994 return 0;
995 }
996
998 {
999 switch (*format) {
1002 return 1;
1005 return 1;
1008 return 1;
1011 return 1;
1014 return 1;
1016 return 1;
1017 default:
1018 return 0;
1019 }
1020 }
1021
1023 {
1024 switch (*format) {
1029 default: return 0;
1030 }
1031 }
1032
1034 {
1035 switch (*format) {
1038 default: return 0;
1039 }
1040 }
1041
1043 {
1045
1046 if (c) {
1049 }
1050
1052 }
1053
1056 {
1057 int i, j;
1058 int usesVFilter, usesHFilter;
1059 int unscaled;
1060 SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };
1065 int dst_stride =
FFALIGN(dstW *
sizeof(int16_t) + 66, 16);
1071
1077
1078 unscaled = (srcW == dstW && srcH == dstH);
1079
1083 av_log(c,
AV_LOG_WARNING,
"deprecated pixel format used, make sure you did set range correctly\n");
1088
1092 }
1093
1100 }
1105 }
1106 }
1107
1119 if (!i || (i & (i - 1))) {
1122 }
1123 /* sanity check */
1124 if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
1125 /* FIXME check if these are enough and try to lower them after
1126 * fixing the relevant parts of the code */
1128 srcW, srcH, dstW, dstH);
1130 }
1131
1132 if (!dstFilter)
1133 dstFilter = &dummyFilter;
1134 if (!srcFilter)
1135 srcFilter = &dummyFilter;
1136
1137 c->
lumXInc = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;
1138 c->
lumYInc = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;
1141 c->
vRounder = 4 * 0x0001000100010001ULL;
1142
1143 usesVFilter = (srcFilter->
lumV && srcFilter->
lumV->
length > 1) ||
1147 usesHFilter = (srcFilter->
lumH && srcFilter->
lumH->
length > 1) ||
1151
1154
1156 if (dstW&1) {
1160 }
1161 }
1162
1169 "Error diffusion dither is only supported in full chroma interpolation for destination format '%s'\n",
1173 }
1176 "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
1180 }
1181 }
1183 if (!(flags & SWS_FULL_CHR_H_INT)) {
1185 "%s output is not supported with half chroma resolution, switching to full\n",
1189 }
1190 }
1191
1192 /* reuse chroma for 2 pixels RGB/BGR unless user wants full
1193 * chroma interpolation */
1194 if (flags & SWS_FULL_CHR_H_INT &&
1207 ) {
1209 "full chroma interpolation for destination format '%s' not yet implemented\n",
1211 flags &= ~SWS_FULL_CHR_H_INT;
1213 }
1214 if (
isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
1216
1217 // drop some chroma lines if the user wants it
1221
1222 /* drop every other pixel for chroma calculation unless user
1223 * wants full chroma */
1236
1237 // Note the FF_CEIL_RSHIFT is so that we always round toward +inf.
1242
1244
1245 /* unscaled special cases */
1246 if (unscaled && !usesHFilter && !usesVFilter &&
1249
1253 "using unscaled %s -> %s special converter\n",
1255 return 0;
1256 }
1257 }
1258
1268 dst_stride <<= 1;
1269
1272 (srcW & 15) == 0) ? 1 : 0;
1274
1278 "output width is not a multiple of 32 -> no MMXEXT scaler\n");
1279 }
1282 } else
1284
1287
1288 /* Match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src
1289 * to pixel n-2 of dst, but only for the FAST_BILINEAR mode otherwise do
1290 * correct scaling.
1291 * n-2 is the last chrominance sample available.
1292 * This is not perfect, but no one should notice the difference, the more
1293 * correct variant would be like the vertical one, but that would require
1294 * some special code for the first and last pixel */
1295 if (flags & SWS_FAST_BILINEAR) {
1299 }
1300 // we don't use the x86 asm scaler if MMX is available
1302 c->
lumXInc = ((int64_t)(srcW - 2) << 16) / (dstW - 2) - 20;
1304 }
1305 }
1306
1307 #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
1308
1309 /* precalculate horizontal scaler filter coefficients */
1310 {
1311 #if HAVE_MMXEXT_INLINE
1312 // can't downscale !!!
1315 NULL, NULL, 8);
1317 NULL, NULL, NULL, 4);
1318
1319 #if USE_MMAP
1321 PROT_READ | PROT_WRITE,
1322 MAP_PRIVATE | MAP_ANONYMOUS,
1323 -1, 0);
1325 PROT_READ | PROT_WRITE,
1326 MAP_PRIVATE | MAP_ANONYMOUS,
1327 -1, 0);
1328 #elif HAVE_VIRTUALALLOC
1331 MEM_COMMIT,
1332 PAGE_EXECUTE_READWRITE);
1335 MEM_COMMIT,
1336 PAGE_EXECUTE_READWRITE);
1337 #else
1340 #endif
1341
1342 #ifdef MAP_ANONYMOUS
1344 #else
1346 #endif
1347 {
1350 }
1351
1356
1361
1362 #if USE_MMAP
1365 #endif
1366 } else
1367 #endif /* HAVE_MMXEXT_INLINE */
1368 {
1369 const int filterAlign =
1372 1;
1373
1376 srcW, dstW, filterAlign, 1 << 14,
1378 cpu_flags, srcFilter->
lumH, dstFilter->
lumH,
1380 goto fail;
1384 (flags & SWS_BICUBLIN) ? (flags |
SWS_BILINEAR) : flags,
1385 cpu_flags, srcFilter->
chrH, dstFilter->
chrH,
1387 goto fail;
1388 }
1389 } // initialize horizontal stuff
1390
1391 /* precalculate vertical scaler filter coefficients */
1392 {
1393 const int filterAlign =
1396 1;
1397
1399 c->
lumYInc, srcH, dstH, filterAlign, (1 << 12),
1403 goto fail;
1406 filterAlign, (1 << 12),
1410 goto fail;
1411
1412 #if HAVE_ALTIVEC
1415
1417 int j;
1418 short *p = (short *)&c->vYCoeffsBank[i];
1419 for (j = 0; j < 8; j++)
1421 }
1422
1424 int j;
1425 short *p = (short *)&c->vCCoeffsBank[i];
1426 for (j = 0; j < 8; j++)
1428 }
1429 #endif
1430 }
1431
1432 // calculate buffer sizes so that they won't run out while handling these damn slices
1435 for (i = 0; i < dstH; i++) {
1436 int chrI = (int64_t)i * c->
chrDstH / dstH;
1440
1449 }
1450
1451 for (i = 0; i < 4; i++)
1453
1454 /* Allocate pixbufs (we use dynamic allocation because otherwise we would
1455 * need to allocate several megabytes to handle all possible cases) */
1461 /* Note we need at least one pixel more at the end because of the MMX code
1462 * (just in case someone wants to replace the 4000/8000). */
1463 /* align at 16 bytes for AltiVec */
1466 dst_stride + 16, fail);
1468 }
1469 // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
1474 dst_stride * 2 + 32, fail);
1478 }
1479 if (CONFIG_SWSCALE_ALPHA && c->
alpPixBuf)
1482 dst_stride + 16, fail);
1484 }
1485
1486 // try to avoid drawing green stuff between the right end and the stride end
1490 for(j=0; j<dst_stride/2+1; j++)
1492 } else
1493 for(j=0; j<dst_stride+1; j++)
1495
1497
1499 if (flags & SWS_FAST_BILINEAR)
1505 else if (flags &
SWS_X)
1521 else
1523
1530 "dithered " : "",
1531 #else
1532 "",
1533 #endif
1535
1544 else
1546
1549 "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1552 "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1555 }
1556
1558 return 0;
1559 fail: // FIXME replace things by appropriate error codes
1560 return -1;
1561 }
1562
1563 #if FF_API_SWS_GETCONTEXT
1567 SwsFilter *dstFilter,
const double *param)
1568 {
1570
1572 return NULL;
1573
1587
1588 if (param) {
1589 c->
param[0] = param[0];
1590 c->
param[1] = param[1];
1591 }
1595
1598 return NULL;
1599 }
1600
1602 }
1603 #endif
1604
1606 float lumaSharpen, float chromaSharpen,
1607 float chromaHShift, float chromaVShift,
1608 int verbose)
1609 {
1611 if (!filter)
1612 return NULL;
1613
1614 if (lumaGBlur != 0.0) {
1617 } else {
1620 }
1621
1622 if (chromaGBlur != 0.0) {
1625 } else {
1628 }
1629
1630 if (chromaSharpen != 0.0) {
1637 }
1638
1639 if (lumaSharpen != 0.0) {
1646 }
1647
1648 if (chromaHShift != 0.0)
1650
1651 if (chromaVShift != 0.0)
1653
1658
1659 if (verbose)
1661 if (verbose)
1663
1665 }
1666
1668 {
1670
1671 if(length <= 0 || length > INT_MAX/ sizeof(double))
1672 return NULL;
1673
1675 if (!vec)
1676 return NULL;
1681 return vec;
1682 }
1683
1685 {
1686 const int length = (int)(variance * quality + 0.5) | 1;
1687 int i;
1688 double middle = (length - 1) * 0.5;
1690
1691 if(variance < 0 || quality < 0)
1692 return NULL;
1693
1695
1696 if (!vec)
1697 return NULL;
1698
1699 for (i = 0; i <
length; i++) {
1700 double dist = i - middle;
1701 vec->
coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
1702 sqrt(2 * variance *
M_PI);
1703 }
1704
1706
1707 return vec;
1708 }
1709
1711 {
1712 int i;
1714
1715 if (!vec)
1716 return NULL;
1717
1718 for (i = 0; i <
length; i++)
1720
1721 return vec;
1722 }
1723
1725 {
1727 }
1728
1730 {
1731 int i;
1732 double sum = 0;
1733
1734 for (i = 0; i < a->
length; i++)
1736
1737 return sum;
1738 }
1739
1741 {
1742 int i;
1743
1744 for (i = 0; i < a->
length; i++)
1745 a->
coeff[i] *= scalar;
1746 }
1747
1749 {
1751 }
1752
1754 {
1756 int i, j;
1758
1759 if (!vec)
1760 return NULL;
1761
1762 for (i = 0; i < a->
length; i++) {
1763 for (j = 0; j < b->
length; j++) {
1765 }
1766 }
1767
1768 return vec;
1769 }
1770
1772 {
1774 int i;
1776
1777 if (!vec)
1778 return NULL;
1779
1780 for (i = 0; i < a->
length; i++)
1784
1785 return vec;
1786 }
1787
1789 {
1791 int i;
1793
1794 if (!vec)
1795 return NULL;
1796
1797 for (i = 0; i < a->
length; i++)
1801
1802 return vec;
1803 }
1804
1805 /* shift left / or right if "shift" is negative */
1807 {
1809 int i;
1811
1812 if (!vec)
1813 return NULL;
1814
1815 for (i = 0; i < a->
length; i++) {
1816 vec->
coeff[i + (length - 1) / 2 -
1818 }
1819
1820 return vec;
1821 }
1822
1824 {
1830 }
1831
1833 {
1839 }
1840
1842 {
1848 }
1849
1851 {
1857 }
1858
1860 {
1861 int i;
1863
1864 if (!vec)
1865 return NULL;
1866
1867 for (i = 0; i < a->
length; i++)
1869
1870 return vec;
1871 }
1872
1874 {
1875 int i;
1876 double max = 0;
1878 double range;
1879
1880 for (i = 0; i < a->
length; i++)
1881 if (a->
coeff[i] > max)
1883
1884 for (i = 0; i < a->
length; i++)
1885 if (a->
coeff[i] < min)
1887
1889
1890 for (i = 0; i < a->
length; i++) {
1891 int x = (int)((a->
coeff[i] - min) * 60.0 / range + 0.5);
1892 av_log(log_ctx, log_level,
"%1.3f ", a->
coeff[i]);
1893 for (; x > 0; x--)
1894 av_log(log_ctx, log_level,
" ");
1895 av_log(log_ctx, log_level,
"|\n");
1896 }
1897 }
1898
1900 {
1901 if (!a)
1902 return;
1906 }
1907
1909 {
1910 if (!filter)
1911 return;
1912
1922 }
1923
1925 {
1926 int i;
1927 if (!c)
1928 return;
1929
1934 }
1935
1941 }
1942
1943 if (CONFIG_SWSCALE_ALPHA && c->
alpPixBuf) {
1947 }
1948
1949 for (i = 0; i < 4; i++)
1951
1956 #if HAVE_ALTIVEC
1959 #endif
1960
1965
1966 #if HAVE_MMX_INLINE
1967 #if USE_MMAP
1972 #elif HAVE_VIRTUALALLOC
1977 #else
1980 #endif
1983 #endif /* HAVE_MMX_INLINE */
1984
1987
1989 }
1990
1997 const double *
param)
1998 {
2001
2002 if (!param)
2003 param = default_param;
2004
2005 if (context &&
2006 (context->
srcW != srcW ||
2007 context->
srcH != srcH ||
2009 context->
dstW != dstW ||
2010 context->
dstH != dstH ||
2012 context->
flags != flags ||
2013 context->
param[0] != param[0] ||
2014 context->
param[1] != param[1])) {
2016 context = NULL;
2017 }
2018
2019 if (!context) {
2021 return NULL;
2035 context->
param[0] = param[0];
2036 context->
param[1] = param[1];
2040 context->
dstRange, 0, 1 << 16, 1 << 16);
2043 return NULL;
2044 }
2045 }
2046 return context;
2047 }