]> git.sesse.net Git - vlc/commitdiff
* ALL: converted the video output module "picture" to a stream output
authorChristophe Massiot <massiot@videolan.org>
Fri, 15 Apr 2005 20:01:19 +0000 (20:01 +0000)
committerChristophe Massiot <massiot@videolan.org>
Fri, 15 Apr 2005 20:01:19 +0000 (20:01 +0000)
   module "mosaic-bridge".

configure.ac
modules/stream_out/Modules.am
modules/stream_out/bridge.c
modules/stream_out/mosaic_bridge.c [new file with mode: 0644]
modules/video_filter/Modules.am
modules/video_filter/mosaic.c
modules/video_filter/mosaic.h [moved from modules/video_output/picture.h with 63% similarity]
modules/video_output/Modules.am
modules/video_output/picture.c [deleted file]

index 17de8c99358df7e788dbf10c0f94a6d5afba257e..2bb1a97e187c240c3736dba81ab3d82dd92e1d3f 100644 (file)
@@ -986,7 +986,7 @@ if test "${SYS}" != "mingwce"; then
   VLC_ADD_PLUGINS([externrun])
   VLC_ADD_PLUGINS([access_fake access_filter_timeshift])
   VLC_ADD_PLUGINS([gestures rc telnet hotkeys netsync showintf time marq sap shout])
-  VLC_ADD_PLUGINS([picture mosaic wall motiondetect clone crop])
+  VLC_ADD_PLUGINS([mosaic wall motiondetect clone crop])
   VLC_ADD_PLUGINS([i420_yuy2 i422_yuy2 i420_ymga])
   VLC_ADD_PLUGINS([aout_file linear_resampler bandlimited_resampler])
   VLC_ADD_PLUGINS([float32_mixer spdif_mixer simple_channel_mixer])
@@ -1227,7 +1227,7 @@ then
   VLC_ADD_PLUGINS([packetizer_copy])
 
   VLC_ADD_PLUGINS([stream_out_dummy stream_out_standard stream_out_es stream_out_rtp stream_out_description vod_rtsp])
-  VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display stream_out_transcode stream_out_bridge])
+  VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display stream_out_transcode stream_out_bridge stream_out_mosaic_bridge])
 #  VLC_ADD_PLUGINS([stream_out_transrate])
 
   AC_DEFINE(ENABLE_SOUT, 1, Define if you want the stream output support)
@@ -2533,7 +2533,7 @@ AC_ARG_ENABLE(speex,
 if test "${enable_speex}" != "no"
 then
   AC_CHECK_HEADERS(speex/speex.h, [
-    LDFLAGS="${LDFLAGS_save} ${LDFLAGS_toolame}"
+    LDFLAGS="${LDFLAGS_save} ${LDFLAGS_speex}"
     AC_CHECK_LIB(speex, speex_decode_int, [
       VLC_ADD_PLUGINS([speex])
       VLC_ADD_LDFLAGS([speex],[-lspeex]) ],
index 5693036be59410372534ac9baeaa0065323e7df9..a1c03bcf25ad4a6905f8a1dd41bffa3dbb47c555 100644 (file)
@@ -11,3 +11,4 @@ SOURCES_stream_out_gather = gather.c
 SOURCES_stream_out_rtp = rtp.c
 SOURCES_stream_out_switcher = switcher.c
 SOURCES_stream_out_bridge = bridge.c
+SOURCES_stream_out_mosaic_bridge = mosaic_bridge.c
index b2cfc522b50b065d1b508fe2d918224704ab5c01..1b24f663d9ed15a7472f46a09b6b8806aa22d71f 100644 (file)
@@ -58,7 +58,7 @@ vlc_module_begin();
     set_shortname( _("Bridge"));
     set_description( _("Bridge stream output"));
     add_submodule();
-    set_section( N_("Bridge out"),NULL);
+    set_section( N_("Bridge out"), NULL );
     set_capability( "sout stream", 50 );
     add_shortcut( "bridge-out" );
     /* Only usable with VLM. No category so not in gui preferences
@@ -69,12 +69,12 @@ vlc_module_begin();
     set_callbacks( OpenOut, CloseOut );
 
     add_submodule();
-    set_section( N_("Bridge in"),NULL);
+    set_section( N_("Bridge in"), NULL );
     set_capability( "sout stream", 50 );
     add_shortcut( "bridge-in" );
     /*set_category( CAT_SOUT );
     set_subcategory( SUBCAT_SOUT_STREAM );*/
-    add_integer( SOUT_CFG_PREFIX_IN "delay", 100, NULL, DELAY_TEXT,
+    add_integer( SOUT_CFG_PREFIX_IN "delay", 0, NULL, DELAY_TEXT,
                  DELAY_LONGTEXT, VLC_FALSE );
     add_integer( SOUT_CFG_PREFIX_IN "id-offset", 8192, NULL, ID_OFFSET_TEXT,
                  ID_OFFSET_LONGTEXT, VLC_FALSE );
@@ -109,7 +109,6 @@ typedef struct bridged_es_t
     block_t *p_block;
     block_t **pp_last;
     vlc_bool_t b_empty;
-    int i_id;
 
     /* bridge in part */
     sout_stream_id_t *id;
@@ -150,9 +149,9 @@ static bridge_t *__GetBridge( vlc_object_t *p_object )
 typedef struct out_sout_stream_sys_t
 {
     vlc_mutex_t *p_lock;
+    bridged_es_t *p_es;
     int i_id;
     vlc_bool_t b_inited;
-    int i_position;
 } out_sout_stream_sys_t;
 
 /*****************************************************************************
@@ -160,7 +159,7 @@ typedef struct out_sout_stream_sys_t
  *****************************************************************************/
 static int OpenOut( vlc_object_t *p_this )
 {
-    sout_stream_t     *p_stream = (sout_stream_t*)p_this;
+    sout_stream_t     *p_stream = (sout_stream_t *)p_this;
     out_sout_stream_sys_t *p_sys;
     vlc_value_t val;
 
@@ -182,7 +181,6 @@ static int OpenOut( vlc_object_t *p_this )
 
     p_stream->p_sys     = (sout_stream_sys_t *)p_sys;
 
-    /* update p_sout->i_out_pace_nocontrol */
     p_stream->p_sout->i_out_pace_nocontrol++;
 
     return VLC_SUCCESS;
@@ -243,14 +241,12 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt )
         p_bridge->pp_es = realloc( p_bridge->pp_es,
                                    (p_bridge->i_es_num + 1)
                                      * sizeof(bridged_es_t *) );
-        p_sys->i_position = p_bridge->i_es_num;
         p_bridge->i_es_num++;
         p_bridge->pp_es[i] = malloc( sizeof(bridged_es_t) );
     }
-    else
-        p_sys->i_position = i;
 
-    p_es = p_bridge->pp_es[ p_sys->i_position ];
+    p_sys->p_es = p_es = p_bridge->pp_es[i];
+
     p_es->fmt = *p_fmt;
     p_es->fmt.i_id = p_sys->i_id;
     p_es->p_block = NULL;
@@ -262,7 +258,7 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt )
     p_es->b_changed = VLC_TRUE;
 
     msg_Dbg( p_stream, "bridging out input codec=%4.4s id=%d pos=%d",
-             (char*)&p_es->fmt.i_codec, p_es->fmt.i_id, p_sys->i_position );
+             (char*)&p_es->fmt.i_codec, p_es->fmt.i_id, i );
 
     vlc_mutex_unlock( p_sys->p_lock );
 
@@ -272,7 +268,6 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt )
 static int DelOut( sout_stream_t *p_stream, sout_stream_id_t *id )
 {
     out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys;
-    bridge_t *p_bridge;
     bridged_es_t *p_es;
 
     if ( !p_sys->b_inited )
@@ -282,8 +277,7 @@ static int DelOut( sout_stream_t *p_stream, sout_stream_id_t *id )
 
     vlc_mutex_lock( p_sys->p_lock );
 
-    p_bridge = GetBridge( p_stream );
-    p_es = p_bridge->pp_es[ p_sys->i_position ];
+    p_es = p_sys->p_es;
 
     p_es->b_empty = VLC_TRUE;
     block_ChainRelease( p_es->p_block );
@@ -299,7 +293,6 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id,
                     block_t *p_buffer )
 {
     out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys;
-    bridge_t *p_bridge;
     bridged_es_t *p_es;
 
     if ( (out_sout_stream_sys_t *)id != p_sys )
@@ -310,8 +303,7 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id,
 
     vlc_mutex_lock( p_sys->p_lock );
 
-    p_bridge = GetBridge( p_stream );
-    p_es = p_bridge->pp_es[ p_sys->i_position ];
+    p_es = p_sys->p_es;
     *p_es->pp_last = p_buffer;
     while ( p_buffer != NULL )
     {
diff --git a/modules/stream_out/mosaic_bridge.c b/modules/stream_out/mosaic_bridge.c
new file mode 100644 (file)
index 0000000..41c2a98
--- /dev/null
@@ -0,0 +1,512 @@
+/*****************************************************************************
+ * mosaic_bridge.c:
+ *****************************************************************************
+ * Copyright (C) 2004-2005 VideoLAN
+ * $Id$
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *          Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>                                                 /* ENOMEM */
+#include <stdlib.h>                                                /* free() */
+#include <string.h>                                            /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/sout.h>
+#include <vlc/decoder.h>
+
+#include "vlc_image.h"
+
+#include "../video_filter/mosaic.h"
+
+/*****************************************************************************
+ * Local structures
+ *****************************************************************************/
+struct sout_stream_sys_t
+{
+    bridged_es_t *p_es;
+    vlc_mutex_t *p_lock;
+
+    decoder_t       *p_decoder;
+    image_handler_t *p_image; /* filter for resizing */
+    int i_height, i_width;
+    char *psz_id;
+    vlc_bool_t b_inited;
+};
+
+#define PICTURE_RING_SIZE 64
+struct decoder_owner_sys_t
+{
+    picture_t *pp_pics[PICTURE_RING_SIZE];
+};
+
+typedef void (* pf_release_t)( picture_t * );
+static void ReleasePicture( picture_t *p_pic )
+{
+    p_pic->i_refcount--;
+
+    if ( p_pic->i_refcount <= 0 )
+    {
+        if ( p_pic->p_sys != NULL )
+        {
+            pf_release_t pf_release = (pf_release_t)p_pic->p_sys;
+            p_pic->p_sys = NULL;
+            pf_release( p_pic );
+        }
+        else
+        {
+            if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
+            if( p_pic ) free( p_pic );
+        }
+    }
+}
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int  Open    ( vlc_object_t * );
+static void Close   ( vlc_object_t * );
+static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
+static int               Del ( sout_stream_t *, sout_stream_id_t * );
+static int               Send( sout_stream_t *, sout_stream_id_t *, block_t * );
+
+static void video_del_buffer( decoder_t *, picture_t * );
+static picture_t *video_new_buffer( decoder_t * );
+static void video_link_picture_decoder( decoder_t *, picture_t * );
+static void video_unlink_picture_decoder( decoder_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define ID_TEXT N_("ID")
+#define ID_LONGTEXT N_( \
+    "Specify an identifier string for this subpicture" )
+
+#define WIDTH_TEXT N_("Video width")
+#define WIDTH_LONGTEXT N_( \
+    "Allows you to specify the output video width." )
+#define HEIGHT_TEXT N_("Video height")
+#define HEIGHT_LONGTEXT N_( \
+    "Allows you to specify the output video height." )
+
+#define SOUT_CFG_PREFIX "sout-mosaic-bridge-"
+
+vlc_module_begin();
+    set_shortname( _( "Mosaic bridge" ) );
+    set_description(_("Mosaic bridge stream output") );
+    set_capability( "sout stream", 0 );
+    add_shortcut( "mosaic-bridge" );
+
+    add_string( SOUT_CFG_PREFIX "id", "Id", NULL, ID_TEXT, ID_LONGTEXT,
+                VLC_FALSE );
+    add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
+                 WIDTH_LONGTEXT, VLC_TRUE );
+    add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
+                 HEIGHT_LONGTEXT, VLC_TRUE );
+
+    set_callbacks( Open, Close );
+
+    var_Create( p_module->p_libvlc, "mosaic-lock", VLC_VAR_MUTEX );
+vlc_module_end();
+
+static const char *ppsz_sout_options[] = {
+    "id", "width", "height", NULL
+};
+
+/*****************************************************************************
+ * Open
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+    sout_stream_t     *p_stream = (sout_stream_t *)p_this;
+    sout_stream_sys_t *p_sys;
+    libvlc_t *p_libvlc = p_this->p_libvlc;
+    vlc_value_t val;
+
+    sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
+                   p_stream->p_cfg );
+
+    p_sys          = malloc( sizeof( sout_stream_sys_t ) );
+    p_stream->p_sys = p_sys;
+    p_sys->b_inited = VLC_FALSE;
+
+    var_Get( p_libvlc, "mosaic-lock", &val );
+    p_sys->p_lock = val.p_address;
+
+    var_Get( p_stream, SOUT_CFG_PREFIX "id", &val );
+    p_sys->psz_id = val.psz_string;
+
+    var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
+    p_sys->i_height = val.i_int; 
+
+    var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
+    p_sys->i_width = val.i_int; 
+
+    if ( p_sys->i_height || p_sys->i_width )
+    {
+        p_sys->p_image = image_HandlerCreate( p_stream );
+    }
+
+    p_stream->pf_add    = Add;
+    p_stream->pf_del    = Del;
+    p_stream->pf_send   = Send;
+
+    p_stream->p_sout->i_out_pace_nocontrol++;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close
+ *****************************************************************************/
+static void Close( vlc_object_t * p_this )
+{
+    sout_stream_t     *p_stream = (sout_stream_t*)p_this;
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+    p_stream->p_sout->i_out_pace_nocontrol--;
+
+    if ( p_sys->psz_id )
+        free( p_sys->psz_id );
+
+    free( p_sys );
+}
+
+static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
+{
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+    bridge_t *p_bridge;
+    bridged_es_t *p_es;
+    int i;
+
+    if ( p_sys->b_inited )
+    {
+        return NULL;
+    }
+
+    /* Create decoder object */
+    p_sys->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
+    vlc_object_attach( p_sys->p_decoder, p_stream );
+    p_sys->p_decoder->p_module = NULL;
+    p_sys->p_decoder->fmt_in = *p_fmt;
+    p_sys->p_decoder->b_pace_control = VLC_FALSE;
+    p_sys->p_decoder->fmt_out = p_sys->p_decoder->fmt_in;
+    p_sys->p_decoder->fmt_out.i_extra = 0;
+    p_sys->p_decoder->fmt_out.p_extra = 0;
+    p_sys->p_decoder->pf_decode_video = 0;
+    p_sys->p_decoder->pf_vout_buffer_new = video_new_buffer;
+    p_sys->p_decoder->pf_vout_buffer_del = video_del_buffer;
+    p_sys->p_decoder->pf_picture_link    = video_link_picture_decoder;
+    p_sys->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
+    p_sys->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
+    for( i = 0; i < PICTURE_RING_SIZE; i++ )
+        p_sys->p_decoder->p_owner->pp_pics[i] = 0;
+    //p_sys->p_decoder->p_cfg = p_sys->p_video_cfg;
+
+    p_sys->p_decoder->p_module =
+        module_Need( p_sys->p_decoder, "decoder", "$codec", 0 );
+
+    if( !p_sys->p_decoder->p_module )
+    {
+        msg_Err( p_stream, "cannot find decoder" );
+        vlc_object_detach( p_sys->p_decoder );
+        vlc_object_destroy( p_sys->p_decoder );
+        return NULL;
+    }
+
+    p_sys->b_inited = VLC_TRUE;
+    vlc_mutex_lock( p_sys->p_lock );
+
+    p_bridge = GetBridge( p_stream );
+    if ( p_bridge == NULL )
+    {
+        libvlc_t *p_libvlc = p_stream->p_libvlc;
+        vlc_value_t val;
+
+        p_bridge = malloc( sizeof( bridge_t ) );
+
+        var_Create( p_libvlc, "mosaic-struct", VLC_VAR_ADDRESS );
+        val.p_address = p_bridge;
+        var_Set( p_libvlc, "mosaic-struct", val );
+
+        p_bridge->i_es_num = 0;
+        p_bridge->pp_es = NULL;
+    }
+
+    for ( i = 0; i < p_bridge->i_es_num; i++ )
+    {
+        if ( p_bridge->pp_es[i]->b_empty )
+            break;
+    }
+
+    if ( i == p_bridge->i_es_num )
+    {
+        p_bridge->pp_es = realloc( p_bridge->pp_es,
+                                   (p_bridge->i_es_num + 1)
+                                     * sizeof(bridged_es_t *) );
+        p_bridge->i_es_num++;
+        p_bridge->pp_es[i] = malloc( sizeof(bridged_es_t) );
+    }
+
+    p_sys->p_es = p_es = p_bridge->pp_es[i];
+
+    //p_es->fmt = *p_fmt;
+    p_es->psz_id = p_sys->psz_id;
+    p_es->p_picture = NULL;
+    p_es->pp_last = &p_es->p_picture;
+    p_es->b_empty = VLC_FALSE;
+
+    vlc_mutex_unlock( p_sys->p_lock );
+
+    msg_Dbg( p_stream, "mosaic bridge id=%s pos=%d", p_es->psz_id, i );
+
+    return (sout_stream_id_t *)p_sys;
+}
+
+static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+    bridge_t *p_bridge;
+    bridged_es_t *p_es;
+    vlc_bool_t b_last_es = VLC_TRUE;
+    int i;
+
+    if ( !p_sys->b_inited )
+    {
+        return VLC_SUCCESS;
+    }
+
+    if ( p_sys->p_decoder )
+    {
+        if( p_sys->p_decoder->p_module )
+            module_Unneed( p_sys->p_decoder, p_sys->p_decoder->p_module );
+        vlc_object_detach( p_sys->p_decoder );
+        vlc_object_destroy( p_sys->p_decoder );
+    }
+
+    vlc_mutex_lock( p_sys->p_lock );
+
+    p_bridge = GetBridge( p_stream );
+    p_es = p_sys->p_es;
+
+    p_es->b_empty = VLC_TRUE;
+    while ( p_es->p_picture )
+    {
+        picture_t *p_next = p_es->p_picture->p_next;
+        p_es->p_picture->pf_release( p_es->p_picture );
+        p_es->p_picture = p_next;
+    }
+
+    for ( i = 0; i < p_bridge->i_es_num; i++ )
+    {
+        if ( !p_bridge->pp_es[i]->b_empty )
+        {
+            b_last_es = VLC_FALSE;
+            break;
+        }
+    }
+
+    if ( b_last_es )
+    {
+        libvlc_t *p_libvlc = p_stream->p_libvlc;
+        for ( i = 0; i < p_bridge->i_es_num; i++ )
+            free( p_bridge->pp_es[i] );
+        free( p_bridge->pp_es );
+        free( p_bridge );
+        var_Destroy( p_libvlc, "mosaic-struct" );
+    }
+
+    vlc_mutex_unlock( p_sys->p_lock );
+
+    if ( p_sys->i_height || p_sys->i_width )
+    {
+        image_HandlerDelete( p_sys->p_image );
+    }
+
+    p_sys->b_inited = VLC_FALSE;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * PushPicture : push a picture in the mosaic-struct structure
+ *****************************************************************************/
+static void PushPicture( sout_stream_t *p_stream, picture_t *p_picture )
+{
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+    bridged_es_t *p_es = p_sys->p_es;
+
+    vlc_mutex_lock( p_sys->p_lock );
+
+    *p_es->pp_last = p_picture;
+    p_picture->p_next = NULL;
+    p_es->pp_last = &p_picture->p_next;
+
+    vlc_mutex_unlock( p_sys->p_lock );
+}
+
+static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
+                 block_t *p_buffer )
+{
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+    picture_t *p_pic;
+
+    if ( (sout_stream_sys_t *)id != p_sys )
+    {
+        block_ChainRelease( p_buffer );
+        return VLC_SUCCESS;
+    }
+
+    while ( (p_pic = p_sys->p_decoder->pf_decode_video( p_sys->p_decoder,
+                                                        &p_buffer )) )
+    {
+        picture_t *p_new_pic;
+
+        if ( p_sys->i_height || p_sys->i_width )
+        {
+            video_format_t fmt_out = {0}, fmt_in = {0};
+            fmt_in = p_sys->p_decoder->fmt_out.video;
+
+            fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
+            fmt_out.i_width = p_sys->i_width;
+            fmt_out.i_height = p_sys->i_height;
+            fmt_out.i_visible_width = fmt_out.i_width;
+            fmt_out.i_visible_height = fmt_out.i_height;
+
+            p_new_pic = image_Convert( p_sys->p_image,
+                                       p_pic, &fmt_in, &fmt_out );
+            if ( p_new_pic == NULL )
+            {
+                msg_Err( p_stream, "image conversion failed" );
+                continue;
+            }
+        }
+        else
+        {
+            p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
+            vout_AllocatePicture( p_stream, p_new_pic, p_pic->format.i_chroma,
+                                  p_pic->format.i_width, p_pic->format.i_height,
+                                  p_sys->p_decoder->fmt_out.video.i_aspect );
+
+            vout_CopyPicture( p_stream, p_new_pic, p_pic );
+        }
+        p_pic->pf_release( p_pic );
+
+        p_new_pic->i_refcount = 1;
+        p_new_pic->i_status = DESTROYED_PICTURE;
+        p_new_pic->i_type   = DIRECT_PICTURE;
+        p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release;
+        p_new_pic->pf_release = ReleasePicture;
+        p_new_pic->date = p_pic->date;
+
+        PushPicture( p_stream, p_new_pic );
+    }
+
+    return VLC_SUCCESS;
+}
+
+struct picture_sys_t
+{
+    vlc_object_t *p_owner;
+};
+
+static void video_release_buffer( picture_t *p_pic )
+{
+    if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
+    {
+        video_del_buffer( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
+    }
+    else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
+}
+
+static picture_t *video_new_buffer( decoder_t *p_dec )
+{
+    picture_t **pp_ring = p_dec->p_owner->pp_pics;
+    picture_t *p_pic;
+    int i;
+
+    /* Find an empty space in the picture ring buffer */
+    for( i = 0; i < PICTURE_RING_SIZE; i++ )
+    {
+        if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
+        {
+            pp_ring[i]->i_status = RESERVED_PICTURE;
+            return pp_ring[i];
+        }
+    }
+    for( i = 0; i < PICTURE_RING_SIZE; i++ )
+    {
+        if( pp_ring[i] == 0 ) break;
+    }
+
+    if( i == PICTURE_RING_SIZE )
+    {
+        msg_Err( p_dec, "decoder/filter is leaking pictures, "
+                 "resetting its ring buffer" );
+
+        for( i = 0; i < PICTURE_RING_SIZE; i++ )
+        {
+            pp_ring[i]->pf_release( pp_ring[i] );
+        }
+
+        i = 0;
+    }
+
+    p_pic = malloc( sizeof(picture_t) );
+    p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
+    vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
+                          p_dec->fmt_out.video.i_chroma,
+                          p_dec->fmt_out.video.i_width,
+                          p_dec->fmt_out.video.i_height,
+                          p_dec->fmt_out.video.i_aspect );
+
+    if( !p_pic->i_planes )
+    {
+        free( p_pic );
+        return 0;
+    }
+
+    p_pic->pf_release = video_release_buffer;
+    p_pic->p_sys = malloc( sizeof(picture_sys_t) );
+    p_pic->p_sys->p_owner = VLC_OBJECT(p_dec);
+    p_pic->i_status = RESERVED_PICTURE;
+
+    pp_ring[i] = p_pic;
+
+    return p_pic;
+}
+
+static void video_del_buffer( decoder_t *p_this, picture_t *p_pic )
+{
+    p_pic->i_refcount = 0;
+    p_pic->i_status = DESTROYED_PICTURE;
+}
+
+static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
+{
+    p_pic->i_refcount++;
+}
+
+static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
+{
+    video_release_buffer( p_pic );
+}
+
index 453a4aef6b586375725945d27660165c06185ca9..b1526662801d8d85b71de3acf536c4ee06445125 100644 (file)
@@ -1,4 +1,4 @@
-SOURCES_mosaic = mosaic.c
+SOURCES_mosaic = mosaic.c mosaic.h
 SOURCES_transform = transform.c
 SOURCES_invert = invert.c
 SOURCES_adjust = adjust.c
index 40fd66c8628d9e1f0b0e197fca2d80db61ad0c13..83a096553ce99c00380a902d6d36bfaf619c91e4 100644 (file)
@@ -39,7 +39,9 @@
 #include "vlc_filter.h"
 #include "vlc_image.h"
 
-#include "../video_output/picture.h"
+#include "mosaic.h"
+
+#define BLANK_DELAY I64C(1000000)
 
 /*****************************************************************************
  * Local prototypes
@@ -58,11 +60,9 @@ static int MosaicCallback( vlc_object_t *, char const *, vlc_value_t,
 struct filter_sys_t
 {
     vlc_mutex_t lock;
+    vlc_mutex_t *p_lock;
 
     image_handler_t *p_image;
-#ifdef IMAGE_2PASSES
-    image_handler_t *p_image2;
-#endif
     picture_t *p_pic;
 
     int i_position; /* mosaic positioning method */
@@ -108,7 +108,7 @@ struct filter_sys_t
 
 #define DELAY_TEXT N_("Delay")
 #define DELAY_LONGTEXT N_("Pictures coming from the picture video outputs " \
-        "will be delayed accordingly (in milliseconds, >= 100 ms). For high " \
+        "will be delayed accordingly (in milliseconds). For high " \
         "values you will need to raise file-caching and others.")
 
 static int pi_pos_values[] = { 0, 1 };
@@ -145,8 +145,10 @@ vlc_module_begin();
     add_bool( "mosaic-keep-picture", 0, NULL, KEEP_TEXT, KEEP_TEXT, VLC_FALSE );
     add_string( "mosaic-order", "", NULL, ORDER_TEXT, ORDER_TEXT, VLC_FALSE );
 
-    add_integer( "mosaic-delay", 100, NULL, DELAY_TEXT, DELAY_LONGTEXT,
+    add_integer( "mosaic-delay", 0, NULL, DELAY_TEXT, DELAY_LONGTEXT,
                  VLC_FALSE );
+
+    var_Create( p_module->p_libvlc, "mosaic-lock", VLC_VAR_MUTEX );
 vlc_module_end();
 
 
@@ -160,6 +162,7 @@ static int CreateFilter( vlc_object_t *p_this )
     libvlc_t *p_libvlc = p_filter->p_libvlc;
     char *psz_order;
     int i_index;
+    vlc_value_t val;
 
     /* Allocate structure */
     p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
@@ -175,6 +178,9 @@ static int CreateFilter( vlc_object_t *p_this )
     vlc_mutex_init( p_filter, &p_sys->lock );
     vlc_mutex_lock( &p_sys->lock );
 
+    var_Get( p_libvlc, "mosaic-lock", &val );
+    p_sys->p_lock = val.p_address;
+
 #define GET_VAR( name, min, max )                                           \
     p_sys->i_##name = __MIN( max, __MAX( min,                               \
                 var_CreateGetInteger( p_filter, "mosaic-" #name ) ) );      \
@@ -216,9 +222,6 @@ static int CreateFilter( vlc_object_t *p_this )
     if ( !p_sys->b_keep )
     {
         p_sys->p_image = image_HandlerCreate( p_filter );
-#ifdef IMAGE_2PASSES
-        p_sys->p_image2 = image_HandlerCreate( p_filter );
-#endif
     }
 
     p_sys->i_order_length = 0;
@@ -244,8 +247,6 @@ static int CreateFilter( vlc_object_t *p_this )
 
     vlc_mutex_unlock( &p_sys->lock );
 
-    vlc_thread_set_priority( p_filter, VLC_THREAD_PRIORITY_OUTPUT );
-
     return VLC_SUCCESS;
 }
 
@@ -264,9 +265,6 @@ static void DestroyFilter( vlc_object_t *p_this )
     if( !p_sys->b_keep )
     {
         image_HandlerDelete( p_sys->p_image );
-#ifdef IMAGE_2PASSES
-        image_HandlerDelete( p_sys->p_image2 );
-#endif
     }
 
     if( p_sys->i_order_length )
@@ -313,7 +311,7 @@ static void MosaicReleasePicture( picture_t *p_picture )
 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
 {
     filter_sys_t *p_sys = p_filter->p_sys;
-    libvlc_t *p_libvlc = p_filter->p_libvlc;
+    bridge_t *p_bridge;
 
     subpicture_t *p_spu;
 
@@ -323,26 +321,6 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
     subpicture_region_t *p_region;
     subpicture_region_t *p_region_prev = NULL;
 
-    picture_vout_t *p_picture_vout;
-    vlc_value_t val, lockval;
-
-    /* Wait for the specified date. This is to avoid running too fast and
-     * take twice the same pictures. */
-    mwait( date - p_sys->i_delay );
-
-    if ( var_Get( p_libvlc, "picture-lock", &lockval ) )
-        return NULL;
-
-    vlc_mutex_lock( lockval.p_address );
-
-    if( var_Get( p_libvlc, "p_picture_vout", &val ) )
-    {
-        vlc_mutex_unlock( lockval.p_address );
-        return NULL;
-    }
-
-    p_picture_vout = val.p_address;
-
     /* Allocate the subpicture internal data. */
     p_spu = p_filter->pf_sub_buffer_new( p_filter );
     if( !p_spu )
@@ -360,28 +338,33 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
     p_spu->b_absolute = VLC_FALSE;
 
     vlc_mutex_lock( &p_sys->lock );
+    vlc_mutex_lock( p_sys->p_lock );
+
+    p_bridge = GetBridge( p_filter );
+    if ( p_bridge == NULL )
+    {
+        vlc_mutex_unlock( p_sys->p_lock );
+        vlc_mutex_unlock( &p_sys->lock );
+        return p_spu;
+    }
 
-    if( p_sys->i_position == 0 ) /* use automatic positioning */
+    if ( p_sys->i_position == 0 ) /* use automatic positioning */
     {
         int i_numpics = p_sys->i_order_length; /* keep slots and all */
-        for( i_index = 0;
-             i_index < p_picture_vout->i_picture_num;
-             i_index++ )
+        for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ )
         {
-            if( p_picture_vout->p_pic[i_index].i_status
-                           == PICTURE_VOUT_E_OCCUPIED )
+            bridged_es_t *p_es = p_bridge->pp_es[i_index];
+            if ( !p_es->b_empty )
             {
                 i_numpics ++;
-                if( p_sys->i_order_length
-                    && p_picture_vout->p_pic[i_index].psz_id != 0 )
+                if( p_sys->i_order_length && p_es->psz_id != 0 )
                 {
                     /* We also want to leave slots for images given in
                      * mosaic-order that are not available in p_vout_picture */
                     int i;
                     for( i = 0; i < p_sys->i_order_length ; i++ )
                     {
-                        if( !strcmp( p_sys->ppsz_order[i],
-                                     p_picture_vout->p_pic[i_index].psz_id ) )
+                        if( !strcmp( p_sys->ppsz_order[i], p_es->psz_id ) )
                         {
                             i_numpics--;
                             break;
@@ -399,50 +382,66 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
 
     i_real_index = 0;
 
-    for( i_index = 0; i_index < p_picture_vout->i_picture_num; i_index++ )
+    for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ )
     {
-        picture_vout_e_t *p_pic = &p_picture_vout->p_pic[i_index];
+        bridged_es_t *p_es = p_bridge->pp_es[i_index];
         video_format_t fmt_in = {0}, fmt_out = {0};
         picture_t *p_converted;
-#ifdef IMAGE_2PASSES
-        video_format_t fmt_middle = {0};
-        picture_t *p_middle;
-#endif
 
-        if( p_pic->i_status == PICTURE_VOUT_E_AVAILABLE
-             || p_pic->p_picture == NULL )
-        {
+        if ( p_es->b_empty || p_es->p_picture == NULL )
             continue;
+
+        if ( p_es->p_picture->date + p_sys->i_delay < date )
+        {
+            if ( p_es->p_picture->p_next != NULL )
+            {
+                picture_t *p_next = p_es->p_picture->p_next;
+                p_es->p_picture->pf_release( p_es->p_picture );
+                p_es->p_picture = p_next;
+            }
+            else if ( p_es->p_picture->date + p_sys->i_delay + BLANK_DELAY <
+                        date )
+            {
+                /* Display blank */
+                p_es->p_picture->pf_release( p_es->p_picture );
+                p_es->p_picture = NULL;
+                p_es->pp_last = &p_es->p_picture;
+                continue;
+            }
+            else
+                msg_Dbg( p_filter, "too late picture %lld for %s",
+                         date - p_es->p_picture->date - p_sys->i_delay,
+                         p_es->psz_id );
         }
 
-        if( p_sys->i_order_length == 0 )
+        if ( p_sys->i_order_length == 0 )
         {
             i_real_index++;
         }
         else
         {
             int i;
-            for( i = 0; i <= p_sys->i_order_length; i++ )
+            for ( i = 0; i <= p_sys->i_order_length; i++ )
             {
-                if( i == p_sys->i_order_length ) break;
-                if( strcmp( p_pic->psz_id, p_sys->ppsz_order[i] ) == 0 )
+                if ( i == p_sys->i_order_length ) break;
+                if ( strcmp( p_es->psz_id, p_sys->ppsz_order[i] ) == 0 )
                 {
                     i_real_index = i;
                     break;
                 }
             }
-            if( i == p_sys->i_order_length )
+            if ( i == p_sys->i_order_length )
                 i_real_index = ++i_greatest_real_index_used;
         }
         i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows;
         i_col = i_real_index % p_sys->i_cols ;
 
-        if( !p_sys->b_keep )
+        if ( !p_sys->b_keep )
         {
             /* Convert the images */
-            fmt_in.i_chroma = p_pic->p_picture->format.i_chroma;
-            fmt_in.i_height = p_pic->p_picture->format.i_height;
-            fmt_in.i_width = p_pic->p_picture->format.i_width;
+            fmt_in.i_chroma = p_es->p_picture->format.i_chroma;
+            fmt_in.i_height = p_es->p_picture->format.i_height;
+            fmt_in.i_width = p_es->p_picture->format.i_width;
 
             fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
             fmt_out.i_width = fmt_in.i_width *
@@ -457,42 +456,19 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
                       > (float)fmt_in.i_width / (float)fmt_in.i_height )
                 {
                     fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width )
-                                         / fmt_in.i_height ;
+                                         / fmt_in.i_height;
                 }
                 else
                 {
                     fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height )
-                                        / fmt_in.i_width ;
+                                        / fmt_in.i_width;
                 }
              }
 
             fmt_out.i_visible_width = fmt_out.i_width;
             fmt_out.i_visible_height = fmt_out.i_height;
 
-#ifdef IMAGE_2PASSES
-            fmt_middle.i_chroma = fmt_in.i_chroma;
-            fmt_middle.i_visible_width = fmt_middle.i_width = fmt_out.i_width;
-            fmt_middle.i_visible_height = fmt_middle.i_height = fmt_out.i_height;
-
-            p_middle = image_Convert( p_sys->p_image2, p_pic->p_picture,
-                                      &fmt_in, &fmt_middle );
-            if( !p_middle )
-            {
-                msg_Warn( p_filter, "image resizing failed" );
-                continue;
-            }
-
-            p_converted = image_Convert( p_sys->p_image, p_middle,
-                                         &fmt_middle, &fmt_out );
-            p_middle->pf_release( p_middle );
-
-            if( !p_converted )
-            {
-                msg_Warn( p_filter, "image chroma conversion failed" );
-                continue;
-            }
-#else
-            p_converted = image_Convert( p_sys->p_image, p_pic->p_picture,
+            p_converted = image_Convert( p_sys->p_image, p_es->p_picture,
                                          &fmt_in, &fmt_out );
             if( !p_converted )
             {
@@ -500,11 +476,10 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
                            "image resizing and chroma conversion failed" );
                 continue;
             }
-#endif
         }
         else
         {
-            p_converted = p_pic->p_picture;
+            p_converted = p_es->p_picture;
             p_converted->i_refcount++;
             fmt_in.i_width = fmt_out.i_width = p_converted->format.i_width;
             fmt_in.i_height = fmt_out.i_height = p_converted->format.i_height;
@@ -520,8 +495,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
             msg_Err( p_filter, "cannot allocate SPU region" );
             p_filter->pf_sub_buffer_del( p_filter, p_spu );
             vlc_mutex_unlock( &p_sys->lock );
-            vlc_mutex_unlock( lockval.p_address );
-            return NULL;
+            vlc_mutex_unlock( p_sys->p_lock );
+            return p_spu;
         }
 
         /* HACK ALERT : let's fix the pointers to avoid picture duplication.
@@ -578,8 +553,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
         p_region_prev = p_region;
     }
 
+    vlc_mutex_unlock( p_sys->p_lock );
     vlc_mutex_unlock( &p_sys->lock );
-    vlc_mutex_unlock( lockval.p_address );
 
     return p_spu;
 }
similarity index 63%
rename from modules/video_output/picture.h
rename to modules/video_filter/mosaic.h
index d1681d414bf30f49b76da5812b6d496465f2e316..4983732402e895170fc6dd93ffa0df86d480ed2a 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
- * picture.h:
+ * mosaic.h:
  *****************************************************************************
  * Copyright (C) 2004-2005 VideoLAN
  * $Id$
  *
  * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *          Christophe Massiot <massiot@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-#ifndef _PICTURE_VOUT_H
-#define _PICTURE_VOUT_H 1
-
-#define PICTURE_VOUT_E_AVAILABLE 0
-#define PICTURE_VOUT_E_OCCUPIED 1
-typedef struct picture_vout_e_t
+typedef struct bridged_es_t
 {
+    es_format_t fmt;
     picture_t *p_picture;
-    int i_status;
+    picture_t **pp_last;
+    vlc_bool_t b_empty;
     char *psz_id;
-} picture_vout_e_t;
+} bridged_es_t;
+
+typedef struct bridge_t
+{
+    bridged_es_t **pp_es;
+    int i_es_num;
+} bridge_t;
 
-typedef struct picture_vout_t
+#define GetBridge(a) __GetBridge( VLC_OBJECT(a) )
+static bridge_t *__GetBridge( vlc_object_t *p_object )
 {
-    int i_picture_num;
-    picture_vout_e_t *p_pic;
-} picture_vout_t;
+    libvlc_t *p_libvlc = p_object->p_libvlc;
+    bridge_t *p_bridge;
+    vlc_value_t val;
+
+    if( var_Get( p_libvlc, "mosaic-struct", &val ) != VLC_SUCCESS )
+    {
+        p_bridge = NULL;
+    }
+    else
+    {
+        p_bridge = val.p_address;
+    }    
 
-#undef IMAGE_2PASSES
+    return p_bridge;
+}
 
-#endif
index 9beb64eff1f2208e9da81869d936b2993200abff..08964b87150eeafc1734d3a379431be21d3ab350 100644 (file)
@@ -12,5 +12,3 @@ SOURCES_hd1000v = hd1000v.cpp
 SOURCES_snapshot = snapshot.c
 SOURCES_opengl = opengl.c
 SOURCES_image = image.c
-SOURCES_picture = picture.h \
-                  picture.c
diff --git a/modules/video_output/picture.c b/modules/video_output/picture.c
deleted file mode 100644 (file)
index 31008b4..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/*****************************************************************************
- * picture.c:
- *****************************************************************************
- * Copyright (C) 2004-2005 VideoLAN
- * $Id$
- *
- * Authors: Antoine Cellerier <dionoea@videolan.org>
- *          Christophe Massiot <massiot@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <errno.h>                                                 /* ENOMEM */
-#include <stdlib.h>                                                /* free() */
-#include <string.h>                                            /* strerror() */
-
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-
-#include "vlc_image.h"
-
-#include "picture.h"
-
-/*****************************************************************************
- * Local structures
- *****************************************************************************/
-struct vout_sys_t
-{
-    picture_vout_t *p_picture_vout;
-    vlc_mutex_t *p_lock;
-
-    int i_picture_pos; /* picture position in p_picture_vout */
-    image_handler_t *p_image; /* filters for resizing */
-#ifdef IMAGE_2PASSES
-    image_handler_t *p_image2;
-#endif
-    int i_height, i_width;
-    mtime_t i_last_pic;
-};
-
-/* Delay after which the picture is blanked out if there hasn't been any
- * new picture. */
-#define BLANK_DELAY     I64C(1000000)
-
-typedef void (* pf_release_t)( picture_t * );
-static void ReleasePicture( picture_t *p_pic )
-{
-    p_pic->i_refcount--;
-
-    if ( p_pic->i_refcount <= 0 )
-    {
-        if ( p_pic->p_sys != NULL )
-        {
-            pf_release_t pf_release = (pf_release_t)p_pic->p_sys;
-            p_pic->p_sys = NULL;
-            pf_release( p_pic );
-        }
-        else
-        {
-            if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
-            if( p_pic ) free( p_pic );
-        }
-    }
-}
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-static int  Open    ( vlc_object_t * );
-static void Close   ( vlc_object_t * );
-static int  Init    ( vout_thread_t * );
-static void End     ( vout_thread_t * );
-static int  Manage  ( vout_thread_t * );
-static void Display ( vout_thread_t *, picture_t * );
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-#define ID_TEXT N_("ID")
-#define ID_LONGTEXT N_( \
-    "Specify an identifier string for this subpicture" )
-
-#define WIDTH_TEXT N_("Video width")
-#define WIDTH_LONGTEXT N_( \
-    "Allows you to specify the output video width." )
-#define HEIGHT_TEXT N_("Video height")
-#define HEIGHT_LONGTEXT N_( \
-    "Allows you to specify the output video height." )
-
-vlc_module_begin();
-    set_shortname( _( "Picture" ) );
-    set_description(_("VLC internal picture video output") );
-    set_capability( "video output", 0 );
-
-    add_string( "picture-id", "Id", NULL, ID_TEXT, ID_LONGTEXT, VLC_FALSE );
-    add_integer( "picture-width", 0, NULL, WIDTH_TEXT,
-                 WIDTH_LONGTEXT, VLC_TRUE );
-    add_integer( "picture-height", 0, NULL, HEIGHT_TEXT,
-                 HEIGHT_LONGTEXT, VLC_TRUE );
-
-    set_callbacks( Open, Close );
-
-    var_Create( p_module->p_libvlc, "picture-lock", VLC_VAR_MUTEX );
-vlc_module_end();
-
-/*****************************************************************************
- * Open : allocate video thread output method
- *****************************************************************************/
-static int Open( vlc_object_t *p_this )
-{
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    vout_sys_t *p_sys;
-    libvlc_t *p_libvlc = p_vout->p_libvlc;
-    picture_vout_t *p_picture_vout = NULL;
-    picture_vout_e_t *p_pic;
-    vlc_value_t val, lockval;
-
-    p_sys = p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
-    if( p_sys == NULL )
-    {
-        msg_Err( p_vout, "out of memory" );
-        return VLC_ENOMEM;
-    }
-
-    var_Get( p_libvlc, "picture-lock", &lockval );
-    p_sys->p_lock = lockval.p_address;
-    vlc_mutex_lock( p_sys->p_lock );
-
-    p_sys->i_picture_pos = -1;
-    if( var_Get( p_libvlc, "p_picture_vout", &val ) != VLC_SUCCESS )
-    {
-        p_picture_vout = malloc( sizeof( struct picture_vout_t ) );
-        if( p_picture_vout == NULL )
-        {
-            msg_Err( p_vout, "out of memory" );
-            return VLC_ENOMEM;
-        }
-
-        var_Create( p_libvlc, "p_picture_vout", VLC_VAR_ADDRESS );
-        val.p_address = p_picture_vout;
-        var_Set( p_libvlc, "p_picture_vout", val );
-
-        p_picture_vout->i_picture_num = 0;
-        p_picture_vout->p_pic = NULL;
-    }
-    else
-    {
-        int i;
-        p_picture_vout = val.p_address;
-        for ( i = 0; i < p_picture_vout->i_picture_num; i++ )
-        {
-            if ( p_picture_vout->p_pic[i].i_status == PICTURE_VOUT_E_AVAILABLE )
-                break;
-        }
-
-        if ( i != p_picture_vout->i_picture_num )
-            p_sys->i_picture_pos = i;
-    }
-
-    p_sys->p_picture_vout = p_picture_vout;
-
-    if ( p_sys->i_picture_pos == -1 )
-    {
-        p_picture_vout->p_pic = realloc( p_picture_vout->p_pic,
-                                         (p_picture_vout->i_picture_num + 1)
-                                           * sizeof(picture_vout_e_t) );
-        p_sys->i_picture_pos = p_picture_vout->i_picture_num;
-        p_picture_vout->i_picture_num++;
-    }
-
-    p_pic = &p_picture_vout->p_pic[p_sys->i_picture_pos];
-    p_pic->p_picture = NULL;
-    p_pic->i_status = PICTURE_VOUT_E_OCCUPIED;
-
-    var_Create( p_vout, "picture-id", VLC_VAR_STRING );
-    var_Change( p_vout, "picture-id", VLC_VAR_INHERITVALUE, &val, NULL );
-    p_pic->psz_id = val.psz_string;
-
-    vlc_mutex_unlock( p_sys->p_lock );
-
-    var_Create( p_vout, "picture-height", VLC_VAR_INTEGER );
-    var_Change( p_vout, "picture-height", VLC_VAR_INHERITVALUE, &val, NULL );
-    p_sys->i_height = val.i_int; 
-
-    var_Create( p_vout, "picture-width", VLC_VAR_INTEGER );
-    var_Change( p_vout, "picture-width", VLC_VAR_INHERITVALUE, &val, NULL );
-    p_sys->i_width = val.i_int; 
-
-    if ( p_sys->i_height || p_sys->i_width )
-    {
-        p_sys->p_image = image_HandlerCreate( p_vout );
-#ifdef IMAGE_2PASSES
-        p_sys->p_image2 = image_HandlerCreate( p_vout );
-#endif
-    }
-
-    p_sys->i_last_pic = 0;
-
-    p_vout->pf_init = Init;
-    p_vout->pf_end = End;
-    p_vout->pf_manage = Manage;
-    p_vout->pf_render = NULL;
-    p_vout->pf_display = Display;
-
-    return VLC_SUCCESS;
-}
-
-
-/*****************************************************************************
- * Init
- *****************************************************************************/
-static int Init( vout_thread_t *p_vout )
-{
-    picture_t *p_pic;
-    int i_index;
-
-    I_OUTPUTPICTURES = 0;
-
-    p_vout->output.i_chroma = p_vout->render.i_chroma;
-    p_vout->output.i_width  = p_vout->render.i_width;
-    p_vout->output.i_height = p_vout->render.i_height;
-    p_vout->output.i_aspect = p_vout->render.i_aspect;
-
-    while( VLC_TRUE )
-    {
-        p_pic = NULL;
-
-        for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
-        {
-            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
-            {
-                p_pic = p_vout->p_picture + i_index;
-                break;
-            }
-        }
-
-        if( p_pic == NULL )
-        {
-            return VLC_SUCCESS;
-        }
-
-        vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic,
-                              p_vout->output.i_chroma,
-                              p_vout->output.i_width, p_vout->output.i_height,
-                              p_vout->output.i_aspect );
-
-        if( p_pic->i_planes == 0 )
-        {
-            return VLC_EGENERIC;
-        }
-
-        p_pic->i_status = DESTROYED_PICTURE;
-        p_pic->i_type   = DIRECT_PICTURE;
-
-        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
-
-        I_OUTPUTPICTURES++;
-
-        //return VLC_SUCCESS;
-    }
-
-}
-
-/*****************************************************************************
- * End
- *****************************************************************************/
-static void End( vout_thread_t *p_vout )
-{
-    return;
-}
-
-/*****************************************************************************
- * Close
- *****************************************************************************/
-static void Close( vlc_object_t *p_this )
-{
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    vout_sys_t *p_sys = p_vout->p_sys;
-    picture_vout_t *p_picture_vout = p_sys->p_picture_vout;
-    picture_vout_e_t *p_pic;
-    vlc_bool_t b_last_picture = VLC_TRUE;
-    int i;
-
-    vlc_mutex_lock( p_sys->p_lock );
-    p_pic = &p_picture_vout->p_pic[p_sys->i_picture_pos];
-
-    if( p_pic->p_picture )
-    {
-        p_pic->p_picture->pf_release( p_pic->p_picture );
-        p_pic->p_picture = NULL;
-    }
-    p_pic->i_status = PICTURE_VOUT_E_AVAILABLE;
-    if( p_pic->psz_id )
-        free( p_pic->psz_id );
-
-    for( i = 0; i < p_picture_vout->i_picture_num; i ++)
-    {
-        if( p_picture_vout->p_pic[i].i_status == PICTURE_VOUT_E_OCCUPIED )
-        {
-            b_last_picture = VLC_FALSE;
-            break;
-        }
-    }
-
-    if( b_last_picture )
-    {
-        free( p_picture_vout->p_pic );
-        free( p_picture_vout );
-        var_Destroy( p_this->p_libvlc, "p_picture_vout" );
-    }
-
-    vlc_mutex_unlock( p_sys->p_lock );
-
-    if ( p_sys->i_height || p_sys->i_width )
-    {
-        image_HandlerDelete( p_sys->p_image );
-#ifdef IMAGE_2PASSES
-        image_HandlerDelete( p_sys->p_image2 );
-#endif
-    }
-
-    free( p_sys );
-}
-
-/*****************************************************************************
- * PushPicture : push a picture in the p_picture_vout structure
- *****************************************************************************/
-static void PushPicture( vout_thread_t *p_vout, picture_t *p_picture )
-{
-    vout_sys_t *p_sys = p_vout->p_sys;
-    picture_vout_t *p_picture_vout = p_sys->p_picture_vout;
-    picture_vout_e_t *p_pic;
-
-    vlc_mutex_lock( p_sys->p_lock );
-    p_pic = &p_picture_vout->p_pic[p_sys->i_picture_pos];
-
-    if( p_pic->p_picture != NULL )
-    {
-        p_pic->p_picture->pf_release( p_pic->p_picture );
-    }
-    p_pic->p_picture = p_picture;
-
-    vlc_mutex_unlock( p_sys->p_lock );
-}
-
-/*****************************************************************************
- * Manage
- *****************************************************************************/
-static int Manage( vout_thread_t *p_vout )
-{
-    vout_sys_t *p_sys = p_vout->p_sys;
-
-    if ( mdate() - p_sys->i_last_pic > BLANK_DELAY )
-    {
-        /* Display black */
-#if 0
-        picture_t *p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
-        int i;
-
-        if ( p_sys->i_height || p_sys->i_width )
-        {
-            vout_AllocatePicture( p_vout, p_new_pic,
-                                  VLC_FOURCC('Y','U','V','A'),
-                                  p_sys->i_width, p_sys->i_height,
-                                  p_vout->render.i_aspect );
-        }
-        else
-        {
-            vout_AllocatePicture( p_vout, p_new_pic, p_vout->render.i_chroma,
-                                  p_vout->render.i_width,
-                                  p_vout->render.i_height,
-                                  p_vout->render.i_aspect );
-        }
-
-        p_new_pic->i_refcount++;
-        p_new_pic->i_status = DESTROYED_PICTURE;
-        p_new_pic->i_type   = DIRECT_PICTURE;
-        p_new_pic->pf_release = ReleasePicture;
-
-        for ( i = 0; i < p_pic->i_planes; i++ )
-        {
-            /* This assumes planar YUV format */
-            p_vout->p_vlc->pf_memset( p_pic->p[i].p_pixels, i ? 0x80 : 0,
-                                      p_pic->p[i].i_lines
-                                       * p_pic->p[i].i_pitch );
-        }
-
-        PushPicture( p_vout, p_new_pic );
-#else
-        PushPicture( p_vout, NULL );
-#endif
-        p_sys->i_last_pic = INT64_MAX;
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Display
- *****************************************************************************/
-static void Display( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    vout_sys_t *p_sys = p_vout->p_sys;
-    picture_t *p_new_pic;
-
-    if ( p_sys->i_height || p_sys->i_width )
-    {
-        video_format_t fmt_out = {0}, fmt_in = {0};
-#ifdef IMAGE_2PASSES
-        vide_format_t fmt_middle = {0};
-        picture_t *p_new_pic2;
-#endif
-
-        fmt_in = p_vout->fmt_in;
-
-#ifdef IMAGE_2PASSES
-        fmt_middle.i_chroma = p_vout->render.i_chroma;
-        fmt_middle.i_width = p_vout->p_sys->i_width;
-        fmt_middle.i_height = p_vout->p_sys->i_height;
-        fmt_middle.i_visible_width = fmt_middle.i_width;
-        fmt_middle.i_visible_height = fmt_middle.i_height;
-
-        p_new_pic2 = image_Convert( p_vout->p_sys->p_image2,
-                                    p_pic, &fmt_in, &fmt_middle );
-        if ( p_new_pic2 == NULL )
-        {
-            msg_Err( p_vout, "image resizing failed %dx%d->%dx%d %4.4s",
-                     p_vout->render.i_width, p_vout->render.i_height,
-                     fmt_middle.i_width, fmt_middle.i_height,
-                     (char *)&p_vout->render.i_chroma);
-            return;
-        }
-#endif
-
-        fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
-        fmt_out.i_width = p_sys->i_width;
-        fmt_out.i_height = p_sys->i_height;
-        fmt_out.i_visible_width = fmt_out.i_width;
-        fmt_out.i_visible_height = fmt_out.i_height;
-
-#ifdef IMAGE_2PASSES
-        p_new_pic = image_Convert( p_vout->p_sys->p_image,
-                                   p_new_pic2, &fmt_middle, &fmt_out );
-        p_new_pic2->pf_release( p_new_pic2 );
-#else
-        p_new_pic = image_Convert( p_vout->p_sys->p_image,
-                                   p_pic, &fmt_in, &fmt_out );
-#endif
-        if ( p_new_pic == NULL )
-        {
-            msg_Err( p_vout, "image conversion failed" );
-            return;
-        }
-    }
-    else
-    {
-        p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
-        vout_AllocatePicture( p_vout, p_new_pic, p_pic->format.i_chroma,
-                              p_pic->format.i_width, p_pic->format.i_height,
-                              p_vout->render.i_aspect );
-
-        vout_CopyPicture( p_vout, p_new_pic, p_pic );
-    }
-
-    p_new_pic->i_refcount = 1;
-    p_new_pic->i_status = DESTROYED_PICTURE;
-    p_new_pic->i_type   = DIRECT_PICTURE;
-    p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release;
-    p_new_pic->pf_release = ReleasePicture;
-
-    PushPicture( p_vout, p_new_pic );
-    p_sys->i_last_pic = p_pic->date;
-}