intrax8dsp.c
Go to the documentation of this file.
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 
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 
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];
156  uint16_t top_sum[2][8];
157  memset(left_sum,0,2*8*sizeof(uint16_t));
158  memset( top_sum,0,2*8*sizeof(uint16_t));
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 
432 }