[vlc-devel] [PATCH] mosaic improvement: user-defined offsets for substreams

Thomas Parmelan tom+vlc at ankh.fr.EU.org
Fri Sep 22 21:03:33 CEST 2006


Hi,

The patch below adds to the mosaic filter plugin a third positioning
mode named "offsets" in which the position of each substream image is
completely defined by the user. More precisely, he can fix the (x,y)
offsets of the top-left corner of each substream image, relative to the
tof-left corner of the mosaic.

It is therefore possible to put each image exactly where one wishes
(yes, this really means that the mosaic is not necessarily in the usual
form of well-aligned rows and columns!).

The offsets listed in mosaic-offsets are parsed as (x,y) pairs, each
pair applies to the substream specified at the same position in the
mosaic-order parameter (mosaic-order is mandatory when using this
positioning mode).

Sample configuration:

----- 8< -----[ mosaic.vlm ]----- 8< -----
new   source1 broadcast enabled
setup source1 input ....
setup source1 output #duplicate{dst=mosaic-bridge{id=1,height=96,width=128},select=video,dst=bridge-out{id=1},select=audio}

new   source2 broadcast enabled
setup source2 input ....
setup source2 output #duplicate{dst=mosaic-bridge{id=2,height=96,width=128},select=video,dst=bridge-out{id=2},select=audio}

new   source3 broadcast enabled
setup source3 input ....
setup source3 output #duplicate{dst=mosaic-bridge{id=3,height=96,width=128},select=video,dst=bridge-out{id=3},select=audio}

new   background broadcast enabled
setup background input fake:
setup background output #transcode{sfilter=mosaic,vcodec=mp2v,vb=10000,scale=1}:bridge-in{delay=0,id-offset=100}:standard{access
=http,mux=ts,url=192.168.1.1:8080,name="mosaic"}

control background play
control source1 play
control source2 play
control source3 play
----- 8< -----[ mosaic.vlm ]----- 8< -----

And run vlc like this :

vlc -I telnet --vlm-conf mosaic.vlm \
  --fake-file background.png --fake-aspect-ratio "4:3" \
  --mosaic-width 720 --mosaic-height 576 --udp-caching 800 \
  --mosaic-keep-aspect-ratio --mosaic-keep-picture \
  --mosaic-position 2 --mosaic-order 1,2,3 \
  --mosaic-offsets 100,100,200,200,300,300

to have the three images at (100,100), (200, 200) and (300, 300).

The offsets values are not verified against the size of the mosaic (vlc
will crop it anyway). If positions overlap, I think the one on top will
be the last one defined in the vlm. Maybe there's something to add there
if someone cares.

This is my first contact with vlc internals, I hope I did things
correctly. Please note the patch is against the 0.8.6 branch of the SVN,
because this is what I used to develop it.

Regards,
Tom


Index: modules/control/rc.c
===================================================================
--- modules/control/rc.c	(revision 16781)
+++ modules/control/rc.c	(working copy)
@@ -434,6 +434,8 @@
     var_AddCallback( p_intf, "mosaic-rows", Other, NULL );
     var_Create( p_intf, "mosaic-cols", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
     var_AddCallback( p_intf, "mosaic-cols", Other, NULL );
+    var_Create( p_intf, "mosaic-offsets", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
+    var_AddCallback( p_intf, "mosaic-offsets", Other, NULL );
     var_Create( p_intf, "mosaic-keep-aspect-ratio",
                      VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
     var_AddCallback( p_intf, "mosaic-keep-aspect-ratio", Other, NULL );
@@ -1666,6 +1668,14 @@
             var_Set( p_input->p_libvlc, "mosaic-cols", val );
         }
     }
+    else if( !strcmp( psz_cmd, "mosaic-offsets" ) )
+    {
+	if( strlen( newval.psz_string ) > 0)
+	{
+	    val.psz_string = newval.psz_string;
+	    var_Set( p_input->p_libvlc, "mosaic-offsets", val );
+	}
+    }
     else if( !strcmp( psz_cmd, "mosaic-keep-aspect-ratio" ) )
     {
         if( strlen( newval.psz_string ) > 0)
Index: modules/video_filter/mosaic.c
===================================================================
--- modules/video_filter/mosaic.c	(revision 16781)
+++ modules/video_filter/mosaic.c	(working copy)
@@ -81,6 +81,10 @@
     char **ppsz_order; /* list of picture-id */
     int i_order_length;
 
+    int *pi_x_offsets; /* list of substreams x offsets */
+    int *pi_y_offsets; /* list of substreams y offsets */
+    int i_offsets_length;
+
     mtime_t i_delay;
 };
 
@@ -116,7 +120,8 @@
 #define POS_TEXT N_("Positioning method")
 #define POS_LONGTEXT N_("Positioning method for the mosaic. auto: " \
         "automatically choose the best number of rows and columns. " \
-        "fixed: use the user-defined number of rows and columns.")
+        "fixed: use the user-defined number of rows and columns. " \
+        "offsets: use the user-defined offsets for each image." )
 
 /// \bug [String] missing closing parenthesis
 #define ROWS_TEXT N_("Number of rows")
@@ -137,6 +142,11 @@
         "the mosaic. You must give a comma-separated list of picture ID(s)." \
         "These IDs are assigned in the \"mosaic-bridge\" module." )
 
+#define OFFSETS_TEXT N_("Offsets in order" )
+#define OFFSETS_LONGTEXT N_( "You can enforce the (x,y) offsets of the elements on " \
+        "the mosaic (only used if positioning method is set to \"offsets\"). You " \
+        "must give a comma-separated list of coordinates (eg: 10,10,150,10)." )
+
 #define DELAY_TEXT N_("Delay")
 #define DELAY_LONGTEXT N_("Pictures coming from the mosaic elements " \
         "will be delayed according to this value (in milliseconds). For high " \
@@ -163,9 +173,9 @@
         "on color variations for the V plane. A value between 10 and 20 " \
         "seems sensible." )
 
-static int pi_pos_values[] = { 0, 1 };
+static int pi_pos_values[] = { 0, 1, 2 };
 static char * ppsz_pos_descriptions[] =
-{ N_("auto"), N_("fixed") };
+{ N_("auto"), N_("fixed"), N_("offsets") };
 
 static int pi_align_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
 static char *ppsz_align_descriptions[] =
@@ -198,6 +208,7 @@
     add_bool( "mosaic-keep-aspect-ratio", 0, NULL, AR_TEXT, AR_LONGTEXT, VLC_FALSE );
     add_bool( "mosaic-keep-picture", 0, NULL, KEEP_TEXT, KEEP_LONGTEXT, VLC_FALSE );
     add_string( "mosaic-order", "", NULL, ORDER_TEXT, ORDER_LONGTEXT, VLC_FALSE );
+    add_string( "mosaic-offsets", "", NULL, OFFSETS_TEXT, OFFSETS_LONGTEXT, VLC_FALSE );
 
     add_integer( "mosaic-delay", 0, NULL, DELAY_TEXT, DELAY_LONGTEXT,
                  VLC_FALSE );
@@ -218,6 +229,38 @@
 
 
 /*****************************************************************************
+ * mosaic_ParseSetOffsets:
+ * parse the "--mosaic-offsets x1,y1,x2,y2,x3,y3" parameter
+ * and set the corresponding struct filter_sys_t entries.
+ *****************************************************************************/
+void mosaic_ParseSetOffsets( vlc_object_t *p_this, filter_sys_t *p_sys, char *psz_offsets )
+{
+    if( psz_offsets[0] != 0 )
+    {
+        char *psz_end = NULL;
+        int i_index = 0;
+        do
+        {
+            i_index++;
+
+            p_sys->pi_x_offsets = realloc( p_sys->pi_x_offsets, i_index * sizeof(int) );
+            p_sys->pi_x_offsets[i_index - 1] = atoi( psz_offsets );
+            psz_end = strchr( psz_offsets, ',' );
+            psz_offsets = psz_end + 1;
+
+            p_sys->pi_y_offsets = realloc( p_sys->pi_y_offsets, i_index * sizeof(int) );
+            p_sys->pi_y_offsets[i_index - 1] = atoi( psz_offsets );
+            psz_end = strchr( psz_offsets, ',' );
+            psz_offsets = psz_end + 1;
+
+            msg_Dbg( p_this, "mosaic-offset: id %d, x=%d, y=%d", i_index, p_sys->pi_x_offsets[i_index - 1], p_sys->pi_y_offsets[i_index - 1] );
+
+        } while( NULL != psz_end );
+        p_sys->i_offsets_length = i_index;
+    }
+}
+
+/*****************************************************************************
  * CreateFiler: allocate mosaic video filter
  *****************************************************************************/
 static int CreateFilter( vlc_object_t *p_this )
@@ -226,6 +269,7 @@
     filter_sys_t *p_sys;
     libvlc_t *p_libvlc = p_filter->p_libvlc;
     char *psz_order;
+    char *psz_offsets;
     int i_index;
     vlc_value_t val;
 
@@ -275,7 +319,7 @@
     GET_VAR( rows, 1, INT_MAX );
     GET_VAR( cols, 1, INT_MAX );
     GET_VAR( alpha, 0, 255 );
-    GET_VAR( position, 0, 1 );
+    GET_VAR( position, 0, 2 );
     GET_VAR( delay, 100, INT_MAX );
     p_sys->i_delay *= 1000;
 
@@ -313,6 +357,17 @@
         p_sys->i_order_length = i_index;
     }
 
+    /* Manage specific offsets for substreams */
+    psz_offsets = var_CreateGetString( p_filter, "mosaic-offsets" );
+    var_Destroy( p_filter, "mosaic-offsets" );
+    p_sys->i_offsets_length = 0;
+    p_sys->pi_x_offsets = NULL;
+    p_sys->pi_y_offsets = NULL;
+    mosaic_ParseSetOffsets( (vlc_object_t *) p_filter, p_sys, psz_offsets );
+    var_Create( p_libvlc, "mosaic-offsets", VLC_VAR_STRING);
+    var_SetString( p_libvlc, "mosaic-offsets", psz_offsets );
+    var_AddCallback( p_libvlc, "mosaic-offsets", MosaicCallback, p_sys );
+
     /* Bluescreen specific stuff */
     GET_VAR( bsu, 0x00, 0xff );
     GET_VAR( bsv, 0x00, 0xff );
@@ -360,6 +415,14 @@
         free( p_sys->ppsz_order );
     }
 
+    if( p_sys->i_offsets_length )
+    {
+        free( p_sys->pi_x_offsets );
+        free( p_sys->pi_y_offsets );
+        p_sys->i_offsets_length = 0;
+    }
+    var_Destroy( p_libvlc, "mosaic-offsets" );
+
     var_Destroy( p_libvlc, "mosaic-alpha" );
     var_Destroy( p_libvlc, "mosaic-height" );
     var_Destroy( p_libvlc, "mosaic-align" );
@@ -440,6 +503,17 @@
         return p_spu;
     }
 
+    if ( p_sys->i_position == 2 ) /* user-defined offsets for positioning */
+    {
+        /* If we have either too much or not enough offsets, fall-back
+         * to automatic positioning. */
+        if ( p_sys->i_offsets_length != p_sys->i_order_length )
+        {
+            msg_Err( p_filter, "Number of specified offsets (%d) does not match number of input substreams in mosaic-order (%d), falling back to mosaic-position=0", p_sys->i_offsets_length, p_sys->i_order_length );
+            p_sys->i_position = 0;
+        }
+    }
+
     if ( p_sys->i_position == 0 ) /* use automatic positioning */
     {
         int i_numpics = p_sys->i_order_length; /* keep slots and all */
@@ -694,7 +768,11 @@
             p_region->picture.pf_release = MosaicReleasePicture;
         }
 
-        if( fmt_out.i_width > col_inner_width ||
+        if( p_sys->i_position == 2 ) /* user-defined offset */
+        {
+            p_region->i_x = p_sys->pi_x_offsets[i_real_index];
+        }
+        else if( fmt_out.i_width > col_inner_width ||
             p_sys->b_ar || p_sys->b_keep )
         {
             /* we don't have to center the video since it takes the
@@ -712,7 +790,11 @@
                     + ( col_inner_width - fmt_out.i_width ) / 2;
         }
 
-        if( fmt_out.i_height < row_inner_height
+        if( p_sys->i_position == 2 ) /* user-defined offset */
+        {
+            p_region->i_y = p_sys->pi_y_offsets[i_real_index];
+        }
+        else if( fmt_out.i_height < row_inner_height
             || p_sys->b_ar || p_sys->b_keep )
         {
             /* we don't have to center the video since it takes the
@@ -859,6 +941,22 @@
         p_sys->i_cols = __MAX( newval.i_int, 1 );
         vlc_mutex_unlock( &p_sys->lock );
     }
+    else if( !strcmp( psz_var, "mosaic-offsets" ) )
+    {
+        vlc_mutex_lock( &p_sys->lock );
+        msg_Info( p_this, "Changing mosaic-offsets to %s", newval.psz_string );
+
+        if( p_sys->i_offsets_length != 0 )
+        {
+            free( p_sys->pi_x_offsets );
+            free( p_sys->pi_y_offsets );
+        }
+        p_sys->i_offsets_length = 0;
+
+        mosaic_ParseSetOffsets( (vlc_object_t *) p_this, p_sys, newval.psz_string );
+
+        vlc_mutex_unlock( &p_sys->lock );
+    }
     else if( !strcmp( psz_var, "mosaic-keep-aspect-ratio" ) )
     {
         vlc_mutex_lock( &p_sys->lock );

-- 
Thomas Parmelan

-- 
This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
To unsubscribe, please read http://developers.videolan.org/lists.html



More information about the vlc-devel mailing list