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