]> git.sesse.net Git - vlc/blob - plugins/filter/clone.c
* ALL: changed "struct foo_s" into "struct foo_t" to make greppers happy.
[vlc] / plugins / filter / clone.c
1 /*****************************************************************************
2  * clone.c : Clone video plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: clone.c,v 1.8 2002/07/20 18:01: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 <vlc/vlc.h>
32 #include <vlc/vout.h>
33
34 #include "filter_common.h"
35
36 /*****************************************************************************
37  * Capabilities defined in the other files.
38  *****************************************************************************/
39 static void vout_getfunctions( function_list_t * p_function_list );
40
41 /*****************************************************************************
42  * Build configuration tree.
43  *****************************************************************************/
44 #define COUNT_TEXT N_("Number of clones")
45 #define COUNT_LONGTEXT N_("Select the number of video windows in which to "\
46     "clone the video")
47
48 MODULE_CONFIG_START
49 ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
50 ADD_INTEGER ( "clone-count", 2, NULL, COUNT_TEXT, COUNT_LONGTEXT )
51 MODULE_CONFIG_STOP
52
53 MODULE_INIT_START
54     SET_DESCRIPTION( _("image clone video module") )
55     /* Capability score set to 0 because we don't want to be spawned
56      * as a video output unless explicitly requested to */
57     ADD_CAPABILITY( VOUT_FILTER, 0 )
58     ADD_SHORTCUT( "clone" )
59 MODULE_INIT_STOP
60
61 MODULE_ACTIVATE_START
62     vout_getfunctions( &p_module->p_functions->vout );
63 MODULE_ACTIVATE_STOP
64
65 MODULE_DEACTIVATE_START
66 MODULE_DEACTIVATE_STOP
67
68 /*****************************************************************************
69  * vout_sys_t: Clone video output method descriptor
70  *****************************************************************************
71  * This structure is part of the video output thread descriptor.
72  * It describes the Clone specific properties of an output thread.
73  *****************************************************************************/
74 struct vout_sys_t
75 {
76     int    i_clones;
77     vout_thread_t **pp_vout;
78 };
79
80 /*****************************************************************************
81  * Local prototypes
82  *****************************************************************************/
83 static int  vout_Create    ( vout_thread_t * );
84 static int  vout_Init      ( vout_thread_t * );
85 static void vout_End       ( vout_thread_t * );
86 static void vout_Destroy   ( vout_thread_t * );
87 static int  vout_Manage    ( vout_thread_t * );
88 static void vout_Render    ( vout_thread_t *, picture_t * );
89 static void vout_Display   ( vout_thread_t *, picture_t * );
90
91 static void RemoveAllVout  ( vout_thread_t *p_vout );
92
93 /*****************************************************************************
94  * Functions exported as capabilities. They are declared as static so that
95  * we don't pollute the namespace too much.
96  *****************************************************************************/
97 static void vout_getfunctions( function_list_t * p_function_list )
98 {
99     p_function_list->functions.vout.pf_create     = vout_Create;
100     p_function_list->functions.vout.pf_init       = vout_Init;
101     p_function_list->functions.vout.pf_end        = vout_End;
102     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
103     p_function_list->functions.vout.pf_manage     = vout_Manage;
104     p_function_list->functions.vout.pf_render     = vout_Render;
105     p_function_list->functions.vout.pf_display    = vout_Display;
106 }
107
108 /*****************************************************************************
109  * vout_Create: allocates Clone video thread output method
110  *****************************************************************************
111  * This function allocates and initializes a Clone vout method.
112  *****************************************************************************/
113 static int vout_Create( vout_thread_t *p_vout )
114 {
115
116     /* Allocate structure */
117     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
118     if( p_vout->p_sys == NULL )
119     {
120         msg_Err( p_vout, "out of memory" );
121         return( 1 );
122     }
123
124     /* Look what method was requested */
125     p_vout->p_sys->i_clones = config_GetInt( p_vout, "clone-count" );
126
127     p_vout->p_sys->i_clones = __MAX( 1, __MIN( 99, p_vout->p_sys->i_clones ) );
128
129     msg_Dbg( p_vout, "spawning %i clone(s)", p_vout->p_sys->i_clones );
130
131     p_vout->p_sys->pp_vout = malloc( p_vout->p_sys->i_clones *
132                                      sizeof(vout_thread_t *) );
133     if( p_vout->p_sys->pp_vout == NULL )
134     {
135         msg_Err( p_vout, "out of memory" );
136         free( p_vout->p_sys );
137         return( 1 );
138     }
139
140     return( 0 );
141 }
142
143 /*****************************************************************************
144  * vout_Init: initialize Clone video thread output method
145  *****************************************************************************/
146 static int vout_Init( vout_thread_t *p_vout )
147 {
148     int   i_index, i_vout;
149     picture_t *p_pic;
150     
151     I_OUTPUTPICTURES = 0;
152
153     /* Initialize the output structure */
154     p_vout->output.i_chroma = p_vout->render.i_chroma;
155     p_vout->output.i_width  = p_vout->render.i_width;
156     p_vout->output.i_height = p_vout->render.i_height;
157     p_vout->output.i_aspect = p_vout->render.i_aspect;
158
159     /* Try to open the real video output */
160     msg_Dbg( p_vout, "spawning the real video outputs" );
161
162     for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
163     {
164         p_vout->p_sys->pp_vout[ i_vout ] =
165                 vout_CreateThread( p_vout,
166                             p_vout->render.i_width, p_vout->render.i_height,
167                             p_vout->render.i_chroma, p_vout->render.i_aspect );
168         if( p_vout->p_sys->pp_vout[ i_vout ] == NULL )
169         {
170             msg_Err( p_vout, "failed to clone %i vout threads",
171                              p_vout->p_sys->i_clones );
172             p_vout->p_sys->i_clones = i_vout;
173             RemoveAllVout( p_vout );
174             return 0;
175         }
176     }
177
178     ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
179
180     return( 0 );
181 }
182
183 /*****************************************************************************
184  * vout_End: terminate Clone video thread output method
185  *****************************************************************************/
186 static void vout_End( vout_thread_t *p_vout )
187 {
188     int i_index;
189
190     /* Free the fake output buffers we allocated */
191     for( i_index = I_OUTPUTPICTURES ; i_index ; )
192     {
193         i_index--;
194         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
195     }
196 }
197
198 /*****************************************************************************
199  * vout_Destroy: destroy Clone video thread output method
200  *****************************************************************************
201  * Terminate an output method created by CloneCreateOutputMethod
202  *****************************************************************************/
203 static void vout_Destroy( vout_thread_t *p_vout )
204 {
205     RemoveAllVout( p_vout );
206
207     free( p_vout->p_sys->pp_vout );
208     free( p_vout->p_sys );
209 }
210
211 /*****************************************************************************
212  * vout_Manage: handle Clone events
213  *****************************************************************************
214  * This function should be called regularly by video output thread. It manages
215  * console events. It returns a non null value on error.
216  *****************************************************************************/
217 static int vout_Manage( vout_thread_t *p_vout )
218 {
219     return( 0 );
220 }
221
222 /*****************************************************************************
223  * vout_Render: displays previously rendered output
224  *****************************************************************************
225  * This function send the currently rendered image to Clone image, waits
226  * until it is displayed and switch the two rendering buffers, preparing next
227  * frame.
228  *****************************************************************************/
229 static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
230 {
231     picture_t *p_outpic = NULL;
232     int i_vout, i_plane;
233
234     for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
235     {
236         while( ( p_outpic =
237             vout_CreatePicture( p_vout->p_sys->pp_vout[ i_vout ], 0, 0, 0 )
238                ) == NULL )
239         {
240             if( p_vout->b_die || p_vout->b_error )
241             {
242                 vout_DestroyPicture(
243                     p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
244                 return;
245             }
246
247             msleep( VOUT_OUTMEM_SLEEP );
248         }
249
250         vout_DatePicture( p_vout->p_sys->pp_vout[ i_vout ],
251                           p_outpic, p_pic->date );
252         vout_LinkPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
253
254         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
255         {
256             u8 *p_in, *p_in_end, *p_out;
257             int i_in_pitch = p_pic->p[i_plane].i_pitch;
258             const int i_out_pitch = p_outpic->p[i_plane].i_pitch;
259
260             p_in = p_pic->p[i_plane].p_pixels;
261
262             p_in_end = p_in + p_outpic->p[i_plane].i_lines
263                                * p_pic->p[i_plane].i_pitch;
264
265             p_out = p_outpic->p[i_plane].p_pixels;
266
267             while( p_in < p_in_end )
268             {
269                 p_vout->p_vlc->pf_memcpy( p_out, p_in, i_out_pitch );
270                 p_in += i_in_pitch;
271                 p_out += i_out_pitch;
272             }
273         }
274
275         vout_UnlinkPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
276         vout_DisplayPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
277     }
278 }
279
280 /*****************************************************************************
281  * vout_Display: displays previously rendered output
282  *****************************************************************************
283  * This function send the currently rendered image to Invert image, waits
284  * until it is displayed and switch the two rendering buffers, preparing next
285  * frame.
286  *****************************************************************************/
287 static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
288 {
289     ;
290 }
291
292 /*****************************************************************************
293  * RemoveAllVout: destroy all the child video output threads
294  *****************************************************************************/
295 static void RemoveAllVout( vout_thread_t *p_vout )
296 {
297     while( p_vout->p_sys->i_clones )
298     {
299          --p_vout->p_sys->i_clones;
300          vout_DestroyThread( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] );
301     }
302 }
303