]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/postprocessing/postprocessing.c
* ./include/modules_inner.h: support for several modules with the same
[vlc] / modules / codec / ffmpeg / postprocessing / postprocessing.c
1 /*****************************************************************************
2  * postprocessing.c
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: postprocessing.c,v 1.2 2002/08/08 22:28:22 sam 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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc/vout.h>
32
33 #include "postprocessing.h"
34 #include "postprocessing_common.h"
35
36
37 static int Open ( vlc_object_t *p_this );
38
39 static u32 pp_getmode( int i_quality, int b_autolevel );
40 static int pp_postprocess( picture_t *,
41                            QT_STORE_T *, unsigned int,
42                            unsigned int i_mode );
43
44 /*****************************************************************************
45  * Module descriptor
46  *****************************************************************************/
47 vlc_module_begin();
48 #ifdef MODULE_NAME_IS_postprocessing_c
49     set_description( _("C Post Processing module") );
50     set_capability( "postprocessing", 50 );
51     add_shortcut( "c" );
52 #elif defined( MODULE_NAME_IS_postprocessing_mmx )
53     set_description( _("MMX Post Processing module") );
54     set_capability( "postprocessing", 100 );
55     add_requirement( MMX );
56     add_shortcut( "mmx" );
57 #elif defined( MODULE_NAME_IS_postprocessing_mmxext )
58     set_description( _("MMXEXT Post Processing module") );
59     set_capability( "postprocessing", 150 );
60     add_requirement( MMXEXT );
61     add_shortcut( "mmxext" );
62     add_shortcut( "mmx2" );
63 #endif
64     set_callbacks( Open, NULL );
65 vlc_module_end();
66
67 /*****************************************************************************
68  * Module initializer
69  *****************************************************************************/
70 static int Open ( vlc_object_t *p_this )
71 {
72     postprocessing_t *p_pp = (postprocessing_t *)p_this;
73
74     p_pp->pf_getmode = pp_getmode;
75     p_pp->pf_postprocess = pp_postprocess;
76     
77     return VLC_SUCCESS;
78 }
79
80
81 static u32 pp_getmode( int i_quality, int b_autolevel )
82 {
83     u32 i_mode;
84     i_quality = i_quality < 0 ? 0 : i_quality;
85     i_quality = i_quality > 6 ? 6 : i_quality;
86
87     switch( i_quality )
88     {
89         case( 0 ):
90             i_mode = 0;
91             break;
92         case( 1 ):
93             i_mode = PP_DEBLOCK_Y_H;
94             break;
95         case( 2 ):
96             i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V;
97             break;
98         case( 3 ):
99             i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
100                      PP_DEBLOCK_C_H;
101             break;
102         case( 4 ):
103             i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
104                      PP_DEBLOCK_C_H|PP_DEBLOCK_C_V;
105             break;
106         case( 5 ):
107             i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
108                      PP_DEBLOCK_C_H|PP_DEBLOCK_C_V|
109                      PP_DERING_Y;
110             break;
111         case( 6 ):
112             i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
113                      PP_DEBLOCK_C_H|PP_DEBLOCK_C_V|
114                      PP_DERING_Y|PP_DERING_C;
115             break;
116         default:
117             i_mode = 0;
118     }
119     if( b_autolevel )
120     {
121         i_mode |= PP_AUTOLEVEL;
122     }
123
124     return( i_mode );
125 }
126
127 /*****************************************************************************
128  * pp_postprocess : make post-filter as defined in MPEG4-ISO 
129  *****************************************************************************
130  *****************************************************************************/
131
132 static int pp_postprocess( picture_t *p_pic,
133                            QT_STORE_T *p_QP_store, unsigned int i_QP_stride,
134                            unsigned int i_mode )
135 {
136     /* Some sanity checks */
137 /*    if( ( p_pic->i_height&0x0f )||( p_pic->i_width&0x0f )||*/
138     if( ( p_pic->p_heap->i_chroma != VLC_FOURCC( 'I', '4', '2', '0' ) )&&
139         ( p_pic->p_heap->i_chroma != VLC_FOURCC( 'Y', 'V', '1', '2' ) ) )
140     {
141         return( PP_ERR_INVALID_PICTURE );
142     }
143
144     if( ( !p_QP_store )||( i_QP_stride < p_pic->p_heap->i_width >> 4 ) )
145     {
146         return( PP_ERR_INVALID_QP );
147     }
148
149     /* First do vertical deblocking and then horizontal */
150     /* Luminance */
151
152     if( i_mode&PP_DEBLOCK_Y_V )
153     {
154         E_( pp_deblock_V )( p_pic->Y_PIXELS,
155                             p_pic->p_heap->i_width, p_pic->p_heap->i_height, p_pic->Y_PITCH,
156                             p_QP_store, i_QP_stride,
157                             0 );
158     }
159     if( i_mode&PP_DEBLOCK_Y_H )
160     {
161         E_( pp_deblock_H )( p_pic->Y_PIXELS,
162                             p_pic->p_heap->i_width, p_pic->p_heap->i_height, p_pic->Y_PITCH,
163                             p_QP_store, i_QP_stride,
164                             0 );
165     }
166
167     /* Chrominance */
168     if( i_mode&PP_DEBLOCK_C_V )
169     {
170         E_( pp_deblock_V )( p_pic->U_PIXELS,
171                             p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1, 
172                             p_pic->U_PITCH,
173                             p_QP_store, i_QP_stride,
174                             1 );
175         E_( pp_deblock_V )( p_pic->V_PIXELS,
176                             p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1, 
177                             p_pic->V_PITCH,
178                             p_QP_store, i_QP_stride,
179                             1 );
180     }
181     if( i_mode&PP_DEBLOCK_C_H )
182     {
183         E_( pp_deblock_H )( p_pic->U_PIXELS,
184                             p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1, 
185                             p_pic->U_PITCH,
186                             p_QP_store, i_QP_stride,
187                             1 );
188         E_( pp_deblock_H )( p_pic->V_PIXELS,
189                             p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1, 
190                             p_pic->V_PITCH,
191                             p_QP_store, i_QP_stride,
192                             1 );
193     }
194  
195     /* After deblocking do dering */   
196     /* TODO check for min size */
197     
198     if( i_mode&PP_DERING_Y )
199     {
200         E_( pp_dering_Y )( p_pic->Y_PIXELS,
201                            p_pic->p_heap->i_width, p_pic->p_heap->i_height, 
202                            p_pic->Y_PITCH,
203                            p_QP_store, i_QP_stride );
204     }
205     if( i_mode&PP_DERING_C )
206     {
207         E_( pp_dering_C )( p_pic->U_PIXELS,
208                            p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1, 
209                            p_pic->U_PITCH,
210                            p_QP_store, i_QP_stride );
211
212         E_( pp_dering_C )( p_pic->V_PIXELS,
213                            p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1, 
214                            p_pic->V_PITCH,
215                            p_QP_store, i_QP_stride );
216
217     }
218 #if defined( MODULE_NAME_IS_postprocessing_mmx )||defined( MODULE_NAME_IS_postprocessing_mmxext )
219     /* We have used MMX so return to safe FPU state */
220     __asm__ __volatile__ ( "emms"  );
221 #endif
222     return( PP_ERR_OK );
223 }