Libav
|
00001 /* 00002 * This file is part of FFmpeg. 00003 * 00004 * FFmpeg is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * FFmpeg is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with FFmpeg; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 */ 00018 00024 #include "dsputil.h" 00025 00026 /* 00027 area positions, #3 is 1 pixel only, other are 8 pixels 00028 |66666666| 00029 3|44444444|55555555| 00030 - -+--------+--------+ 00031 1 2|XXXXXXXX| 00032 1 2|XXXXXXXX| 00033 1 2|XXXXXXXX| 00034 1 2|XXXXXXXX| 00035 1 2|XXXXXXXX| 00036 1 2|XXXXXXXX| 00037 1 2|XXXXXXXX| 00038 1 2|XXXXXXXX| 00039 ^-start 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 //this triggers flat_dc for sure. 00077 //flat_dc avoids all (other) prediction modes, but requires dc_level decoding. 00078 return; 00079 } 00080 00081 min_pix=256; 00082 max_pix=-1; 00083 00084 sum=0; 00085 00086 if(!(edges&1)){//(mb_x!=0)//there is previous block on this row 00087 ptr=src-1;//left column, area 2 00088 for(i=7;i>=0;i--){ 00089 c=*(ptr-1);//area1, same mb as area2, no need to check 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)){ //(mb_y!=0)//there is row above 00103 ptr=src-linesize;//top line 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){//last block on the row? 00111 memset(dst+area5,c,8);//set with last pixel fr 00112 memcpy(dst+area4, ptr, 8); 00113 }else{ 00114 memcpy(dst+area4, ptr, 16);//both area4 and 5 00115 } 00116 memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block 00117 } 00118 //now calculate the stuff we need 00119 if(edges&3){//mb_x==0 || mb_y==0){ 00120 int avg=(sum+4)>>3; 00121 if(edges&1){ //(mb_x==0) {//implies mb_y!=0 00122 memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged 00123 }else{//implies y==0 x!=0 00124 memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6 00125 } 00126 sum+=avg*9; 00127 }else{ 00128 uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column 00129 dst[area3]=c; 00130 sum+=c; 00131 //edge pixel is not part of min/max 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;//power divided by 2 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;//181 is sqrt(2)/2 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){//You need at least 1 to be able to reach a total score of 6. 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){//early stop 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;//abs(m) 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 }