]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/postprocessing/postprocessing_c.c
f77624cc3c7d8b9d73f7520dc7f50d7c338cf047
[vlc] / modules / codec / ffmpeg / postprocessing / postprocessing_c.c
1 /*****************************************************************************
2  * postprocessing_c.c: Post Processing plugin in C
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: postprocessing_c.c,v 1.1 2002/08/04 22:13:06 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <vlc/vlc.h> /* only use u8, u32 .... */
25
26 #include "postprocessing.h"
27 #include "postprocessing_common.h"
28
29 /*****************************************************************************
30  *
31  * Internals functions common to pp_deblock_V and pp_deblock_H
32  *
33  *****************************************************************************/
34
35 /****************************************************************************
36  * pp_deblock_isDC_mode : Check if we will use DC mode or Default mode
37  ****************************************************************************
38  * Use constant PP_THR1 and PP_THR2 ( PP_2xTHR1 )
39  *
40  * Called for for each pixel on a boundary block when doing deblocking
41  *  so need to be fast ...
42  *
43  ****************************************************************************/
44 static inline int pp_deblock_isDC_mode( u8 *p_v )
45 {
46     int i_eq_cnt;
47
48     /* algo :  if ( | v[i] -v[i+1] | <= PP_THR1 ) { i_eq_cnt++; } */
49     i_eq_cnt = 0;
50     if((  ( p_v[0] - p_v[1] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
51     if((  ( p_v[1] - p_v[2] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
52     if((  ( p_v[2] - p_v[3] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
53     if((  ( p_v[3] - p_v[4] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
54     if((  ( p_v[4] - p_v[5] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
55     if((  ( p_v[5] - p_v[6] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
56     if((  ( p_v[6] - p_v[7] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
57     if((  ( p_v[7] - p_v[8] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
58     if((  ( p_v[8] - p_v[9] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
59
60 #if 0
61     int i;
62     for( i =0; i < 9; i++ )
63     {
64         if((  ( p_v[i] - p_v[i+1] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) 
65         {   
66             i_eq_cnt++;
67         }
68     }
69 #endif
70     return( (i_eq_cnt >= PP_THR2 ) ? 1 : 0 );
71 }
72
73 static inline int pp_deblock_isMinMaxOk( u8 *p_v, int i_QP )
74 {
75     int i_max, i_min;
76
77     i_min = i_max = p_v[1];  
78     if( i_max < p_v[1] ) i_max = p_v[1];
79     if( i_min > p_v[1] ) i_min = p_v[1];
80     if( i_max < p_v[2] ) i_max = p_v[2];
81     if( i_min > p_v[2] ) i_min = p_v[2];
82     if( i_max < p_v[3] ) i_max = p_v[3];
83     if( i_min > p_v[3] ) i_min = p_v[3];
84     if( i_max < p_v[4] ) i_max = p_v[4];
85     if( i_min > p_v[4] ) i_min = p_v[4];
86     if( i_max < p_v[5] ) i_max = p_v[5];
87     if( i_min > p_v[5] ) i_min = p_v[5];
88     if( i_max < p_v[6] ) i_max = p_v[6];
89     if( i_min > p_v[6] ) i_min = p_v[6];
90     if( i_max < p_v[7] ) i_max = p_v[7];
91     if( i_min > p_v[7] ) i_min = p_v[7];
92     if( i_max < p_v[8] ) i_max = p_v[8];
93     if( i_min > p_v[8] ) i_min = p_v[8];
94
95 #if 0
96     int i;
97     int i_range;
98     for( i = 2; i < 9; i++ )
99     {
100         if( i_max < p_v[i] ) i_max = p_v[i];
101         if( i_min > p_v[i] ) i_min = p_v[i];
102     }
103     i_range = i_max - i_min;
104 #endif
105     return( i_max - i_min < 2*i_QP ? 1 : 0 );
106 }
107
108
109 static inline void pp_deblock_DefaultMode( u8 i_v[10], int i_stride,
110                                       int i_QP )
111 {
112     int d, i_delta;
113     int a3x0, a3x0_, a3x1, a3x2;
114     int b_neg;
115
116     /* d = CLIP( 5(a3x0' - a3x0)//8, 0, (v4-v5)/2 ).d( abs(a3x0) < QP ) */
117
118     /* First calculate a3x0 */
119     a3x0 = 2 * ( i_v[3] - i_v[6] ) + 5 *( i_v[5] - i_v[4] );
120
121     if( a3x0 < 0 )
122     {
123         b_neg = 1;
124         a3x0  = -a3x0;
125     } 
126     else
127     {
128         b_neg = 0;
129     }
130     /* XXX Now a3x0 is abs( a3x0 ) */
131     if( ( a3x0 < 8 * i_QP )&&( a3x0 != 0 ) ) /* |a3x0| < 8*i_QP */
132     {
133         /* calculate a3x1 et a3x2 */
134         a3x1 = 2 * ( i_v[1] - i_v[4] ) + 5 * ( i_v[3] - i_v[2] );
135         a3x2 = 2 * ( i_v[5] - i_v[8] ) + 5 * ( i_v[7] - i_v[6] );
136
137         if( a3x1 < 0) a3x1 = -a3x1; /* abs( a3x1 ) */
138         if( a3x2 < 0) a3x2 = -a3x2; /* abs( a3x2 ) */
139
140         a3x0_ = PP_MIN3( a3x0, a3x1, a3x2 );
141         
142         d = 5 *( a3x0 - a3x0_ ) / 8; /* always > 0 */
143
144         i_delta = ( i_v[4] - i_v[5] ) / 2;
145         /* clip into [0, i_delta] or [i_delta, 0] */
146         if( i_delta < 0 )
147         {
148             if( !b_neg ) /* since true d has sgn(d) = - sgn( a3x0 ) */
149             {
150                 d = -d;
151                 if( d < i_delta ) d = i_delta;
152                 i_v[4] -= d;
153                 i_v[5] += d;
154             }
155         }
156         else
157         {
158             if( b_neg )
159             {
160                 if( d > i_delta ) d = i_delta;
161                 i_v[4] -= d;
162                 i_v[5] += d;
163             }
164         }
165     }
166 }
167
168
169
170 static inline void pp_deblock_DCMode( u8 *p_v, /*  = int i_v[10] */
171                                  int i_QP )
172 {
173     int v[10];
174
175     int i;
176     
177     int i_p0, i_p9;
178     i_p0 = PP_ABS( p_v[1] - p_v[0] ) < i_QP ? p_v[0] : p_v[1];
179     i_p9 = PP_ABS( p_v[8] - p_v[9] ) < i_QP ? p_v[9] : p_v[8];
180
181     for( i = 1; i < 9; i++ )
182     {
183         v[i] = p_v[i]; /* save 8 pix that will be modified */
184     }
185
186     p_v[1] = ( 6 * i_p0                        + 4 * v[1] 
187                 + 2 *( v[2] + v[3]) + v[4] + v[5]) >> 4;
188     
189     p_v[2] = ( 4 * i_p0    + 2 * v[1]          + 4 * v[2] 
190                 + 2 *( v[3] + v[4]) + v[5] + v[6]) >> 4;
191
192     p_v[3] = ( 2 * i_p0    + 2 * (v[1] + v[2]) + 4 * v[3] 
193                 + 2 *( v[4] + v[5]) + v[6] + v[7]) >> 4;
194
195     p_v[4] = ( i_p0 + v[1] + 2 * (v[2] + v[3]) + 4 * v[4] 
196                 + 2 *( v[5] + v[6]) + v[7] + v[8]) >> 4;
197
198     p_v[5] = ( v[1] + v[2] + 2 * (v[3] + v[4]) + 4 * v[5] 
199                 + 2 *( v[6] + v[7]) + v[8] + i_p9) >> 4;
200
201     p_v[6] = ( v[2] + v[3] + 2 * (v[4] + v[5]) + 4 * v[6] 
202             + 2 *( v[7] + v[8]) + 2 * i_p9) >> 4;
203
204     p_v[7] = ( v[3] + v[4] + 2 * (v[5] + v[6]) + 4 * v[7] 
205                 + 2 * v[8] + 4 * i_p9) >> 4;
206
207     p_v[8] = ( v[4] + v[5] + 2 * (v[6] + v[7]) + 4 * v[8] 
208                                     + 6 * i_p9) >> 4;
209
210 }
211
212
213
214 /*****************************************************************************/
215 /*---------------------------------------------------------------------------*/
216 /*                                                                           */
217 /*    ---------- filter Vertical lines so follow horizontal edges --------   */
218 /*                                                                           */
219 /*---------------------------------------------------------------------------*/
220 /*****************************************************************************/
221
222 void E_( pp_deblock_V )( u8 *p_plane, 
223                          int i_width, int i_height, int i_stride,
224                          QT_STORE_T *p_QP_store, int i_QP_stride,
225                          int b_chroma )
226 {
227     int x, y, i;
228     u8 *p_v;
229     int i_QP_scale; /* use to do ( ? >> i_QP_scale ) */
230     int i_QP;
231     
232     u8 i_v[10];
233     
234     i_QP_scale = b_chroma ? 5 : 4 ;
235
236     for( y = 8; y < i_height - 4; y += 8 ) 
237     {
238         p_v = p_plane + ( y - 5 )* i_stride;
239         for( x = 0; x < i_width; x++ )
240         {
241             /* First get  10 vert pix to use them without i_stride */
242             for( i = 0; i < 10; i++ )
243             {
244                 i_v[i] = p_v[i*i_stride + x];
245             }
246
247             i_QP = p_QP_store[(y>>i_QP_scale)*i_QP_stride+
248                                 (x>>i_QP_scale)];
249             /* XXX QP is for v5 */
250             if( pp_deblock_isDC_mode( i_v ) )
251             {
252                 if( pp_deblock_isMinMaxOk( i_v, i_QP ) )
253                 {
254                     pp_deblock_DCMode( i_v, i_QP );
255                 }
256             }
257             else
258             {
259                 pp_deblock_DefaultMode( i_v, i_stride, i_QP );
260
261             }
262             /* Copy back, XXX only 1-8 were modified */
263             for( i = 1; i < 9; i++ )
264             {
265                 p_v[i*i_stride + x] = i_v[i];
266             }
267
268         }
269     }
270
271     return;
272 }
273 /*****************************************************************************/
274 /*---------------------------------------------------------------------------*/
275 /*                                                                           */
276 /*     --------- filter Horizontal lines so follow vertical edges --------   */
277 /*                                                                           */
278 /*---------------------------------------------------------------------------*/
279 /*****************************************************************************/
280
281 void E_( pp_deblock_H )( u8 *p_plane, 
282                          int i_width, int i_height, int i_stride,
283                          QT_STORE_T *p_QP_store, int i_QP_stride,
284                          int b_chroma )
285 {
286     int x, y;
287     u8 *p_v;
288     int i_QP_scale;
289     int i_QP;
290     
291     i_QP_scale = b_chroma ? 5 : 4 ;
292
293     for( y = 0; y < i_height; y++ ) 
294     {
295         p_v = p_plane + y * i_stride - 5;
296         for( x = 8; x < i_width - 4; x += 8 ) 
297         {
298             /* p_v point 5 pix before a block boundary */
299             /* XXX QP is for v5 */
300             i_QP = p_QP_store[(y>>i_QP_scale)*i_QP_stride+
301                                  (x>>i_QP_scale)];
302             if( pp_deblock_isDC_mode( p_v + x ) )
303             {
304                 if( pp_deblock_isMinMaxOk( p_v+ x, i_QP ) )
305                 {
306                     pp_deblock_DCMode( p_v+x, i_QP );
307                 }
308             }
309             else
310             {
311                 pp_deblock_DefaultMode( p_v+x, i_stride, i_QP );
312             }
313         }
314     }
315             
316     return;
317 }
318
319
320 /*****************************************************************************
321  *
322  * Internals functions common to pp_Dering_Y pp_Dering_C
323  *
324  *****************************************************************************/
325
326 static inline void pp_dering_MinMax( u8 *p_block, int i_stride,
327                                      int *pi_min, int *pi_max )
328 {
329     int y;
330     int i_min, i_max;
331
332     i_min = 255; i_max = 0;
333     
334     for( y = 0; y < 8; y++ )
335     {
336         if( i_min > p_block[0] ) i_min = p_block[0];
337         if( i_max < p_block[0] ) i_max = p_block[0];
338         if( i_min > p_block[1] ) i_min = p_block[1];
339         if( i_max < p_block[1] ) i_max = p_block[1];
340         if( i_min > p_block[2] ) i_min = p_block[2];
341         if( i_max < p_block[2] ) i_max = p_block[2];
342         if( i_min > p_block[3] ) i_min = p_block[3];
343         if( i_max < p_block[3] ) i_max = p_block[3];
344         if( i_min > p_block[4] ) i_min = p_block[4];
345         if( i_max < p_block[4] ) i_max = p_block[4];
346         if( i_min > p_block[5] ) i_min = p_block[5];
347         if( i_max < p_block[5] ) i_max = p_block[5];
348         if( i_min > p_block[6] ) i_min = p_block[6];
349         if( i_max < p_block[6] ) i_max = p_block[6];
350         if( i_min > p_block[7] ) i_min = p_block[7];
351         if( i_max < p_block[7] ) i_max = p_block[7];
352 #if 0
353         int x;
354         for( x = 0; x < 8; x++ )
355         {
356             if( i_min > p_block[x] ) i_min = p_block[x];
357             if( i_max < p_block[x] ) i_max = p_block[x];
358         }
359 #endif
360         p_block += i_stride;
361     }
362             
363     *pi_min = i_min;
364     *pi_max = i_max;
365 }
366
367
368 static inline void pp_dering_BinIndex( u8  *p_block, int i_stride, int i_thr,
369                                        u32 *p_bin )
370 {
371     int x, y;
372     u32 i_bin;
373
374     for( y = 0; y < 10; y++ )
375     {
376         i_bin = 0;
377         for( x = 0; x < 10; x++ )
378         {
379             if( p_block[x] > i_thr )
380             {
381                 i_bin |= 1 << x;
382             }
383         }
384         i_bin |= (~i_bin) << 16;  /* for detect also three 0 */
385         *p_bin = i_bin&( i_bin >> 1 )&( i_bin << 1 );
386
387         p_block += i_stride;
388         p_bin++;
389     }
390 }
391
392 static inline void pp_dering_Filter( u8  *p_block, int i_stride,
393                                      u32 *p_bin,
394                                      int i_QP )
395 {
396     int x, y;
397     u32 i_bin;
398     int i_flt[8][8];
399     int i_f;
400     u8 *p_sav;
401     int i_QP_2;
402     
403     p_sav = p_block;
404     i_QP_2 = i_QP >> 1;
405     
406     for( y = 0; y < 8; y++ )
407     {
408         i_bin = p_bin[y] & p_bin[y+1] & p_bin[y+2]; /* To be optimised */
409         i_bin |= i_bin >> 16; /* detect 0 or 1 */
410
411         for( x = 0; x < 8; x++ )
412         {       
413             if( i_bin&0x02 ) /* 0x02 since 10 index but want 1-9 */
414             {
415                 /* apply dering */
416                 /* 1 2 1
417                    2 4 2   + (8)
418                    1 2 1 */
419                 i_f =   p_block[x - i_stride - 1] +
420                       ( p_block[x - i_stride    ] << 1)+
421                         p_block[x - i_stride + 1] +
422                       
423                       ( p_block[x - 1] << 1 )+
424                       ( p_block[x    ] << 2 )+
425                       ( p_block[x + 1] << 1 )+
426                       
427                         p_block[x + i_stride - 1] +
428                       ( p_block[x + i_stride    ] << 1 ) +
429                         p_block[x + i_stride + 1];
430
431                 i_f = ( 8 + i_f ) >> 4;
432
433                 /* Clamp this value */
434
435                 if( i_f - p_block[x] > ( i_QP_2 ) )
436                 {
437                     i_flt[y][x] = p_block[x] + i_QP_2;
438                 }
439                 else
440                 if( i_f - p_block[x] < -i_QP_2 )
441                 {
442                     i_flt[y][x] = p_block[x] - i_QP_2;
443                 }
444                 else
445                 {
446                     i_flt[y][x] = i_f ; 
447                 }
448             }
449             else
450             {
451                 i_flt[y][x] = p_block[x];
452             }
453             i_bin >>= 1;
454  
455         }
456         p_block += i_stride;
457     }
458     for( y = 0; y < 8; y++ )
459     {
460         for( x = 0; x < 8; x++ )
461         {
462             p_sav[x] = i_flt[y][x];
463         }
464         p_sav+= i_stride;
465     }
466 }
467
468
469 /*****************************************************************************/
470 /*---------------------------------------------------------------------------*/
471 /*                                                                           */
472 /*     ----------------- Dering filter on Y and C blocks -----------------   */
473 /*                                                                           */
474 /*---------------------------------------------------------------------------*/
475 /*****************************************************************************/
476
477 void E_( pp_dering_Y )( u8 *p_plane, 
478                         int i_width, int i_height, int i_stride,
479                         QT_STORE_T *p_QP_store, int i_QP_stride )
480 {
481     int x, y, k;
482     int i_max[4], i_min[4], i_range[4];
483     int i_thr[4];
484     int i_max_range, i_kmax;
485     u32 i_bin[4][10];
486     u8  *p_block[4];
487     QT_STORE_T *p_QP;
488     
489     /* We process 4 blocks/loop*/
490     for( y = 8; y < i_height-8; y += 16 )
491     {
492         /* +---+
493            |0|1|
494            +-+-+   :))
495            |2|3|
496            +-+-+ */
497
498         p_block[0] = p_plane + y * i_stride + 8;
499         p_block[1] = p_block[0] + 8;
500         p_block[2] = p_block[0] + ( i_stride << 3 );
501         p_block[3] = p_block[2] + 8;
502
503         for( x = 8; x < i_width-8; x += 16 )
504         {
505             /* 1: Calculate threshold */
506             /* Calculate max/min for each block */
507             pp_dering_MinMax( p_block[0], i_stride, &i_min[0], &i_max[0] );
508             pp_dering_MinMax( p_block[1], i_stride, &i_min[1], &i_max[1] );
509             pp_dering_MinMax( p_block[2], i_stride, &i_min[2], &i_max[2] );
510             pp_dering_MinMax( p_block[3], i_stride, &i_min[3], &i_max[3] );
511             /* Calculate range, max_range and thr */
512             i_max_range = 0; i_kmax = 0;
513             for( k = 0; k <= 4; k++ )
514             {
515                 i_range[k] = i_max[k] - i_min[k];
516                 i_thr[k] = ( i_max[k] + i_min[k] + 1 )/2;
517                 if( i_max_range < i_max[k])
518                 {
519                     i_max_range = i_max[k];
520                     i_kmax = k;
521                 }
522             }
523             /* Now rearrange thr */
524             if(  i_max_range > 64 )
525             {
526                 for( k = 1; k < 5; k++ )
527                 {
528                     if( i_range[k] < 16 )
529                     {
530                         i_thr[k] = 0;
531                     }
532                     else
533                     if( i_range[k] < 32 )
534                     {
535                         i_thr[k] = i_thr[i_kmax];
536                     }
537                 }
538             }
539             else
540             {
541                 for( k = 1; k < 5; k++ )
542                 {
543                     if( i_range[k] < 16 )
544                     {
545                         i_thr[k] = 0;
546                     }
547                 }
548             }
549             /* 2: Index acquisition 10x10 ! so " -i_stride - 1"*/
550             pp_dering_BinIndex( p_block[0] - i_stride - 1, i_stride,
551                                 i_thr[0], i_bin[0] );
552             pp_dering_BinIndex( p_block[1] - i_stride - 1, i_stride,
553                                 i_thr[1], i_bin[1] );
554             pp_dering_BinIndex( p_block[2] - i_stride - 1, i_stride,
555                                 i_thr[2], i_bin[2] );
556             pp_dering_BinIndex( p_block[3] - i_stride - 1, i_stride,
557                                 i_thr[3], i_bin[3] );
558             
559             
560             /* 3: adaptive smoothing */
561             /* since we begin at (8,8) QP can be different for each block */
562             p_QP = &( p_QP_store[( y >> 4) * i_QP_stride + (x >> 4)] );
563
564             pp_dering_Filter( p_block[0], i_stride,
565                               i_bin[0], p_QP[0] );
566
567             pp_dering_Filter( p_block[1], i_stride,
568                               i_bin[1], p_QP[1] );
569
570             pp_dering_Filter( p_block[2], i_stride,
571                               i_bin[2], p_QP[i_QP_stride] );
572
573             pp_dering_Filter( p_block[3], i_stride,
574                               i_bin[3], p_QP[i_QP_stride+1] );
575                     
576             p_block[0] += 8;
577             p_block[1] += 8;
578             p_block[2] += 8;
579             p_block[3] += 8;
580         }
581     }
582     
583 }
584
585 void E_( pp_dering_C )( u8 *p_plane, 
586                         int i_width, int i_height, int i_stride,
587                         QT_STORE_T *p_QP_store, int i_QP_stride )
588 {
589     int x, y;
590     int i_max, i_min;
591     int i_thr;
592     u32 i_bin[10];
593    
594     u8 *p_block;
595     
596
597     for( y = 8; y < i_height-8; y += 8 )
598     {
599
600         p_block = p_plane + y * i_stride + 8;
601         for( x = 8; x < i_width-8; x += 8 )
602         {
603
604             /* 1: Calculate threshold */
605             /* Calculate max/min for each block */
606             pp_dering_MinMax( p_block, i_stride,
607                               &i_min, &i_max );
608             /* Calculate thr*/
609             i_thr = ( i_max + i_min + 1 )/2;
610
611             /* 2: Index acquisition 10x10 */
612             /* point on 10x10 in wich we have our 8x8 block */
613             pp_dering_BinIndex( p_block - i_stride -1, i_stride,
614                                 i_thr,
615                                 i_bin );
616             
617             /* 3: adaptive smoothing */
618             pp_dering_Filter( p_block, i_stride,
619                               i_bin, 
620                               p_QP_store[(y>>5)*i_QP_stride+ (x>>5)]);
621             p_block += 8;
622         }
623     }
624     
625 }