+ if( psz_bind ) psz_url = psz_bind;
+ if( psz_url && psz_path )
+ {
+ if( asprintf( &psz_url,"%s/%s",psz_url,psz_path ) == -1 )
+ psz_url = NULL;
+ free( psz_path );
+ }
+
+ var_Get( p_stream, SOUT_CFG_PREFIX "dst", &val );
+ if( *val.psz_string )
+ {
+ free( psz_url);
+ psz_url = val.psz_string;
+ }
+ else
+ free( val.psz_string );
+
+ p_sys = p_stream->p_sys = malloc( sizeof( sout_stream_sys_t) );
+ if( !p_sys ) return VLC_ENOMEM;
+ p_stream->p_sys->p_session = NULL;
+
+ msg_Dbg( p_this, "creating `%s/%s://%s'", psz_access, psz_mux, psz_url );
+
+ /* ext -> muxer name */
+ if( psz_url && strrchr( psz_url, '.' ) )
+ {
+ /* by extension */
+ static struct { const char ext[6]; const char mux[32]; } exttomux[] =
+ {
+ { "avi", "avi" },
+ { "ogg", "ogg" },
+ { "ogm", "ogg" },
+ { "mp4", "mp4" },
+ { "mov", "mov" },
+ { "moov","mov" },
+ { "asf", "asf" },
+ { "wma", "asf" },
+ { "wmv", "asf" },
+ { "trp", "ts" },
+ { "ts", "ts" },
+ { "mpg", "ps" },
+ { "mpeg","ps" },
+ { "ps", "ps" },
+ { "mpeg1","mpeg1" },
+ { "wav", "wav" },
+ { "flv", "ffmpeg{mux=flv}" },
+ { "mkv", "ffmpeg{mux=matroska}"},
+ { "", "" }
+ };
+ const char *psz_ext = strrchr( psz_url, '.' ) + 1;
+ int i;
+
+ msg_Dbg( p_this, "extension is %s", psz_ext );
+ for( i = 0; exttomux[i].ext[0]; i++ )
+ {
+ if( !strcasecmp( psz_ext, exttomux[i].ext ) )
+ {
+ psz_mux_byext = exttomux[i].mux;
+ break;
+ }
+ }
+ msg_Dbg( p_this, "extension -> mux=%s", psz_mux_byext );
+ }
+
+ /* We fix access/mux to valid couple */
+
+ if( !psz_access && !psz_mux )
+ {
+ if( psz_mux_byext )
+ {
+ msg_Warn( p_stream,
+ "no access _and_ no muxer, extension gives file/%s",
+ psz_mux_byext );
+ psz_access = strdup("file");
+ psz_mux = strdup(psz_mux_byext);
+ }
+ else
+ {
+ msg_Err( p_stream, "no access _and_ no muxer (fatal error)" );
+ return VLC_EGENERIC;
+ }
+ }
+
+ if( psz_access && !psz_mux )
+ {
+ /* access given, no mux */
+ if( !strncmp( psz_access, "mmsh", 4 ) )
+ {
+ psz_mux = strdup("asfh");
+ }
+ else if (!strcmp (psz_access, "udp"))
+ {
+ psz_mux = strdup("ts");
+ }
+ else if( psz_mux_byext )
+ {
+ psz_mux = strdup(psz_mux_byext);
+ }
+ else
+ {
+ msg_Err( p_stream, "no mux specified or found by extension" );
+ return VLC_EGENERIC;
+ }
+ }
+ else if( psz_mux && !psz_access )
+ {
+ /* mux given, no access */
+ if( !strncmp( psz_mux, "asfh", 4 ) )
+ {
+ psz_access = strdup("mmsh");
+ }
+ else
+ {
+ /* default file */
+ psz_access = strdup("file");
+ }
+ }
+
+ /* fix or warn of incompatible couple */
+ if( !strncmp( psz_access, "mmsh", 4 ) &&
+ strncmp( psz_mux, "asfh", 4 ) )
+ {
+ char *p = strchr( psz_mux,'{' );
+
+ msg_Warn( p_stream, "fixing to mmsh/asfh" );
+ if( p )
+ {
+ if( asprintf( &p, "asfh%s", p ) == -1 )
+ p = NULL;
+ free( psz_mux );
+ psz_mux = p;
+ }
+ else
+ {
+ free( psz_mux );
+ psz_mux = strdup("asfh");
+ }
+ }
+ else if( !strncmp( psz_access, "udp", 3 ) )
+ {
+ if( !strncmp( psz_mux, "ffmpeg", 6 ) )
+ { /* why would you use ffmpeg's ts muxer ? YOU DON'T LOVE VLC ??? */
+ char *psz_ffmpeg_mux = var_CreateGetString( p_this, "ffmpeg-mux" );
+ if( !psz_ffmpeg_mux || strncmp( psz_ffmpeg_mux, "mpegts", 6 ) )
+ msg_Err( p_stream, "UDP is only valid with TS" );
+ free( psz_ffmpeg_mux );
+ }
+ else if( strncmp( psz_mux, "ts", 2 ) )
+ {
+ msg_Err( p_stream, "UDP is only valid with TS" );
+ }
+ }
+ else if( strncmp( psz_access, "file", 4 ) &&
+ ( !strncmp( psz_mux, "mov", 3 ) ||
+ !strncmp( psz_mux, "mp4", 3 ) ) )
+ {
+ msg_Err( p_stream, "mov and mp4 work only with file output" );
+ }
+
+ msg_Dbg( p_this, "using `%s/%s://%s'", psz_access, psz_mux, psz_url );