comparison libpostproc/postprocess.c @ 156:c09459686be3 libavcodec

temporal noise reducer in C (-pp 0x100000) setting the thresholds from the commandline requires postprocess2() / getPpModeByNameAndQuality() (someone could perhaps modify mplayer so that they are beiing used, iam too lazy for it ;)
author michael
date Tue, 13 Nov 2001 02:40:56 +0000
parents 561ec01a1a78
children bc12fd7e6153
comparison
equal deleted inserted replaced
155:3c3449bce692 156:c09459686be3
27 doHorizLowPass E e e 27 doHorizLowPass E e e
28 doHorizDefFilter Ec Ec Ec 28 doHorizDefFilter Ec Ec Ec
29 deRing E e e* 29 deRing E e e*
30 Vertical RKAlgo1 E a a 30 Vertical RKAlgo1 E a a
31 Horizontal RKAlgo1 a a 31 Horizontal RKAlgo1 a a
32 Vertical X1 a E E 32 Vertical X1# a E E
33 Horizontal X1 a E E 33 Horizontal X1# a E E
34 LinIpolDeinterlace e E E* 34 LinIpolDeinterlace e E E*
35 CubicIpolDeinterlace a e e* 35 CubicIpolDeinterlace a e e*
36 LinBlendDeinterlace e E E* 36 LinBlendDeinterlace e E E*
37 MedianDeinterlace Ec Ec 37 MedianDeinterlace# Ec Ec
38 38 TempDeNoiser# a
39 39
40 * i dont have a 3dnow CPU -> its untested 40 * i dont have a 3dnow CPU -> its untested, but noone said it doesnt work so it seems to work
41 # more or less selfinvented filters so the exactness isnt too meaningfull
41 E = Exact implementation 42 E = Exact implementation
42 e = allmost exact implementation (slightly different rounding,...) 43 e = allmost exact implementation (slightly different rounding,...)
43 a = alternative / approximate impl 44 a = alternative / approximate impl
44 c = checked against the other implementations (-vo md5) 45 c = checked against the other implementations (-vo md5)
45 */ 46 */
46 47
47 /* 48 /*
48 TODO: 49 TODO:
49 verify that everything workes as it should (how?) 50 verify that everything workes as it should (how?)
50 reduce the time wasted on the mem transfer 51 reduce the time wasted on the mem transfer
51 implement dering
52 implement everything in C at least (done at the moment but ...) 52 implement everything in C at least (done at the moment but ...)
53 unroll stuff if instructions depend too much on the prior one 53 unroll stuff if instructions depend too much on the prior one
54 we use 8x8 blocks for the horizontal filters, opendivx seems to use 8x4? 54 we use 8x8 blocks for the horizontal filters, opendivx seems to use 8x4?
55 move YScale thing to the end instead of fixing QP 55 move YScale thing to the end instead of fixing QP
56 write a faster and higher quality deblocking filter :) 56 write a faster and higher quality deblocking filter :)
57 do something about the speed of the horizontal filters
58 make the mainloop more flexible (variable number of blocks at once 57 make the mainloop more flexible (variable number of blocks at once
59 (the if/else stuff per block is slowing things down) 58 (the if/else stuff per block is slowing things down)
60 compare the quality & speed of all filters 59 compare the quality & speed of all filters
61 split this huge file 60 split this huge file
62 fix warnings (unused vars, ...)
63 noise reduction filters
64 border remover 61 border remover
65 optimize c versions 62 optimize c versions
63 try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks
66 ... 64 ...
67 65
68 Notes: 66 Notes:
69 */ 67 */
70 68
180 {"al", "autolevels", 0, 1, 2, LEVEL_FIX}, 178 {"al", "autolevels", 0, 1, 2, LEVEL_FIX},
181 {"lb", "linblenddeint", 0, 1, 6, LINEAR_BLEND_DEINT_FILTER}, 179 {"lb", "linblenddeint", 0, 1, 6, LINEAR_BLEND_DEINT_FILTER},
182 {"li", "linipoldeint", 0, 1, 6, LINEAR_IPOL_DEINT_FILTER}, 180 {"li", "linipoldeint", 0, 1, 6, LINEAR_IPOL_DEINT_FILTER},
183 {"ci", "cubicipoldeint", 0, 1, 6, CUBIC_IPOL_DEINT_FILTER}, 181 {"ci", "cubicipoldeint", 0, 1, 6, CUBIC_IPOL_DEINT_FILTER},
184 {"md", "mediandeint", 0, 1, 6, MEDIAN_DEINT_FILTER}, 182 {"md", "mediandeint", 0, 1, 6, MEDIAN_DEINT_FILTER},
183 {"tn", "tmpnoise", 1, 7, 8, TEMP_NOISE_FILTER},
185 {NULL, NULL,0,0,0,0} //End Marker 184 {NULL, NULL,0,0,0,0} //End Marker
186 }; 185 };
187 186
188 static char *replaceTable[]= 187 static char *replaceTable[]=
189 { 188 {
190 "default", "hdeblock:a,vdeblock:a,dering:a,autolevels", 189 "default", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
191 "de", "hdeblock:a,vdeblock:a,dering:a,autolevels", 190 "de", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
192 "fast", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels", 191 "fast", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
193 "fa", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels", 192 "fa", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
194 NULL //End Marker 193 NULL //End Marker
195 }; 194 };
196 195
197 #ifdef HAVE_MMX 196 #ifdef HAVE_MMX
198 static inline void unusedVariableWarningFixer() 197 static inline void unusedVariableWarningFixer()
2592 : "%eax", "%ebx" 2591 : "%eax", "%ebx"
2593 ); 2592 );
2594 } 2593 }
2595 #endif 2594 #endif
2596 2595
2596 static void inline tempNoiseReducer(uint8_t *src, int stride,
2597 uint8_t *tempBlured, int *maxNoise)
2598 {
2599 int y;
2600 int d=0;
2601 int sysd=0;
2602
2603 for(y=0; y<8; y++)
2604 {
2605 int x;
2606 for(x=0; x<8; x++)
2607 {
2608 int ref= tempBlured[ x + y*stride ];
2609 int cur= src[ x + y*stride ];
2610 int d1=ref - cur;
2611 d+= ABS(d1); //d1*d1;
2612 sysd+= d1;
2613 }
2614 }
2615 //printf("%d %d %d\n", maxNoise[0], maxNoise[1], maxNoise[2]);
2616 /*
2617 Switch between
2618 1 0 0 0 0 0 0 (0)
2619 64 32 16 8 4 2 1 (1)
2620 64 48 36 27 20 15 11 (33) (approx)
2621 64 56 49 43 37 33 29 (200) (approx)
2622 */
2623 if(d > maxNoise[1])
2624 {
2625 if(d < maxNoise[2])
2626 {
2627 for(y=0; y<8; y++)
2628 {
2629 int x;
2630 for(x=0; x<8; x++)
2631 {
2632 int ref= tempBlured[ x + y*stride ];
2633 int cur= src[ x + y*stride ];
2634 tempBlured[ x + y*stride ]=
2635 src[ x + y*stride ]=
2636 (ref + cur + 1)>>1;
2637 }
2638 }
2639 }
2640 else
2641 {
2642 for(y=0; y<8; y++)
2643 {
2644 int x;
2645 for(x=0; x<8; x++)
2646 {
2647 tempBlured[ x + y*stride ]= src[ x + y*stride ];
2648 }
2649 }
2650 }
2651 }
2652 else
2653 {
2654 if(d < maxNoise[0])
2655 {
2656 for(y=0; y<8; y++)
2657 {
2658 int x;
2659 for(x=0; x<8; x++)
2660 {
2661 int ref= tempBlured[ x + y*stride ];
2662 int cur= src[ x + y*stride ];
2663 tempBlured[ x + y*stride ]=
2664 src[ x + y*stride ]=
2665 (ref*7 + cur + 4)>>3;
2666 }
2667 }
2668 }
2669 else
2670 {
2671 for(y=0; y<8; y++)
2672 {
2673 int x;
2674 for(x=0; x<8; x++)
2675 {
2676 int ref= tempBlured[ x + y*stride ];
2677 int cur= src[ x + y*stride ];
2678 tempBlured[ x + y*stride ]=
2679 src[ x + y*stride ]=
2680 (ref*3 + cur + 2)>>2;
2681 }
2682 }
2683 }
2684 }
2685 }
2686
2597 #ifdef HAVE_ODIVX_POSTPROCESS 2687 #ifdef HAVE_ODIVX_POSTPROCESS
2598 #include "../opendivx/postprocess.h" 2688 #include "../opendivx/postprocess.h"
2599 int use_old_pp=0; 2689 int use_old_pp=0;
2600 #endif 2690 #endif
2601 2691
2602 static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, 2692 static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
2603 QP_STORE_T QPs[], int QPStride, int isColor, int mode); 2693 QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode);
2604 2694
2605 /* -pp Command line Help 2695 /* -pp Command line Help
2606 NOTE/FIXME: put this at an appropriate place (--help, html docs, man mplayer)? 2696 NOTE/FIXME: put this at an appropriate place (--help, html docs, man mplayer)?
2607 2697
2608 -pp <filterName>[:<option>[:<option>...]][,[-]<filterName>[:<option>...]]... 2698 -pp <filterName>[:<option>[:<option>...]][,[-]<filterName>[:<option>...]]...
2609 2699
2610 long form example: 2700 long form example:
2611 -pp vdeblock:autoq,hdeblock:autoq,linblenddeint -pp default,-vdeblock 2701 -pp vdeblock:autoq,hdeblock:autoq,linblenddeint -pp default,-vdeblock
2612 short form example: 2702 short form example:
2613 -pp vb:a,hb:a,lb -pp de,-vb 2703 -pp vb:a,hb:a,lb -pp de,-vb
2704 more examples:
2705 -pp tn:64:128:256
2614 2706
2615 Filters Options 2707 Filters Options
2616 short long name short long option Description 2708 short long name short long option Description
2617 * * a autoq cpu power dependant enabler 2709 * * a autoq cpu power dependant enabler
2618 c chrom chrominance filtring enabled 2710 c chrom chrominance filtring enabled
2629 li linipoldeint linear interpolating deinterlacer 2721 li linipoldeint linear interpolating deinterlacer
2630 ci cubicipoldeint cubic interpolating deinterlacer 2722 ci cubicipoldeint cubic interpolating deinterlacer
2631 md mediandeint median deinterlacer 2723 md mediandeint median deinterlacer
2632 de default hdeblock:a,vdeblock:a,dering:a,autolevels 2724 de default hdeblock:a,vdeblock:a,dering:a,autolevels
2633 fa fast x1hdeblock:a,x1vdeblock:a,dering:a,autolevels 2725 fa fast x1hdeblock:a,x1vdeblock:a,dering:a,autolevels
2726 tn tmpnoise (3 Thresholds) Temporal Noise Reducer
2634 */ 2727 */
2635 2728
2636 /** 2729 /**
2637 * returns a PPMode struct which will have a non 0 error variable if an error occured 2730 * returns a PPMode struct which will have a non 0 error variable if an error occured
2638 * name is the string after "-pp" on the command line 2731 * name is the string after "-pp" on the command line
2642 { 2735 {
2643 char temp[GET_MODE_BUFFER_SIZE]; 2736 char temp[GET_MODE_BUFFER_SIZE];
2644 char *p= temp; 2737 char *p= temp;
2645 char *filterDelimiters= ","; 2738 char *filterDelimiters= ",";
2646 char *optionDelimiters= ":"; 2739 char *optionDelimiters= ":";
2647 struct PPMode ppMode= {0,0,0,0,0,0}; 2740 struct PPMode ppMode= {0,0,0,0,0,0,{150,200,400}};
2648 char *filterToken; 2741 char *filterToken;
2649 2742
2650 strncpy(temp, name, GET_MODE_BUFFER_SIZE); 2743 strncpy(temp, name, GET_MODE_BUFFER_SIZE);
2744
2745 printf("%s\n", name);
2651 2746
2652 for(;;){ 2747 for(;;){
2653 char *filterName; 2748 char *filterName;
2654 int q= GET_PP_QUALITY_MAX; 2749 int q= 1000000; //GET_PP_QUALITY_MAX;
2655 int chrom=-1; 2750 int chrom=-1;
2656 char *option; 2751 char *option;
2657 char *options[OPTIONS_ARRAY_SIZE]; 2752 char *options[OPTIONS_ARRAY_SIZE];
2658 int i; 2753 int i;
2659 int filterNameOk=0; 2754 int filterNameOk=0;
2660 int numOfUnknownOptions=0; 2755 int numOfUnknownOptions=0;
2661 int enable=1; //does the user want us to enabled or disabled the filter 2756 int enable=1; //does the user want us to enabled or disabled the filter
2662 2757
2663 filterToken= strtok(p, filterDelimiters); 2758 filterToken= strtok(p, filterDelimiters);
2664 if(filterToken == NULL) break; 2759 if(filterToken == NULL) break;
2665 p+= strlen(filterToken) + 1; 2760 p+= strlen(filterToken) + 1; // p points to next filterToken
2666 filterName= strtok(filterToken, optionDelimiters); 2761 filterName= strtok(filterToken, optionDelimiters);
2667 printf("%s::%s\n", filterToken, filterName); 2762 printf("%s::%s\n", filterToken, filterName);
2668 2763
2669 if(*filterName == '-') 2764 if(*filterName == '-')
2670 { 2765 {
2671 enable=0; 2766 enable=0;
2672 filterName++; 2767 filterName++;
2673 } 2768 }
2769
2674 for(;;){ //for all options 2770 for(;;){ //for all options
2675 option= strtok(NULL, optionDelimiters); 2771 option= strtok(NULL, optionDelimiters);
2676 if(option == NULL) break; 2772 if(option == NULL) break;
2677 2773
2678 printf("%s\n", option); 2774 printf("%s\n", option);
2681 else if(!strcmp("chrom", option) || !strcmp("c", option)) chrom=1; 2777 else if(!strcmp("chrom", option) || !strcmp("c", option)) chrom=1;
2682 else 2778 else
2683 { 2779 {
2684 options[numOfUnknownOptions] = option; 2780 options[numOfUnknownOptions] = option;
2685 numOfUnknownOptions++; 2781 numOfUnknownOptions++;
2686 options[numOfUnknownOptions] = NULL;
2687 } 2782 }
2688 if(numOfUnknownOptions >= OPTIONS_ARRAY_SIZE-1) break; 2783 if(numOfUnknownOptions >= OPTIONS_ARRAY_SIZE-1) break;
2689 } 2784 }
2785 options[numOfUnknownOptions] = NULL;
2690 2786
2691 /* replace stuff from the replace Table */ 2787 /* replace stuff from the replace Table */
2692 for(i=0; replaceTable[2*i]!=NULL; i++) 2788 for(i=0; replaceTable[2*i]!=NULL; i++)
2693 { 2789 {
2694 if(!strcmp(replaceTable[2*i], filterName)) 2790 if(!strcmp(replaceTable[2*i], filterName))
2713 } 2809 }
2714 } 2810 }
2715 2811
2716 for(i=0; filters[i].shortName!=NULL; i++) 2812 for(i=0; filters[i].shortName!=NULL; i++)
2717 { 2813 {
2814 // printf("Compareing %s, %s, %s\n", filters[i].shortName,filters[i].longName, filterName);
2718 if( !strcmp(filters[i].longName, filterName) 2815 if( !strcmp(filters[i].longName, filterName)
2719 || !strcmp(filters[i].shortName, filterName)) 2816 || !strcmp(filters[i].shortName, filterName))
2720 { 2817 {
2721 ppMode.lumMode &= ~filters[i].mask; 2818 ppMode.lumMode &= ~filters[i].mask;
2722 ppMode.chromMode &= ~filters[i].mask; 2819 ppMode.chromMode &= ~filters[i].mask;
2742 ppMode.minAllowedY= 0; 2839 ppMode.minAllowedY= 0;
2743 ppMode.maxAllowedY= 255; 2840 ppMode.maxAllowedY= 255;
2744 numOfUnknownOptions--; 2841 numOfUnknownOptions--;
2745 } 2842 }
2746 } 2843 }
2844 else if(filters[i].mask == TEMP_NOISE_FILTER)
2845 {
2846 int o;
2847 int numOfNoises=0;
2848 ppMode.maxTmpNoise[0]= 150;
2849 ppMode.maxTmpNoise[1]= 200;
2850 ppMode.maxTmpNoise[2]= 400;
2851
2852 for(o=0; options[o]!=NULL; o++)
2853 {
2854 char *tail;
2855 ppMode.maxTmpNoise[numOfNoises]=
2856 strtol(options[o], &tail, 0);
2857 if(tail!=options[o])
2858 {
2859 numOfNoises++;
2860 numOfUnknownOptions--;
2861 if(numOfNoises >= 3) break;
2862 }
2863 }
2864 }
2747 } 2865 }
2748 } 2866 }
2749 if(!filterNameOk) ppMode.error++; 2867 if(!filterNameOk) ppMode.error++;
2750 ppMode.error += numOfUnknownOptions; 2868 ppMode.error += numOfUnknownOptions;
2751 } 2869 }
2761 2879
2762 return ppMode; 2880 return ppMode;
2763 } 2881 }
2764 2882
2765 /** 2883 /**
2766 * ... 2884 * Obsolete, dont use it, use postprocess2() instead
2767 */ 2885 */
2768 void postprocess(unsigned char * src[], int src_stride, 2886 void postprocess(unsigned char * src[], int src_stride,
2769 unsigned char * dst[], int dst_stride, 2887 unsigned char * dst[], int dst_stride,
2770 int horizontal_size, int vertical_size, 2888 int horizontal_size, int vertical_size,
2771 QP_STORE_T *QP_store, int QP_stride, 2889 QP_STORE_T *QP_store, int QP_stride,
2772 int mode) 2890 int mode)
2773 { 2891 {
2892 struct PPMode ppMode;
2893 static QP_STORE_T zeroArray[2048/8];
2774 /* 2894 /*
2775 static int qual=0; 2895 static int qual=0;
2776 2896
2777 struct PPMode ppMode= getPPModeByNameAndQuality("fast,default,-hdeblock,-vdeblock", qual); 2897 ppMode= getPPModeByNameAndQuality("fast,default,-hdeblock,-vdeblock,tmpnoise:150:200:300", qual);
2898 printf("OK\n");
2778 qual++; 2899 qual++;
2779 qual%=7; 2900 qual%=7;
2780 printf("\n%d %d %d %d\n", ppMode.lumMode, ppMode.chromMode, ppMode.oldMode, ppMode.error); 2901 printf("\n%X %X %X %X :%d: %d %d %d\n", ppMode.lumMode, ppMode.chromMode, ppMode.oldMode, ppMode.error,
2902 qual, ppMode.maxTmpNoise[0], ppMode.maxTmpNoise[1], ppMode.maxTmpNoise[2]);
2781 postprocess2(src, src_stride, dst, dst_stride, 2903 postprocess2(src, src_stride, dst, dst_stride,
2782 horizontal_size, vertical_size, QP_store, QP_stride, &ppMode); 2904 horizontal_size, vertical_size, QP_store, QP_stride, &ppMode);
2783 2905
2784 return; 2906 return;
2785 */ 2907 */
2786 static QP_STORE_T zeroArray[2048/8];
2787 if(QP_store==NULL) 2908 if(QP_store==NULL)
2788 { 2909 {
2789 QP_store= zeroArray; 2910 QP_store= zeroArray;
2790 QP_stride= 0; 2911 QP_stride= 0;
2791 } 2912 }
2913
2914 ppMode.lumMode= mode;
2915 mode= ((mode&0xFF)>>4) | (mode&0xFFFFFF00);
2916 ppMode.chromMode= mode;
2917 ppMode.maxTmpNoise[0]= 150;
2918 ppMode.maxTmpNoise[1]= 200;
2919 ppMode.maxTmpNoise[2]= 400;
2792 2920
2793 #ifdef HAVE_ODIVX_POSTPROCESS 2921 #ifdef HAVE_ODIVX_POSTPROCESS
2794 // Note: I could make this shit outside of this file, but it would mean one 2922 // Note: I could make this shit outside of this file, but it would mean one
2795 // more function call... 2923 // more function call...
2796 if(use_old_pp){ 2924 if(use_old_pp){
2798 return; 2926 return;
2799 } 2927 }
2800 #endif 2928 #endif
2801 2929
2802 postProcess(src[0], src_stride, dst[0], dst_stride, 2930 postProcess(src[0], src_stride, dst[0], dst_stride,
2803 horizontal_size, vertical_size, QP_store, QP_stride, 0, mode); 2931 horizontal_size, vertical_size, QP_store, QP_stride, 0, &ppMode);
2804 2932
2805 horizontal_size >>= 1; 2933 horizontal_size >>= 1;
2806 vertical_size >>= 1; 2934 vertical_size >>= 1;
2807 src_stride >>= 1; 2935 src_stride >>= 1;
2808 dst_stride >>= 1; 2936 dst_stride >>= 1;
2809 mode= ((mode&0xFF)>>4) | (mode&0xFFFFFF00);
2810 // mode&= ~(LINEAR_IPOL_DEINT_FILTER | LINEAR_BLEND_DEINT_FILTER | 2937 // mode&= ~(LINEAR_IPOL_DEINT_FILTER | LINEAR_BLEND_DEINT_FILTER |
2811 // MEDIAN_DEINT_FILTER | CUBIC_IPOL_DEINT_FILTER); 2938 // MEDIAN_DEINT_FILTER | CUBIC_IPOL_DEINT_FILTER);
2812 2939
2813 if(1) 2940 if(1)
2814 { 2941 {
2815 postProcess(src[1], src_stride, dst[1], dst_stride, 2942 postProcess(src[1], src_stride, dst[1], dst_stride,
2816 horizontal_size, vertical_size, QP_store, QP_stride, 1, mode); 2943 horizontal_size, vertical_size, QP_store, QP_stride, 1, &ppMode);
2817 postProcess(src[2], src_stride, dst[2], dst_stride, 2944 postProcess(src[2], src_stride, dst[2], dst_stride,
2818 horizontal_size, vertical_size, QP_store, QP_stride, 2, mode); 2945 horizontal_size, vertical_size, QP_store, QP_stride, 2, &ppMode);
2819 } 2946 }
2820 else 2947 else
2821 { 2948 {
2822 memcpy(dst[1], src[1], src_stride*horizontal_size); 2949 memset(dst[1], 128, dst_stride*vertical_size);
2823 memcpy(dst[2], src[2], src_stride*horizontal_size); 2950 memset(dst[2], 128, dst_stride*vertical_size);
2951 // memcpy(dst[1], src[1], src_stride*horizontal_size);
2952 // memcpy(dst[2], src[2], src_stride*horizontal_size);
2824 } 2953 }
2825 } 2954 }
2826 2955
2827 void postprocess2(unsigned char * src[], int src_stride, 2956 void postprocess2(unsigned char * src[], int src_stride,
2828 unsigned char * dst[], int dst_stride, 2957 unsigned char * dst[], int dst_stride,
2847 return; 2976 return;
2848 } 2977 }
2849 #endif 2978 #endif
2850 2979
2851 postProcess(src[0], src_stride, dst[0], dst_stride, 2980 postProcess(src[0], src_stride, dst[0], dst_stride,
2852 horizontal_size, vertical_size, QP_store, QP_stride, 0, mode->lumMode); 2981 horizontal_size, vertical_size, QP_store, QP_stride, 0, mode);
2853 2982
2854 horizontal_size >>= 1; 2983 horizontal_size >>= 1;
2855 vertical_size >>= 1; 2984 vertical_size >>= 1;
2856 src_stride >>= 1; 2985 src_stride >>= 1;
2857 dst_stride >>= 1; 2986 dst_stride >>= 1;
2858 2987
2859 postProcess(src[1], src_stride, dst[1], dst_stride, 2988 postProcess(src[1], src_stride, dst[1], dst_stride,
2860 horizontal_size, vertical_size, QP_store, QP_stride, 1, mode->chromMode); 2989 horizontal_size, vertical_size, QP_store, QP_stride, 1, mode);
2861 postProcess(src[2], src_stride, dst[2], dst_stride, 2990 postProcess(src[2], src_stride, dst[2], dst_stride,
2862 horizontal_size, vertical_size, QP_store, QP_stride, 2, mode->chromMode); 2991 horizontal_size, vertical_size, QP_store, QP_stride, 2, mode);
2863 } 2992 }
2864 2993
2865 2994
2866 /** 2995 /**
2867 * gets the mode flags for a given quality (larger values mean slower but better postprocessing) 2996 * gets the mode flags for a given quality (larger values mean slower but better postprocessing)
3021 3150
3022 /** 3151 /**
3023 * Filters array of bytes (Y or U or V values) 3152 * Filters array of bytes (Y or U or V values)
3024 */ 3153 */
3025 static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, 3154 static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
3026 QP_STORE_T QPs[], int QPStride, int isColor, int mode) 3155 QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode)
3027 { 3156 {
3028 int x,y; 3157 int x,y;
3158 const int mode= isColor ? ppMode->chromMode : ppMode->lumMode;
3159
3029 /* we need 64bit here otherwise weŽll going to have a problem 3160 /* we need 64bit here otherwise weŽll going to have a problem
3030 after watching a black picture for 5 hours*/ 3161 after watching a black picture for 5 hours*/
3031 static uint64_t *yHistogram= NULL; 3162 static uint64_t *yHistogram= NULL;
3032 int black=0, white=255; // blackest black and whitest white in the picture 3163 int black=0, white=255; // blackest black and whitest white in the picture
3033 int QPCorrecture= 256; 3164 int QPCorrecture= 256;
3038 3169
3039 /* Temporary buffers for handling the last block */ 3170 /* Temporary buffers for handling the last block */
3040 static uint8_t *tempDstBlock= NULL; 3171 static uint8_t *tempDstBlock= NULL;
3041 static uint8_t *tempSrcBlock= NULL; 3172 static uint8_t *tempSrcBlock= NULL;
3042 3173
3174 /* Temporal noise reducing buffers */
3175 static uint8_t *tempBlured[3]= {NULL,NULL,NULL};
3176
3043 #ifdef PP_FUNNY_STRIDE 3177 #ifdef PP_FUNNY_STRIDE
3044 uint8_t *dstBlockPtrBackup; 3178 uint8_t *dstBlockPtrBackup;
3045 uint8_t *srcBlockPtrBackup; 3179 uint8_t *srcBlockPtrBackup;
3046 #endif 3180 #endif
3047 3181
3058 { 3192 {
3059 tempDst= (uint8_t*)memalign(8, 1024*24); 3193 tempDst= (uint8_t*)memalign(8, 1024*24);
3060 tempSrc= (uint8_t*)memalign(8, 1024*24); 3194 tempSrc= (uint8_t*)memalign(8, 1024*24);
3061 tempDstBlock= (uint8_t*)memalign(8, 1024*24); 3195 tempDstBlock= (uint8_t*)memalign(8, 1024*24);
3062 tempSrcBlock= (uint8_t*)memalign(8, 1024*24); 3196 tempSrcBlock= (uint8_t*)memalign(8, 1024*24);
3197 }
3198
3199 if(tempBlured[isColor]==NULL && (mode & TEMP_NOISE_FILTER))
3200 {
3201 // printf("%d %d %d\n", isColor, dstStride, height);
3202 //FIXME works only as long as the size doesnt increase
3203 //Note:the +17*1024 is just there so i dont have to worry about r/w over te end
3204 tempBlured[isColor]= (uint8_t*)memalign(8, dstStride*((height+7)&(~7)) + 17*1024);
3205
3206 memset(tempBlured[isColor], 0, dstStride*((height+7)&(~7)) + 17*1024);
3063 } 3207 }
3064 3208
3065 if(!yHistogram) 3209 if(!yHistogram)
3066 { 3210 {
3067 int i; 3211 int i;
3217 int QPDelta= isColor ? 1<<(32-3) : 1<<(32-4); 3361 int QPDelta= isColor ? 1<<(32-3) : 1<<(32-4);
3218 int QPFrac= QPDelta; 3362 int QPFrac= QPDelta;
3219 uint8_t *tempBlock1= tempBlocks; 3363 uint8_t *tempBlock1= tempBlocks;
3220 uint8_t *tempBlock2= tempBlocks + 8; 3364 uint8_t *tempBlock2= tempBlocks + 8;
3221 #endif 3365 #endif
3366 int QP=0;
3222 /* can we mess with a 8x16 block from srcBlock/dstBlock downwards and 1 line upwards 3367 /* can we mess with a 8x16 block from srcBlock/dstBlock downwards and 1 line upwards
3223 if not than use a temporary buffer */ 3368 if not than use a temporary buffer */
3224 if(y+15 >= height) 3369 if(y+15 >= height)
3225 { 3370 {
3371 int i;
3226 /* copy from line 8 to 15 of src, these will be copied with 3372 /* copy from line 8 to 15 of src, these will be copied with
3227 blockcopy to dst later */ 3373 blockcopy to dst later */
3228 memcpy(tempSrc + srcStride*8, srcBlock + srcStride*8, 3374 memcpy(tempSrc + srcStride*8, srcBlock + srcStride*8,
3229 srcStride*MAX(height-y-8, 0) ); 3375 srcStride*MAX(height-y-8, 0) );
3230 3376
3231 /* duplicate last line to fill the void upto line 15 */ 3377 /* duplicate last line of src to fill the void upto line 15 */
3232 if(y+15 >= height) 3378 for(i=MAX(height-y, 8); i<=15; i++)
3233 { 3379 memcpy(tempSrc + srcStride*i, src + srcStride*(height-1), srcStride);
3234 int i; 3380
3235 for(i=height-y; i<=15; i++) 3381 /* copy up to 9 lines of dst (line -1 to 7)*/
3236 memcpy(tempSrc + srcStride*i,
3237 src + srcStride*(height-1), srcStride);
3238 }
3239
3240 /* copy up to 9 lines of dst */
3241 memcpy(tempDst, dstBlock - dstStride, dstStride*MIN(height-y+1, 9) ); 3382 memcpy(tempDst, dstBlock - dstStride, dstStride*MIN(height-y+1, 9) );
3383
3384 /* duplicate last line of dst to fill the void upto line 8 */
3385 for(i=height-y+1; i<=8; i++)
3386 memcpy(tempDst + dstStride*i, dst + dstStride*(height-1), dstStride);
3387
3242 dstBlock= tempDst + dstStride; 3388 dstBlock= tempDst + dstStride;
3243 srcBlock= tempSrc; 3389 srcBlock= tempSrc;
3244 } 3390 }
3245 3391
3246 // From this point on it is guranteed that we can read and write 16 lines downward 3392 // From this point on it is guranteed that we can read and write 16 lines downward
3249 for(x=0; x<width; x+=BLOCK_SIZE) 3395 for(x=0; x<width; x+=BLOCK_SIZE)
3250 { 3396 {
3251 const int stride= dstStride; 3397 const int stride= dstStride;
3252 uint8_t *tmpXchg; 3398 uint8_t *tmpXchg;
3253 #ifdef ARCH_X86 3399 #ifdef ARCH_X86
3254 int QP= *QPptr; 3400 QP= *QPptr;
3255 asm volatile( 3401 asm volatile(
3256 "addl %2, %1 \n\t" 3402 "addl %2, %1 \n\t"
3257 "sbbl %%eax, %%eax \n\t" 3403 "sbbl %%eax, %%eax \n\t"
3258 "shll $2, %%eax \n\t" 3404 "shll $2, %%eax \n\t"
3259 "subl %%eax, %0 \n\t" 3405 "subl %%eax, %0 \n\t"
3260 : "+r" (QPptr), "+m" (QPFrac) 3406 : "+r" (QPptr), "+m" (QPFrac)
3261 : "r" (QPDelta) 3407 : "r" (QPDelta)
3262 : "%eax" 3408 : "%eax"
3263 ); 3409 );
3264 #else 3410 #else
3265 int QP= isColor ? 3411 QP= isColor ?
3266 QPs[(y>>3)*QPStride + (x>>3)]: 3412 QPs[(y>>3)*QPStride + (x>>3)]:
3267 QPs[(y>>4)*QPStride + (x>>4)]; 3413 QPs[(y>>4)*QPStride + (x>>4)];
3268 #endif 3414 #endif
3269 if(!isColor) 3415 if(!isColor)
3270 { 3416 {
3440 if(mode & DERING) 3586 if(mode & DERING)
3441 { 3587 {
3442 //FIXME filter first line 3588 //FIXME filter first line
3443 if(y>0) dering(dstBlock - stride - 8, stride, QP); 3589 if(y>0) dering(dstBlock - stride - 8, stride, QP);
3444 } 3590 }
3591
3592 if(mode & TEMP_NOISE_FILTER)
3593 {
3594 tempNoiseReducer(dstBlock-8, stride,
3595 tempBlured[isColor] + y*dstStride + x,
3596 ppMode->maxTmpNoise);
3597 }
3445 } 3598 }
3446 else if(mode & DERING)
3447 {
3448 //FIXME y+15 is required cuz of the tempBuffer thing -> bottom right block isnt filtered
3449 if(y > 8 && y+15 < height) dering(dstBlock - stride*9 + width - 8, stride, QP);
3450 }
3451
3452 3599
3453 #ifdef PP_FUNNY_STRIDE 3600 #ifdef PP_FUNNY_STRIDE
3454 /* did we use a tmp-block buffer */ 3601 /* did we use a tmp-block buffer */
3455 if(x+7 >= width) 3602 if(x+7 >= width)
3456 { 3603 {
3471 #ifdef HAVE_MMX 3618 #ifdef HAVE_MMX
3472 tmpXchg= tempBlock1; 3619 tmpXchg= tempBlock1;
3473 tempBlock1= tempBlock2; 3620 tempBlock1= tempBlock2;
3474 tempBlock2 = tmpXchg; 3621 tempBlock2 = tmpXchg;
3475 #endif 3622 #endif
3623 }
3624
3625 if(mode & DERING)
3626 {
3627 if(y > 0) dering(dstBlock - dstStride - 8, dstStride, QP);
3628 }
3629
3630 if((mode & TEMP_NOISE_FILTER))
3631 {
3632 tempNoiseReducer(dstBlock-8, dstStride,
3633 tempBlured[isColor] + y*dstStride + x,
3634 ppMode->maxTmpNoise);
3476 } 3635 }
3477 3636
3478 /* did we use a tmp buffer for the last lines*/ 3637 /* did we use a tmp buffer for the last lines*/
3479 if(y+15 >= height) 3638 if(y+15 >= height)
3480 { 3639 {