cosmetic
[ffmpeg.git] / libavcodec / intrax8dsp.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 /**
20 * @file intrax8dsp.c
21  *@brief IntraX8 frame sub-decoder image manipulation routines
22  *
23  */
24
25 #include "dsputil.h"
26
27 /*
28 area positions, #3 is 1 pixel only, other are 8 pixels
29    |66666666|
30   3|44444444|55555555|
31 - -+--------+--------+
32 1 2|XXXXXXXX|
33 1 2|XXXXXXXX|
34 1 2|XXXXXXXX|
35 1 2|XXXXXXXX|
36 1 2|XXXXXXXX|
37 1 2|XXXXXXXX|
38 1 2|XXXXXXXX|
39 1 2|XXXXXXXX|
40 ^-start
41 */
42
43 #define area1 (0)
44 #define area2 (8)
45 #define area3 (8+8)
46 #define area4 (8+8+1)
47 #define area5 (8+8+1+8)
48 #define area6 (8+8+1+16)
49
50 /**
51  Collect statistics and prepare the edge pixels required by the other spacial compensation functions.
52
53  * @param src pointer to the beginning of the processed block
54  * @param dst pointer to emu_edge, edge pixels are stored in way other compensation routines use.
55  * @param linesize byte offset between 2 vertical pixels in the source image
56  * @param range pointer to the variable where the range of edge pixels is to be stored (max-min values)
57  * @param psum  pointer to the variable where the sum of edge pixels is to be stored
58  * @param edges informs this routine that the block is on image border, so it have to interpolate the missing edge pixels.
59                 and some of the edge pixels should be interpolated, flag have following meaning:
60                 1   - mb_x==0 - first block in the row, interpolate area #1,#2,#3;
61                 2   - mb_y==0 - first row, interpolate area #3,#4,#5,#6;
62         note:   1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas;
63                 4   - mb_x>= (mb_width-1) last block on the row, interpolate area #5;
64 */
65 static void x8_setup_spacial_compensation(uint8_t *src, uint8_t *dst, int linesize,
66            int * range, int * psum,  int edges){
67     uint8_t * ptr;
68     int sum;
69     int i;
70     int min_pix,max_pix;
71     uint8_t c;
72
73     if((edges&3)==3){
74         *psum=0x80*(8+1+8+2);
75         *range=0;
76         memset(dst,0x80,16+1+16+8);
77         //this triggers flat_dc for sure.
78         //flat_dc avoids all (other) prediction modes, but requires dc_level decoding.
79         return;
80     }
81
82     min_pix=256;
83     max_pix=-1;
84
85     sum=0;
86
87     if(!(edges&1)){//(mb_x!=0)//there is previous block on this row
88         ptr=src-1;//left column, area 2
89         for(i=7;i>=0;i--){
90             c=*(ptr-1);//area1, same mb as area2, no need to check
91             dst[area1+i]=c;
92             c=*(ptr);
93
94             sum+=c;
95             min_pix=FFMIN(min_pix,c);
96             max_pix=FFMAX(max_pix,c);
97             dst[area2+i]=c;
98
99             ptr+=linesize;
100         }
101     }
102
103     if(!(edges&2)){  //(mb_y!=0)//there is row above
104         ptr=src-linesize;//top line
105         for(i=0;i<8;i++){
106             c=*(ptr+i);
107             sum+=c;
108             min_pix=FFMIN(min_pix, c);
109             max_pix=FFMAX(max_pix, c);
110         }
111         if(edges&4){//last block on the row?
112             memset(dst+area5,c,8);//set with last pixel fr
113             memcpy(dst+area4, ptr, 8);
114         }else{
115             memcpy(dst+area4, ptr, 16);//both area4 and 5
116         }
117         memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block
118     }
119 //now calc the stuff we need
120     if(edges&3){//mb_x==0 || mb_y==0){
121         int avg=(sum+4)>>3;
122         if(edges&1){ //(mb_x==0) {//implies mb_y!=0
123             memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged
124         }else{//implies y==0 x!=0
125             memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6
126         }
127         sum+=avg*9;
128     }else{
129         uint8_t c=*(src-1-linesize);//the edge pixel,in the top line and left column
130         dst[area3]=c;
131         sum+=c;
132         //edge pixel is not part of min/max
133     }
134     (*range) = max_pix - min_pix;
135     sum += *(dst+area5) + *(dst+area5+1);
136     *psum = sum;
137 }
138
139
140 static const uint16_t zero_prediction_weights[64*2] = {
141     640,  640,  669,  480,  708,  354,  748, 257,  792, 198,  760, 143,  808, 101,  772,  72,
142     480,  669,  537,  537,  598,  416,  661, 316,  719, 250,  707, 185,  768, 134,  745,  97,
143     354,  708,  416,  598,  488,  488,  564, 388,  634, 317,  642, 241,  716, 179,  706, 132,
144     257,  748,  316,  661,  388,  564,  469, 469,  543, 395,  571, 311,  655, 238,  660, 180,
145     198,  792,  250,  719,  317,  634,  395, 543,  469, 469,  507, 380,  597, 299,  616, 231,
146     161,  855,  206,  788,  266,  710,  340, 623,  411, 548,  455, 455,  548, 366,  576, 288,
147     122,  972,  159,  914,  211,  842,  276, 758,  341, 682,  389, 584,  483, 483,  520, 390,
148     110, 1172,  144, 1107,  193, 1028,  254, 932,  317, 846,  366, 731,  458, 611,  499, 499
149 };
150
151 static void spacial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
152     int i,j;
153     int x,y;
154     unsigned int p;//power divided by 2
155     int a;
156     uint16_t left_sum[2][8];
157     uint16_t  top_sum[2][8];
158     memset(left_sum,0,2*8*sizeof(uint16_t));
159     memset( top_sum,0,2*8*sizeof(uint16_t));
160
161     for(i=0;i<8;i++){
162         a=src[area2+7-i]<<4;
163         for(j=0;j<8;j++){
164             p=abs(i-j);
165             left_sum[p&1][j]+= a>>(p>>1);
166         }
167     }
168
169     for(i=0;i<8;i++){
170         a=src[area4+i]<<4;
171         for(j=0;j<8;j++){
172             p=abs(i-j);
173             top_sum[p&1][j]+=   a>>(p>>1);
174         }
175     }
176     for(;i<10;i++){
177         a=src[area4+i]<<4;
178         for(j=5;j<8;j++){
179             p=abs(i-j);
180             top_sum[p&1][j]+=   a>>(p>>1);
181         }
182     }
183     for(;i<12;i++){
184         a=src[area4+i]<<4;
185         for(j=7;j<8;j++){
186             p=abs(i-j);
187             top_sum[p&1][j]+=   a>>(p>>1);
188         }
189     }
190
191     for(i=0;i<8;i++){
192         top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
193         left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
194     }
195     for(y=0;y<8;y++){
196         for(x=0;x<8;x++){
197             dst[x] = (
198                       (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
199                       (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
200                        0x8000
201                       )>>16;
202         }
203         dst+=linesize;
204     }
205 }
206 static void spacial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
207     int x,y;
208
209     for(y=0;y<8;y++){
210         for(x=0;x<8;x++){
211             dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
212         }
213         dst+=linesize;
214     }
215 }
216 static void spacial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
217     int x,y;
218
219     for(y=0;y<8;y++){
220         for(x=0;x<8;x++){
221             dst[x]=src[area4 +1+y+x];
222         }
223         dst+=linesize;
224     }
225 }
226 static void spacial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
227     int x,y;
228
229     for(y=0;y<8;y++){
230         for(x=0;x<8;x++){
231             dst[x]=src[area4 +((y+1)>>1)+x];
232         }
233         dst+=linesize;
234     }
235 }
236 static void spacial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
237     int x,y;
238
239     for(y=0;y<8;y++){
240         for(x=0;x<8;x++){
241             dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
242         }
243         dst+=linesize;
244     }
245 }
246 static void spacial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
247     int x,y;
248
249     for(y=0;y<8;y++){
250         for(x=0;x<8;x++){
251             if(2*x-y<0){
252                 dst[x]=src[area2+9+2*x-y];
253             }else{
254                 dst[x]=src[area4 +x-((y+1)>>1)];
255             }
256         }
257         dst+=linesize;
258     }
259 }
260 static void spacial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
261     int x,y;
262
263     for(y=0;y<8;y++){
264         for(x=0;x<8;x++){
265             dst[x]=src[area3+x-y];
266         }
267         dst+=linesize;
268     }
269 }
270 static void spacial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
271     int x,y;
272
273     for(y=0;y<8;y++){
274         for(x=0;x<8;x++){
275             if(x-2*y>0){
276                 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
277             }else{
278                 dst[x]=src[area2+8-y +(x>>1)];
279             }
280         }
281         dst+=linesize;
282     }
283 }
284 static void spacial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
285     int x,y;
286
287     for(y=0;y<8;y++){
288         for(x=0;x<8;x++){
289             dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
290         }
291         dst+=linesize;
292     }
293 }
294 static void spacial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
295     int x,y;
296
297     for(y=0;y<8;y++){
298         for(x=0;x<8;x++){
299             dst[x]=src[area2+6-FFMIN(x+y,6)];
300         }
301         dst+=linesize;
302     }
303 }
304 static void spacial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
305     int x,y;
306
307     for(y=0;y<8;y++){
308         for(x=0;x<8;x++){
309             dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
310         }
311         dst+=linesize;
312     }
313 }
314 static void spacial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
315     int x,y;
316
317     for(y=0;y<8;y++){
318         for(x=0;x<8;x++){
319             dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
320         }
321         dst+=linesize;
322     }
323 }
324
325 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
326     int i,t;
327     int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
328     int ql=(quant+10)>>3;
329
330     for(i=0; i<8; i++,ptr+=b_stride){
331         p0=ptr[-5*a_stride];
332         p1=ptr[-4*a_stride];
333         p2=ptr[-3*a_stride];
334         p3=ptr[-2*a_stride];
335         p4=ptr[-1*a_stride];
336         p5=ptr[ 0         ];
337         p6=ptr[ 1*a_stride];
338         p7=ptr[ 2*a_stride];
339         p8=ptr[ 3*a_stride];
340         p9=ptr[ 4*a_stride];
341
342         t=
343             (FFABS(p1-p2) <= ql) +
344             (FFABS(p2-p3) <= ql) +
345             (FFABS(p3-p4) <= ql) +
346             (FFABS(p4-p5) <= ql);
347         if(t>0){//you need at least 1 to be able to reach total score of 6.
348             t+=
349                 (FFABS(p5-p6) <= ql) +
350                 (FFABS(p6-p7) <= ql) +
351                 (FFABS(p7-p8) <= ql) +
352                 (FFABS(p8-p9) <= ql) +
353                 (FFABS(p0-p1) <= ql);
354             if(t>=6){
355                 int min,max;
356
357                 min=max=p1;
358                 min=FFMIN(min,p3); max=FFMAX(max,p3);
359                 min=FFMIN(min,p5); max=FFMAX(max,p5);
360                 min=FFMIN(min,p8); max=FFMAX(max,p8);
361                 if(max-min<2*quant){//early stop
362                     min=FFMIN(min,p2); max=FFMAX(max,p2);
363                     min=FFMIN(min,p4); max=FFMAX(max,p4);
364                     min=FFMIN(min,p6); max=FFMAX(max,p6);
365                     min=FFMIN(min,p7); max=FFMAX(max,p7);
366                     if(max-min<2*quant){
367                         ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
368                         ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
369                         ptr[ 0         ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
370                         ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
371                         continue;
372                     };
373                 }
374             }
375         }
376         {
377             int x,x0,x1,x2;
378             int m;
379
380             x0 =   (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
381             if(FFABS(x0) < quant){
382                 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
383                 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
384
385                 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
386                 m=p4-p5;
387
388                 if( x > 0 && (m^x0) <0){
389                     int32_t sign;
390
391                     sign=m>>31;
392                     m=(m^sign)-sign;//abs(m)
393                     m>>=1;
394
395                     x=(5*x)>>3;
396
397                     if(x>m) x=m;
398
399                     x=(x^sign)-sign;
400
401                     ptr[-1*a_stride] -= x;
402                     ptr[ 0]          += x;
403                 }
404             }
405         }
406     }
407 }
408
409 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
410     x8_loop_filter(src, stride, 1, qscale);
411 }
412
413 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
414     x8_loop_filter(src, 1, stride, qscale);
415 }
416
417 void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
418     dsp->x8_h_loop_filter=x8_h_loop_filter;
419     dsp->x8_v_loop_filter=x8_v_loop_filter;
420     dsp->x8_setup_spacial_compensation=x8_setup_spacial_compensation;
421     dsp->x8_spacial_compensation[0]=spacial_compensation_0;
422     dsp->x8_spacial_compensation[1]=spacial_compensation_1;
423     dsp->x8_spacial_compensation[2]=spacial_compensation_2;
424     dsp->x8_spacial_compensation[3]=spacial_compensation_3;
425     dsp->x8_spacial_compensation[4]=spacial_compensation_4;
426     dsp->x8_spacial_compensation[5]=spacial_compensation_5;
427     dsp->x8_spacial_compensation[6]=spacial_compensation_6;
428     dsp->x8_spacial_compensation[7]=spacial_compensation_7;
429     dsp->x8_spacial_compensation[8]=spacial_compensation_8;
430     dsp->x8_spacial_compensation[9]=spacial_compensation_9;
431     dsp->x8_spacial_compensation[10]=spacial_compensation_10;
432     dsp->x8_spacial_compensation[11]=spacial_compensation_11;
433 }
434
435 #if 0
436 static void wmv2_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
437     int i,t;
438     int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
439
440     for(i=0; i<8; i++,ptr+=b_stride){
441         p1=ptr[-4*a_stride];
442         p2=ptr[-3*a_stride];
443         p3=ptr[-2*a_stride];
444         p4=ptr[-1*a_stride];
445         p5=ptr[ 0         ];
446         p6=ptr[ 1*a_stride];
447         p7=ptr[ 2*a_stride];
448         p8=ptr[ 3*a_stride];
449
450         {
451             int x,x0,x1,x2;
452             int m;
453
454             x0 =   (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
455             if(abs(x0) < quant){
456                 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
457                 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
458
459                 x=abs(x0) - FFMIN( abs(x1), abs(x2) );
460                 m=p4-p5;
461
462                 if( x > 0 && (m^x0) < 0){
463                     int32_t sign;
464
465                     sign=m>>31;
466                     m=(m^sign)-sign;//abs(m)
467                     m>>=1;
468
469                     x=(5*x)>>3;
470
471                     if(x>m) x=m;
472
473                     x=(x^sign)-sign;
474
475                     ptr[-1*a_stride] -= x;
476                     ptr[ 0]          += x;
477                 }
478             }
479         }
480     }
481 }
482 #endif