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] = { { 0 } };
00156 uint16_t top_sum[2][8] = { { 0 } };
00157
00158 for(i=0;i<8;i++){
00159 a=src[area2+7-i]<<4;
00160 for(j=0;j<8;j++){
00161 p=abs(i-j);
00162 left_sum[p&1][j]+= a>>(p>>1);
00163 }
00164 }
00165
00166 for(i=0;i<8;i++){
00167 a=src[area4+i]<<4;
00168 for(j=0;j<8;j++){
00169 p=abs(i-j);
00170 top_sum[p&1][j]+= a>>(p>>1);
00171 }
00172 }
00173 for(;i<10;i++){
00174 a=src[area4+i]<<4;
00175 for(j=5;j<8;j++){
00176 p=abs(i-j);
00177 top_sum[p&1][j]+= a>>(p>>1);
00178 }
00179 }
00180 for(;i<12;i++){
00181 a=src[area4+i]<<4;
00182 for(j=7;j<8;j++){
00183 p=abs(i-j);
00184 top_sum[p&1][j]+= a>>(p>>1);
00185 }
00186 }
00187
00188 for(i=0;i<8;i++){
00189 top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;
00190 left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
00191 }
00192 for(y=0;y<8;y++){
00193 for(x=0;x<8;x++){
00194 dst[x] = (
00195 (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
00196 (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
00197 0x8000
00198 )>>16;
00199 }
00200 dst+=linesize;
00201 }
00202 }
00203 static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
00204 int x,y;
00205
00206 for(y=0;y<8;y++){
00207 for(x=0;x<8;x++){
00208 dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
00209 }
00210 dst+=linesize;
00211 }
00212 }
00213 static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
00214 int x,y;
00215
00216 for(y=0;y<8;y++){
00217 for(x=0;x<8;x++){
00218 dst[x]=src[area4 +1+y+x];
00219 }
00220 dst+=linesize;
00221 }
00222 }
00223 static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
00224 int x,y;
00225
00226 for(y=0;y<8;y++){
00227 for(x=0;x<8;x++){
00228 dst[x]=src[area4 +((y+1)>>1)+x];
00229 }
00230 dst+=linesize;
00231 }
00232 }
00233 static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
00234 int x,y;
00235
00236 for(y=0;y<8;y++){
00237 for(x=0;x<8;x++){
00238 dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
00239 }
00240 dst+=linesize;
00241 }
00242 }
00243 static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
00244 int x,y;
00245
00246 for(y=0;y<8;y++){
00247 for(x=0;x<8;x++){
00248 if(2*x-y<0){
00249 dst[x]=src[area2+9+2*x-y];
00250 }else{
00251 dst[x]=src[area4 +x-((y+1)>>1)];
00252 }
00253 }
00254 dst+=linesize;
00255 }
00256 }
00257 static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
00258 int x,y;
00259
00260 for(y=0;y<8;y++){
00261 for(x=0;x<8;x++){
00262 dst[x]=src[area3+x-y];
00263 }
00264 dst+=linesize;
00265 }
00266 }
00267 static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
00268 int x,y;
00269
00270 for(y=0;y<8;y++){
00271 for(x=0;x<8;x++){
00272 if(x-2*y>0){
00273 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
00274 }else{
00275 dst[x]=src[area2+8-y +(x>>1)];
00276 }
00277 }
00278 dst+=linesize;
00279 }
00280 }
00281 static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
00282 int x,y;
00283
00284 for(y=0;y<8;y++){
00285 for(x=0;x<8;x++){
00286 dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
00287 }
00288 dst+=linesize;
00289 }
00290 }
00291 static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
00292 int x,y;
00293
00294 for(y=0;y<8;y++){
00295 for(x=0;x<8;x++){
00296 dst[x]=src[area2+6-FFMIN(x+y,6)];
00297 }
00298 dst+=linesize;
00299 }
00300 }
00301 static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
00302 int x,y;
00303
00304 for(y=0;y<8;y++){
00305 for(x=0;x<8;x++){
00306 dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
00307 }
00308 dst+=linesize;
00309 }
00310 }
00311 static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
00312 int x,y;
00313
00314 for(y=0;y<8;y++){
00315 for(x=0;x<8;x++){
00316 dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
00317 }
00318 dst+=linesize;
00319 }
00320 }
00321
00322 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
00323 int i,t;
00324 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
00325 int ql=(quant+10)>>3;
00326
00327 for(i=0; i<8; i++,ptr+=b_stride){
00328 p0=ptr[-5*a_stride];
00329 p1=ptr[-4*a_stride];
00330 p2=ptr[-3*a_stride];
00331 p3=ptr[-2*a_stride];
00332 p4=ptr[-1*a_stride];
00333 p5=ptr[ 0 ];
00334 p6=ptr[ 1*a_stride];
00335 p7=ptr[ 2*a_stride];
00336 p8=ptr[ 3*a_stride];
00337 p9=ptr[ 4*a_stride];
00338
00339 t=
00340 (FFABS(p1-p2) <= ql) +
00341 (FFABS(p2-p3) <= ql) +
00342 (FFABS(p3-p4) <= ql) +
00343 (FFABS(p4-p5) <= ql);
00344 if(t>0){
00345 t+=
00346 (FFABS(p5-p6) <= ql) +
00347 (FFABS(p6-p7) <= ql) +
00348 (FFABS(p7-p8) <= ql) +
00349 (FFABS(p8-p9) <= ql) +
00350 (FFABS(p0-p1) <= ql);
00351 if(t>=6){
00352 int min,max;
00353
00354 min=max=p1;
00355 min=FFMIN(min,p3); max=FFMAX(max,p3);
00356 min=FFMIN(min,p5); max=FFMAX(max,p5);
00357 min=FFMIN(min,p8); max=FFMAX(max,p8);
00358 if(max-min<2*quant){
00359 min=FFMIN(min,p2); max=FFMAX(max,p2);
00360 min=FFMIN(min,p4); max=FFMAX(max,p4);
00361 min=FFMIN(min,p6); max=FFMAX(max,p6);
00362 min=FFMIN(min,p7); max=FFMAX(max,p7);
00363 if(max-min<2*quant){
00364 ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
00365 ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
00366 ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
00367 ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
00368 continue;
00369 };
00370 }
00371 }
00372 }
00373 {
00374 int x,x0,x1,x2;
00375 int m;
00376
00377 x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
00378 if(FFABS(x0) < quant){
00379 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
00380 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
00381
00382 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
00383 m=p4-p5;
00384
00385 if( x > 0 && (m^x0) <0){
00386 int32_t sign;
00387
00388 sign=m>>31;
00389 m=(m^sign)-sign;
00390 m>>=1;
00391
00392 x=(5*x)>>3;
00393
00394 if(x>m) x=m;
00395
00396 x=(x^sign)-sign;
00397
00398 ptr[-1*a_stride] -= x;
00399 ptr[ 0] += x;
00400 }
00401 }
00402 }
00403 }
00404 }
00405
00406 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
00407 x8_loop_filter(src, stride, 1, qscale);
00408 }
00409
00410 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
00411 x8_loop_filter(src, 1, stride, qscale);
00412 }
00413
00414 av_cold void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
00415 dsp->x8_h_loop_filter=x8_h_loop_filter;
00416 dsp->x8_v_loop_filter=x8_v_loop_filter;
00417 dsp->x8_setup_spatial_compensation=x8_setup_spatial_compensation;
00418 dsp->x8_spatial_compensation[0]=spatial_compensation_0;
00419 dsp->x8_spatial_compensation[1]=spatial_compensation_1;
00420 dsp->x8_spatial_compensation[2]=spatial_compensation_2;
00421 dsp->x8_spatial_compensation[3]=spatial_compensation_3;
00422 dsp->x8_spatial_compensation[4]=spatial_compensation_4;
00423 dsp->x8_spatial_compensation[5]=spatial_compensation_5;
00424 dsp->x8_spatial_compensation[6]=spatial_compensation_6;
00425 dsp->x8_spatial_compensation[7]=spatial_compensation_7;
00426 dsp->x8_spatial_compensation[8]=spatial_compensation_8;
00427 dsp->x8_spatial_compensation[9]=spatial_compensation_9;
00428 dsp->x8_spatial_compensation[10]=spatial_compensation_10;
00429 dsp->x8_spatial_compensation[11]=spatial_compensation_11;
00430 }