]> git.sesse.net Git - vlc/blob - plugins/filter/invert.c
77f161fb90151801940a8a79a8560989bddee4ae
[vlc] / plugins / filter / invert.c
1 /*****************************************************************************
2  * invert.c : Invert video plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id: invert.c,v 1.4 2002/01/02 14:37:42 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
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 <errno.h>
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <videolan/vlc.h>
32
33 #include "video.h"
34 #include "video_output.h"
35
36 #include "filter_common.h"
37
38 /*****************************************************************************
39  * Capabilities defined in the other files.
40  *****************************************************************************/
41 static void vout_getfunctions( function_list_t * p_function_list );
42
43 /*****************************************************************************
44  * Build configuration tree.
45  *****************************************************************************/
46 MODULE_CONFIG_START
47 MODULE_CONFIG_STOP
48
49 MODULE_INIT_START
50     SET_DESCRIPTION( "invert video module" )
51     /* Capability score set to 0 because we don't want to be spawned
52      * as a video output unless explicitly requested to */
53     ADD_CAPABILITY( VOUT, 0 )
54     ADD_SHORTCUT( "invert" )
55 MODULE_INIT_STOP
56
57 MODULE_ACTIVATE_START
58     vout_getfunctions( &p_module->p_functions->vout );
59 MODULE_ACTIVATE_STOP
60
61 MODULE_DEACTIVATE_START
62 MODULE_DEACTIVATE_STOP
63
64 /*****************************************************************************
65  * vout_sys_t: Invert video output method descriptor
66  *****************************************************************************
67  * This structure is part of the video output thread descriptor.
68  * It describes the Invert specific properties of an output thread.
69  *****************************************************************************/
70 typedef struct vout_sys_s
71 {
72     struct vout_thread_s *p_vout;
73
74 } vout_sys_t;
75
76 /*****************************************************************************
77  * Local prototypes
78  *****************************************************************************/
79 static int  vout_Probe     ( probedata_t *p_data );
80 static int  vout_Create    ( struct vout_thread_s * );
81 static int  vout_Init      ( struct vout_thread_s * );
82 static void vout_End       ( struct vout_thread_s * );
83 static void vout_Destroy   ( struct vout_thread_s * );
84 static int  vout_Manage    ( struct vout_thread_s * );
85 static void vout_Display   ( struct vout_thread_s *, struct picture_s * );
86
87 /*****************************************************************************
88  * Functions exported as capabilities. They are declared as static so that
89  * we don't pollute the namespace too much.
90  *****************************************************************************/
91 static void vout_getfunctions( function_list_t * p_function_list )
92 {
93     p_function_list->pf_probe = vout_Probe;
94     p_function_list->functions.vout.pf_create     = vout_Create;
95     p_function_list->functions.vout.pf_init       = vout_Init;
96     p_function_list->functions.vout.pf_end        = vout_End;
97     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
98     p_function_list->functions.vout.pf_manage     = vout_Manage;
99     p_function_list->functions.vout.pf_display    = vout_Display;
100     p_function_list->functions.vout.pf_setpalette = NULL;
101 }
102
103 /*****************************************************************************
104  * intf_Probe: return a score
105  *****************************************************************************/
106 static int vout_Probe( probedata_t *p_data )
107 {
108     return( 0 );
109 }
110
111 /*****************************************************************************
112  * vout_Create: allocates Invert video thread output method
113  *****************************************************************************
114  * This function allocates and initializes a Invert vout method.
115  *****************************************************************************/
116 static int vout_Create( vout_thread_t *p_vout )
117 {
118     /* Allocate structure */
119     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
120     if( p_vout->p_sys == NULL )
121     {
122         intf_ErrMsg("error: %s", strerror(ENOMEM) );
123         return( 1 );
124     }
125
126     return( 0 );
127 }
128
129 /*****************************************************************************
130  * vout_Init: initialize Invert video thread output method
131  *****************************************************************************/
132 static int vout_Init( vout_thread_t *p_vout )
133 {
134     int i_index;
135     char *psz_filter;
136     picture_t *p_pic;
137     
138     I_OUTPUTPICTURES = 0;
139
140     /* Initialize the output structure */
141     switch( p_vout->render.i_chroma )
142     {
143         case FOURCC_I420:
144         case FOURCC_IYUV:
145         case FOURCC_YV12:
146         case FOURCC_I422:
147         case FOURCC_I444:
148             p_vout->output.i_chroma = p_vout->render.i_chroma;
149             p_vout->output.i_width  = p_vout->render.i_width;
150             p_vout->output.i_height = p_vout->render.i_height;
151             p_vout->output.i_aspect = p_vout->render.i_aspect;
152             break;
153
154         default:
155             return( 0 ); /* unknown chroma */
156             break;
157     }
158
159     /* Try to open the real video output */
160     psz_filter = main_GetPszVariable( VOUT_FILTER_VAR, "" );
161     main_PutPszVariable( VOUT_FILTER_VAR, "" );
162
163     intf_WarnMsg( 1, "filter: spawning the real video output" );
164         
165     p_vout->p_sys->p_vout =
166         vout_CreateThread( NULL,
167                            p_vout->render.i_width, p_vout->render.i_height,
168                            p_vout->render.i_chroma, p_vout->render.i_aspect );
169
170     /* Everything failed */
171     if( p_vout->p_sys->p_vout == NULL )
172     {
173         intf_ErrMsg( "filter error: can't open vout, aborting" );
174
175         return( 0 );
176     }
177  
178     main_PutPszVariable( VOUT_FILTER_VAR, psz_filter );
179
180     ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
181
182     return( 0 );
183 }
184
185 /*****************************************************************************
186  * vout_End: terminate Invert video thread output method
187  *****************************************************************************/
188 static void vout_End( vout_thread_t *p_vout )
189 {
190     int i_index;
191
192     /* Free the fake output buffers we allocated */
193     for( i_index = I_OUTPUTPICTURES ; i_index ; )
194     {
195         i_index--;
196         free( PP_OUTPUTPICTURE[ i_index ]->planes[ 0 ].p_data );
197     }
198 }
199
200 /*****************************************************************************
201  * vout_Destroy: destroy Invert video thread output method
202  *****************************************************************************
203  * Terminate an output method created by InvertCreateOutputMethod
204  *****************************************************************************/
205 static void vout_Destroy( vout_thread_t *p_vout )
206 {
207     vout_DestroyThread( p_vout->p_sys->p_vout, NULL );
208
209     free( p_vout->p_sys );
210 }
211
212 /*****************************************************************************
213  * vout_Manage: handle Invert events
214  *****************************************************************************
215  * This function should be called regularly by video output thread. It manages
216  * console events. It returns a non null value on error.
217  *****************************************************************************/
218 static int vout_Manage( vout_thread_t *p_vout )
219 {
220     return( 0 );
221 }
222
223 /*****************************************************************************
224  * vout_Display: displays previously rendered output
225  *****************************************************************************
226  * This function send the currently rendered image to Invert image, waits
227  * until it is displayed and switch the two rendering buffers, preparing next
228  * frame.
229  *****************************************************************************/
230 static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
231 {
232     picture_t *p_outpic;
233     int i_index;
234
235     /* This is a new frame. Get a structure from the video_output. */
236     while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
237               == NULL )
238     {
239         if( p_vout->b_die || p_vout->b_error )
240         {
241             return;
242         }
243         msleep( VOUT_OUTMEM_SLEEP );
244     }   
245
246     vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, mdate() + 50000 );
247     vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
248
249     for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
250     {
251         pixel_data_t *p_in, *p_in_end, *p_out;
252
253         p_in = p_pic->planes[ i_index ].p_data;
254         p_in_end = p_in + p_pic->planes[ i_index ].i_bytes - 64;
255
256         p_out = p_outpic->planes[ i_index ].p_data;
257
258         for( ; p_in < p_in_end ; )
259         {
260             /* Do 64 pixels at a time */
261             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
262             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
263             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
264             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
265             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
266             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
267             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
268             *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
269         }
270
271         p_in_end += 64;
272
273         for( ; p_in < p_in_end ; )
274         {
275             /* Do 1 pixel at a time */
276             *p_out++ = ~( *p_in++ );
277         }
278     }
279
280     vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
281
282     vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
283 }
284