+ /* remove the stream out chain */
+ sout_StreamDelete( p_sout->p_stream );
+
+ /* *** free all string *** */
+ FREENULL( p_sout->psz_sout );
+ FREENULL( p_sout->psz_chain );
+
+ /* delete meta */
+ if( p_sout->p_meta )
+ {
+ vlc_meta_Delete( p_sout->p_meta );
+ }
+
+ vlc_mutex_destroy( &p_sout->lock );
+
+ /* *** free structure *** */
+ vlc_object_destroy( p_sout );
+}
+
+/*****************************************************************************
+ * Packetizer/Input
+ *****************************************************************************/
+sout_packetizer_input_t *sout_InputNew( sout_instance_t *p_sout,
+ es_format_t *p_fmt )
+{
+ sout_packetizer_input_t *p_input;
+
+ msg_Dbg( p_sout, "adding a new input" );
+
+ /* *** create a packetizer input *** */
+ p_input = malloc( sizeof( sout_packetizer_input_t ) );
+ p_input->p_sout = p_sout;
+ p_input->p_fmt = p_fmt;
+
+ if( p_fmt->i_codec == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
+ {
+ vlc_object_release( p_sout );
+ return p_input;
+ }
+
+ /* *** add it to the stream chain */
+ vlc_mutex_lock( &p_sout->lock );
+ p_input->id = p_sout->p_stream->pf_add( p_sout->p_stream, p_fmt );
+ vlc_mutex_unlock( &p_sout->lock );
+
+ if( p_input->id == NULL )
+ {
+ free( p_input );
+ return NULL;
+ }
+
+ return( p_input );
+}
+
+/*****************************************************************************
+ *
+ *****************************************************************************/
+int sout_InputDelete( sout_packetizer_input_t *p_input )
+{
+ sout_instance_t *p_sout = p_input->p_sout;
+
+ msg_Dbg( p_sout, "removing an input" );
+
+ if( p_input->p_fmt->i_codec != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
+ {
+ vlc_mutex_lock( &p_sout->lock );
+ p_sout->p_stream->pf_del( p_sout->p_stream, p_input->id );
+ vlc_mutex_unlock( &p_sout->lock );
+ }
+
+ free( p_input );
+
+ return( VLC_SUCCESS);
+}
+
+/*****************************************************************************
+ *
+ *****************************************************************************/
+int sout_InputSendBuffer( sout_packetizer_input_t *p_input,
+ block_t *p_buffer )
+{
+ sout_instance_t *p_sout = p_input->p_sout;
+ int i_ret;
+
+ if( p_input->p_fmt->i_codec == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
+ {
+ block_Release( p_buffer );
+ return VLC_SUCCESS;
+ }
+ if( p_buffer->i_dts <= 0 )
+ {
+ msg_Warn( p_sout, "trying to send non-dated packet to stream output!");
+ block_Release( p_buffer );
+ return VLC_SUCCESS;
+ }
+
+ vlc_mutex_lock( &p_sout->lock );
+ i_ret = p_sout->p_stream->pf_send( p_sout->p_stream,
+ p_input->id, p_buffer );
+ vlc_mutex_unlock( &p_sout->lock );
+
+ return i_ret;
+}
+
+/*****************************************************************************
+ * sout_AccessOutNew: allocate a new access out
+ *****************************************************************************/
+sout_access_out_t *sout_AccessOutNew( sout_instance_t *p_sout,
+ const char *psz_access, const char *psz_name )
+{
+ sout_access_out_t *p_access;
+ char *psz_next;
+
+ if( !( p_access = vlc_object_create( p_sout,
+ sizeof( sout_access_out_t ) ) ) )
+ {
+ msg_Err( p_sout, "out of memory" );
+ return NULL;
+ }
+
+ psz_next = config_ChainCreate( &p_access->psz_access, &p_access->p_cfg,
+ psz_access );
+ if( psz_next )
+ {
+ free( psz_next );
+ }
+ p_access->psz_path = strdup( psz_name ? psz_name : "" );
+ p_access->p_sout = p_sout;
+ p_access->p_sys = NULL;
+ p_access->pf_seek = NULL;
+ p_access->pf_read = NULL;
+ p_access->pf_write = NULL;
+ p_access->pf_control = NULL;
+ p_access->p_module = NULL;
+
+ p_access->i_writes = 0;
+ p_access->i_sent_bytes = 0;
+
+ vlc_object_attach( p_access, p_sout );
+
+ p_access->p_module =
+ module_Need( p_access, "sout access", p_access->psz_access, VLC_TRUE );
+
+ if( !p_access->p_module )
+ {
+ free( p_access->psz_access );
+ free( p_access->psz_path );
+ vlc_object_detach( p_access );
+ vlc_object_destroy( p_access );
+ return( NULL );
+ }
+
+ return p_access;
+}
+/*****************************************************************************
+ * sout_AccessDelete: delete an access out
+ *****************************************************************************/
+void sout_AccessOutDelete( sout_access_out_t *p_access )
+{
+ vlc_object_detach( p_access );
+ if( p_access->p_module )
+ {
+ module_Unneed( p_access, p_access->p_module );
+ }
+ free( p_access->psz_access );
+
+ config_ChainDestroy( p_access->p_cfg );
+
+ free( p_access->psz_path );
+
+ vlc_object_destroy( p_access );
+}
+
+/*****************************************************************************
+ * sout_AccessSeek:
+ *****************************************************************************/
+int sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos )
+{
+ return p_access->pf_seek( p_access, i_pos );
+}
+
+/*****************************************************************************
+ * sout_AccessRead:
+ *****************************************************************************/
+int sout_AccessOutRead( sout_access_out_t *p_access, block_t *p_buffer )
+{
+ return( p_access->pf_read ?
+ p_access->pf_read( p_access, p_buffer ) : VLC_EGENERIC );
+}
+
+/*****************************************************************************
+ * sout_AccessWrite:
+ *****************************************************************************/
+int sout_AccessOutWrite( sout_access_out_t *p_access, block_t *p_buffer )
+{
+ int i_total = 0;
+ p_access->i_writes++;
+ p_access->i_sent_bytes += p_buffer->i_buffer;
+ if( p_access->p_libvlc->b_stats && p_access->i_writes % 30 == 0 )
+ {
+ /* Access_out -> sout_instance -> input_thread_t */
+ input_thread_t *p_input =
+ (input_thread_t *)vlc_object_find( p_access, VLC_OBJECT_INPUT,
+ FIND_PARENT );
+ if( p_input )
+ {
+ stats_UpdateInteger( p_input, p_input->p->counters.p_sout_sent_packets,
+ 30, NULL );
+ stats_UpdateInteger( p_input, p_input->p->counters.p_sout_sent_bytes,
+ p_access->i_sent_bytes, &i_total );
+ stats_UpdateFloat( p_input, p_input->p->counters.p_sout_send_bitrate,
+ (float)i_total, NULL );
+ p_access->i_sent_bytes = 0;
+ vlc_object_release( p_input );
+ }
+ }
+ return p_access->pf_write( p_access, p_buffer );
+}
+
+/**
+ * sout_AccessOutControl
+ */
+int sout_AccessOutControl (sout_access_out_t *access, int query, va_list args)
+{
+ return (access->pf_control) ? access->pf_control (access, query, args)
+ : VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * sout_MuxNew: create a new mux
+ *****************************************************************************/
+sout_mux_t * sout_MuxNew( sout_instance_t *p_sout, char *psz_mux,
+ sout_access_out_t *p_access )
+{
+ sout_mux_t *p_mux;
+ char *psz_next;
+
+ p_mux = vlc_object_create( p_sout, sizeof( sout_mux_t ) );
+ if( p_mux == NULL )
+ {
+ msg_Err( p_sout, "out of memory" );
+ return NULL;
+ }
+
+ p_mux->p_sout = p_sout;
+ psz_next = config_ChainCreate( &p_mux->psz_mux, &p_mux->p_cfg, psz_mux );
+ if( psz_next ) free( psz_next );
+
+ p_mux->p_access = p_access;
+ p_mux->pf_control = NULL;
+ p_mux->pf_addstream = NULL;
+ p_mux->pf_delstream = NULL;
+ p_mux->pf_mux = NULL;
+ p_mux->i_nb_inputs = 0;
+ p_mux->pp_inputs = NULL;
+
+ p_mux->p_sys = NULL;
+ p_mux->p_module = NULL;
+
+ p_mux->b_add_stream_any_time = VLC_FALSE;
+ p_mux->b_waiting_stream = VLC_TRUE;
+ p_mux->i_add_stream_start = -1;
+
+ vlc_object_attach( p_mux, p_sout );
+
+ p_mux->p_module =
+ module_Need( p_mux, "sout mux", p_mux->psz_mux, VLC_TRUE );
+
+ if( p_mux->p_module == NULL )
+ {
+ FREENULL( p_mux->psz_mux );
+
+ vlc_object_detach( p_mux );
+ vlc_object_destroy( p_mux );
+ return NULL;
+ }
+
+ /* *** probe mux capacity *** */
+ if( p_mux->pf_control )
+ {
+ int b_answer = VLC_FALSE;
+
+ if( sout_MuxControl( p_mux, MUX_CAN_ADD_STREAM_WHILE_MUXING,
+ &b_answer ) )
+ {
+ b_answer = VLC_FALSE;
+ }
+
+ if( b_answer )
+ {
+ msg_Dbg( p_sout, "muxer support adding stream at any time" );
+ p_mux->b_add_stream_any_time = VLC_TRUE;
+ p_mux->b_waiting_stream = VLC_FALSE;