669923d9da75df254dcd7efb83b83b86b569fb27
[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 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