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