factorize
[libav.git] / libavcodec / intrax8dsp.c
CommitLineData
9abc7e0f
MN
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/*
28area positions, #3 is 1 pixel only, other are 8 pixels
29 |66666666|
30 3|44444444|55555555|
31- -+--------+--------+
321 2|XXXXXXXX|
331 2|XXXXXXXX|
341 2|XXXXXXXX|
351 2|XXXXXXXX|
361 2|XXXXXXXX|
371 2|XXXXXXXX|
381 2|XXXXXXXX|
391 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*/
65static 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){
29160257 121 int avg=(sum+4)>>3;
9abc7e0f 122 if(edges&1){ //(mb_x==0) {//implies mb_y!=0
9abc7e0f 123 memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged
9abc7e0f 124 }else{//implies y==0 x!=0
9abc7e0f 125 memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6
9abc7e0f 126 }
29160257 127 sum+=avg*9;
9abc7e0f
MN
128 }else{
129 uint8_t c;
130 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
141static 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
152static void spacial_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];
158 uint16_t top_sum[2][8];
159 memset(left_sum,0,2*8*sizeof(uint16_t));
160 memset( top_sum,0,2*8*sizeof(uint16_t));
161
162 for(i=0;i<8;i++){
163 a=src[area2+7-i]<<4;
164 for(j=0;j<8;j++){
165 p=abs(i-j);
166 left_sum[p&1][j]+= a>>(p>>1);
167 }
168 }
169
170 for(i=0;i<8;i++){
171 a=src[area4+i]<<4;
172 for(j=0;j<8;j++){
173 p=abs(i-j);
174 top_sum[p&1][j]+= a>>(p>>1);
175 }
176 }
177 for(;i<10;i++){
178 a=src[area4+i]<<4;
179 for(j=5;j<8;j++){
180 p=abs(i-j);
181 top_sum[p&1][j]+= a>>(p>>1);
182 }
183 }
184 for(;i<12;i++){
185 a=src[area4+i]<<4;
186 for(j=7;j<8;j++){
187 p=abs(i-j);
188 top_sum[p&1][j]+= a>>(p>>1);
189 }
190 }
191
192 for(i=0;i<8;i++){
193 top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
194 left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
195 }
196 for(y=0;y<8;y++){
197 for(x=0;x<8;x++){
198 dst[x] = (
199 (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
200 (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
201 0x8000
202 )>>16;
203 }
204 dst+=linesize;
205 }
206}
207static void spacial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
208 int x,y;
209
210 for(y=0;y<8;y++){
211 for(x=0;x<8;x++){
212 dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
213 }
214 dst+=linesize;
215 }
216}
217static void spacial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
218 int x,y;
219
220 for(y=0;y<8;y++){
221 for(x=0;x<8;x++){
222 dst[x]=src[area4 +1+y+x];
223 }
224 dst+=linesize;
225 }
226}
227static void spacial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
228 int x,y;
229
230 for(y=0;y<8;y++){
231 for(x=0;x<8;x++){
232 dst[x]=src[area4 +((y+1)>>1)+x];
233 }
234 dst+=linesize;
235 }
236}
237static void spacial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
238 int x,y;
239
240 for(y=0;y<8;y++){
241 for(x=0;x<8;x++){
242 dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
243 }
244 dst+=linesize;
245 }
246}
247static void spacial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
248 int x,y;
249
250 for(y=0;y<8;y++){
251 for(x=0;x<8;x++){
252 if(2*x-y<0){
253 dst[x]=src[area2+9+2*x-y];
254 }else{
255 dst[x]=src[area4 +x-((y+1)>>1)];
256 }
257 }
258 dst+=linesize;
259 }
260}
261static void spacial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
262 int x,y;
263
264 for(y=0;y<8;y++){
265 for(x=0;x<8;x++){
266 dst[x]=src[area3+x-y];
267 }
268 dst+=linesize;
269 }
270}
271static void spacial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
272 int x,y;
273
274 for(y=0;y<8;y++){
275 for(x=0;x<8;x++){
276 if(x-2*y>0){
277 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
278 }else{
279 dst[x]=src[area2+8-y +(x>>1)];
280 }
281 }
282 dst+=linesize;
283 }
284}
285static void spacial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
286 int x,y;
287
288 for(y=0;y<8;y++){
289 for(x=0;x<8;x++){
290 dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
291 }
292 dst+=linesize;
293 }
294}
295static void spacial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
296 int x,y;
297
298 for(y=0;y<8;y++){
299 for(x=0;x<8;x++){
300 dst[x]=src[area2+6-FFMIN(x+y,6)];
301 }
302 dst+=linesize;
303 }
304}
305static void spacial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
306 int x,y;
307
308 for(y=0;y<8;y++){
309 for(x=0;x<8;x++){
310 dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
311 }
312 dst+=linesize;
313 }
314}
315static void spacial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
316 int x,y;
317
318 for(y=0;y<8;y++){
319 for(x=0;x<8;x++){
320 dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
321 }
322 dst+=linesize;
323 }
324}
325
326static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
327 int i,t;
328 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
329 int ql=(quant+10)>>3;
330
331 for(i=0; i<8; i++,ptr+=b_stride){
332 p0=ptr[-5*a_stride];
333 p1=ptr[-4*a_stride];
334 p2=ptr[-3*a_stride];
335 p3=ptr[-2*a_stride];
336 p4=ptr[-1*a_stride];
337 p5=ptr[ 0 ];
338 p6=ptr[ 1*a_stride];
339 p7=ptr[ 2*a_stride];
340 p8=ptr[ 3*a_stride];
341 p9=ptr[ 4*a_stride];
342
343 t=
344 (FFABS(p1-p2) <= ql) +
345 (FFABS(p2-p3) <= ql) +
346 (FFABS(p3-p4) <= ql) +
347 (FFABS(p4-p5) <= ql);
348 if(t>0){//you need at least 1 to be able to reach total score of 6.
349 t+=
350 (FFABS(p5-p6) <= ql) +
351 (FFABS(p6-p7) <= ql) +
352 (FFABS(p7-p8) <= ql) +
353 (FFABS(p8-p9) <= ql) +
354 (FFABS(p0-p1) <= ql);
355 if(t>=6){
356 int min,max;
357
358 min=max=p1;
359 min=FFMIN(min,p3); max=FFMAX(max,p3);
360 min=FFMIN(min,p5); max=FFMAX(max,p5);
361 min=FFMIN(min,p8); max=FFMAX(max,p8);
362 if(max-min<2*quant){//early stop
363 min=FFMIN(min,p2); max=FFMAX(max,p2);
364 min=FFMIN(min,p4); max=FFMAX(max,p4);
365 min=FFMIN(min,p6); max=FFMAX(max,p6);
366 min=FFMIN(min,p7); max=FFMAX(max,p7);
367 if(max-min<2*quant){
368 ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
369 ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
370 ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
371 ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
372 continue;
373 };
374 }
375 }
376 }
377 {
378 int x,x0,x1,x2;
379 int m;
380
381 x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
382 if(FFABS(x0) < quant){
383 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
384 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
385
386 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
387 m=p4-p5;
388
389 if( x > 0 && (m^x0) <0){
390 int32_t sign;
391
392 sign=m>>31;
393 m=(m^sign)-sign;//abs(m)
394 m>>=1;
395
396 x=(5*x)>>3;
397
398 if(x>m) x=m;
399
400 x=(x^sign)-sign;
401
402 ptr[-1*a_stride] -= x;
403 ptr[ 0] += x;
404 }
405 }
406 }
407 }
408}
409
410static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
411 x8_loop_filter(src, stride, 1, qscale);
412}
413
414static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
415 x8_loop_filter(src, 1, stride, qscale);
416}
417
418void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
419 dsp->x8_h_loop_filter=x8_h_loop_filter;
420 dsp->x8_v_loop_filter=x8_v_loop_filter;
421 dsp->x8_setup_spacial_compensation=x8_setup_spacial_compensation;
422 dsp->x8_spacial_compensation[0]=spacial_compensation_0;
423 dsp->x8_spacial_compensation[1]=spacial_compensation_1;
424 dsp->x8_spacial_compensation[2]=spacial_compensation_2;
425 dsp->x8_spacial_compensation[3]=spacial_compensation_3;
426 dsp->x8_spacial_compensation[4]=spacial_compensation_4;
427 dsp->x8_spacial_compensation[5]=spacial_compensation_5;
428 dsp->x8_spacial_compensation[6]=spacial_compensation_6;
429 dsp->x8_spacial_compensation[7]=spacial_compensation_7;
430 dsp->x8_spacial_compensation[8]=spacial_compensation_8;
431 dsp->x8_spacial_compensation[9]=spacial_compensation_9;
432 dsp->x8_spacial_compensation[10]=spacial_compensation_10;
433 dsp->x8_spacial_compensation[11]=spacial_compensation_11;
434}
435
436#if 0
437static void wmv2_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
438 int i,t;
439 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
440
441 for(i=0; i<8; i++,ptr+=b_stride){
442 p1=ptr[-4*a_stride];
443 p2=ptr[-3*a_stride];
444 p3=ptr[-2*a_stride];
445 p4=ptr[-1*a_stride];
446 p5=ptr[ 0 ];
447 p6=ptr[ 1*a_stride];
448 p7=ptr[ 2*a_stride];
449 p8=ptr[ 3*a_stride];
450
451 {
452 int x,x0,x1,x2;
453 int m;
454
455 x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
456 if(abs(x0) < quant){
457 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
458 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
459
460 x=abs(x0) - FFMIN( abs(x1), abs(x2) );
461 m=p4-p5;
462
463 if( x > 0 && (m^x0) < 0){
464 int32_t sign;
465
466 sign=m>>31;
467 m=(m^sign)-sign;//abs(m)
468 m>>=1;
469
470 x=(5*x)>>3;
471
472 if(x>m) x=m;
473
474 x=(x^sign)-sign;
475
476 ptr[-1*a_stride] -= x;
477 ptr[ 0] += x;
478 }
479 }
480 }
481 }
482}
483#endif