FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
intrax8dsp.c
Go to the documentation of this file.
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
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 
417 {
433 }