1 /*****************************************************************************
2 * clone.c : Clone video plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: clone.c,v 1.5 2002/06/01 12:31:59 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
34 #include "filter_common.h"
36 /*****************************************************************************
37 * Capabilities defined in the other files.
38 *****************************************************************************/
39 static void vout_getfunctions( function_list_t * p_function_list );
41 /*****************************************************************************
42 * Build configuration tree.
43 *****************************************************************************/
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") )
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" )
59 vout_getfunctions( &p_module->p_functions->vout );
62 MODULE_DEACTIVATE_START
63 MODULE_DEACTIVATE_STOP
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 *****************************************************************************/
74 vout_thread_t **pp_vout;
77 /*****************************************************************************
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 * );
88 static void RemoveAllVout ( vout_thread_t *p_vout );
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 )
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;
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 )
113 /* Allocate structure */
114 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
115 if( p_vout->p_sys == NULL )
117 msg_Err( p_vout, "out of memory" );
121 /* Look what method was requested */
122 p_vout->p_sys->i_clones = config_GetInt( p_vout, "clone-count" );
124 p_vout->p_sys->i_clones = __MAX( 1, __MIN( 99, p_vout->p_sys->i_clones ) );
126 msg_Dbg( p_vout, "spawning %i clone(s)", p_vout->p_sys->i_clones );
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 )
132 msg_Err( p_vout, "out of memory" );
133 free( p_vout->p_sys );
140 /*****************************************************************************
141 * vout_Init: initialize Clone video thread output method
142 *****************************************************************************/
143 static int vout_Init( vout_thread_t *p_vout )
149 I_OUTPUTPICTURES = 0;
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;
157 /* Try to open the real video output */
158 psz_filter = config_GetPsz( p_vout, "filter" );
159 config_PutPsz( p_vout, "filter", NULL );
161 msg_Dbg( p_vout, "spawning the real video outputs" );
163 for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
165 p_vout->p_sys->pp_vout[ i_vout ] =
166 vout_CreateThread( p_vout->p_this,
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 )
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 );
181 config_PutPsz( p_vout, "filter", psz_filter );
182 if( psz_filter ) free( psz_filter );
184 ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
189 /*****************************************************************************
190 * vout_End: terminate Clone video thread output method
191 *****************************************************************************/
192 static void vout_End( vout_thread_t *p_vout )
196 /* Free the fake output buffers we allocated */
197 for( i_index = I_OUTPUTPICTURES ; i_index ; )
200 free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
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 )
211 RemoveAllVout( p_vout );
213 free( p_vout->p_sys->pp_vout );
214 free( p_vout->p_sys );
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 )
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
234 *****************************************************************************/
235 static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
237 picture_t *p_outpic = NULL;
240 for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
243 vout_CreatePicture( p_vout->p_sys->pp_vout[ i_vout ], 0, 0, 0 )
246 if( p_vout->b_die || p_vout->b_error )
249 p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
253 msleep( VOUT_OUTMEM_SLEEP );
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 );
260 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
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;
266 p_in = p_pic->p[i_plane].p_pixels;
268 p_in_end = p_in + p_outpic->p[i_plane].i_lines
269 * p_pic->p[i_plane].i_pitch;
271 p_out = p_outpic->p[i_plane].p_pixels;
273 while( p_in < p_in_end )
275 p_vout->p_vlc->pf_memcpy( p_out, p_in, i_out_pitch );
277 p_out += i_out_pitch;
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 );
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
292 *****************************************************************************/
293 static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
298 /*****************************************************************************
299 * RemoveAllVout: destroy all the child video output threads
300 *****************************************************************************/
301 static void RemoveAllVout( vout_thread_t *p_vout )
303 while( p_vout->p_sys->i_clones )
305 --p_vout->p_sys->i_clones;
306 vout_DestroyThread( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] );