X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fstream_output%2Fprofiles.c;h=b374c39a5eb4df1f45df95d5aea4c764b11aaa12;hb=305d523565cd254e45a24c830dbe199c3be0dcf9;hp=18c6a11963863fc038e46215a2caeabceb70f6e9;hpb=961d6594eb76c903e1b5a1d08009e2f83560d430;p=vlc diff --git a/src/stream_output/profiles.c b/src/stream_output/profiles.c index 18c6a11963..b374c39a5e 100644 --- a/src/stream_output/profiles.c +++ b/src/stream_output/profiles.c @@ -4,7 +4,7 @@ * Copyright (C) 2006 the VideoLAN team * $Id$ * - * Authors: Clément Stenac + * Authors: Clément Stenac * * 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 @@ -21,6 +21,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include @@ -37,20 +41,27 @@ /********************************************************************** * General chain manipulation **********************************************************************/ -sout_duplicate_t *streaming_ChainAddDup( sout_chain_t *p_chain ) +/** Add a new duplicate element to a streaming chain + * \return the new element + */ +static sout_duplicate_t *streaming_ChainAddDup( sout_chain_t *p_chain ) { DECMALLOC_NULL( p_module, sout_module_t ); MALLOC_NULL( DUPM, sout_duplicate_t ); p_module->i_type = SOUT_MOD_DUPLICATE; DUPM->i_children = 0; DUPM->pp_children = NULL; - INSERT_ELEM( p_chain->pp_modules, p_chain->i_modules, p_chain->i_modules, - p_module ); - return p_module->typed.p_duplicate; + TAB_APPEND( p_chain->i_modules, p_chain->pp_modules, p_module ); + return DUPM; } -sout_std_t *streaming_ChainAddStd( sout_chain_t *p_chain, char *psz_access, - char *psz_mux, char *psz_url ) +/** Add a new standard element to a streaming chain + * \return the new element + */ +static sout_std_t *streaming_ChainAddStd( sout_chain_t *p_chain, + const char *psz_access, + const char *psz_mux, + const char *psz_url ) { DECMALLOC_NULL( p_module, sout_module_t ); MALLOC_NULL( STDM, sout_std_t ); @@ -58,46 +69,51 @@ sout_std_t *streaming_ChainAddStd( sout_chain_t *p_chain, char *psz_access, STDM->psz_mux = strdup( psz_mux ); STDM->psz_access = strdup( psz_access ); STDM->psz_url = strdup( psz_url ); - INSERT_ELEM( p_chain->pp_modules, p_chain->i_modules, p_chain->i_modules, - p_module ); + TAB_APPEND( p_chain->i_modules, p_chain->pp_modules, p_module ); return STDM; } -sout_display_t *streaming_ChainAddDisplay( sout_chain_t *p_chain ) +/** Add a new display element to a streaming chain + * \return the new element + */ +static sout_display_t *streaming_ChainAddDisplay( sout_chain_t *p_chain ) { DECMALLOC_NULL( p_module, sout_module_t ); MALLOC_NULL( DISM, sout_display_t ); p_module->i_type = SOUT_MOD_DISPLAY; + TAB_APPEND( p_chain->i_modules, p_chain->pp_modules, p_module ); return DISM; } -sout_transcode_t *streaming_ChainAddTranscode( sout_chain_t *p_chain, +/** Add a new transcode element to a streaming chain + * \return the new element + */ +static sout_transcode_t *streaming_ChainAddTranscode( sout_chain_t *p_chain, char *psz_vcodec, char * psz_acodec, char * psz_scodec, - int i_vb, float f_scale, int i_ab, int i_channels, - vlc_bool_t b_soverlay, char *psz_additional ) + int i_vb, float f_scale, int i_ab, int i_channels, + bool b_soverlay, char *psz_additional ) { DECMALLOC_NULL( p_module, sout_module_t ); MALLOC_NULL( TRAM, sout_transcode_t ); p_module->i_type = SOUT_MOD_TRANSCODE; - + memset( TRAM, 0, sizeof( sout_transcode_t ) ); assert( !( b_soverlay && psz_scodec ) ); if( psz_vcodec ) TRAM->psz_vcodec = strdup( psz_vcodec ); if( psz_acodec ) TRAM->psz_acodec = strdup( psz_acodec ); if( psz_scodec ) TRAM->psz_scodec = strdup( psz_scodec ); TRAM->i_vb = i_vb; TRAM->i_ab = i_ab; TRAM->f_scale = f_scale; TRAM->i_channels = i_channels; TRAM->b_soverlay = b_soverlay; - if( TRAM->psz_additional ) TRAM->psz_additional = strdup( psz_additional ); + if( psz_additional ) TRAM->psz_additional = strdup( psz_additional ); + TAB_APPEND( p_chain->i_modules, p_chain->pp_modules, p_module ); return TRAM; } - -void streaming_DupAddChild( sout_duplicate_t *p_dup ) + +/** Add a new clean child chain to an existing duplicate element */ +static void streaming_DupAddChild( sout_duplicate_t *p_dup ) { - if( p_dup ) - { - sout_chain_t * p_child = streaming_ChainNew(); - INSERT_ELEM( p_dup->pp_children, p_dup->i_children, - p_dup->i_children, p_child ); - } + assert( p_dup ); + sout_chain_t * p_child = streaming_ChainNew(); + TAB_APPEND( p_dup->i_children, p_dup->pp_children, p_child ); } #define DUP_OR_CHAIN p_dup ? p_dup->pp_children[p_dup->i_children-1] : p_chain @@ -108,7 +124,8 @@ void streaming_DupAddChild( sout_duplicate_t *p_dup ) psz_opt );\ free( psz_opt ); } -void streaming_ChainClean( sout_chain_t *p_chain ) +/** Clean up a chain (recursively if it has some children) */ +static void streaming_ChainClean( sout_chain_t *p_chain ) { int i,j; sout_module_t *p_module; @@ -122,9 +139,7 @@ void streaming_ChainClean( sout_chain_t *p_chain ) case SOUT_MOD_DUPLICATE: if( DUPM->i_children == 0 ) break; for( j = DUPM->i_children - 1 ; j >= 0; j-- ) - { streaming_ChainClean( DUPM->pp_children[j] ); - } break; case SOUT_MOD_STD: FREENULL( STDM->psz_url ); @@ -146,50 +161,149 @@ void streaming_ChainClean( sout_chain_t *p_chain ) } } +/********************************************************************** + * Parameters handling + **********************************************************************/ + +#define APPLY_PSZ( element, field ) case element: \ +streaming_ParameterApply( p_param, &p_module->field, NULL, NULL, NULL ); break; +#define APPLY_INT( element, field ) case element: \ +streaming_ParameterApply( p_param, NULL, &p_module->field, NULL, NULL ); break; +#define APPLY_FLOAT( element, field ) case element: \ +streaming_ParameterApply( p_param, NULL, NULL, &p_module->field, NULL ); break; +#define APPLY_BOOL( element, field ) case element: \ +streaming_ParameterApply( p_param, NULL, NULL, NULL, &p_module->field ); break; + +/** Apply the parameters for the Std module. It will copy the values from + * the parameters to the fields themselves + */ +void streaming_StdParametersApply( sout_std_t *p_module ) +{ + int i; + for( i = 0 ; i< p_module->i_params; i++ ) + { + sout_param_t *p_param = p_module->pp_params[i]; + switch( p_param->i_element ) + { + APPLY_PSZ( PSZ_MUX, psz_mux ); + APPLY_PSZ( PSZ_ACCESS, psz_access ); + APPLY_PSZ( PSZ_URL, psz_url ); + APPLY_PSZ( PSZ_NAME, psz_name ); + APPLY_PSZ( PSZ_GROUP, psz_group ); + } + } +} + +/** Apply the parameters for the Transcode module. It will copy the values from + * the parameters to the fields themselves + */ +void streaming_TranscodeParametersApply( sout_transcode_t *p_module ) +{ + int i; + for( i = 0 ; i< p_module->i_params; i++ ) + { + sout_param_t *p_param = p_module->pp_params[i]; + switch( p_param->i_element ) + { + APPLY_INT( I_VB, i_vb ); APPLY_INT( I_AB, i_ab ); + APPLY_INT( I_CHANNELS, i_channels ) ; + APPLY_FLOAT( F_SCALE, f_scale ); + APPLY_BOOL( B_SOVERLAY, b_soverlay ); + APPLY_PSZ( PSZ_VC, psz_vcodec ); + APPLY_PSZ( PSZ_AC, psz_acodec ); + APPLY_PSZ( PSZ_SC, psz_scodec ); + APPLY_PSZ( PSZ_VE, psz_venc ); APPLY_PSZ( PSZ_AE, psz_aenc ); + } + } +} + +/** Apply a single parameter + * \param p_param the parameter to apply + * \param ppsz_dest target string, if param is a string + * \param pi_dest target int, if param is an integer + * \param pf_dest target float, if param is a float + * \param pb_dest target bool, if param is a bool + */ +void streaming_ParameterApply( sout_param_t *p_param, char **ppsz_dest, + int *pi_dest, float *pf_dest, bool *pb_dest ) +{ + /* Todo : Handle psz_string like formatting */ + if( p_param->psz_string ) + { + assert( ppsz_dest ); + fprintf( stderr, "Unsupported !\n" ); + } + else + { + switch( p_param->i_type ) + { + case VLC_VAR_INTEGER: + assert( pi_dest ); + *pi_dest = p_param->value.i_int; + break; + case VLC_VAR_FLOAT: + assert( pf_dest ); + *pf_dest = p_param->value.f_float; + break; + case VLC_VAR_STRING: + assert( ppsz_dest ); + free( *ppsz_dest ); + *ppsz_dest = p_param->value.psz_string ? + strdup( p_param->value.psz_string ) : + NULL; + break; + case VLC_VAR_BOOL: + assert( pb_dest ); + *pb_dest = p_param->value.b_bool; + break; + } + } +} + /********************************************************************** * Interaction with streaming GUI descriptors **********************************************************************/ #define DO_ENABLE_ACCESS \ if( !strcmp( STDM->psz_access, "file" ) )\ { \ - pd->b_file = VLC_TRUE; pd->psz_file = strdup( STDM->psz_url ); \ + pd->b_file = true; pd->psz_file = strdup( STDM->psz_url ); \ } \ - else if( !strcmp( STDM->psz_access, "http" ) )\ + else if( !strcmp( STDM->psz_access, "http" ) )\ { \ - pd->b_http = VLC_TRUE; pd->psz_http = strdup( STDM->psz_url ); \ + pd->b_http = true; pd->psz_http = strdup( STDM->psz_url ); \ } \ - else if( !strcmp( STDM->psz_access, "mms" ) )\ + else if( !strcmp( STDM->psz_access, "mms" ) )\ { \ - pd->b_mms = VLC_TRUE; pd->psz_mms = strdup( STDM->psz_url ); \ + pd->b_mms = true; pd->psz_mms = strdup( STDM->psz_url ); \ } \ - else if( !strcmp( STDM->psz_access, "udp" ) )\ + else if( !strcmp( STDM->psz_access, "udp" ) )\ { \ - pd->b_udp = VLC_TRUE; pd->psz_udp = strdup( STDM->psz_url ); \ + pd->b_udp = true; pd->psz_udp = strdup( STDM->psz_url ); \ } \ else \ { \ msg_Err( p_this, "unahandled access %s", STDM->psz_access ); \ } - +#if 0 /** - * Try to convert a chain to a gui descriptor. This is only possible for - * "simple" chains. + * Try to convert a chain to a gui descriptor. This is only possible for + * "simple" chains. * \param p_this vlc object * \param p_chain the source streaming chain * \param pd the destination gui descriptor object * \return TRUE if the conversion succeeded, false else */ -vlc_bool_t streaming_ChainToGuiDesc( vlc_object_t *p_this, +bool streaming_ChainToGuiDesc( vlc_object_t *p_this, sout_chain_t *p_chain, sout_gui_descr_t *pd ) { int j, i_last = 0; sout_module_t *p_module; - if( p_chain->i_modules == 0 || p_chain->i_modules > 2 ) return VLC_FALSE; + if( p_chain->i_modules == 0 || p_chain->i_modules > 2 ) return false; if( p_chain->pp_modules[0]->i_type == SOUT_MOD_TRANSCODE ) { - if( p_chain->i_modules == 1 ) return VLC_FALSE; + if( p_chain->i_modules == 1 ) return false; p_module = p_chain->pp_modules[0]; i_last++; @@ -203,25 +317,25 @@ vlc_bool_t streaming_ChainToGuiDesc( vlc_object_t *p_this, if( p_chain->pp_modules[i_last]->i_type == SOUT_MOD_DUPLICATE ) { p_module = p_chain->pp_modules[i_last]; - + // Nothing allowed after duplicate. Duplicate mustn't be empty - if( p_chain->i_modules > i_last +1 || !DUPM->i_children ) - return VLC_FALSE; + if( p_chain->i_modules > i_last +1 || !DUPM->i_children ) + return false; for( j = 0 ; j< DUPM->i_children ; j++ ) { sout_chain_t *p_child = DUPM->pp_children[j]; - if( p_child->i_modules != 1 ) return VLC_FALSE; + if( p_child->i_modules != 1 ) return false; p_module = p_child->pp_modules[0]; if( p_module->i_type == SOUT_MOD_STD ) { DO_ENABLE_ACCESS } else if( p_module->i_type == SOUT_MOD_DISPLAY ) - pd->b_local = VLC_TRUE; + pd->b_local = true; else if( p_module->i_type == SOUT_MOD_RTP ) { msg_Err( p_this, "RTP unhandled" ); - return VLC_FALSE; + return false; } } i_last++; @@ -233,20 +347,21 @@ vlc_bool_t streaming_ChainToGuiDesc( vlc_object_t *p_this, } else if( p_chain->pp_modules[i_last]->i_type == SOUT_MOD_DISPLAY ) { - pd->b_local = VLC_TRUE; + pd->b_local = true; } else if( p_chain->pp_modules[i_last]->i_type == SOUT_MOD_RTP ) { msg_Err( p_this, "RTP unhandled" ); - return VLC_FALSE; + return false; } - return VLC_TRUE; + return true; } +#endif #define HANDLE_GUI_URL( type, access ) if( pd->b_##type ) { \ - streaming_DupAddChild( p_dup ); \ + if( p_dup ) streaming_DupAddChild( p_dup ); \ if( pd->i_##type > 0 ) \ { \ char *psz_url; \ @@ -266,38 +381,41 @@ void streaming_GuiDescToChain( vlc_object_t *p_obj, sout_chain_t *p_chain, sout_gui_descr_t *pd ) { sout_duplicate_t *p_dup = NULL; + (void)p_obj; + /* Clean up the chain */ streaming_ChainClean( p_chain ); /* Transcode */ if( pd->psz_vcodec || pd->psz_acodec || pd->psz_scodec || pd->b_soverlay ) { + fprintf( stderr, "382 vcodec %s\n", pd->psz_vcodec ); streaming_ChainAddTranscode( p_chain, pd->psz_vcodec, pd->psz_acodec, pd->psz_scodec, pd->i_vb, pd->f_scale, - pd->i_ab, pd->i_channels, + pd->i_ab, pd->i_channels, pd->b_soverlay, NULL ); } /* #std{} */ - if( pd->b_local + pd->b_file + pd->b_http + pd->b_mms + pd->b_rtp + - pd->b_udp > 1 ) + if( pd->b_local + pd->b_file + pd->b_http + pd->b_mms + pd->b_rtp + + pd->b_udp + pd->b_icecast > 1 ) { p_dup = streaming_ChainAddDup( p_chain ); } if( pd->b_local ) { - streaming_DupAddChild( p_dup ); - streaming_ChainAddDisplay( DUP_OR_CHAIN ); + if( p_dup ) streaming_DupAddChild( p_dup ); + streaming_ChainAddDisplay( DUP_OR_CHAIN ); } if( pd->b_file ) { - streaming_DupAddChild( p_dup ); + if( p_dup ) streaming_DupAddChild( p_dup ); streaming_ChainAddStd( DUP_OR_CHAIN, "file", pd->psz_mux, pd->psz_file ); } if( pd->b_udp ) { sout_std_t *p_std; - streaming_DupAddChild( p_dup ); + if( p_dup ) streaming_DupAddChild( p_dup ); if( pd->i_udp > 0 ) { char *psz_url; @@ -311,14 +429,52 @@ void streaming_GuiDescToChain( vlc_object_t *p_obj, sout_chain_t *p_chain, p_std = streaming_ChainAddStd( DUP_OR_CHAIN, "udp", pd->psz_mux, pd->psz_udp ); } - if( pd->i_ttl ) ADD_OPT( "ttl=%i", pd->i_ttl ); + if( pd->i_ttl ) + ADD_OPT( "ttl=%i", pd->i_ttl ); if( pd->b_sap ) { - pd->b_sap = VLC_TRUE; - p_std->psz_name = strdup( pd->psz_name ); + pd->b_sap = true; + p_std->psz_name = strdup( pd->psz_name ); p_std->psz_group = pd->psz_group ? strdup( pd->psz_group ) : NULL; } } + if( pd->b_icecast ) + { + sout_std_t *p_std; + char *psz_username; + + if( p_dup ) streaming_DupAddChild( p_dup ); + + if( !strcmp( pd->sa_icecast.psz_username, "" ) ) + { + asprintf( &psz_username, "%s", "" ); + } + else + { + asprintf( &psz_username, "%s:%s@", pd->sa_icecast.psz_username, + pd->sa_icecast.psz_password ); + } + if( pd->i_icecast > 0 ) + { + char *psz_url; + asprintf( &psz_url, "%s%s:%i%s", psz_username, pd->psz_icecast, + pd->i_icecast, pd->psz_icecast_mountpoint ); + p_std = streaming_ChainAddStd( DUP_OR_CHAIN, "shout", + pd->psz_mux, psz_url ); + free( psz_url ); + } + else + { + char *psz_url; + asprintf( &psz_url, "%s:%s@%s%s", pd->sa_icecast.psz_username, + pd->sa_icecast.psz_password, pd->psz_icecast, + pd->psz_icecast_mountpoint ); + p_std = streaming_ChainAddStd( DUP_OR_CHAIN, "shout", + pd->psz_mux, psz_url ); + free( psz_url ); + } + free( psz_username ); + } HANDLE_GUI_URL( http, "http" ) HANDLE_GUI_URL( mms, "mms" ) } @@ -327,17 +483,31 @@ void streaming_GuiDescToChain( vlc_object_t *p_obj, sout_chain_t *p_chain, /********************************************************************** * Create a sout string from a chain **********************************************************************/ -char * streaming_ChainToPsz( sout_chain_t *p_chain ) +static char * ChainToPsz( sout_chain_t *p_chain, bool b_root ) { - int i; + int i, j; char psz_output[MAX_CHAIN]; char psz_temp[MAX_CHAIN]; - sprintf( psz_output, "#" ); + if( b_root ) sprintf( psz_output, "#" ); + else psz_output[0] = '\0'; + for( i = 0 ; i< p_chain->i_modules; i++ ) { sout_module_t *p_module = p_chain->pp_modules[i]; switch( p_module->i_type ) { + case SOUT_MOD_DUPLICATE: + CHAIN_APPEND( "duplicate{" ); + for( j = 0 ; j < DUPM->i_children ; j ++ ) + { + char *psz_child = ChainToPsz( DUPM->pp_children[j], false); + fprintf(stderr, "child %s\n", psz_child); + CHAIN_APPEND( "dst=%s", psz_child ); + free( psz_child ); + if( j != DUPM->i_children - 1 ) CHAIN_APPEND( "," ); + } + CHAIN_APPEND( "}" ); + break; case SOUT_MOD_TRANSCODE: CHAIN_APPEND( "transcode{" ); if( TRAM->psz_vcodec ) @@ -363,28 +533,36 @@ char * streaming_ChainToPsz( sout_chain_t *p_chain ) break; case SOUT_MOD_DISPLAY: - CHAIN_APPEND( "display" ) + CHAIN_APPEND( "display" ); break; case SOUT_MOD_STD: - CHAIN_APPEND( "std{access=%s,url=%s,mux=%s}", STDM->psz_access, + CHAIN_APPEND( "std{access=%s,dst=%s,mux=%s}", STDM->psz_access, STDM->psz_url, STDM->psz_mux ); + break; } + if( i != p_chain->i_modules - 1 ) CHAIN_APPEND( ":" ); } return strdup( psz_output ); } +char * streaming_ChainToPsz( sout_chain_t *p_chain ) +{ + return ChainToPsz( p_chain, true ); +} + /********************************************************************** * Handle streaming profiles **********************************************************************/ +#if 0 /** * List the available profiles. Fills the pp_profiles list with preinitialized - * values. Only metadata is decoded + * values. * \param p_this vlc object * \param pi_profiles number of listed profiles * \param pp_profiles array of profiles */ -void streaming_ProfilesList( vlc_object_t *p_this, int *pi_profiles, +void streaming_ProfilesList( vlc_object_t *p_this, int *pi_profiles, streaming_profile_t **pp_profiles ) { } @@ -404,9 +582,12 @@ int streaming_ProfileParse( vlc_object_t *p_this,streaming_profile_t *p_profile, p_this->p_private = (void *)p_parser; /* And call the module ! All work is done now */ - p_module = module_Need( p_this, "profile parser", "", VLC_TRUE ); + p_module = module_Need( p_this, "profile parser", "", true ); if( !p_module ) { msg_Warn( p_this, "parsing profile failed" ); + return VLC_EGENERIC; } + return VLC_SUCCESS; } +#endif