]> git.sesse.net Git - vlc/blob - modules/video_filter/mosaic.c
Preferences consistency fixes by Christophe Mutricy <xtophe at nxtelevision d0t com>
[vlc] / modules / video_filter / mosaic.c
1 /*****************************************************************************
2 * mosaic.c : Mosaic video plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2004-2005 VideoLAN
5 * $Id$
6 *
7 * Authors: Antoine Cellerier <dionoea@via.ecp.fr>
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 <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>
29 #include <math.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/vout.h>
33
34 #include "vlc_filter.h"
35 #include "vlc_input.h"
36
37 #include "vlc_image.h"
38
39 /*****************************************************************************
40 * Local prototypes
41 *****************************************************************************/
42
43 static int  CreateFilter    ( vlc_object_t * );
44 static void DestroyFilter   ( vlc_object_t * );
45
46 static subpicture_t *Filter( filter_t *, mtime_t );
47
48 static int MosaicCallback( vlc_object_t *, char const *, vlc_value_t,
49                             vlc_value_t, void * );
50
51 /*****************************************************************************
52 * filter_sys_t : filter desriptor
53 *****************************************************************************/
54
55 #include "../video_output/picture.h"
56
57 struct filter_sys_t
58 {
59
60     image_handler_t *p_image;
61     image_handler_t *p_image2;
62     picture_t *p_pic;
63
64     int i_pos; /* mosaic positioning method */
65     int i_ar; /* do we keep aspect ratio ? */
66     int i_width, i_height; /* mosaic height and width */
67     int i_cols, i_rows; /* mosaic rows and cols */
68     int i_xoffset, i_yoffset; /* top left corner offset */
69     int i_vborder, i_hborder; /* border width/height between miniatures */
70     int i_alpha; /* subfilter alpha blending */
71
72     char **ppsz_order; /* list of picture-id */
73     int i_order_length;
74
75 };
76
77 /*****************************************************************************
78 * Module descriptor
79 *****************************************************************************/
80
81 #define ALPHA_TEXT N_("Mosaic alpha blending (0 -> 255)")
82 #define ALPHA_LONGTEXT N_("Mosaic alpha blending (0 -> 255). default is 255")
83
84 #define HEIGHT_TEXT N_("Mosaic height in pixels")
85 #define WIDTH_TEXT N_("Mosaic width in pixels")
86 #define XOFFSET_TEXT N_("Mosaic top left corner x coordinate")
87 #define YOFFSET_TEXT N_("Mosaic top left corner y coordinate")
88 #define VBORDER_TEXT N_("Mosaic vertical border width in pixels")
89 #define HBORDER_TEXT N_("Mosaic horizontal border width in pixels")
90
91 #define POS_TEXT N_("Mosaic positioning method")
92 #define POS_LONGTEXT N_("Mosaic positioning method. auto : automatically chose the best number of rows and columns. fixed : used the user defined number of rows and columns.")
93 #define ROWS_TEXT N_("Mosaic number of rows")
94 #define COLS_TEXT N_("Mosaic number of columns")
95 #define AR_TEXT N_("Keep aspect ratio when resizing")
96
97 #define ORDER_TEXT N_("Order as a comma separated list of picture-id(s)")
98
99 static int pi_pos_values[] = { 0, 1 };
100 static char * ppsz_pos_descriptions[] =
101 { N_("auto"), N_("fixed") };
102
103
104 vlc_module_begin();
105     set_description( _("Mosaic video sub filter") );
106     set_shortname( N_("Mosaic") );
107     set_capability( "sub filter", 0 );
108     set_callbacks( CreateFilter, DestroyFilter );
109
110     add_integer( "mosaic-alpha", 255, NULL, ALPHA_TEXT, ALPHA_LONGTEXT, VLC_FALSE );
111     add_integer( "mosaic-height", 100, NULL, HEIGHT_TEXT, HEIGHT_TEXT, VLC_FALSE );
112     add_integer( "mosaic-width", 100, NULL, WIDTH_TEXT, WIDTH_TEXT, VLC_FALSE );
113     add_integer( "mosaic-xoffset", 0, NULL, XOFFSET_TEXT, XOFFSET_TEXT, VLC_TRUE );
114     add_integer( "mosaic-yoffset", 0, NULL, YOFFSET_TEXT, YOFFSET_TEXT, VLC_TRUE );
115     add_integer( "mosaic-vborder", 0, NULL, VBORDER_TEXT, VBORDER_TEXT, VLC_TRUE );
116     add_integer( "mosaic-hborder", 0, NULL, HBORDER_TEXT, HBORDER_TEXT, VLC_TRUE );
117
118     add_integer( "mosaic-position", 0, NULL, POS_TEXT, POS_LONGTEXT, VLC_FALSE );
119         change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
120     add_integer( "mosaic-rows", 2, NULL, ROWS_TEXT, ROWS_TEXT, VLC_FALSE );
121     add_integer( "mosaic-cols", 2, NULL, COLS_TEXT, COLS_TEXT, VLC_FALSE );
122     add_bool( "mosaic-keep-aspect-ratio", 0, NULL, AR_TEXT, AR_TEXT, VLC_FALSE );
123     add_string( "mosaic-order", "", NULL, ORDER_TEXT, ORDER_TEXT, VLC_FALSE );
124 vlc_module_end();
125
126
127 /*****************************************************************************
128 * CreateFiler: allocates mosaic video filter
129 *****************************************************************************/
130
131 static int CreateFilter( vlc_object_t *p_this )
132 {
133     filter_t *p_filter = (filter_t *)p_this;
134     filter_sys_t *p_sys;
135     char *psz_order;
136     int i_index;
137
138     /* Allocate structure */
139     p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
140     if( p_sys == NULL )
141     {
142         msg_Err( p_filter, "out of memory" );
143         return VLC_ENOMEM;
144     }
145     p_sys->p_image = image_HandlerCreate( p_filter );
146     p_sys->p_image2 = image_HandlerCreate( p_filter );
147
148     p_filter->pf_sub_filter = Filter;
149     p_sys->p_pic = NULL;
150
151     p_sys->i_width = __MAX( 0, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-width" ) );
152     p_sys->i_height = __MAX( 0, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-height" ) );
153
154     p_sys->i_xoffset = __MAX( 0, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-xoffset" ) );
155     p_sys->i_yoffset = __MAX( 0, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-yoffset" ) );
156
157     p_sys->i_vborder = __MAX( 0, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-vborder" ) );
158     p_sys->i_hborder = __MAX( 0, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-hborder" ) );
159
160     p_sys->i_rows = __MAX( 1, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-rows") );
161     p_sys->i_cols = __MAX( 1, var_CreateGetInteger( p_filter->p_libvlc, "mosaic-cols") );
162
163     p_sys->i_alpha = var_CreateGetInteger( p_filter->p_libvlc, "mosaic-alpha" );
164     p_sys->i_alpha = __MIN( 255, __MAX( 0, p_sys->i_alpha ) );
165
166     p_sys->i_pos = var_CreateGetInteger( p_filter->p_libvlc, "mosaic-position" );
167     if( p_sys->i_pos > 1 || p_sys->i_pos < 0 ) p_sys->i_pos = 0;
168
169     p_sys->i_ar = var_CreateGetInteger( p_filter->p_libvlc, "mosaic-keep-aspect-ratio" );
170
171     p_sys->i_order_length = 0;
172     p_sys->ppsz_order = NULL;
173     psz_order = var_CreateGetString( p_filter->p_libvlc, "mosaic-order" );
174
175     if( psz_order[0] != 0 )
176     {
177         char* psz_end=NULL;
178         i_index = 0;
179         do
180         { 
181             psz_end = strchr( psz_order, ',' );
182             i_index++;
183             p_sys->ppsz_order = realloc( p_sys->ppsz_order,
184                                          i_index * sizeof(char *) );
185             p_sys->ppsz_order[i_index - 1] = strndup( psz_order,
186                                            psz_end - psz_order );
187             psz_order = psz_end+1;
188         } while( NULL !=  psz_end );
189         p_sys->i_order_length = i_index;
190     }
191
192     var_AddCallback( p_filter->p_libvlc, "mosaic-alpha",
193                      MosaicCallback, p_sys );
194     var_AddCallback( p_filter->p_libvlc, "mosaic-height",
195                      MosaicCallback, p_sys );
196     var_AddCallback( p_filter->p_libvlc, "mosaic-width",
197                      MosaicCallback, p_sys );
198     var_AddCallback( p_filter->p_libvlc, "mosaic-xoffset",
199                      MosaicCallback, p_sys );
200     var_AddCallback( p_filter->p_libvlc, "mosaic-yoffset",
201                      MosaicCallback, p_sys );
202     var_AddCallback( p_filter->p_libvlc, "mosaic-vborder",
203                      MosaicCallback, p_sys );
204     var_AddCallback( p_filter->p_libvlc, "mosaic-hborder",
205                      MosaicCallback, p_sys );
206     var_AddCallback( p_filter->p_libvlc, "mosaic-position",
207                      MosaicCallback, p_sys );
208     var_AddCallback( p_filter->p_libvlc, "mosaic-rows",
209                      MosaicCallback, p_sys );
210     var_AddCallback( p_filter->p_libvlc, "mosaic-cols",
211                      MosaicCallback, p_sys );
212     var_AddCallback( p_filter->p_libvlc, "mosaic-keep-aspect-ratio",
213                      MosaicCallback, p_sys );
214
215     return VLC_SUCCESS;
216 }
217
218 /*****************************************************************************
219 * DestroyFilter: destroy mosaic video filter
220 *****************************************************************************/
221
222 static void DestroyFilter( vlc_object_t *p_this )
223 {
224     filter_t *p_filter = (filter_t*)p_this;
225     filter_sys_t *p_sys = p_filter->p_sys;
226     int i_index;
227
228     image_HandlerDelete( p_sys->p_image );
229     image_HandlerDelete( p_sys->p_image2 );
230
231     if( p_sys->i_order_length )
232     {
233         for( i_index = 0; i_index < p_sys->i_order_length; i_index++ )
234         {
235             free( p_sys->ppsz_order[i_index] );
236         }
237         free( p_sys->ppsz_order );
238     }
239
240     var_Destroy( p_filter->p_libvlc, "mosaic-alpha" );
241     var_Destroy( p_filter->p_libvlc, "mosaic-height" );
242     var_Destroy( p_filter->p_libvlc, "mosaic-width" );
243     var_Destroy( p_filter->p_libvlc, "mosaic-xoffset" );
244     var_Destroy( p_filter->p_libvlc, "mosaic-yoffset" );
245     var_Destroy( p_filter->p_libvlc, "mosaic-vborder" );
246     var_Destroy( p_filter->p_libvlc, "mosaic-hborder" );
247     var_Destroy( p_filter->p_libvlc, "mosaic-position" );
248     var_Destroy( p_filter->p_libvlc, "mosaic-rows" );
249     var_Destroy( p_filter->p_libvlc, "mosaic-cols" );
250     var_Destroy( p_filter->p_libvlc, "mosaic-keep-aspect-ratio" );
251     if( p_sys->p_pic ) p_sys->p_pic->pf_release( p_sys->p_pic );
252     free( p_sys );
253 }
254
255 /*****************************************************************************
256 * Filter
257 *****************************************************************************/
258
259 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
260 {
261
262     filter_sys_t *p_sys = p_filter->p_sys;
263     subpicture_t *p_spu;
264
265     libvlc_t *p_libvlc = p_filter->p_libvlc;
266     vlc_value_t val;
267     int i_index, i_real_index, i_row, i_col;
268     int i_greatest_real_index_used = p_sys->i_order_length - 1;
269
270     subpicture_region_t *p_region;
271     subpicture_region_t *p_region_prev = NULL;
272
273     struct picture_vout_t *p_picture_vout;
274
275     if( var_Get( p_libvlc, "p_picture_vout", &val ) )
276     {
277         return NULL;
278     }
279
280     p_picture_vout = val.p_address;
281
282     /* Allocate the subpicture internal data. */
283     p_spu = p_filter->pf_sub_buffer_new( p_filter );
284     if( !p_spu )
285     {
286         return NULL;
287     }
288
289     /* Initialize subpicture */
290     p_spu->i_channel = 0;
291     p_spu->i_start  = date;
292     p_spu->i_stop = 0;
293     p_spu->b_ephemer = VLC_TRUE;
294     p_spu->i_alpha = p_sys->i_alpha;
295
296     vlc_mutex_lock( &p_picture_vout->lock );
297
298     if( p_sys->i_pos == 0 ) /* use automatic positioning */
299     {
300         int i_numpics = p_sys->i_order_length; /* keep slots and all */
301         for( i_index = 0 ;
302              i_index < p_picture_vout->i_picture_num ;
303              i_index ++ )
304         {
305             if( p_picture_vout->p_pic[i_index].i_status
306                            == PICTURE_VOUT_E_OCCUPIED ) {
307                 i_numpics ++;
308                 if( p_sys->i_order_length
309                     && p_picture_vout->p_pic[i_index].psz_id != 0 ){
310                 /* we also want to leave slots for images given in mosaic-order
311                 that are not available in p_vout_picture */
312                     int i;
313                     for( i = 0; i < p_sys->i_order_length ; i++ )
314                     {
315                         if( ! strcmp( p_sys->ppsz_order[i],
316                                     p_picture_vout->p_pic[i_index].psz_id ) )
317                         {
318                             i_numpics --;
319                             break;
320                         }
321                     }
322
323                 }
324             }
325         }
326         p_sys->i_rows = ((int)ceil(sqrt( (float)i_numpics )));
327         p_sys->i_cols = ( i_numpics%p_sys->i_rows == 0 ?
328                             i_numpics/p_sys->i_rows :
329                             i_numpics/p_sys->i_rows + 1 );
330     }
331
332     i_real_index = 0;
333
334     for( i_index = 0 ; i_index < p_picture_vout->i_picture_num ; i_index ++ )
335     {
336
337         video_format_t fmt_in = {0}, fmt_middle = {0}, fmt_out = {0};
338
339         picture_t *p_converted, *p_middle;
340
341         if(  p_picture_vout->p_pic[i_index].p_picture == NULL )
342         {
343             break;
344         }
345
346         if(  p_picture_vout->p_pic[i_index].i_status
347                == PICTURE_VOUT_E_AVAILABLE )
348         {
349             msg_Dbg( p_filter, "Picture Vout Element is empty");
350             break;
351         }
352         if( p_sys->i_order_length == 0 )
353             i_real_index ++;
354         else
355         {
356             int i;
357             for( i =0; i <= p_sys->i_order_length; i++ )
358             {
359                 if( i == p_sys->i_order_length ) break;
360                 if( strcmp( p_picture_vout->p_pic[i_index].psz_id,
361                     p_sys->ppsz_order[ i ] ) == 0 )
362                 {
363                     i_real_index = i;
364                     break;
365                 }
366             }
367             if( i == p_sys->i_order_length )
368                 i_real_index = ++i_greatest_real_index_used;
369         }
370         i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows ;
371         i_col = i_real_index % p_sys->i_cols ;
372
373         /* Convert the images */
374 /*        fprintf (stderr, "Input image %ix%i %4.4s\n",
375                   p_picture_vout->p_pic[i_index].p_picture->format.i_width,
376                   p_picture_vout->p_pic[i_index].p_picture->format.i_height,
377                   (char *)&p_picture_vout->p_pic[i_index].p_picture->format.i_chroma );*/
378
379         fmt_in.i_chroma = p_picture_vout->p_pic[i_index].
380                                                 p_picture->format.i_chroma;
381         fmt_in.i_height = p_picture_vout->p_pic[i_index].
382                                                 p_picture->format.i_height;
383         fmt_in.i_width = p_picture_vout->p_pic[i_index].
384                                                 p_picture->format.i_width;
385
386
387         fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
388         fmt_out.i_width = fmt_in.i_width *
389             ( ( p_sys->i_width - ( p_sys->i_cols - 1 ) * p_sys->i_vborder )
390               / p_sys->i_cols ) / fmt_in.i_width;
391         fmt_out.i_height = fmt_in.i_height *
392             ( ( p_sys->i_height - ( p_sys->i_rows - 1 ) * p_sys->i_hborder )
393               / p_sys->i_rows ) / fmt_in.i_height;
394         if( p_sys->i_ar ) /* keep aspect ratio */
395         {
396             if( (float)fmt_out.i_width/(float)fmt_out.i_height
397                 > (float)fmt_in.i_width/(float)fmt_in.i_height )
398             {
399                 fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width ) / fmt_in.i_height ;
400             } else {
401                 fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height ) / fmt_in.i_width ;
402             }
403          }
404
405         fmt_out.i_visible_width = fmt_out.i_width;
406         fmt_out.i_visible_height = fmt_out.i_height;
407
408         fmt_middle.i_chroma = fmt_in.i_chroma;
409         fmt_middle.i_visible_width = fmt_middle.i_width = fmt_out.i_width;
410         fmt_middle.i_visible_height = fmt_middle.i_height = fmt_out.i_height;
411
412         p_middle = image_Convert( p_sys->p_image,
413             p_picture_vout->p_pic[i_index].p_picture, &fmt_in, &fmt_middle );
414         if( !p_middle )
415         {
416             msg_Err( p_filter, "image resizing failed" );
417             p_filter->pf_sub_buffer_del( p_filter, p_spu );
418             vlc_mutex_unlock( &p_picture_vout->lock );
419             return NULL;
420         }
421
422         p_converted = image_Convert( p_sys->p_image2,
423                  p_middle, &fmt_middle, &fmt_out );
424         if( !p_converted )
425         {
426             msg_Err( p_filter, "image chroma convertion failed" );
427             p_filter->pf_sub_buffer_del( p_filter, p_spu );
428             vlc_mutex_unlock( &p_picture_vout->lock );
429             return NULL;
430         }
431
432 /*        fprintf( stderr, "Converted %ix%i %4.4s\n", p_converted->format.i_width, p_converted->format.i_height, (char *)&p_converted->format.i_chroma);*/
433
434
435         p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt_out);
436         if( !p_region )
437         {
438             msg_Err( p_filter, "cannot allocate SPU region" );
439             p_filter->pf_sub_buffer_del( p_filter, p_spu );
440             vlc_mutex_unlock( &p_picture_vout->lock );
441             return NULL;
442         }
443
444         if( p_sys->i_ar ) /* keep aspect ratio */
445         {
446             /* center the video in the dedicated rectangle */
447             p_region->i_x = p_sys->i_xoffset
448                             + i_col * ( p_sys->i_width / p_sys->i_cols )
449                             + ( i_col * p_sys->i_vborder ) / p_sys->i_cols
450                         + ( fmt_in.i_width *
451             ( ( p_sys->i_width - ( p_sys->i_cols - 1 ) * p_sys->i_vborder )
452               / p_sys->i_cols ) / fmt_in.i_width - fmt_out.i_width ) / 2;
453             p_region->i_y = p_sys->i_yoffset
454                         + i_row * ( p_sys->i_height / p_sys->i_rows )
455                         + ( i_row * p_sys->i_hborder ) / p_sys->i_rows
456                         + ( fmt_in.i_height *
457             ( ( p_sys->i_height - ( p_sys->i_rows - 1 ) * p_sys->i_hborder )
458               / p_sys->i_rows ) / fmt_in.i_height - fmt_out.i_height ) / 2;
459         } else {
460             /* we don't have to center the video since it takes the
461             whole rectangle area */
462             p_region->i_x = p_sys->i_xoffset
463                             + i_col * ( p_sys->i_width / p_sys->i_cols )
464                             + ( i_col * p_sys->i_vborder ) / p_sys->i_cols;
465             p_region->i_y = p_sys->i_yoffset
466                         + i_row * ( p_sys->i_height / p_sys->i_rows )
467                         + ( i_row * p_sys->i_hborder ) / p_sys->i_rows;
468         }
469
470         if( p_region_prev == NULL ){
471             p_spu->p_region = p_region;
472         } else {
473             p_region_prev->p_next = p_region;
474         }
475
476         p_region_prev = p_region;
477
478         vout_CopyPicture( p_filter, &p_region->picture, p_converted );
479
480         p_middle->pf_release( p_middle );
481         p_converted->pf_release( p_converted );
482     }
483
484     vlc_mutex_unlock( &p_picture_vout->lock );
485
486     return p_spu;
487 }
488
489 /*****************************************************************************
490 * Callback to update params on the fly
491 *****************************************************************************/
492
493 static int MosaicCallback( vlc_object_t *p_this, char const *psz_var,
494                             vlc_value_t oldval, vlc_value_t newval,
495                             void *p_data )
496 {
497     filter_sys_t *p_sys = (filter_sys_t *) p_data;
498     if( !strcmp( psz_var, "mosaic-alpha" ) )
499     {
500         msg_Dbg( p_this, "Changing alpha from %d/255 to %d/255",
501                          p_sys->i_alpha, newval.i_int);
502         p_sys->i_alpha = __MIN( __MAX( newval.i_int, 0 ), 255 );
503     }
504     else if( !strcmp( psz_var, "mosaic-height" ) )
505     {
506         msg_Dbg( p_this, "Changing height from %dpx to %dpx",
507                           p_sys->i_height, newval.i_int );
508         p_sys->i_height = __MAX( newval.i_int, 0 );
509     }
510     else if( !strcmp( psz_var, "mosaic-width" ) )
511     {
512         msg_Dbg( p_this, "Changing width from %dpx to %dpx",
513                          p_sys->i_width, newval.i_int );
514         p_sys->i_width = __MAX( newval.i_int, 0 );
515     }
516     else if( !strcmp( psz_var, "mosaic-xoffset" ) )
517     {
518         msg_Dbg( p_this, "Changing x offset from %dpx to %dpx",
519                          p_sys->i_xoffset, newval.i_int );
520         p_sys->i_xoffset = __MAX( newval.i_int, 0 );
521     }
522     else if( !strcmp( psz_var, "mosaic-yoffset" ) )
523     {
524         msg_Dbg( p_this, "Changing y offset from %dpx to %dpx",
525                          p_sys->i_yoffset, newval.i_int );
526         p_sys->i_yoffset = __MAX( newval.i_int, 0 );
527     }
528     else if( !strcmp( psz_var, "mosaic-vborder" ) )
529     {
530         msg_Dbg( p_this, "Changing vertical border from %dpx to %dpx",
531                          p_sys->i_vborder, newval.i_int );
532         p_sys->i_vborder = __MAX( newval.i_int, 0 );
533     }
534     else if( !strcmp( psz_var, "mosaic-hborder" ) )
535     {
536         msg_Dbg( p_this, "Changing horizontal border from %dpx to %dpx",
537                          p_sys->i_vborder, newval.i_int );
538         p_sys->i_hborder = __MAX( newval.i_int, 0 );
539     }
540     else if( !strcmp( psz_var, "mosaic-position" ) )
541     {
542         if( newval.i_int > 1 || newval.i_int < 0 )
543         {
544             msg_Err( p_this, "Position is either 0 (auto) or 1 (fixed)" );
545         }
546         else
547         {
548             msg_Dbg( p_this, "Changing position method from %d (%s) to %d (%s)",
549                              p_sys->i_pos, ppsz_pos_descriptions[p_sys->i_pos],
550                              newval.i_int, ppsz_pos_descriptions[newval.i_int]);
551             p_sys->i_pos = newval.i_int;
552         }
553     }
554     else if( !strcmp( psz_var, "mosaic-rows" ) )
555     {
556         msg_Dbg( p_this, "Changing number of rows from %d to %d",
557                          p_sys->i_rows, newval.i_int );
558         p_sys->i_rows = __MAX( newval.i_int, 1 );
559     }
560     else if( !strcmp( psz_var, "mosaic-cols" ) )
561     {
562         msg_Dbg( p_this, "Changing number of columns from %d to %d",
563                          p_sys->i_cols, newval.i_int );
564         p_sys->i_cols = __MAX( newval.i_int, 1 );
565     }
566     else if( !strcmp( psz_var, "mosaic-keep-aspect-ratio" ) )
567     {
568         if( newval.i_int )
569         {
570             msg_Dbg( p_this, "Keep aspect ratio" );
571             p_sys->i_ar = 1;
572         }
573         else
574         {
575             msg_Dbg( p_this, "Don't keep aspect ratio" );
576             p_sys->i_ar = 0;
577         }
578     }
579     return VLC_SUCCESS;
580 }