00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include "dsputil.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define area1 (0)
00043 #define area2 (8)
00044 #define area3 (8+8)
00045 #define area4 (8+8+1)
00046 #define area5 (8+8+1+8)
00047 #define area6 (8+8+1+16)
00048
00064 static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize,
00065 int * range, int * psum, int edges){
00066 uint8_t * ptr;
00067 int sum;
00068 int i;
00069 int min_pix,max_pix;
00070 uint8_t c;
00071
00072 if((edges&3)==3){
00073 *psum=0x80*(8+1+8+2);
00074 *range=0;
00075 memset(dst,0x80,16+1+16+8);
00076
00077
00078 return;
00079 }
00080
00081 min_pix=256;
00082 max_pix=-1;
00083
00084 sum=0;
00085
00086 if(!(edges&1)){
00087 ptr=src-1;
00088 for(i=7;i>=0;i--){
00089 c=*(ptr-1);
00090 dst[area1+i]=c;
00091 c=*(ptr);
00092
00093 sum+=c;
00094 min_pix=FFMIN(min_pix,c);
00095 max_pix=FFMAX(max_pix,c);
00096 dst[area2+i]=c;
00097
00098 ptr+=linesize;
00099 }
00100 }
00101
00102 if(!(edges&2)){
00103 ptr=src-linesize;
00104 for(i=0;i<8;i++){
00105 c=*(ptr+i);
00106 sum+=c;
00107 min_pix=FFMIN(min_pix, c);
00108 max_pix=FFMAX(max_pix, c);
00109 }
00110 if(edges&4){
00111 memset(dst+area5,c,8);
00112 memcpy(dst+area4, ptr, 8);
00113 }else{
00114 memcpy(dst+area4, ptr, 16);
00115 }
00116 memcpy(dst+area6, ptr-linesize, 8);
00117 }
00118
00119 if(edges&3){
00120 int avg=(sum+4)>>3;
00121 if(edges&1){
00122 memset(dst+area1,avg,8+8+1);
00123 }else{
00124 memset(dst+area3,avg, 1+16+8);
00125 }
00126 sum+=avg*9;
00127 }else{
00128 uint8_t c=*(src-1-linesize);
00129 dst[area3]=c;
00130 sum+=c;
00131
00132 }
00133 (*range) = max_pix - min_pix;
00134 sum += *(dst+area5) + *(dst+area5+1);
00135 *psum = sum;
00136 }
00137
00138
00139 static const uint16_t zero_prediction_weights[64*2] = {
00140 640, 640, 669, 480, 708, 354, 748, 257, 792, 198, 760, 143, 808, 101, 772, 72,
00141 480, 669, 537, 537, 598, 416, 661, 316, 719, 250, 707, 185, 768, 134, 745, 97,
00142 354, 708, 416, 598, 488, 488, 564, 388, 634, 317, 642, 241, 716, 179, 706, 132,
00143 257, 748, 316, 661, 388, 564, 469, 469, 543, 395, 571, 311, 655, 238, 660, 180,
00144 198, 792, 250, 719, 317, 634, 395, 543, 469, 469, 507, 380, 597, 299, 616, 231,
00145 161, 855, 206, 788, 266, 710, 340, 623, 411, 548, 455, 455, 548, 366, 576, 288,
00146 122, 972, 159, 914, 211, 842, 276, 758, 341, 682, 389, 584, 483, 483, 520, 390,
00147 110, 1172, 144, 1107, 193, 1028, 254, 932, 317, 846, 366, 731, 458, 611, 499, 499
00148 };
00149
00150 static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
00151 int i,j;
00152 int x,y;
00153 unsigned int p;
00154 int a;
00155 uint16_t left_sum[2][8];
00156 uint16_t top_sum[2][8];
00157 memset(left_sum,0,2*8*sizeof(uint16_t));
00158 memset( top_sum,0,2*8*sizeof(uint16_t));
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(DSPContext* dsp, AVCodecContext *avctx) {
00417 dsp->x8_h_loop_filter=x8_h_loop_filter;
00418 dsp->x8_v_loop_filter=x8_v_loop_filter;
00419 dsp->x8_setup_spatial_compensation=x8_setup_spatial_compensation;
00420 dsp->x8_spatial_compensation[0]=spatial_compensation_0;
00421 dsp->x8_spatial_compensation[1]=spatial_compensation_1;
00422 dsp->x8_spatial_compensation[2]=spatial_compensation_2;
00423 dsp->x8_spatial_compensation[3]=spatial_compensation_3;
00424 dsp->x8_spatial_compensation[4]=spatial_compensation_4;
00425 dsp->x8_spatial_compensation[5]=spatial_compensation_5;
00426 dsp->x8_spatial_compensation[6]=spatial_compensation_6;
00427 dsp->x8_spatial_compensation[7]=spatial_compensation_7;
00428 dsp->x8_spatial_compensation[8]=spatial_compensation_8;
00429 dsp->x8_spatial_compensation[9]=spatial_compensation_9;
00430 dsp->x8_spatial_compensation[10]=spatial_compensation_10;
00431 dsp->x8_spatial_compensation[11]=spatial_compensation_11;
00432 }