876bd398cdae0313584c3978130bfe03771b3c1d
[libav.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 if(edges&1){ //(mb_x==0) {//implies mb_y!=0
122 int avg=(sum+4)>>3;
123 memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged
124 sum+=avg*9;//8+1(egde pixel)
125 }else{//implies y==0 x!=0
126 int avg=(sum+4)>>3;
127 memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6
128 sum+=avg*9;
129 }
130 }else{
131 uint8_t c;
132 c=*(src-1-linesize);//the edge pixel,in the top line and left column
133 dst[area3]=c;
134 sum+=c;
135 //edge pixel is not part of min/max
136 }
137 (*range) = max_pix - min_pix;
138 sum += *(dst+area5) + *(dst+area5+1);
139 *psum = sum;
140 }
141
142
143 static const uint16_t zero_prediction_weights[64*2] = {
144 640, 640, 669, 480, 708, 354, 748, 257, 792, 198, 760, 143, 808, 101, 772, 72,
145 480, 669, 537, 537, 598, 416, 661, 316, 719, 250, 707, 185, 768, 134, 745, 97,
146 354, 708, 416, 598, 488, 488, 564, 388, 634, 317, 642, 241, 716, 179, 706, 132,
147 257, 748, 316, 661, 388, 564, 469, 469, 543, 395, 571, 311, 655, 238, 660, 180,
148 198, 792, 250, 719, 317, 634, 395, 543, 469, 469, 507, 380, 597, 299, 616, 231,
149 161, 855, 206, 788, 266, 710, 340, 623, 411, 548, 455, 455, 548, 366, 576, 288,
150 122, 972, 159, 914, 211, 842, 276, 758, 341, 682, 389, 584, 483, 483, 520, 390,
151 110, 1172, 144, 1107, 193, 1028, 254, 932, 317, 846, 366, 731, 458, 611, 499, 499
152 };
153
154 static void spacial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
155 int i,j;
156 int x,y;
157 unsigned int p;//power divided by 2
158 int a;
159 uint16_t left_sum[2][8];
160 uint16_t top_sum[2][8];
161 memset(left_sum,0,2*8*sizeof(uint16_t));
162 memset( top_sum,0,2*8*sizeof(uint16_t));
163
164 for(i=0;i<8;i++){
165 a=src[area2+7-i]<<4;
166 for(j=0;j<8;j++){
167 p=abs(i-j);
168 left_sum[p&1][j]+= a>>(p>>1);
169 }
170 }
171
172 for(i=0;i<8;i++){
173 a=src[area4+i]<<4;
174 for(j=0;j<8;j++){
175 p=abs(i-j);
176 top_sum[p&1][j]+= a>>(p>>1);
177 }
178 }
179 for(;i<10;i++){
180 a=src[area4+i]<<4;
181 for(j=5;j<8;j++){
182 p=abs(i-j);
183 top_sum[p&1][j]+= a>>(p>>1);
184 }
185 }
186 for(;i<12;i++){
187 a=src[area4+i]<<4;
188 for(j=7;j<8;j++){
189 p=abs(i-j);
190 top_sum[p&1][j]+= a>>(p>>1);
191 }
192 }
193
194 for(i=0;i<8;i++){
195 top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
196 left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
197 }
198 for(y=0;y<8;y++){
199 for(x=0;x<8;x++){
200 dst[x] = (
201 (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
202 (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
203 0x8000
204 )>>16;
205 }
206 dst+=linesize;
207 }
208 }
209 static void spacial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
210 int x,y;
211
212 for(y=0;y<8;y++){
213 for(x=0;x<8;x++){
214 dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
215 }
216 dst+=linesize;
217 }
218 }
219 static void spacial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
220 int x,y;
221
222 for(y=0;y<8;y++){
223 for(x=0;x<8;x++){
224 dst[x]=src[area4 +1+y+x];
225 }
226 dst+=linesize;
227 }
228 }
229 static void spacial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
230 int x,y;
231
232 for(y=0;y<8;y++){
233 for(x=0;x<8;x++){
234 dst[x]=src[area4 +((y+1)>>1)+x];
235 }
236 dst+=linesize;
237 }
238 }
239 static void spacial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
240 int x,y;
241
242 for(y=0;y<8;y++){
243 for(x=0;x<8;x++){
244 dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
245 }
246 dst+=linesize;
247 }
248 }
249 static void spacial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
250 int x,y;
251
252 for(y=0;y<8;y++){
253 for(x=0;x<8;x++){
254 if(2*x-y<0){
255 dst[x]=src[area2+9+2*x-y];
256 }else{
257 dst[x]=src[area4 +x-((y+1)>>1)];
258 }
259 }
260 dst+=linesize;
261 }
262 }
263 static void spacial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
264 int x,y;
265
266 for(y=0;y<8;y++){
267 for(x=0;x<8;x++){
268 dst[x]=src[area3+x-y];
269 }
270 dst+=linesize;
271 }
272 }
273 static void spacial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
274 int x,y;
275
276 for(y=0;y<8;y++){
277 for(x=0;x<8;x++){
278 if(x-2*y>0){
279 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
280 }else{
281 dst[x]=src[area2+8-y +(x>>1)];
282 }
283 }
284 dst+=linesize;
285 }
286 }
287 static void spacial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
288 int x,y;
289
290 for(y=0;y<8;y++){
291 for(x=0;x<8;x++){
292 dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
293 }
294 dst+=linesize;
295 }
296 }
297 static void spacial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
298 int x,y;
299
300 for(y=0;y<8;y++){
301 for(x=0;x<8;x++){
302 dst[x]=src[area2+6-FFMIN(x+y,6)];
303 }
304 dst+=linesize;
305 }
306 }
307 static void spacial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
308 int x,y;
309
310 for(y=0;y<8;y++){
311 for(x=0;x<8;x++){
312 dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
313 }
314 dst+=linesize;
315 }
316 }
317 static void spacial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
318 int x,y;
319
320 for(y=0;y<8;y++){
321 for(x=0;x<8;x++){
322 dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
323 }
324 dst+=linesize;
325 }
326 }
327
328 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
329 int i,t;
330 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
331 int ql=(quant+10)>>3;
332
333 for(i=0; i<8; i++,ptr+=b_stride){
334 p0=ptr[-5*a_stride];
335 p1=ptr[-4*a_stride];
336 p2=ptr[-3*a_stride];
337 p3=ptr[-2*a_stride];
338 p4=ptr[-1*a_stride];
339 p5=ptr[ 0 ];
340 p6=ptr[ 1*a_stride];
341 p7=ptr[ 2*a_stride];
342 p8=ptr[ 3*a_stride];
343 p9=ptr[ 4*a_stride];
344
345 t=
346 (FFABS(p1-p2) <= ql) +
347 (FFABS(p2-p3) <= ql) +
348 (FFABS(p3-p4) <= ql) +
349 (FFABS(p4-p5) <= ql);
350 if(t>0){//you need at least 1 to be able to reach total score of 6.
351 t+=
352 (FFABS(p5-p6) <= ql) +
353 (FFABS(p6-p7) <= ql) +
354 (FFABS(p7-p8) <= ql) +
355 (FFABS(p8-p9) <= ql) +
356 (FFABS(p0-p1) <= ql);
357 if(t>=6){
358 int min,max;
359
360 min=max=p1;
361 min=FFMIN(min,p3); max=FFMAX(max,p3);
362 min=FFMIN(min,p5); max=FFMAX(max,p5);
363 min=FFMIN(min,p8); max=FFMAX(max,p8);
364 if(max-min<2*quant){//early stop
365 min=FFMIN(min,p2); max=FFMAX(max,p2);
366 min=FFMIN(min,p4); max=FFMAX(max,p4);
367 min=FFMIN(min,p6); max=FFMAX(max,p6);
368 min=FFMIN(min,p7); max=FFMAX(max,p7);
369 if(max-min<2*quant){
370 ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
371 ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
372 ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
373 ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
374 continue;
375 };
376 }
377 }
378 }
379 {
380 int x,x0,x1,x2;
381 int m;
382
383 x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
384 if(FFABS(x0) < quant){
385 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
386 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
387
388 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
389 m=p4-p5;
390
391 if( x > 0 && (m^x0) <0){
392 int32_t sign;
393
394 sign=m>>31;
395 m=(m^sign)-sign;//abs(m)
396 m>>=1;
397
398 x=(5*x)>>3;
399
400 if(x>m) x=m;
401
402 x=(x^sign)-sign;
403
404 ptr[-1*a_stride] -= x;
405 ptr[ 0] += x;
406 }
407 }
408 }
409 }
410 }
411
412 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
413 x8_loop_filter(src, stride, 1, qscale);
414 }
415
416 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
417 x8_loop_filter(src, 1, stride, qscale);
418 }
419
420 void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
421 dsp->x8_h_loop_filter=x8_h_loop_filter;
422 dsp->x8_v_loop_filter=x8_v_loop_filter;
423 dsp->x8_setup_spacial_compensation=x8_setup_spacial_compensation;
424 dsp->x8_spacial_compensation[0]=spacial_compensation_0;
425 dsp->x8_spacial_compensation[1]=spacial_compensation_1;
426 dsp->x8_spacial_compensation[2]=spacial_compensation_2;
427 dsp->x8_spacial_compensation[3]=spacial_compensation_3;
428 dsp->x8_spacial_compensation[4]=spacial_compensation_4;
429 dsp->x8_spacial_compensation[5]=spacial_compensation_5;
430 dsp->x8_spacial_compensation[6]=spacial_compensation_6;
431 dsp->x8_spacial_compensation[7]=spacial_compensation_7;
432 dsp->x8_spacial_compensation[8]=spacial_compensation_8;
433 dsp->x8_spacial_compensation[9]=spacial_compensation_9;
434 dsp->x8_spacial_compensation[10]=spacial_compensation_10;
435 dsp->x8_spacial_compensation[11]=spacial_compensation_11;
436 }
437
438 #if 0
439 static void wmv2_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
440 int i,t;
441 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
442
443 for(i=0; i<8; i++,ptr+=b_stride){
444 p1=ptr[-4*a_stride];
445 p2=ptr[-3*a_stride];
446 p3=ptr[-2*a_stride];
447 p4=ptr[-1*a_stride];
448 p5=ptr[ 0 ];
449 p6=ptr[ 1*a_stride];
450 p7=ptr[ 2*a_stride];
451 p8=ptr[ 3*a_stride];
452
453 {
454 int x,x0,x1,x2;
455 int m;
456
457 x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
458 if(abs(x0) < quant){
459 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
460 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
461
462 x=abs(x0) - FFMIN( abs(x1), abs(x2) );
463 m=p4-p5;
464
465 if( x > 0 && (m^x0) < 0){
466 int32_t sign;
467
468 sign=m>>31;
469 m=(m^sign)-sign;//abs(m)
470 m>>=1;
471
472 x=(5*x)>>3;
473
474 if(x>m) x=m;
475
476 x=(x^sign)-sign;
477
478 ptr[-1*a_stride] -= x;
479 ptr[ 0] += x;
480 }
481 }
482 }
483 }
484 }
485 #endif