* libvlc.h: main libvlc header
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
- * $Id: libvlc.h,v 1.83 2003/08/28 21:11:54 gbazin Exp $
+ * $Id: libvlc.h,v 1.84 2003/09/07 22:43:17 fenrir Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
#define Nothing here, this is just to prevent update-po from being stupid
#include "vlc_keys.h"
-static char *ppsz_sout_acodec[] = { "", "mpga", "mp3", "vorb", "a52", NULL };
-static char *ppsz_sout_vcodec[] = { "", "mpgv", "mp4v", "DIV1", "DIV2",
- "DIV3", "h263", "i263", "WMV1", "WMV2",
- "MJPG", NULL };
-
static char *ppsz_language[] = { "auto", "en", "en_GB", "de", "fr", "it", "ja",
"nl", "no", "pl", "pt_BR", "ru", "sv", NULL };
"This allows you to choose if the video stream should be redirected to " \
"the stream output facility when this last one is enabled.")
-#define SOUT_VCODEC_TEXT N_("Video encoding codec" )
-#define SOUT_VCODEC_LONGTEXT N_( \
- "This allows you to force video encoding")
-
-#define SOUT_VBITRATE_TEXT N_("Video bitrate encoding (kB/s)" )
-#define SOUT_VBITRATE_LONGTEXT N_( \
- "This allows you to specify video bitrate in kB/s.")
-
#define SOUT_AUDIO_TEXT N_("Enable audio stream output")
#define SOUT_AUDIO_LONGTEXT N_( \
"This allows you to choose if the video stream should be redirected to " \
"the stream output facility when this last one is enabled.")
-#define SOUT_ACODEC_TEXT N_("Audio encoding codec" )
-#define SOUT_ACODEC_LONGTEXT N_( \
- "This allows you to force audio encoding")
-
-#define SOUT_ABITRATE_TEXT N_("Audio bitrate encoding (kB/s)" )
-#define SOUT_ABITRATE_LONGTEXT N_( \
- "This allows you to specify audio bitrate in kB/s.")
+#define SOUT_KEEP_TEXT N_("Keep sout open" )
+#define SOUT_KEEP_LONGTEXT N_( \
+ "This allows you to keep an unique sout instance across " \
+ "multiple playlist item (automatically insert gather stream_out " \
+ "if not specified)" )
#define PACKETIZER_TEXT N_("Choose preferred packetizer list")
#define PACKETIZER_LONGTEXT N_( \
add_category_hint( N_("Decoders"), NULL, VLC_TRUE );
add_module( "codec", "decoder", NULL, NULL, CODEC_TEXT, CODEC_LONGTEXT, VLC_TRUE );
-#if 0 // Encoders have been disabled for now as we are using the stream output transcoder instead
- add_category_hint( N_("Encoders"), NULL, VLC_TRUE );
- add_module( "video-encoder", "video encoder", NULL, NULL, ENCODER_VIDEO_TEXT, ENCODER_VIDEO_LONGTEXT, VLC_TRUE );
- add_module( "audio-encoder", "audio encoder", NULL, NULL, ENCODER_AUDIO_TEXT, ENCODER_AUDIO_LONGTEXT, VLC_TRUE );
-#endif
/* Stream output options */
add_category_hint( N_("Stream output"), NULL, VLC_TRUE );
add_string( "sout", NULL, NULL, SOUT_TEXT, SOUT_LONGTEXT, VLC_TRUE );
add_bool( "sout-display", VLC_FALSE, NULL, SOUT_DISPLAY_TEXT, SOUT_DISPLAY_LONGTEXT, VLC_TRUE );
+ add_bool( "sout-keep", VLC_FALSE, NULL, SOUT_KEEP_TEXT, SOUT_KEEP_LONGTEXT, VLC_TRUE );
add_bool( "sout-audio", 1, NULL, SOUT_AUDIO_TEXT, SOUT_AUDIO_LONGTEXT, VLC_TRUE );
- add_string_from_list( "sout-acodec", "", ppsz_sout_acodec, NULL, SOUT_ACODEC_TEXT, SOUT_ACODEC_LONGTEXT, VLC_TRUE );
- add_bool( "sout-abitrate", 0, NULL, SOUT_ABITRATE_TEXT, SOUT_ABITRATE_LONGTEXT, VLC_TRUE );
-
add_bool( "sout-video", 1, NULL, SOUT_VIDEO_TEXT, SOUT_VIDEO_LONGTEXT, VLC_TRUE );
- add_string_from_list( "sout-vcodec", "", ppsz_sout_vcodec, NULL, SOUT_VCODEC_TEXT, SOUT_VCODEC_LONGTEXT, VLC_TRUE );
- add_bool( "sout-vbitrate", 0, NULL, SOUT_VBITRATE_TEXT, SOUT_VBITRATE_LONGTEXT, VLC_TRUE );
add_module( "packetizer", "packetizer", NULL, NULL,
PACKETIZER_TEXT, PACKETIZER_LONGTEXT, VLC_TRUE );
ACCESS_OUTPUT_TEXT, ACCESS_OUTPUT_LONGTEXT, VLC_TRUE );
add_integer( "ttl", 1, NULL, TTL_TEXT, TTL_LONGTEXT, VLC_TRUE );
+
/* CPU options */
add_category_hint( N_("CPU"), NULL, VLC_TRUE );
#if defined( __i386__ )
* playlist.c : Playlist management functions
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: playlist.c,v 1.47 2003/08/28 15:59:04 gbazin Exp $
+ * $Id: playlist.c,v 1.48 2003/09/07 22:43:17 fenrir Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
#include <string.h> /* strerror() */
#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/sout.h>
#include "stream_control.h"
#include "input_ext-intf.h"
}
/* Following functions are local */
+static void ObjectGarbageCollector( playlist_t *p_playlist,
+ int i_type,
+ vlc_bool_t *pb_obj_destroyed,
+ mtime_t *pi_obj_destroyed_date )
+{
+ vlc_object_t *p_obj;
+ if( *pb_obj_destroyed || *pi_obj_destroyed_date > mdate() )
+ {
+ return;
+ }
+
+ if( *pi_obj_destroyed_date == 0 )
+ {
+ /* give a little time */
+ *pi_obj_destroyed_date = mdate() + 300000LL;
+ }
+ else
+ {
+ while( ( p_obj = vlc_object_find( p_playlist,
+ i_type,
+ FIND_CHILD ) ) )
+ {
+ if( p_obj->p_parent != (vlc_object_t*)p_playlist )
+ {
+ /* only first chiled (ie unused) */
+ vlc_object_release( p_obj );
+ break;
+ }
+ if( i_type == VLC_OBJECT_VOUT )
+ {
+ msg_Dbg( p_playlist, "vout garbage collector destroying 1 vout" );
+ vlc_object_detach( p_obj );
+ vlc_object_release( p_obj );
+ vout_Destroy( (vout_thread_t *)p_obj );
+ }
+ else if( i_type == VLC_OBJECT_SOUT )
+ {
+ vlc_object_release( p_obj );
+ sout_DeleteInstance( (sout_instance_t*)p_obj );
+ }
+ }
+ *pb_obj_destroyed = VLC_TRUE;
+ }
+}
+
/*****************************************************************************
* RunThread: main playlist thread
*****************************************************************************/
static void RunThread ( playlist_t *p_playlist )
{
+ vlc_object_t *p_obj;
+ vlc_bool_t b_vout_destroyed = VLC_FALSE; /*we do vout garbage collector */
+ mtime_t i_vout_destroyed_date = 0;
+
+ vlc_bool_t b_sout_destroyed = VLC_FALSE; /*we do vout garbage collector */
+ mtime_t i_sout_destroyed_date = 0;
+
/* Tell above that we're ready */
vlc_thread_ready( p_playlist );
{
input_thread_t *p_input;
- /* Unlink current input */
p_input = p_playlist->p_input;
p_playlist->p_input = NULL;
- vlc_object_detach( p_input );
/* Release the playlist lock, because we may get stuck
* in input_DestroyThread() for some time. */
/* Destroy input */
input_DestroyThread( p_input );
+
+ /* Unlink current input (_after_ input_DestroyThread for vout garbage collector)*/
+ vlc_object_detach( p_input );
+
+ /* Destroy object */
vlc_object_destroy( p_input );
+
+ b_vout_destroyed = VLC_FALSE;
+ i_vout_destroyed_date = 0;
+ b_sout_destroyed = VLC_FALSE;
+ i_sout_destroyed_date = 0;
continue;
}
/* This input is dying, let him do */
input_StopThread( p_playlist->p_input );
continue;
}
+ else if( p_playlist->p_input->stream.control.i_status != INIT_S )
+ {
+ ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT,
+ &b_vout_destroyed, &i_vout_destroyed_date );
+ ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT,
+ &b_sout_destroyed, &i_sout_destroyed_date );
+ }
}
else if( p_playlist->i_status != PLAYLIST_STOPPED )
{
SkipItem( p_playlist, 0 );
PlayItem( p_playlist );
}
+ else if( p_playlist->i_status == PLAYLIST_STOPPED )
+ {
+ ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT,
+ &b_vout_destroyed, &i_vout_destroyed_date );
+ ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT,
+ &b_sout_destroyed, &i_sout_destroyed_date );
+ }
vlc_mutex_unlock( &p_playlist->object_lock );
msleep( INTF_IDLE_SLEEP );
msleep( INTF_IDLE_SLEEP );
}
+
+ /* close all remaining vout */
+ while( ( p_obj = vlc_object_find( p_playlist,
+ VLC_OBJECT_VOUT, FIND_CHILD ) ) )
+ {
+ vlc_object_detach( p_obj );
+ vlc_object_release( p_obj );
+ vout_Destroy( (vout_thread_t *)p_obj );
+ }
+ /* close all remaining sout */
+ while( ( p_obj = vlc_object_find( p_playlist,
+ VLC_OBJECT_SOUT, FIND_CHILD ) ) )
+ {
+ vlc_object_release( p_obj );
+ sout_DeleteInstance( (sout_instance_t*)p_obj );
+ }
}
/*****************************************************************************
* stream_output.c : stream output module
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: stream_output.c,v 1.33 2003/08/09 14:59:24 gbazin Exp $
+ * $Id: stream_output.c,v 1.34 2003/09/07 22:43:17 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
char * psz_dest )
{
sout_instance_t *p_sout;
+ vlc_value_t keep;
+
+ if( var_Get( p_parent, "sout-keep", &keep ) < 0 )
+ {
+ msg_Warn( p_parent, "cannot get sout-keep value" );
+ keep.b_bool = VLC_FALSE;
+ }
+ else if( keep.b_bool )
+ {
+ msg_Warn( p_parent, "sout-keep true" );
+ if( ( p_sout = vlc_object_find( p_parent, VLC_OBJECT_SOUT, FIND_ANYWHERE ) ) )
+ {
+ if( !strcmp( p_sout->psz_sout, psz_dest ) )
+ {
+ msg_Warn( p_parent, "sout keep : reusing sout" );
+ msg_Warn( p_parent, "sout keep : you probably want to use gather stream_out" );
+ vlc_object_detach( p_sout );
+ vlc_object_attach( p_sout, p_parent );
+ vlc_object_release( p_sout );
+ return p_sout;
+ }
+ else
+ {
+ msg_Warn( p_parent, "sout keep : destroying unusable sout" );
+ sout_DeleteInstance( p_sout );
+ }
+ }
+ }
+ else if( !keep.b_bool )
+ {
+ while( ( p_sout = vlc_object_find( p_parent, VLC_OBJECT_SOUT, FIND_PARENT ) ) )
+ {
+ msg_Warn( p_parent, "sout keep : destroying old sout" );
+ sout_DeleteInstance( p_sout );
+ }
+ }
/* *** Allocate descriptor *** */
p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
sout_instance_t *p_sout = NULL;
sout_packetizer_input_t *p_input;
- int i_try;
-
/* search an stream output */
- for( i_try = 0; i_try < 12; i_try++ )
- {
- p_sout = vlc_object_find( p_this, VLC_OBJECT_SOUT, FIND_ANYWHERE );
- if( p_sout )
- {
- break;
- }
-
- msleep( 100*1000 );
- msg_Dbg( p_this, "waiting for sout" );
- }
-
- if( !p_sout )
+ if( !( p_sout = vlc_object_find( p_this, VLC_OBJECT_SOUT, FIND_ANYWHERE ) ) )
{
+ /* can't happen ... */
msg_Err( p_this, "cannot find any stream ouput" );
- return( NULL );
+ return NULL;
}
msg_Dbg( p_sout, "adding a new input" );
{
mrl_t mrl;
char *psz_chain, *p;
- char *psz_vcodec, *psz_acodec;
mrl_Parse( &mrl, psz_url );
- p = psz_chain = malloc( 500 + strlen( mrl.psz_way ) + strlen( mrl.psz_access ) + strlen( mrl.psz_name ) );
-
- psz_vcodec = config_GetPsz( p_this, "sout-vcodec" );
- if( psz_vcodec && *psz_vcodec == '\0')
- {
- FREE( psz_vcodec );
- }
- psz_acodec = config_GetPsz( p_this, "sout-acodec" );
- if( psz_acodec && *psz_acodec == '\0' )
- {
- FREE( psz_acodec );
- }
- /* set transcoding */
- if( psz_vcodec || psz_acodec )
- {
- p += sprintf( p, "transcode{" );
- if( psz_vcodec )
- {
- int br;
-
- p += sprintf( p, "vcodec=%s,", psz_vcodec );
-
- if( ( br = config_GetInt( p_this, "sout-vbitrate" ) ) > 0 )
- {
- p += sprintf( p, "vb=%d,", br * 1000 );
- }
- free( psz_vcodec );
- }
- if( psz_acodec )
- {
- int br;
-
- p += sprintf( p, "acodec=%s,", psz_acodec );
- if( ( br = config_GetInt( p_this, "sout-abitrate" ) ) > 0 )
- {
- p += sprintf( p, "ab=%d,", br * 1000 );
- }
-
- free( psz_acodec );
- }
- p += sprintf( p, "}:" );
- }
+ p = psz_chain = malloc( 500 + strlen( mrl.psz_way ) +
+ strlen( mrl.psz_access ) +
+ strlen( mrl.psz_name ) );
if( config_GetInt( p_this, "sout-display" ) )
{
- p += sprintf( p, "duplicate{dst=display,dst=std{mux=\"%s\",access=\"%s\",url=\"%s\"}}", mrl.psz_way, mrl.psz_access, mrl.psz_name );
+ p += sprintf( p, "duplicate{dst=display,dst=std{mux=\"%s\",access=\"%s\",url=\"%s\"}}",
+ mrl.psz_way, mrl.psz_access, mrl.psz_name );
}
else
{
- p += sprintf( p, "std{mux=\"%s\",access=\"%s\",url=\"%s\"}", mrl.psz_way, mrl.psz_access, mrl.psz_name );
+ p += sprintf( p, "std{mux=\"%s\",access=\"%s\",url=\"%s\"}",
+ mrl.psz_way, mrl.psz_access, mrl.psz_name );
}
mrl_Clean( &mrl );
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
- * $Id: video_output.c,v 1.232 2003/08/28 21:11:54 gbazin Exp $
+ * $Id: video_output.c,v 1.233 2003/09/07 22:43:17 fenrir Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
/* Reattach video output to input before bailing out */
if( p_vout )
{
- vlc_object_t *p_input;
+ vlc_object_t *p_playlist;
- p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
+ p_playlist = vlc_object_find( p_this, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
- if( p_input )
+ if( p_playlist )
{
vlc_object_detach( p_vout );
- vlc_object_attach( p_vout, p_input );
+ vlc_object_attach( p_vout, p_playlist );
- vlc_object_release( p_input );
+ vlc_object_release( p_playlist );
}
else
{
+ msg_Dbg( p_this, "cannot find playlist destroying vout" );
vlc_object_detach( p_vout );
- /* vlc_object_release( p_vout ); */
vout_Destroy( p_vout );
}
}
if( !p_vout )
{
- vlc_object_t *p_input;
+ vlc_object_t *p_playlist;
- p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
- if( p_input )
+ p_playlist = vlc_object_find( p_this,
+ VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist )
{
- p_vout = vlc_object_find( p_input, VLC_OBJECT_VOUT,
- FIND_CHILD );
+ p_vout = vlc_object_find( p_playlist,
+ VLC_OBJECT_VOUT, FIND_CHILD );
/* only first children of p_input for unused vout */
- if( p_vout && p_vout->p_parent != p_input )
+ if( p_vout && p_vout->p_parent != p_playlist )
{
vlc_object_release( p_vout );
p_vout = NULL;
}
- vlc_object_release( p_input );
+ vlc_object_release( p_playlist );
}
}
}
}
/* Need to reinitialise the chroma plugin */
- if( p_vout->chroma.p_module->pf_deactivate )
- p_vout->chroma.p_module->pf_deactivate( VLC_OBJECT(p_vout) );
- p_vout->chroma.p_module->pf_activate( VLC_OBJECT(p_vout) );
+ if( p_vout->chroma.p_module )
+ {
+ if( p_vout->chroma.p_module->pf_deactivate )
+ p_vout->chroma.p_module->pf_deactivate( VLC_OBJECT(p_vout) );
+ p_vout->chroma.p_module->pf_activate( VLC_OBJECT(p_vout) );
+ }
}
}