Originally committed as revision 3033 to svn://svn.mplayerhq.hu/mplayer/trunk/postproc
Michael Niedermayer authored on 2001/11/21 03:07:13... | ... |
@@ -859,6 +859,43 @@ static inline void vertX1Filter(uint8_t *src, int stride, int QP) |
859 | 859 |
#endif |
860 | 860 |
} |
861 | 861 |
|
862 |
+/** |
|
863 |
+ * Experimental Filter 1 (Horizontal) |
|
864 |
+ * will not damage linear gradients |
|
865 |
+ * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter |
|
866 |
+ * can only smooth blocks at the expected locations (it cant smooth them if they did move) |
|
867 |
+ * MMX2 version does correct clipping C version doesnt |
|
868 |
+ * not identical with the vertical one |
|
869 |
+ */ |
|
870 |
+static inline void horizX1Filter(uint8_t *src, int stride, int QP) |
|
871 |
+{ |
|
872 |
+ int y; |
|
873 |
+//FIXME (has little in common with the mmx2 version) |
|
874 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
875 |
+ { |
|
876 |
+ int a= src[1] - src[2]; |
|
877 |
+ int b= src[3] - src[4]; |
|
878 |
+ int c= src[5] - src[6]; |
|
879 |
+ |
|
880 |
+ int d= MAX(ABS(b) - (ABS(a) + ABS(c))/2, 0); |
|
881 |
+ |
|
882 |
+ if(d < QP) |
|
883 |
+ { |
|
884 |
+ int v = d * SIGN(-b); |
|
885 |
+ |
|
886 |
+ src[1] +=v/8; |
|
887 |
+ src[2] +=v/4; |
|
888 |
+ src[3] +=3*v/8; |
|
889 |
+ src[4] -=3*v/8; |
|
890 |
+ src[5] -=v/4; |
|
891 |
+ src[6] -=v/8; |
|
892 |
+ |
|
893 |
+ } |
|
894 |
+ src+=stride; |
|
895 |
+ } |
|
896 |
+} |
|
897 |
+ |
|
898 |
+ |
|
862 | 899 |
static inline void doVertDefFilter(uint8_t src[], int stride, int QP) |
863 | 900 |
{ |
864 | 901 |
#if defined (HAVE_MMX2) || defined (HAVE_3DNOW) |
... | ... |
@@ -1438,6 +1475,109 @@ src-=8; |
1438 | 1438 |
#endif |
1439 | 1439 |
} |
1440 | 1440 |
|
1441 |
+/** |
|
1442 |
+ * Check if the given 8x8 Block is mostly "flat" |
|
1443 |
+ */ |
|
1444 |
+static inline int isHorizDC(uint8_t src[], int stride) |
|
1445 |
+{ |
|
1446 |
+ int numEq= 0; |
|
1447 |
+ int y; |
|
1448 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
1449 |
+ { |
|
1450 |
+ if(((src[0] - src[1] + 1) & 0xFFFF) < 3) numEq++; |
|
1451 |
+ if(((src[1] - src[2] + 1) & 0xFFFF) < 3) numEq++; |
|
1452 |
+ if(((src[2] - src[3] + 1) & 0xFFFF) < 3) numEq++; |
|
1453 |
+ if(((src[3] - src[4] + 1) & 0xFFFF) < 3) numEq++; |
|
1454 |
+ if(((src[4] - src[5] + 1) & 0xFFFF) < 3) numEq++; |
|
1455 |
+ if(((src[5] - src[6] + 1) & 0xFFFF) < 3) numEq++; |
|
1456 |
+ if(((src[6] - src[7] + 1) & 0xFFFF) < 3) numEq++; |
|
1457 |
+ src+= stride; |
|
1458 |
+ } |
|
1459 |
+ return numEq > hFlatnessThreshold; |
|
1460 |
+} |
|
1461 |
+ |
|
1462 |
+static inline int isHorizMinMaxOk(uint8_t src[], int stride, int QP) |
|
1463 |
+{ |
|
1464 |
+ if(abs(src[0] - src[7]) > 2*QP) return 0; |
|
1465 |
+ |
|
1466 |
+ return 1; |
|
1467 |
+} |
|
1468 |
+ |
|
1469 |
+static inline void doHorizDefFilter(uint8_t dst[], int stride, int QP) |
|
1470 |
+{ |
|
1471 |
+ int y; |
|
1472 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
1473 |
+ { |
|
1474 |
+ const int middleEnergy= 5*(dst[4] - dst[5]) + 2*(dst[2] - dst[5]); |
|
1475 |
+ |
|
1476 |
+ if(ABS(middleEnergy) < 8*QP) |
|
1477 |
+ { |
|
1478 |
+ const int q=(dst[3] - dst[4])/2; |
|
1479 |
+ const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]); |
|
1480 |
+ const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]); |
|
1481 |
+ |
|
1482 |
+ int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) ); |
|
1483 |
+ d= MAX(d, 0); |
|
1484 |
+ |
|
1485 |
+ d= (5*d + 32) >> 6; |
|
1486 |
+ d*= SIGN(-middleEnergy); |
|
1487 |
+ |
|
1488 |
+ if(q>0) |
|
1489 |
+ { |
|
1490 |
+ d= d<0 ? 0 : d; |
|
1491 |
+ d= d>q ? q : d; |
|
1492 |
+ } |
|
1493 |
+ else |
|
1494 |
+ { |
|
1495 |
+ d= d>0 ? 0 : d; |
|
1496 |
+ d= d<q ? q : d; |
|
1497 |
+ } |
|
1498 |
+ |
|
1499 |
+ dst[3]-= d; |
|
1500 |
+ dst[4]+= d; |
|
1501 |
+ } |
|
1502 |
+ dst+= stride; |
|
1503 |
+ } |
|
1504 |
+} |
|
1505 |
+ |
|
1506 |
+/** |
|
1507 |
+ * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block) |
|
1508 |
+ * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version) |
|
1509 |
+ */ |
|
1510 |
+static inline void doHorizLowPass(uint8_t dst[], int stride, int QP) |
|
1511 |
+{ |
|
1512 |
+ |
|
1513 |
+ int y; |
|
1514 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
1515 |
+ { |
|
1516 |
+ const int first= ABS(dst[-1] - dst[0]) < QP ? dst[-1] : dst[0]; |
|
1517 |
+ const int last= ABS(dst[8] - dst[7]) < QP ? dst[8] : dst[7]; |
|
1518 |
+ |
|
1519 |
+ int sums[9]; |
|
1520 |
+ sums[0] = first + dst[0]; |
|
1521 |
+ sums[1] = dst[0] + dst[1]; |
|
1522 |
+ sums[2] = dst[1] + dst[2]; |
|
1523 |
+ sums[3] = dst[2] + dst[3]; |
|
1524 |
+ sums[4] = dst[3] + dst[4]; |
|
1525 |
+ sums[5] = dst[4] + dst[5]; |
|
1526 |
+ sums[6] = dst[5] + dst[6]; |
|
1527 |
+ sums[7] = dst[6] + dst[7]; |
|
1528 |
+ sums[8] = dst[7] + last; |
|
1529 |
+ |
|
1530 |
+ dst[0]= ((sums[0]<<2) + ((first + sums[2])<<1) + sums[4] + 8)>>4; |
|
1531 |
+ dst[1]= ((dst[1]<<2) + ((first + sums[0] + sums[3])<<1) + sums[5] + 8)>>4; |
|
1532 |
+ dst[2]= ((dst[2]<<2) + ((first + sums[1] + sums[4])<<1) + sums[6] + 8)>>4; |
|
1533 |
+ dst[3]= ((dst[3]<<2) + ((sums[2] + sums[5])<<1) + sums[0] + sums[7] + 8)>>4; |
|
1534 |
+ dst[4]= ((dst[4]<<2) + ((sums[3] + sums[6])<<1) + sums[1] + sums[8] + 8)>>4; |
|
1535 |
+ dst[5]= ((dst[5]<<2) + ((last + sums[7] + sums[4])<<1) + sums[2] + 8)>>4; |
|
1536 |
+ dst[6]= (((last + dst[6])<<2) + ((dst[7] + sums[5])<<1) + sums[3] + 8)>>4; |
|
1537 |
+ dst[7]= ((sums[8]<<2) + ((last + sums[6])<<1) + sums[4] + 8)>>4; |
|
1538 |
+ |
|
1539 |
+ dst+= stride; |
|
1540 |
+ } |
|
1541 |
+} |
|
1542 |
+ |
|
1543 |
+ |
|
1441 | 1544 |
static inline void dering(uint8_t src[], int stride, int QP) |
1442 | 1545 |
{ |
1443 | 1546 |
#if defined (HAVE_MMX2) || defined (HAVE_3DNOW) |
... | ... |
@@ -859,6 +859,43 @@ static inline void vertX1Filter(uint8_t *src, int stride, int QP) |
859 | 859 |
#endif |
860 | 860 |
} |
861 | 861 |
|
862 |
+/** |
|
863 |
+ * Experimental Filter 1 (Horizontal) |
|
864 |
+ * will not damage linear gradients |
|
865 |
+ * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter |
|
866 |
+ * can only smooth blocks at the expected locations (it cant smooth them if they did move) |
|
867 |
+ * MMX2 version does correct clipping C version doesnt |
|
868 |
+ * not identical with the vertical one |
|
869 |
+ */ |
|
870 |
+static inline void horizX1Filter(uint8_t *src, int stride, int QP) |
|
871 |
+{ |
|
872 |
+ int y; |
|
873 |
+//FIXME (has little in common with the mmx2 version) |
|
874 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
875 |
+ { |
|
876 |
+ int a= src[1] - src[2]; |
|
877 |
+ int b= src[3] - src[4]; |
|
878 |
+ int c= src[5] - src[6]; |
|
879 |
+ |
|
880 |
+ int d= MAX(ABS(b) - (ABS(a) + ABS(c))/2, 0); |
|
881 |
+ |
|
882 |
+ if(d < QP) |
|
883 |
+ { |
|
884 |
+ int v = d * SIGN(-b); |
|
885 |
+ |
|
886 |
+ src[1] +=v/8; |
|
887 |
+ src[2] +=v/4; |
|
888 |
+ src[3] +=3*v/8; |
|
889 |
+ src[4] -=3*v/8; |
|
890 |
+ src[5] -=v/4; |
|
891 |
+ src[6] -=v/8; |
|
892 |
+ |
|
893 |
+ } |
|
894 |
+ src+=stride; |
|
895 |
+ } |
|
896 |
+} |
|
897 |
+ |
|
898 |
+ |
|
862 | 899 |
static inline void doVertDefFilter(uint8_t src[], int stride, int QP) |
863 | 900 |
{ |
864 | 901 |
#if defined (HAVE_MMX2) || defined (HAVE_3DNOW) |
... | ... |
@@ -1438,6 +1475,109 @@ src-=8; |
1438 | 1438 |
#endif |
1439 | 1439 |
} |
1440 | 1440 |
|
1441 |
+/** |
|
1442 |
+ * Check if the given 8x8 Block is mostly "flat" |
|
1443 |
+ */ |
|
1444 |
+static inline int isHorizDC(uint8_t src[], int stride) |
|
1445 |
+{ |
|
1446 |
+ int numEq= 0; |
|
1447 |
+ int y; |
|
1448 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
1449 |
+ { |
|
1450 |
+ if(((src[0] - src[1] + 1) & 0xFFFF) < 3) numEq++; |
|
1451 |
+ if(((src[1] - src[2] + 1) & 0xFFFF) < 3) numEq++; |
|
1452 |
+ if(((src[2] - src[3] + 1) & 0xFFFF) < 3) numEq++; |
|
1453 |
+ if(((src[3] - src[4] + 1) & 0xFFFF) < 3) numEq++; |
|
1454 |
+ if(((src[4] - src[5] + 1) & 0xFFFF) < 3) numEq++; |
|
1455 |
+ if(((src[5] - src[6] + 1) & 0xFFFF) < 3) numEq++; |
|
1456 |
+ if(((src[6] - src[7] + 1) & 0xFFFF) < 3) numEq++; |
|
1457 |
+ src+= stride; |
|
1458 |
+ } |
|
1459 |
+ return numEq > hFlatnessThreshold; |
|
1460 |
+} |
|
1461 |
+ |
|
1462 |
+static inline int isHorizMinMaxOk(uint8_t src[], int stride, int QP) |
|
1463 |
+{ |
|
1464 |
+ if(abs(src[0] - src[7]) > 2*QP) return 0; |
|
1465 |
+ |
|
1466 |
+ return 1; |
|
1467 |
+} |
|
1468 |
+ |
|
1469 |
+static inline void doHorizDefFilter(uint8_t dst[], int stride, int QP) |
|
1470 |
+{ |
|
1471 |
+ int y; |
|
1472 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
1473 |
+ { |
|
1474 |
+ const int middleEnergy= 5*(dst[4] - dst[5]) + 2*(dst[2] - dst[5]); |
|
1475 |
+ |
|
1476 |
+ if(ABS(middleEnergy) < 8*QP) |
|
1477 |
+ { |
|
1478 |
+ const int q=(dst[3] - dst[4])/2; |
|
1479 |
+ const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]); |
|
1480 |
+ const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]); |
|
1481 |
+ |
|
1482 |
+ int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) ); |
|
1483 |
+ d= MAX(d, 0); |
|
1484 |
+ |
|
1485 |
+ d= (5*d + 32) >> 6; |
|
1486 |
+ d*= SIGN(-middleEnergy); |
|
1487 |
+ |
|
1488 |
+ if(q>0) |
|
1489 |
+ { |
|
1490 |
+ d= d<0 ? 0 : d; |
|
1491 |
+ d= d>q ? q : d; |
|
1492 |
+ } |
|
1493 |
+ else |
|
1494 |
+ { |
|
1495 |
+ d= d>0 ? 0 : d; |
|
1496 |
+ d= d<q ? q : d; |
|
1497 |
+ } |
|
1498 |
+ |
|
1499 |
+ dst[3]-= d; |
|
1500 |
+ dst[4]+= d; |
|
1501 |
+ } |
|
1502 |
+ dst+= stride; |
|
1503 |
+ } |
|
1504 |
+} |
|
1505 |
+ |
|
1506 |
+/** |
|
1507 |
+ * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block) |
|
1508 |
+ * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version) |
|
1509 |
+ */ |
|
1510 |
+static inline void doHorizLowPass(uint8_t dst[], int stride, int QP) |
|
1511 |
+{ |
|
1512 |
+ |
|
1513 |
+ int y; |
|
1514 |
+ for(y=0; y<BLOCK_SIZE; y++) |
|
1515 |
+ { |
|
1516 |
+ const int first= ABS(dst[-1] - dst[0]) < QP ? dst[-1] : dst[0]; |
|
1517 |
+ const int last= ABS(dst[8] - dst[7]) < QP ? dst[8] : dst[7]; |
|
1518 |
+ |
|
1519 |
+ int sums[9]; |
|
1520 |
+ sums[0] = first + dst[0]; |
|
1521 |
+ sums[1] = dst[0] + dst[1]; |
|
1522 |
+ sums[2] = dst[1] + dst[2]; |
|
1523 |
+ sums[3] = dst[2] + dst[3]; |
|
1524 |
+ sums[4] = dst[3] + dst[4]; |
|
1525 |
+ sums[5] = dst[4] + dst[5]; |
|
1526 |
+ sums[6] = dst[5] + dst[6]; |
|
1527 |
+ sums[7] = dst[6] + dst[7]; |
|
1528 |
+ sums[8] = dst[7] + last; |
|
1529 |
+ |
|
1530 |
+ dst[0]= ((sums[0]<<2) + ((first + sums[2])<<1) + sums[4] + 8)>>4; |
|
1531 |
+ dst[1]= ((dst[1]<<2) + ((first + sums[0] + sums[3])<<1) + sums[5] + 8)>>4; |
|
1532 |
+ dst[2]= ((dst[2]<<2) + ((first + sums[1] + sums[4])<<1) + sums[6] + 8)>>4; |
|
1533 |
+ dst[3]= ((dst[3]<<2) + ((sums[2] + sums[5])<<1) + sums[0] + sums[7] + 8)>>4; |
|
1534 |
+ dst[4]= ((dst[4]<<2) + ((sums[3] + sums[6])<<1) + sums[1] + sums[8] + 8)>>4; |
|
1535 |
+ dst[5]= ((dst[5]<<2) + ((last + sums[7] + sums[4])<<1) + sums[2] + 8)>>4; |
|
1536 |
+ dst[6]= (((last + dst[6])<<2) + ((dst[7] + sums[5])<<1) + sums[3] + 8)>>4; |
|
1537 |
+ dst[7]= ((sums[8]<<2) + ((last + sums[6])<<1) + sums[4] + 8)>>4; |
|
1538 |
+ |
|
1539 |
+ dst+= stride; |
|
1540 |
+ } |
|
1541 |
+} |
|
1542 |
+ |
|
1543 |
+ |
|
1441 | 1544 |
static inline void dering(uint8_t src[], int stride, int QP) |
1442 | 1545 |
{ |
1443 | 1546 |
#if defined (HAVE_MMX2) || defined (HAVE_3DNOW) |