Commit 83a3429c authored by Christophe Massiot's avatar Christophe Massiot

* modules/stream_out/autodel.c: New autodel module to work-around a memory

   leak in the TS mux which is triggered when the input PCR packets
   disappear from the stream without disappearing from the PMT (happens
   on the satellite when the video suddenly gets scrambled). Insert it in
   the sout pipeline : --sout="#autodel:std{...}".
parent 01b16b83
...@@ -1425,7 +1425,7 @@ then ...@@ -1425,7 +1425,7 @@ then
VLC_ADD_PLUGINS([packetizer_copy]) 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_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 stream_out_mosaic_bridge]) VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display stream_out_transcode stream_out_bridge stream_out_mosaic_bridge stream_out_autodel])
# VLC_ADD_PLUGINS([stream_out_transrate]) # VLC_ADD_PLUGINS([stream_out_transrate])
VLC_ADD_PLUGINS([profile_parser]) VLC_ADD_PLUGINS([profile_parser])
......
...@@ -10,3 +10,4 @@ SOURCES_stream_out_rtp = rtp.c ...@@ -10,3 +10,4 @@ SOURCES_stream_out_rtp = rtp.c
SOURCES_stream_out_switcher = switcher.c SOURCES_stream_out_switcher = switcher.c
SOURCES_stream_out_bridge = bridge.c SOURCES_stream_out_bridge = bridge.c
SOURCES_stream_out_mosaic_bridge = mosaic_bridge.c SOURCES_stream_out_mosaic_bridge = mosaic_bridge.c
SOURCES_stream_out_autodel = autodel.c
/*****************************************************************************
* autodel.c: monitor mux inputs and automatically add/delete streams
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
* $Id: autodel.c 12074 2005-08-08 17:18:08Z dionoea $
*
* Authors: 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 <stdlib.h>
#include <string.h>
#include <vlc/vlc.h>
#include <vlc/sout.h>
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
#define SOUT_CFG_PREFIX "sout-autodel-"
vlc_module_begin();
set_shortname( _("Autodel"));
set_description( _("Automatically add/delete input streams"));
set_capability( "sout stream", 50 );
add_shortcut( "autodel" );
set_callbacks( Open, Close );
vlc_module_end();
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static const char *ppsz_sout_options[] = {
NULL
};
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 * );
struct sout_stream_id_t
{
sout_stream_id_t *id;
es_format_t fmt;
mtime_t i_last;
vlc_bool_t b_error;
};
struct sout_stream_sys_t
{
sout_stream_t *p_out;
sout_stream_id_t **pp_es;
int i_es_num;
};
/*****************************************************************************
* 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;
p_sys = malloc( sizeof( sout_stream_sys_t ) );
p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
if( !p_sys->p_out )
{
msg_Err( p_stream, "cannot create chain" );
free( p_sys );
return VLC_EGENERIC;
}
p_sys->pp_es = NULL;
p_sys->i_es_num = 0;
sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
p_stream->p_cfg );
p_stream->pf_add = Add;
p_stream->pf_del = Del;
p_stream->pf_send = Send;
p_stream->p_sys = p_sys;
/* update p_sout->i_out_pace_nocontrol */
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 = (sout_stream_sys_t *)p_stream->p_sys;
sout_StreamDelete( p_sys->p_out );
p_stream->p_sout->i_out_pace_nocontrol--;
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 = (sout_stream_sys_t *)p_stream->p_sys;
sout_stream_id_t *p_es = malloc( sizeof(sout_stream_id_t) );
p_es->fmt = *p_fmt;
p_es->id = NULL;
p_es->i_last = 0;
p_es->b_error = VLC_FALSE;
TAB_APPEND( p_sys->i_es_num, p_sys->pp_es, p_es );
return p_es;
}
static int Del( sout_stream_t *p_stream, sout_stream_id_t *p_es )
{
sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
sout_stream_id_t *id = p_es->id;
TAB_REMOVE( p_sys->i_es_num, p_sys->pp_es, p_es );
free( p_es );
if ( id != NULL )
return p_sys->p_out->pf_del( p_sys->p_out, id );
else
return VLC_SUCCESS;
}
static int Send( sout_stream_t *p_stream, sout_stream_id_t *p_es,
block_t *p_buffer )
{
sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
mtime_t i_current = mdate();
int i;
p_es->i_last = p_buffer->i_dts;
if ( p_es->id == NULL && p_es->b_error != VLC_TRUE )
{
p_es->id = p_sys->p_out->pf_add( p_sys->p_out, &p_es->fmt );
if ( p_es->id == NULL )
{
p_es->b_error = VLC_TRUE;
msg_Err( p_stream, "couldn't create chain for id %d",
p_es->fmt.i_id );
}
}
if ( p_es->b_error != VLC_TRUE )
p_sys->p_out->pf_send( p_sys->p_out, p_es->id, p_buffer );
else
block_ChainRelease( p_buffer );
for ( i = 0; i < p_sys->i_es_num; i++ )
{
if ( p_sys->pp_es[i]->id != NULL
&& (p_sys->pp_es[i]->fmt.i_cat == VIDEO_ES
|| p_sys->pp_es[i]->fmt.i_cat == AUDIO_ES)
&& p_sys->pp_es[i]->i_last < i_current )
{
p_sys->p_out->pf_del( p_sys->p_out, p_sys->pp_es[i]->id );
p_sys->pp_es[i]->id = NULL;
}
}
return VLC_SUCCESS;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment