• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/intrax8dsp.c

Go to the documentation of this file.
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 }

Generated on Fri Sep 16 2011 17:17:38 for FFmpeg by  doxygen 1.7.1