FFmpeg
 All Data Structures Namespaces 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 "intrax8dsp.h"
25 #include "libavutil/common.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 spatial 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 the way other compensation routines do.
55  * @param linesize byte offset between 2 vertical pixels in the source image
56  * @param range pointer to the variable where the edge pixel range is to be stored (max-min values)
57  * @param psum pointer to the variable where the edge pixel sum is to be stored
58  * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels.
59  and some of the edge pixels should be interpolated, the flag has the 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 in the row, interpolate area #5;
64 */
65 static void x8_setup_spatial_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 calculate 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 spatial_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] = { { 0 } };
157  uint16_t top_sum[2][8] = { { 0 } };
158 
159  for(i=0;i<8;i++){
160  a=src[area2+7-i]<<4;
161  for(j=0;j<8;j++){
162  p=abs(i-j);
163  left_sum[p&1][j]+= a>>(p>>1);
164  }
165  }
166 
167  for(i=0;i<8;i++){
168  a=src[area4+i]<<4;
169  for(j=0;j<8;j++){
170  p=abs(i-j);
171  top_sum[p&1][j]+= a>>(p>>1);
172  }
173  }
174  for(;i<10;i++){
175  a=src[area4+i]<<4;
176  for(j=5;j<8;j++){
177  p=abs(i-j);
178  top_sum[p&1][j]+= a>>(p>>1);
179  }
180  }
181  for(;i<12;i++){
182  a=src[area4+i]<<4;
183  for(j=7;j<8;j++){
184  p=abs(i-j);
185  top_sum[p&1][j]+= a>>(p>>1);
186  }
187  }
188 
189  for(i=0;i<8;i++){
190  top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
191  left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
192  }
193  for(y=0;y<8;y++){
194  for(x=0;x<8;x++){
195  dst[x] = (
196  (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
197  (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
198  0x8000
199  )>>16;
200  }
201  dst+=linesize;
202  }
203 }
204 static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
205  int x,y;
206 
207  for(y=0;y<8;y++){
208  for(x=0;x<8;x++){
209  dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
210  }
211  dst+=linesize;
212  }
213 }
214 static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
215  int x,y;
216 
217  for(y=0;y<8;y++){
218  for(x=0;x<8;x++){
219  dst[x]=src[area4 +1+y+x];
220  }
221  dst+=linesize;
222  }
223 }
224 static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
225  int x,y;
226 
227  for(y=0;y<8;y++){
228  for(x=0;x<8;x++){
229  dst[x]=src[area4 +((y+1)>>1)+x];
230  }
231  dst+=linesize;
232  }
233 }
234 static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
235  int x,y;
236 
237  for(y=0;y<8;y++){
238  for(x=0;x<8;x++){
239  dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
240  }
241  dst+=linesize;
242  }
243 }
244 static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
245  int x,y;
246 
247  for(y=0;y<8;y++){
248  for(x=0;x<8;x++){
249  if(2*x-y<0){
250  dst[x]=src[area2+9+2*x-y];
251  }else{
252  dst[x]=src[area4 +x-((y+1)>>1)];
253  }
254  }
255  dst+=linesize;
256  }
257 }
258 static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
259  int x,y;
260 
261  for(y=0;y<8;y++){
262  for(x=0;x<8;x++){
263  dst[x]=src[area3+x-y];
264  }
265  dst+=linesize;
266  }
267 }
268 static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
269  int x,y;
270 
271  for(y=0;y<8;y++){
272  for(x=0;x<8;x++){
273  if(x-2*y>0){
274  dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
275  }else{
276  dst[x]=src[area2+8-y +(x>>1)];
277  }
278  }
279  dst+=linesize;
280  }
281 }
282 static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
283  int x,y;
284 
285  for(y=0;y<8;y++){
286  for(x=0;x<8;x++){
287  dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
288  }
289  dst+=linesize;
290  }
291 }
292 static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
293  int x,y;
294 
295  for(y=0;y<8;y++){
296  for(x=0;x<8;x++){
297  dst[x]=src[area2+6-FFMIN(x+y,6)];
298  }
299  dst+=linesize;
300  }
301 }
302 static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
303  int x,y;
304 
305  for(y=0;y<8;y++){
306  for(x=0;x<8;x++){
307  dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
308  }
309  dst+=linesize;
310  }
311 }
312 static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
313  int x,y;
314 
315  for(y=0;y<8;y++){
316  for(x=0;x<8;x++){
317  dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
318  }
319  dst+=linesize;
320  }
321 }
322 
323 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
324  int i,t;
325  int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
326  int ql=(quant+10)>>3;
327 
328  for(i=0; i<8; i++,ptr+=b_stride){
329  p0=ptr[-5*a_stride];
330  p1=ptr[-4*a_stride];
331  p2=ptr[-3*a_stride];
332  p3=ptr[-2*a_stride];
333  p4=ptr[-1*a_stride];
334  p5=ptr[ 0 ];
335  p6=ptr[ 1*a_stride];
336  p7=ptr[ 2*a_stride];
337  p8=ptr[ 3*a_stride];
338  p9=ptr[ 4*a_stride];
339 
340  t=
341  (FFABS(p1-p2) <= ql) +
342  (FFABS(p2-p3) <= ql) +
343  (FFABS(p3-p4) <= ql) +
344  (FFABS(p4-p5) <= ql);
345  if(t>0){//You need at least 1 to be able to reach a total score of 6.
346  t+=
347  (FFABS(p5-p6) <= ql) +
348  (FFABS(p6-p7) <= ql) +
349  (FFABS(p7-p8) <= ql) +
350  (FFABS(p8-p9) <= ql) +
351  (FFABS(p0-p1) <= ql);
352  if(t>=6){
353  int min,max;
354 
355  min=max=p1;
356  min=FFMIN(min,p3); max=FFMAX(max,p3);
357  min=FFMIN(min,p5); max=FFMAX(max,p5);
358  min=FFMIN(min,p8); max=FFMAX(max,p8);
359  if(max-min<2*quant){//early stop
360  min=FFMIN(min,p2); max=FFMAX(max,p2);
361  min=FFMIN(min,p4); max=FFMAX(max,p4);
362  min=FFMIN(min,p6); max=FFMAX(max,p6);
363  min=FFMIN(min,p7); max=FFMAX(max,p7);
364  if(max-min<2*quant){
365  ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
366  ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
367  ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
368  ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
369  continue;
370  };
371  }
372  }
373  }
374  {
375  int x,x0,x1,x2;
376  int m;
377 
378  x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
379  if(FFABS(x0) < quant){
380  x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
381  x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
382 
383  x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
384  m=p4-p5;
385 
386  if( x > 0 && (m^x0) <0){
387  int32_t sign;
388 
389  sign=m>>31;
390  m=(m^sign)-sign;//abs(m)
391  m>>=1;
392 
393  x=(5*x)>>3;
394 
395  if(x>m) x=m;
396 
397  x=(x^sign)-sign;
398 
399  ptr[-1*a_stride] -= x;
400  ptr[ 0] += x;
401  }
402  }
403  }
404  }
405 }
406 
407 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
408  x8_loop_filter(src, stride, 1, qscale);
409 }
410 
411 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
412  x8_loop_filter(src, 1, stride, qscale);
413 }
414 
416 {
432 }