X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fstream_out%2Fbridge.c;h=1e0a7ada2dbcf3df5df1146e719b785e4a68d6f1;hb=be378fbc80c384e2541517d6853b59411b7e67de;hp=a33a5f0a910db99fb781737587e60a89a744dc29;hpb=6510bfafe768f664f4f609f0ed2125bb4b12e521;p=vlc diff --git a/modules/stream_out/bridge.c b/modules/stream_out/bridge.c index a33a5f0a91..1e0a7ada2d 100644 --- a/modules/stream_out/bridge.c +++ b/modules/stream_out/bridge.c @@ -1,7 +1,7 @@ /***************************************************************************** * bridge.c: bridge stream output module ***************************************************************************** - * Copyright (C) 2005 VideoLAN + * Copyright (C) 2005 the VideoLAN team * $Id$ * * Authors: Christophe Massiot @@ -18,29 +18,34 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include /***************************************************************************** * Module descriptor *****************************************************************************/ #define ID_TEXT N_("ID") #define ID_LONGTEXT N_( \ - "Specify an identifier integer for this elementary stream" ) + "Integer identifier for this elementary stream. This will be used to " \ + "\"find\" this stream later." ) #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 " \ - "values you will need to raise file-caching and others.") + "will be delayed according to this value (in milliseconds, should be "\ + ">= 100 ms). For high values, you will need to raise caching values." ) #define ID_OFFSET_TEXT N_("ID Offset") #define ID_OFFSET_LONGTEXT N_("Offset to add to the stream IDs specified in " \ @@ -55,42 +60,42 @@ static void CloseIn ( vlc_object_t * ); #define SOUT_CFG_PREFIX_IN "sout-bridge-in-" vlc_module_begin(); + set_shortname( N_("Bridge")); + set_description( N_("Bridge stream output")); add_submodule(); - set_shortname( _("Bridge out")); - set_description( _("Bridge out stream output") ); + 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 set_category( CAT_SOUT ); - set_subcategory( SUBCAT_SOUT_STREAM ); + set_subcategory( SUBCAT_SOUT_STREAM );*/ add_integer( SOUT_CFG_PREFIX_OUT "id", 0, NULL, ID_TEXT, ID_LONGTEXT, - VLC_FALSE ); + false ); set_callbacks( OpenOut, CloseOut ); add_submodule(); - set_shortname( _("Bridge in")); - set_description( _("Bridge in stream output") ); + 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, - DELAY_LONGTEXT, VLC_FALSE ); + /*set_category( CAT_SOUT ); + set_subcategory( SUBCAT_SOUT_STREAM );*/ + add_integer( SOUT_CFG_PREFIX_IN "delay", 0, NULL, DELAY_TEXT, + DELAY_LONGTEXT, false ); add_integer( SOUT_CFG_PREFIX_IN "id-offset", 8192, NULL, ID_OFFSET_TEXT, - ID_OFFSET_LONGTEXT, VLC_FALSE ); + ID_OFFSET_LONGTEXT, false ); set_callbacks( OpenIn, CloseIn ); - var_Create( p_module->p_libvlc, "bridge-lock", VLC_VAR_MUTEX ); vlc_module_end(); /***************************************************************************** * Local prototypes *****************************************************************************/ -static const char *ppsz_sout_options_out[] = { +static const char *const ppsz_sout_options_out[] = { "id", NULL }; -static const char *ppsz_sout_options_in[] = { +static const char *const ppsz_sout_options_in[] = { "delay", "id-offset", NULL }; @@ -107,35 +112,34 @@ typedef struct bridged_es_t es_format_t fmt; block_t *p_block; block_t **pp_last; - vlc_bool_t b_empty; - int i_id; + bool b_empty; /* bridge in part */ sout_stream_id_t *id; - vlc_bool_t b_changed; + mtime_t i_last; + bool b_changed; } bridged_es_t; typedef struct bridge_t { - bridged_es_t *p_es; + bridged_es_t **pp_es; int i_es_num; } bridge_t; #define GetBridge(a) __GetBridge( VLC_OBJECT(a) ) static bridge_t *__GetBridge( vlc_object_t *p_object ) { - libvlc_t *p_libvlc = p_object->p_libvlc; bridge_t *p_bridge; vlc_value_t val; - if( var_Get( p_libvlc, "bridge-struct", &val ) != VLC_SUCCESS ) + if( var_Get( p_object->p_libvlc, "bridge-struct", &val ) ) { p_bridge = NULL; } else { p_bridge = val.p_address; - } + } return p_bridge; } @@ -148,9 +152,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; + bool b_inited; } out_sout_stream_sys_t; /***************************************************************************** @@ -158,16 +162,17 @@ 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; - sout_CfgParse( p_stream, SOUT_CFG_PREFIX_OUT, ppsz_sout_options_out, + config_ChainParse( p_stream, SOUT_CFG_PREFIX_OUT, ppsz_sout_options_out, p_stream->p_cfg ); p_sys = malloc( sizeof( out_sout_stream_sys_t ) ); - p_sys->b_inited = VLC_FALSE; + p_sys->b_inited = false; + var_Create( p_this->p_libvlc, "bridge-lock", VLC_VAR_MUTEX ); var_Get( p_this->p_libvlc, "bridge-lock", &val ); p_sys->p_lock = val.p_address; @@ -180,7 +185,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; @@ -194,7 +198,6 @@ static void CloseOut( vlc_object_t * p_this ) sout_stream_t *p_stream = (sout_stream_t*)p_this; out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys; - /* update p_sout->i_out_pace_nocontrol */ p_stream->p_sout->i_out_pace_nocontrol--; free( p_sys ); @@ -211,14 +214,14 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt ) { return NULL; } - p_sys->b_inited = VLC_TRUE; + p_sys->b_inited = 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_object_t *p_libvlc = VLC_OBJECT( p_stream->p_libvlc ); vlc_value_t val; p_bridge = malloc( sizeof( bridge_t ) ); @@ -228,33 +231,38 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt ) var_Set( p_libvlc, "bridge-struct", val ); p_bridge->i_es_num = 0; - p_bridge->p_es = NULL; + p_bridge->pp_es = NULL; } for ( i = 0; i < p_bridge->i_es_num; i++ ) { - if ( p_bridge->p_es[i].b_empty && !p_bridge->p_es[i].b_changed ) + if ( p_bridge->pp_es[i]->b_empty && !p_bridge->pp_es[i]->b_changed ) break; } if ( i == p_bridge->i_es_num ) { - p_bridge->p_es = realloc( p_bridge->p_es, - (p_bridge->i_es_num + 1) - * sizeof(bridged_es_t) ); - p_sys->i_position = 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_es = &p_bridge->p_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; p_es->pp_last = &p_es->p_block; - p_es->b_empty = VLC_FALSE; + p_es->b_empty = false; p_es->id = NULL; - p_es->b_changed = VLC_TRUE; + p_es->i_last = 0; + p_es->b_changed = 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, i ); vlc_mutex_unlock( p_sys->p_lock ); @@ -263,8 +271,8 @@ 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 ) { + VLC_UNUSED(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 ) @@ -274,15 +282,17 @@ 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->p_es[ p_sys->i_position ]; + p_es = p_sys->p_es; - p_es->b_empty = VLC_TRUE; + p_es->b_empty = true; block_ChainRelease( p_es->p_block ); + p_es->p_block = false; - p_es->b_changed = VLC_TRUE; + p_es->b_changed = true; vlc_mutex_unlock( p_sys->p_lock ); + p_sys->b_inited = false; + return VLC_SUCCESS; } @@ -290,7 +300,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 ) @@ -301,8 +310,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->p_es[ p_sys->i_position ]; + p_es = p_sys->p_es; *p_es->pp_last = p_buffer; while ( p_buffer != NULL ) { @@ -347,9 +355,10 @@ static int OpenIn( vlc_object_t *p_this ) return VLC_EGENERIC; } - sout_CfgParse( p_stream, SOUT_CFG_PREFIX_IN, ppsz_sout_options_in, + config_ChainParse( p_stream, SOUT_CFG_PREFIX_IN, ppsz_sout_options_in, p_stream->p_cfg ); + var_Create( p_this->p_libvlc, "bridge-lock", VLC_VAR_MUTEX ); var_Get( p_this->p_libvlc, "bridge-lock", &val ); p_sys->p_lock = val.p_address; @@ -380,11 +389,8 @@ static void CloseIn( vlc_object_t * p_this ) in_sout_stream_sys_t *p_sys = (in_sout_stream_sys_t *)p_stream->p_sys; sout_StreamDelete( p_sys->p_out ); - - /* update p_sout->i_out_pace_nocontrol */ p_stream->p_sout->i_out_pace_nocontrol--; - free( p_sys ); } @@ -407,7 +413,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, { in_sout_stream_sys_t *p_sys = (in_sout_stream_sys_t *)p_stream->p_sys; bridge_t *p_bridge; - vlc_bool_t b_no_es = VLC_TRUE; + bool b_no_es = true; int i; /* First forward the packet for our own ES */ @@ -425,57 +431,102 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, for ( i = 0; i < p_bridge->i_es_num; i++ ) { - if ( p_bridge->p_es[i].b_changed ) + if ( !p_bridge->pp_es[i]->b_empty ) + b_no_es = false; + + while ( p_bridge->pp_es[i]->p_block != NULL + && (p_bridge->pp_es[i]->p_block->i_dts + p_sys->i_delay + < mdate() + || p_bridge->pp_es[i]->p_block->i_dts + p_sys->i_delay + < p_bridge->pp_es[i]->i_last) ) { - if ( p_bridge->p_es[i].b_empty ) + block_t *p_block = p_bridge->pp_es[i]->p_block; + msg_Dbg( p_stream, "dropping a packet (%"PRId64 ")", + mdate() - p_block->i_dts - p_sys->i_delay ); + p_bridge->pp_es[i]->p_block + = p_bridge->pp_es[i]->p_block->p_next; + block_Release( p_block ); + } + + if ( p_bridge->pp_es[i]->p_block == NULL ) + { + p_bridge->pp_es[i]->pp_last = &p_bridge->pp_es[i]->p_block; + } + + if ( p_bridge->pp_es[i]->b_changed ) + { + if ( p_bridge->pp_es[i]->b_empty && p_bridge->pp_es[i]->id != NULL ) { - p_sys->p_out->pf_del( p_sys->p_out, p_bridge->p_es[i].id ); + p_sys->p_out->pf_del( p_sys->p_out, p_bridge->pp_es[i]->id ); } else { - p_bridge->p_es[i].fmt.i_id += p_sys->i_id_offset; - p_bridge->p_es[i].id = p_sys->p_out->pf_add( - p_sys->p_out, &p_bridge->p_es[i].fmt ); - if ( p_bridge->p_es[i].id == NULL ) + /* We need at least two packets to enter the mux. */ + if ( p_bridge->pp_es[i]->p_block == NULL + || p_bridge->pp_es[i]->p_block->p_next == NULL ) + { + continue; + } + + p_bridge->pp_es[i]->fmt.i_id += p_sys->i_id_offset; + p_bridge->pp_es[i]->id = p_sys->p_out->pf_add( + p_sys->p_out, &p_bridge->pp_es[i]->fmt ); + if ( p_bridge->pp_es[i]->id == NULL ) { msg_Warn( p_stream, "couldn't create chain for id %d", - p_bridge->p_es[i].fmt.i_id ); + p_bridge->pp_es[i]->fmt.i_id ); } + msg_Dbg( p_stream, "bridging in input codec=%4.4s id=%d pos=%d", + (char*)&p_bridge->pp_es[i]->fmt.i_codec, + p_bridge->pp_es[i]->fmt.i_id, i ); } } - p_bridge->p_es[i].b_changed = VLC_FALSE; + p_bridge->pp_es[i]->b_changed = false; - if ( p_bridge->p_es[i].b_empty ) + if ( p_bridge->pp_es[i]->b_empty ) continue; - b_no_es = VLC_FALSE; - - if ( p_bridge->p_es[i].p_block == NULL ) + if ( p_bridge->pp_es[i]->p_block == NULL ) + { + if ( p_bridge->pp_es[i]->id != NULL + && p_bridge->pp_es[i]->i_last < mdate() ) + { + p_sys->p_out->pf_del( p_sys->p_out, p_bridge->pp_es[i]->id ); + p_bridge->pp_es[i]->fmt.i_id -= p_sys->i_id_offset; + p_bridge->pp_es[i]->b_changed = true; + p_bridge->pp_es[i]->id = NULL; + } continue; + } - if ( p_bridge->p_es[i].id != NULL ) + if ( p_bridge->pp_es[i]->id != NULL ) { - block_t *p_block = p_bridge->p_es[i].p_block; + block_t *p_block = p_bridge->pp_es[i]->p_block; while ( p_block != NULL ) { + p_bridge->pp_es[i]->i_last = p_block->i_dts; p_block->i_pts += p_sys->i_delay; p_block->i_dts += p_sys->i_delay; p_block = p_block->p_next; } - p_sys->p_out->pf_send( p_sys->p_out, p_bridge->p_es[i].id, - p_bridge->p_es[i].p_block ); + p_sys->p_out->pf_send( p_sys->p_out, p_bridge->pp_es[i]->id, + p_bridge->pp_es[i]->p_block ); } else - block_ChainRelease( p_bridge->p_es[i].p_block ); + { + block_ChainRelease( p_bridge->pp_es[i]->p_block ); + } - p_bridge->p_es[i].p_block = NULL; - p_bridge->p_es[i].pp_last = &p_bridge->p_es[i].p_block; + p_bridge->pp_es[i]->p_block = NULL; + p_bridge->pp_es[i]->pp_last = &p_bridge->pp_es[i]->p_block; } if( b_no_es ) { - libvlc_t *p_libvlc = p_stream->p_libvlc; - free( p_bridge->p_es ); + vlc_object_t *p_libvlc = VLC_OBJECT( 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, "bridge-struct" ); }