indeo3: ensure that decoded cell data is in 7-bit range as presumed by decoder
[ffmpeg.git] / libavcodec / intrax8dsp.c
1 /*
2  * This file is part of Libav.
3  *
4  * Libav 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  * Libav 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 Libav; 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
21  *@brief IntraX8 frame subdecoder image manipulation routines
22  */
23
24 #include "dsputil.h"
25
26 /*
27 area positions, #3 is 1 pixel only, other are 8 pixels
28    |66666666|
29   3|44444444|55555555|
30 - -+--------+--------+
31 1 2|XXXXXXXX|
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 ^-start
40 */
41
42 #define area1 (0)
43 #define area2 (8)
44 #define area3 (8+8)
45 #define area4 (8+8+1)
46 #define area5 (8+8+1+8)
47 #define area6 (8+8+1+16)
48
49 /**
50  Collect statistics and prepare the edge pixels required by the other spatial compensation functions.
51
52  * @param src pointer to the beginning of the processed block
53  * @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do.
54  * @param linesize byte offset between 2 vertical pixels in the source image
55  * @param range pointer to the variable where the edge pixel range is to be stored (max-min values)
56  * @param psum  pointer to the variable where the edge pixel sum is to be stored
57  * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels.
58                 and some of the edge pixels should be interpolated, the flag has the following meaning:
59                 1   - mb_x==0 - first block in the row, interpolate area #1,#2,#3;
60                 2   - mb_y==0 - first row, interpolate area #3,#4,#5,#6;
61         note:   1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas;
62                 4   - mb_x>= (mb_width-1) last block in the row, interpolate area #5;
63 */
64 static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize,
65            int * range, int * psum,  int edges){
66     uint8_t * ptr;
67     int sum;
68     int i;
69     int min_pix,max_pix;
70     uint8_t c;
71
72     if((edges&3)==3){
73         *psum=0x80*(8+1+8+2);
74         *range=0;
75         memset(dst,0x80,16+1+16+8);
76         //this triggers flat_dc for sure.
77         //flat_dc avoids all (other) prediction modes, but requires dc_level decoding.
78         return;
79     }
80
81     min_pix=256;
82     max_pix=-1;
83
84     sum=0;
85
86     if(!(edges&1)){//(mb_x!=0)//there is previous block on this row
87         ptr=src-1;//left column, area 2
88         for(i=7;i>=0;i--){
89             c=*(ptr-1);//area1, same mb as area2, no need to check
90             dst[area1+i]=c;
91             c=*(ptr);
92
93             sum+=c;
94             min_pix=FFMIN(min_pix,c);
95             max_pix=FFMAX(max_pix,c);
96             dst[area2+i]=c;
97
98             ptr+=linesize;
99         }
100     }
101
102     if(!(edges&2)){  //(mb_y!=0)//there is row above
103         ptr=src-linesize;//top line
104         for(i=0;i<8;i++){
105             c=*(ptr+i);
106             sum+=c;
107             min_pix=FFMIN(min_pix, c);
108             max_pix=FFMAX(max_pix, c);
109         }
110         if(edges&4){//last block on the row?
111             memset(dst+area5,c,8);//set with last pixel fr
112             memcpy(dst+area4, ptr, 8);
113         }else{
114             memcpy(dst+area4, ptr, 16);//both area4 and 5
115         }
116         memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block
117     }
118     //now calculate the stuff we need
119     if(edges&3){//mb_x==0 || mb_y==0){
120         int avg=(sum+4)>>3;
121         if(edges&1){ //(mb_x==0) {//implies mb_y!=0
122             memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged
123         }else{//implies y==0 x!=0
124             memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6
125         }
126         sum+=avg*9;
127     }else{
128         uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column
129         dst[area3]=c;
130         sum+=c;
131         //edge pixel is not part of min/max
132     }
133     (*range) = max_pix - min_pix;
134     sum += *(dst+area5) + *(dst+area5+1);
135     *psum = sum;
136 }
137
138
139 static const uint16_t zero_prediction_weights[64*2] = {
140     640,  640,  669,  480,  708,  354,  748, 257,  792, 198,  760, 143,  808, 101,  772,  72,
141     480,  669,  537,  537,  598,  416,  661, 316,  719, 250,  707, 185,  768, 134,  745,  97,
142     354,  708,  416,  598,  488,  488,  564, 388,  634, 317,  642, 241,  716, 179,  706, 132,
143     257,  748,  316,  661,  388,  564,  469, 469,  543, 395,  571, 311,  655, 238,  660, 180,
144     198,  792,  250,  719,  317,  634,  395, 543,  469, 469,  507, 380,  597, 299,  616, 231,
145     161,  855,  206,  788,  266,  710,  340, 623,  411, 548,  455, 455,  548, 366,  576, 288,
146     122,  972,  159,  914,  211,  842,  276, 758,  341, 682,  389, 584,  483, 483,  520, 390,
147     110, 1172,  144, 1107,  193, 1028,  254, 932,  317, 846,  366, 731,  458, 611,  499, 499
148 };
149
150 static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
151     int i,j;
152     int x,y;
153     unsigned int p;//power divided by 2
154     int a;
155     uint16_t left_sum[2][8] = { { 0 } };
156     uint16_t  top_sum[2][8] = { { 0 } };
157
158     for(i=0;i<8;i++){
159         a=src[area2+7-i]<<4;
160         for(j=0;j<8;j++){
161             p=abs(i-j);
162             left_sum[p&1][j]+= a>>(p>>1);
163         }
164     }
165
166     for(i=0;i<8;i++){
167         a=src[area4+i]<<4;
168         for(j=0;j<8;j++){
169             p=abs(i-j);
170             top_sum[p&1][j]+=   a>>(p>>1);
171         }
172     }
173     for(;i<10;i++){
174         a=src[area4+i]<<4;
175         for(j=5;j<8;j++){
176             p=abs(i-j);
177             top_sum[p&1][j]+=   a>>(p>>1);
178         }
179     }
180     for(;i<12;i++){
181         a=src[area4+i]<<4;
182         for(j=7;j<8;j++){
183             p=abs(i-j);
184             top_sum[p&1][j]+=   a>>(p>>1);
185         }
186     }
187
188     for(i=0;i<8;i++){
189         top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
190         left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
191     }
192     for(y=0;y<8;y++){
193         for(x=0;x<8;x++){
194             dst[x] = (
195                       (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
196                       (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
197                        0x8000
198                       )>>16;
199         }
200         dst+=linesize;
201     }
202 }
203 static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
204     int x,y;
205
206     for(y=0;y<8;y++){
207         for(x=0;x<8;x++){
208             dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
209         }
210         dst+=linesize;
211     }
212 }
213 static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
214     int x,y;
215
216     for(y=0;y<8;y++){
217         for(x=0;x<8;x++){
218             dst[x]=src[area4 +1+y+x];
219         }
220         dst+=linesize;
221     }
222 }
223 static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
224     int x,y;
225
226     for(y=0;y<8;y++){
227         for(x=0;x<8;x++){
228             dst[x]=src[area4 +((y+1)>>1)+x];
229         }
230         dst+=linesize;
231     }
232 }
233 static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
234     int x,y;
235
236     for(y=0;y<8;y++){
237         for(x=0;x<8;x++){
238             dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
239         }
240         dst+=linesize;
241     }
242 }
243 static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
244     int x,y;
245
246     for(y=0;y<8;y++){
247         for(x=0;x<8;x++){
248             if(2*x-y<0){
249                 dst[x]=src[area2+9+2*x-y];
250             }else{
251                 dst[x]=src[area4 +x-((y+1)>>1)];
252             }
253         }
254         dst+=linesize;
255     }
256 }
257 static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
258     int x,y;
259
260     for(y=0;y<8;y++){
261         for(x=0;x<8;x++){
262             dst[x]=src[area3+x-y];
263         }
264         dst+=linesize;
265     }
266 }
267 static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
268     int x,y;
269
270     for(y=0;y<8;y++){
271         for(x=0;x<8;x++){
272             if(x-2*y>0){
273                 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
274             }else{
275                 dst[x]=src[area2+8-y +(x>>1)];
276             }
277         }
278         dst+=linesize;
279     }
280 }
281 static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
282     int x,y;
283
284     for(y=0;y<8;y++){
285         for(x=0;x<8;x++){
286             dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
287         }
288         dst+=linesize;
289     }
290 }
291 static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
292     int x,y;
293
294     for(y=0;y<8;y++){
295         for(x=0;x<8;x++){
296             dst[x]=src[area2+6-FFMIN(x+y,6)];
297         }
298         dst+=linesize;
299     }
300 }
301 static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
302     int x,y;
303
304     for(y=0;y<8;y++){
305         for(x=0;x<8;x++){
306             dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
307         }
308         dst+=linesize;
309     }
310 }
311 static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
312     int x,y;
313
314     for(y=0;y<8;y++){
315         for(x=0;x<8;x++){
316             dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
317         }
318         dst+=linesize;
319     }
320 }
321
322 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
323     int i,t;
324     int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
325     int ql=(quant+10)>>3;
326
327     for(i=0; i<8; i++,ptr+=b_stride){
328         p0=ptr[-5*a_stride];
329         p1=ptr[-4*a_stride];
330         p2=ptr[-3*a_stride];
331         p3=ptr[-2*a_stride];
332         p4=ptr[-1*a_stride];
333         p5=ptr[ 0         ];
334         p6=ptr[ 1*a_stride];
335         p7=ptr[ 2*a_stride];
336         p8=ptr[ 3*a_stride];
337         p9=ptr[ 4*a_stride];
338
339         t=
340             (FFABS(p1-p2) <= ql) +
341             (FFABS(p2-p3) <= ql) +
342             (FFABS(p3-p4) <= ql) +
343             (FFABS(p4-p5) <= ql);
344         if(t>0){//You need at least 1 to be able to reach a total score of 6.
345             t+=
346                 (FFABS(p5-p6) <= ql) +
347                 (FFABS(p6-p7) <= ql) +
348                 (FFABS(p7-p8) <= ql) +
349                 (FFABS(p8-p9) <= ql) +
350                 (FFABS(p0-p1) <= ql);
351             if(t>=6){
352                 int min,max;
353
354                 min=max=p1;
355                 min=FFMIN(min,p3); max=FFMAX(max,p3);
356                 min=FFMIN(min,p5); max=FFMAX(max,p5);
357                 min=FFMIN(min,p8); max=FFMAX(max,p8);
358                 if(max-min<2*quant){//early stop
359                     min=FFMIN(min,p2); max=FFMAX(max,p2);
360                     min=FFMIN(min,p4); max=FFMAX(max,p4);
361                     min=FFMIN(min,p6); max=FFMAX(max,p6);
362                     min=FFMIN(min,p7); max=FFMAX(max,p7);
363                     if(max-min<2*quant){
364                         ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
365                         ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
366                         ptr[ 0         ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
367                         ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
368                         continue;
369                     };
370                 }
371             }
372         }
373         {
374             int x,x0,x1,x2;
375             int m;
376
377             x0 =   (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
378             if(FFABS(x0) < quant){
379                 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
380                 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
381
382                 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
383                 m=p4-p5;
384
385                 if( x > 0 && (m^x0) <0){
386                     int32_t sign;
387
388                     sign=m>>31;
389                     m=(m^sign)-sign;//abs(m)
390                     m>>=1;
391
392                     x=(5*x)>>3;
393
394                     if(x>m) x=m;
395
396                     x=(x^sign)-sign;
397
398                     ptr[-1*a_stride] -= x;
399                     ptr[ 0]          += x;
400                 }
401             }
402         }
403     }
404 }
405
406 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
407     x8_loop_filter(src, stride, 1, qscale);
408 }
409
410 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
411     x8_loop_filter(src, 1, stride, qscale);
412 }
413
414 av_cold void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
415     dsp->x8_h_loop_filter=x8_h_loop_filter;
416     dsp->x8_v_loop_filter=x8_v_loop_filter;
417     dsp->x8_setup_spatial_compensation=x8_setup_spatial_compensation;
418     dsp->x8_spatial_compensation[0]=spatial_compensation_0;
419     dsp->x8_spatial_compensation[1]=spatial_compensation_1;
420     dsp->x8_spatial_compensation[2]=spatial_compensation_2;
421     dsp->x8_spatial_compensation[3]=spatial_compensation_3;
422     dsp->x8_spatial_compensation[4]=spatial_compensation_4;
423     dsp->x8_spatial_compensation[5]=spatial_compensation_5;
424     dsp->x8_spatial_compensation[6]=spatial_compensation_6;
425     dsp->x8_spatial_compensation[7]=spatial_compensation_7;
426     dsp->x8_spatial_compensation[8]=spatial_compensation_8;
427     dsp->x8_spatial_compensation[9]=spatial_compensation_9;
428     dsp->x8_spatial_compensation[10]=spatial_compensation_10;
429     dsp->x8_spatial_compensation[11]=spatial_compensation_11;
430 }