1 /*****************************************************************************
2 * transform.c : transform image plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: transform.c,v 1.14 2002/06/01 18:04:48 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 #define TRANSFORM_MODE_HFLIP 1
37 #define TRANSFORM_MODE_VFLIP 2
38 #define TRANSFORM_MODE_90 3
39 #define TRANSFORM_MODE_180 4
40 #define TRANSFORM_MODE_270 5
42 /*****************************************************************************
43 * Capabilities defined in the other files.
44 *****************************************************************************/
45 static void vout_getfunctions( function_list_t * p_function_list );
47 /*****************************************************************************
48 * Build configuration tree.
49 *****************************************************************************/
51 ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
52 ADD_STRING("transform-type", "90", NULL, N_("Transform type"),
53 N_("One of '90', '180', '270', 'hflip' and 'vflip'"))
57 SET_DESCRIPTION( _("image transformation module") )
58 /* Capability score set to 0 because we don't want to be spawned
59 * as a video output unless explicitly requested to */
60 ADD_CAPABILITY( VOUT, 0 )
61 ADD_SHORTCUT( "transform" )
65 vout_getfunctions( &p_module->p_functions->vout );
68 MODULE_DEACTIVATE_START
69 MODULE_DEACTIVATE_STOP
71 /*****************************************************************************
72 * vout_sys_t: Transform video output method descriptor
73 *****************************************************************************
74 * This structure is part of the video output thread descriptor.
75 * It describes the Transform specific properties of an output thread.
76 *****************************************************************************/
80 vlc_bool_t b_rotation;
81 vout_thread_t *p_vout;
84 /*****************************************************************************
86 *****************************************************************************/
87 static int vout_Create ( vout_thread_t * );
88 static int vout_Init ( vout_thread_t * );
89 static void vout_End ( vout_thread_t * );
90 static void vout_Destroy ( vout_thread_t * );
91 static int vout_Manage ( vout_thread_t * );
92 static void vout_Render ( vout_thread_t *, picture_t * );
93 static void vout_Display ( vout_thread_t *, picture_t * );
95 /*****************************************************************************
96 * Functions exported as capabilities. They are declared as static so that
97 * we don't pollute the namespace too much.
98 *****************************************************************************/
99 static void vout_getfunctions( function_list_t * p_function_list )
101 p_function_list->functions.vout.pf_create = vout_Create;
102 p_function_list->functions.vout.pf_init = vout_Init;
103 p_function_list->functions.vout.pf_end = vout_End;
104 p_function_list->functions.vout.pf_destroy = vout_Destroy;
105 p_function_list->functions.vout.pf_manage = vout_Manage;
106 p_function_list->functions.vout.pf_render = vout_Render;
107 p_function_list->functions.vout.pf_display = vout_Display;
110 /*****************************************************************************
111 * vout_Create: allocates Transform video thread output method
112 *****************************************************************************
113 * This function allocates and initializes a Transform vout method.
114 *****************************************************************************/
115 static int vout_Create( vout_thread_t *p_vout )
119 /* Allocate structure */
120 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
121 if( p_vout->p_sys == NULL )
123 msg_Err( p_vout, "out of memory" );
127 /* Look what method was requested */
128 psz_method = config_GetPsz( p_vout, "transform-type" );
130 if( psz_method == NULL )
132 msg_Err( p_vout, "configuration variable %s empty", "transform-type" );
133 msg_Err( p_vout, "no valid transform mode provided, using '90'" );
134 p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
135 p_vout->p_sys->b_rotation = 1;
139 if( !strcmp( psz_method, "hflip" ) )
141 p_vout->p_sys->i_mode = TRANSFORM_MODE_HFLIP;
142 p_vout->p_sys->b_rotation = 0;
144 else if( !strcmp( psz_method, "vflip" ) )
146 p_vout->p_sys->i_mode = TRANSFORM_MODE_VFLIP;
147 p_vout->p_sys->b_rotation = 0;
149 else if( !strcmp( psz_method, "90" ) )
151 p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
152 p_vout->p_sys->b_rotation = 1;
154 else if( !strcmp( psz_method, "180" ) )
156 p_vout->p_sys->i_mode = TRANSFORM_MODE_180;
157 p_vout->p_sys->b_rotation = 0;
159 else if( !strcmp( psz_method, "270" ) )
161 p_vout->p_sys->i_mode = TRANSFORM_MODE_270;
162 p_vout->p_sys->b_rotation = 1;
166 msg_Err( p_vout, "no valid transform mode provided, using '90'" );
167 p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
168 p_vout->p_sys->b_rotation = 1;
177 /*****************************************************************************
178 * vout_Init: initialize Transform video thread output method
179 *****************************************************************************/
180 static int vout_Init( vout_thread_t *p_vout )
186 I_OUTPUTPICTURES = 0;
188 /* Initialize the output structure */
189 p_vout->output.i_chroma = p_vout->render.i_chroma;
190 p_vout->output.i_width = p_vout->render.i_width;
191 p_vout->output.i_height = p_vout->render.i_height;
192 p_vout->output.i_aspect = p_vout->render.i_aspect;
194 /* Try to open the real video output */
195 psz_filter = config_GetPsz( p_vout, "filter" );
196 config_PutPsz( p_vout, "filter", NULL );
198 msg_Dbg( p_vout, "spawning the real video output" );
200 if( p_vout->p_sys->b_rotation )
202 p_vout->p_sys->p_vout =
203 vout_CreateThread( p_vout,
204 p_vout->render.i_height, p_vout->render.i_width,
205 p_vout->render.i_chroma,
206 (u64)VOUT_ASPECT_FACTOR * (u64)VOUT_ASPECT_FACTOR
207 / (u64)p_vout->render.i_aspect );
211 p_vout->p_sys->p_vout =
212 vout_CreateThread( p_vout,
213 p_vout->render.i_width, p_vout->render.i_height,
214 p_vout->render.i_chroma, p_vout->render.i_aspect );
217 config_PutPsz( p_vout, "filter", psz_filter );
218 if( psz_filter ) free( psz_filter );
220 /* Everything failed */
221 if( p_vout->p_sys->p_vout == NULL )
223 msg_Err( p_vout, "cannot open vout, aborting" );
227 ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
232 /*****************************************************************************
233 * vout_End: terminate Transform video thread output method
234 *****************************************************************************/
235 static void vout_End( vout_thread_t *p_vout )
239 /* Free the fake output buffers we allocated */
240 for( i_index = I_OUTPUTPICTURES ; i_index ; )
243 free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
247 /*****************************************************************************
248 * vout_Destroy: destroy Transform video thread output method
249 *****************************************************************************
250 * Terminate an output method created by TransformCreateOutputMethod
251 *****************************************************************************/
252 static void vout_Destroy( vout_thread_t *p_vout )
254 vout_DestroyThread( p_vout->p_sys->p_vout );
256 free( p_vout->p_sys );
259 /*****************************************************************************
260 * vout_Manage: handle Transform events
261 *****************************************************************************
262 * This function should be called regularly by video output thread. It manages
263 * console events. It returns a non null value on error.
264 *****************************************************************************/
265 static int vout_Manage( vout_thread_t *p_vout )
270 /*****************************************************************************
271 * vout_Render: displays previously rendered output
272 *****************************************************************************
273 * This function send the currently rendered image to Transform image, waits
274 * until it is displayed and switch the two rendering buffers, preparing next
276 *****************************************************************************/
277 static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
282 /* This is a new frame. Get a structure from the video_output. */
283 while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
286 if( p_vout->b_die || p_vout->b_error )
290 msleep( VOUT_OUTMEM_SLEEP );
293 vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
294 vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
296 switch( p_vout->p_sys->i_mode )
298 case TRANSFORM_MODE_90:
299 for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
301 int i_pitch = p_pic->p[i_index].i_pitch;
303 u8 *p_in = p_pic->p[i_index].p_pixels;
305 u8 *p_out = p_outpic->p[i_index].p_pixels;
306 u8 *p_out_end = p_out + p_outpic->p[i_index].i_lines
307 * p_outpic->p[i_index].i_pitch;
309 for( ; p_out < p_out_end ; )
313 p_line_end = p_in + p_pic->p[i_index].i_lines
314 * p_pic->p[i_index].i_pitch;
316 for( ; p_in < p_line_end ; )
318 p_line_end -= i_pitch;
319 *(--p_out_end) = *p_line_end;
327 case TRANSFORM_MODE_180:
328 for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
330 u8 *p_in = p_pic->p[i_index].p_pixels;
331 u8 *p_in_end = p_in + p_pic->p[i_index].i_lines
332 * p_pic->p[i_index].i_pitch;
334 u8 *p_out = p_outpic->p[i_index].p_pixels;
336 for( ; p_in < p_in_end ; )
338 *p_out++ = *(--p_in_end);
343 case TRANSFORM_MODE_270:
344 for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
346 int i_pitch = p_pic->p[i_index].i_pitch;
348 u8 *p_in = p_pic->p[i_index].p_pixels;
350 u8 *p_out = p_outpic->p[i_index].p_pixels;
351 u8 *p_out_end = p_out + p_outpic->p[i_index].i_lines
352 * p_outpic->p[i_index].i_pitch;
354 for( ; p_out < p_out_end ; )
358 p_in_end = p_in + p_pic->p[i_index].i_lines
359 * p_pic->p[i_index].i_pitch;
361 for( ; p_in < p_in_end ; )
364 *p_out++ = *p_in_end;
372 case TRANSFORM_MODE_VFLIP:
373 for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
375 u8 *p_in = p_pic->p[i_index].p_pixels;
376 u8 *p_in_end = p_in + p_pic->p[i_index].i_lines
377 * p_pic->p[i_index].i_pitch;
379 u8 *p_out = p_outpic->p[i_index].p_pixels;
381 for( ; p_in < p_in_end ; )
383 p_in_end -= p_pic->p[i_index].i_pitch;
384 p_vout->p_vlc->pf_memcpy( p_out, p_in_end,
385 p_pic->p[i_index].i_pitch );
386 p_out += p_pic->p[i_index].i_pitch;
391 case TRANSFORM_MODE_HFLIP:
392 for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
394 u8 *p_in = p_pic->p[i_index].p_pixels;
395 u8 *p_in_end = p_in + p_pic->p[i_index].i_lines
396 * p_pic->p[i_index].i_pitch;
398 u8 *p_out = p_outpic->p[i_index].p_pixels;
400 for( ; p_in < p_in_end ; )
402 u8 *p_line_end = p_in + p_pic->p[i_index].i_pitch;
404 for( ; p_in < p_line_end ; )
406 *p_out++ = *(--p_line_end);
409 p_in += p_pic->p[i_index].i_pitch;
418 vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
420 vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
423 /*****************************************************************************
424 * vout_Display: displays previously rendered output
425 *****************************************************************************
426 * This function send the currently rendered image to Invert image, waits
427 * until it is displayed and switch the two rendering buffers, preparing next
429 *****************************************************************************/
430 static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )