00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00024 #include "dsputil.h"
00025 #include "intrax8dsp.h"
00026 #include "libavutil/common.h"
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 #define area1 (0)
00045 #define area2 (8)
00046 #define area3 (8+8)
00047 #define area4 (8+8+1)
00048 #define area5 (8+8+1+8)
00049 #define area6 (8+8+1+16)
00050 
00066 static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize,
00067            int * range, int * psum,  int edges){
00068     uint8_t * ptr;
00069     int sum;
00070     int i;
00071     int min_pix,max_pix;
00072     uint8_t c;
00073 
00074     if((edges&3)==3){
00075         *psum=0x80*(8+1+8+2);
00076         *range=0;
00077         memset(dst,0x80,16+1+16+8);
00078         
00079         
00080         return;
00081     }
00082 
00083     min_pix=256;
00084     max_pix=-1;
00085 
00086     sum=0;
00087 
00088     if(!(edges&1)){
00089         ptr=src-1;
00090         for(i=7;i>=0;i--){
00091             c=*(ptr-1);
00092             dst[area1+i]=c;
00093             c=*(ptr);
00094 
00095             sum+=c;
00096             min_pix=FFMIN(min_pix,c);
00097             max_pix=FFMAX(max_pix,c);
00098             dst[area2+i]=c;
00099 
00100             ptr+=linesize;
00101         }
00102     }
00103 
00104     if(!(edges&2)){  
00105         ptr=src-linesize;
00106         for(i=0;i<8;i++){
00107             c=*(ptr+i);
00108             sum+=c;
00109             min_pix=FFMIN(min_pix, c);
00110             max_pix=FFMAX(max_pix, c);
00111         }
00112         if(edges&4){
00113             memset(dst+area5,c,8);
00114             memcpy(dst+area4, ptr, 8);
00115         }else{
00116             memcpy(dst+area4, ptr, 16);
00117         }
00118         memcpy(dst+area6, ptr-linesize, 8);
00119     }
00120     
00121     if(edges&3){
00122         int avg=(sum+4)>>3;
00123         if(edges&1){ 
00124             memset(dst+area1,avg,8+8+1);
00125         }else{
00126             memset(dst+area3,avg, 1+16+8);
00127         }
00128         sum+=avg*9;
00129     }else{
00130         uint8_t c=*(src-1-linesize);
00131         dst[area3]=c;
00132         sum+=c;
00133         
00134     }
00135     (*range) = max_pix - min_pix;
00136     sum += *(dst+area5) + *(dst+area5+1);
00137     *psum = sum;
00138 }
00139 
00140 
00141 static const uint16_t zero_prediction_weights[64*2] = {
00142     640,  640,  669,  480,  708,  354,  748, 257,  792, 198,  760, 143,  808, 101,  772,  72,
00143     480,  669,  537,  537,  598,  416,  661, 316,  719, 250,  707, 185,  768, 134,  745,  97,
00144     354,  708,  416,  598,  488,  488,  564, 388,  634, 317,  642, 241,  716, 179,  706, 132,
00145     257,  748,  316,  661,  388,  564,  469, 469,  543, 395,  571, 311,  655, 238,  660, 180,
00146     198,  792,  250,  719,  317,  634,  395, 543,  469, 469,  507, 380,  597, 299,  616, 231,
00147     161,  855,  206,  788,  266,  710,  340, 623,  411, 548,  455, 455,  548, 366,  576, 288,
00148     122,  972,  159,  914,  211,  842,  276, 758,  341, 682,  389, 584,  483, 483,  520, 390,
00149     110, 1172,  144, 1107,  193, 1028,  254, 932,  317, 846,  366, 731,  458, 611,  499, 499
00150 };
00151 
00152 static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
00153     int i,j;
00154     int x,y;
00155     unsigned int p;
00156     int a;
00157     uint16_t left_sum[2][8] = { { 0 } };
00158     uint16_t  top_sum[2][8] = { { 0 } };
00159 
00160     for(i=0;i<8;i++){
00161         a=src[area2+7-i]<<4;
00162         for(j=0;j<8;j++){
00163             p=abs(i-j);
00164             left_sum[p&1][j]+= a>>(p>>1);
00165         }
00166     }
00167 
00168     for(i=0;i<8;i++){
00169         a=src[area4+i]<<4;
00170         for(j=0;j<8;j++){
00171             p=abs(i-j);
00172             top_sum[p&1][j]+=   a>>(p>>1);
00173         }
00174     }
00175     for(;i<10;i++){
00176         a=src[area4+i]<<4;
00177         for(j=5;j<8;j++){
00178             p=abs(i-j);
00179             top_sum[p&1][j]+=   a>>(p>>1);
00180         }
00181     }
00182     for(;i<12;i++){
00183         a=src[area4+i]<<4;
00184         for(j=7;j<8;j++){
00185             p=abs(i-j);
00186             top_sum[p&1][j]+=   a>>(p>>1);
00187         }
00188     }
00189 
00190     for(i=0;i<8;i++){
00191         top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;
00192         left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
00193     }
00194     for(y=0;y<8;y++){
00195         for(x=0;x<8;x++){
00196             dst[x] = (
00197                       (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
00198                       (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
00199                        0x8000
00200                       )>>16;
00201         }
00202         dst+=linesize;
00203     }
00204 }
00205 static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
00206     int x,y;
00207 
00208     for(y=0;y<8;y++){
00209         for(x=0;x<8;x++){
00210             dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
00211         }
00212         dst+=linesize;
00213     }
00214 }
00215 static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
00216     int x,y;
00217 
00218     for(y=0;y<8;y++){
00219         for(x=0;x<8;x++){
00220             dst[x]=src[area4 +1+y+x];
00221         }
00222         dst+=linesize;
00223     }
00224 }
00225 static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
00226     int x,y;
00227 
00228     for(y=0;y<8;y++){
00229         for(x=0;x<8;x++){
00230             dst[x]=src[area4 +((y+1)>>1)+x];
00231         }
00232         dst+=linesize;
00233     }
00234 }
00235 static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
00236     int x,y;
00237 
00238     for(y=0;y<8;y++){
00239         for(x=0;x<8;x++){
00240             dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
00241         }
00242         dst+=linesize;
00243     }
00244 }
00245 static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
00246     int x,y;
00247 
00248     for(y=0;y<8;y++){
00249         for(x=0;x<8;x++){
00250             if(2*x-y<0){
00251                 dst[x]=src[area2+9+2*x-y];
00252             }else{
00253                 dst[x]=src[area4 +x-((y+1)>>1)];
00254             }
00255         }
00256         dst+=linesize;
00257     }
00258 }
00259 static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
00260     int x,y;
00261 
00262     for(y=0;y<8;y++){
00263         for(x=0;x<8;x++){
00264             dst[x]=src[area3+x-y];
00265         }
00266         dst+=linesize;
00267     }
00268 }
00269 static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
00270     int x,y;
00271 
00272     for(y=0;y<8;y++){
00273         for(x=0;x<8;x++){
00274             if(x-2*y>0){
00275                 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
00276             }else{
00277                 dst[x]=src[area2+8-y +(x>>1)];
00278             }
00279         }
00280         dst+=linesize;
00281     }
00282 }
00283 static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
00284     int x,y;
00285 
00286     for(y=0;y<8;y++){
00287         for(x=0;x<8;x++){
00288             dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
00289         }
00290         dst+=linesize;
00291     }
00292 }
00293 static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
00294     int x,y;
00295 
00296     for(y=0;y<8;y++){
00297         for(x=0;x<8;x++){
00298             dst[x]=src[area2+6-FFMIN(x+y,6)];
00299         }
00300         dst+=linesize;
00301     }
00302 }
00303 static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
00304     int x,y;
00305 
00306     for(y=0;y<8;y++){
00307         for(x=0;x<8;x++){
00308             dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
00309         }
00310         dst+=linesize;
00311     }
00312 }
00313 static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
00314     int x,y;
00315 
00316     for(y=0;y<8;y++){
00317         for(x=0;x<8;x++){
00318             dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
00319         }
00320         dst+=linesize;
00321     }
00322 }
00323 
00324 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
00325     int i,t;
00326     int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
00327     int ql=(quant+10)>>3;
00328 
00329     for(i=0; i<8; i++,ptr+=b_stride){
00330         p0=ptr[-5*a_stride];
00331         p1=ptr[-4*a_stride];
00332         p2=ptr[-3*a_stride];
00333         p3=ptr[-2*a_stride];
00334         p4=ptr[-1*a_stride];
00335         p5=ptr[ 0         ];
00336         p6=ptr[ 1*a_stride];
00337         p7=ptr[ 2*a_stride];
00338         p8=ptr[ 3*a_stride];
00339         p9=ptr[ 4*a_stride];
00340 
00341         t=
00342             (FFABS(p1-p2) <= ql) +
00343             (FFABS(p2-p3) <= ql) +
00344             (FFABS(p3-p4) <= ql) +
00345             (FFABS(p4-p5) <= ql);
00346         if(t>0){
00347             t+=
00348                 (FFABS(p5-p6) <= ql) +
00349                 (FFABS(p6-p7) <= ql) +
00350                 (FFABS(p7-p8) <= ql) +
00351                 (FFABS(p8-p9) <= ql) +
00352                 (FFABS(p0-p1) <= ql);
00353             if(t>=6){
00354                 int min,max;
00355 
00356                 min=max=p1;
00357                 min=FFMIN(min,p3); max=FFMAX(max,p3);
00358                 min=FFMIN(min,p5); max=FFMAX(max,p5);
00359                 min=FFMIN(min,p8); max=FFMAX(max,p8);
00360                 if(max-min<2*quant){
00361                     min=FFMIN(min,p2); max=FFMAX(max,p2);
00362                     min=FFMIN(min,p4); max=FFMAX(max,p4);
00363                     min=FFMIN(min,p6); max=FFMAX(max,p6);
00364                     min=FFMIN(min,p7); max=FFMAX(max,p7);
00365                     if(max-min<2*quant){
00366                         ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
00367                         ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
00368                         ptr[ 0         ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
00369                         ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
00370                         continue;
00371                     };
00372                 }
00373             }
00374         }
00375         {
00376             int x,x0,x1,x2;
00377             int m;
00378 
00379             x0 =   (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
00380             if(FFABS(x0) < quant){
00381                 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
00382                 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
00383 
00384                 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
00385                 m=p4-p5;
00386 
00387                 if( x > 0 && (m^x0) <0){
00388                     int32_t sign;
00389 
00390                     sign=m>>31;
00391                     m=(m^sign)-sign;
00392                     m>>=1;
00393 
00394                     x=(5*x)>>3;
00395 
00396                     if(x>m) x=m;
00397 
00398                     x=(x^sign)-sign;
00399 
00400                     ptr[-1*a_stride] -= x;
00401                     ptr[ 0]          += x;
00402                 }
00403             }
00404         }
00405     }
00406 }
00407 
00408 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
00409     x8_loop_filter(src, stride, 1, qscale);
00410 }
00411 
00412 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
00413     x8_loop_filter(src, 1, stride, qscale);
00414 }
00415 
00416 av_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp)
00417 {
00418     dsp->h_loop_filter=x8_h_loop_filter;
00419     dsp->v_loop_filter=x8_v_loop_filter;
00420     dsp->setup_spatial_compensation=x8_setup_spatial_compensation;
00421     dsp->spatial_compensation[0]=spatial_compensation_0;
00422     dsp->spatial_compensation[1]=spatial_compensation_1;
00423     dsp->spatial_compensation[2]=spatial_compensation_2;
00424     dsp->spatial_compensation[3]=spatial_compensation_3;
00425     dsp->spatial_compensation[4]=spatial_compensation_4;
00426     dsp->spatial_compensation[5]=spatial_compensation_5;
00427     dsp->spatial_compensation[6]=spatial_compensation_6;
00428     dsp->spatial_compensation[7]=spatial_compensation_7;
00429     dsp->spatial_compensation[8]=spatial_compensation_8;
00430     dsp->spatial_compensation[9]=spatial_compensation_9;
00431     dsp->spatial_compensation[10]=spatial_compensation_10;
00432     dsp->spatial_compensation[11]=spatial_compensation_11;
00433 }