/*****************************************************************************
* standard.c: standard stream output module
*****************************************************************************
- * Copyright (C) 2003-2004 the VideoLAN team
+ * Copyright (C) 2003-2007 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
/*****************************************************************************
* Preamble
*****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc_sout.h>
+
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
-#include <vlc/vlc.h>
-#include <vlc/sout.h>
-
-#include "network.h"
+#include <vlc_network.h>
#include "vlc_url.h"
/*****************************************************************************
*****************************************************************************/
#define ACCESS_TEXT N_("Output access method")
#define ACCESS_LONGTEXT N_( \
- "Allows you to specify the output access method used for the streaming " \
- "output." )
+ "Output method to use for the stream." )
#define MUX_TEXT N_("Output muxer")
#define MUX_LONGTEXT N_( \
- "Allows you to specify the output muxer method used for the streaming " \
- "output." )
-#define URL_TEXT N_("Output URL (deprecated)")
-#define URL_LONGTEXT N_( \
- "Allows you to specify the output URL used for the streaming output." \
- "Deprecated, use dst instead." )
-
+ "Muxer to use for the stream." )
#define DST_TEXT N_("Output destination")
#define DST_LONGTEXT N_( \
- "Allows you to specify the output destination used for the streaming output." )
-
+ "Destination (URL) to use for the stream." )
#define NAME_TEXT N_("Session name")
#define NAME_LONGTEXT N_( \
- "Name of the session that will be announced with SAP" )
+ "This allows you to specify a name for the session, that will be announced "\
+ "if you choose to use SAP." )
#define GROUP_TEXT N_("Session groupname")
#define GROUP_LONGTEXT N_( \
- "Name of the group that will be announced for the session" )
+ "This allows you to specify a group for the session, that will be announced "\
+ "if you choose to use SAP." )
+
+#define DESC_TEXT N_("Session descriptipn")
+#define DESC_LONGTEXT N_( \
+ "This allows you to give a short description with details about the stream, " \
+ "that will be announced in the SDP (Session Descriptor)." )
+#define URL_TEXT N_("Session URL")
+#define URL_LONGTEXT N_( \
+ "This allows you to give an URL with more details about the stream " \
+ "(often the website of the streaming organization), that will " \
+ "be announced in the SDP (Session Descriptor)." )
+#define EMAIL_TEXT N_("Session email")
+#define EMAIL_LONGTEXT N_( \
+ "This allows you to give a contact mail address for the stream, that will " \
+ "be announced in the SDP (Session Descriptor)." )
+#define PHONE_TEXT N_("Session phone number")
+#define PHONE_LONGTEXT N_( \
+ "This allows you to give a contact telephone number for the stream, that will " \
+ "be announced in the SDP (Session Descriptor)." )
+
#define SAP_TEXT N_("SAP announcing")
-#define SAP_LONGTEXT N_("Announce this session with SAP")
+#define SAP_LONGTEXT N_("Announce this session with SAP.")
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
MUX_LONGTEXT, VLC_FALSE );
add_string( SOUT_CFG_PREFIX "dst", "", NULL, DST_TEXT,
DST_LONGTEXT, VLC_FALSE );
- add_deprecated( SOUT_CFG_PREFIX "url", VLC_FALSE );
add_bool( SOUT_CFG_PREFIX "sap", 0, NULL, SAP_TEXT, SAP_LONGTEXT, VLC_TRUE );
add_string( SOUT_CFG_PREFIX "name", "", NULL, NAME_TEXT, NAME_LONGTEXT,
VLC_TRUE );
add_string( SOUT_CFG_PREFIX "group", "", NULL, GROUP_TEXT, GROUP_LONGTEXT,
VLC_TRUE );
- add_suppressed_bool( SOUT_CFG_PREFIX "sap-ipv6" );
+ add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT, DESC_LONGTEXT,
+ VLC_TRUE );
+ add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT, URL_LONGTEXT,
+ VLC_TRUE );
+ add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT, EMAIL_LONGTEXT,
+ VLC_TRUE );
+ add_string( SOUT_CFG_PREFIX "phone", "", NULL, PHONE_TEXT, PHONE_LONGTEXT,
+ VLC_TRUE );
+ add_obsolete_bool( SOUT_CFG_PREFIX "sap-ipv6" );
set_callbacks( Open, Close );
vlc_module_end();
*****************************************************************************/
static const char *ppsz_sout_options[] = {
"access", "mux", "url", "dst",
- "sap", "name", "group", NULL
+ "sap", "name", "group", "description", "url", "email", "phone", NULL
};
#define DEFAULT_PORT 1234
sout_access_out_t *p_access;
sout_mux_t *p_mux;
- char *psz_mux_byext = NULL;
+ const char *psz_mux_byext = NULL;
- sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
+ config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
p_stream->p_cfg );
var_Get( p_stream, SOUT_CFG_PREFIX "access", &val );
/* ext -> muxer name */
if( psz_url && strrchr( psz_url, '.' ) )
{
- /* by extention */
- static struct { char *ext; char *mux; } exttomux[] =
+ /* by extension */
+ static struct { const char *ext; const char *mux; } exttomux[] =
{
{ "avi", "avi" },
{ "ogg", "ogg" },
{ "ps", "ps" },
{ "mpeg1","mpeg1" },
{ "wav","wav" },
+ { "flv", "ffmpeg{mux=flv}" },
{ NULL, NULL }
};
- char *psz_ext = strrchr( psz_url, '.' ) + 1;
+ const char *psz_ext = strrchr( psz_url, '.' ) + 1;
int i;
- msg_Dbg( p_this, "extention is %s", psz_ext );
+ msg_Dbg( p_this, "extension is %s", psz_ext );
for( i = 0; exttomux[i].ext != NULL; i++ )
{
if( !strcasecmp( psz_ext, exttomux[i].ext ) )
break;
}
}
- msg_Dbg( p_this, "extention -> mux=%s", psz_mux_byext );
+ msg_Dbg( p_this, "extension -> mux=%s", psz_mux_byext );
}
/* We fix access/mux to valid couple */
if( psz_mux_byext )
{
msg_Warn( p_stream,
- "no access _and_ no muxer, extention gives file/%s",
+ "no access _and_ no muxer, extension gives file/%s",
psz_mux_byext );
psz_access = strdup("file");
psz_mux = strdup(psz_mux_byext);
{
psz_mux = strdup("asfh");
}
- else if( !strncmp( psz_access, "udp", 3 ) ||
- !strncmp( psz_access, "rtp", 3 ) )
+ else if (!strcmp (psz_access, "udp")
+ || !strcmp (psz_access, "rtp") || !strcmp (psz_access, "udplite")
+ || !strcmp (psz_access, "tcp") || !strcmp (psz_access, "sctp")
+ || !strcmp (psz_access, "dccp"))
{
psz_mux = strdup("ts");
}
}
else
{
- msg_Err( p_stream, "no mux specified or found by extention" );
+ msg_Err( p_stream, "no mux specified or found by extension" );
return VLC_EGENERIC;
}
}
}
msg_Dbg( p_stream, "mux opened" );
- /* *** Create the SAP Session structure *** */
- var_Get( p_stream, SOUT_CFG_PREFIX "sap", &val );
- if( val.b_bool &&
- ( strstr( psz_access, "udp" ) || strstr( psz_access , "rtp" ) ) )
+ /* *** Create the SAP Session structure *** */
+ if( var_GetBool( p_stream, SOUT_CFG_PREFIX"sap" ) )
{
- session_descriptor_t *p_session = sout_AnnounceSessionCreate();
- announce_method_t *p_method =
- sout_AnnounceMethodCreate( METHOD_TYPE_SAP );
- vlc_url_t url;
-
- var_Get( p_stream, SOUT_CFG_PREFIX "name", &val );
- if( *val.psz_string )
- p_session->psz_name = val.psz_string;
- else
- {
- p_session->psz_name = strdup( psz_url );
- free( val.psz_string );
- }
+ session_descriptor_t *p_session;
+ announce_method_t *p_method = sout_SAPMethod ();
+ const int payload_type = 33;
- var_Get( p_stream, SOUT_CFG_PREFIX "group", &val );
- if( *val.psz_string )
- p_session->psz_group = val.psz_string;
- else
- free( val.psz_string );
-
- /* Now, parse the URL to extract host and port */
- vlc_UrlParse( &url, psz_url , 0);
-
- if( url.psz_host )
- {
- if( url.i_port == 0 ) url.i_port = DEFAULT_PORT;
-
- p_session->psz_uri = strdup( url.psz_host );
- p_session->i_port = url.i_port;
- p_session->psz_sdp = NULL;
+ static const struct { const char *access; const char *fmt; } fmts[] =
+ {
+ /* TLS/DTLS variants (none implemented): */
+ { "dtlslite", "UDPLite/TLS/RTP/AVP %d" },
+ { "dtls", "UDP/TLS/RTP/AVP %d" },
+ { "dccps", "DCCP/TLS/RTP/AVP %d" },
+ { "tls", "TCP/TLS/RTP/AVP %d" },
+ /* Plain text: */
+ { "udplite", "UDPLite/RTP/AVP %d" },
+ { "udp", "udp mpeg" },
+ { "rtp", "RTP/AVP %d" },
+ /* Currently unsupported access outputs: */
+ { "dccp", "DCCP/RTP/AVP %d" },
+ { "tcp", "TCP/RTP/AVP %d" },
+ /* SRTP (none implemented): */
+ { "srtp", "RTP/SAVP %d" },
+ { "sudplite", "UDPLite/RTP/SAVP %d" },
+ { "sdccp", "DCCP/RTP/SAVP %d" },
+ { "stcp", "TCP/RTP/SAVP %d" },
+ { NULL, NULL }
+ };
+ const char *psz_sdp_fmt = NULL;
+ char *fmt, *src, *dst;
+ int sport, dport;
+
+ for (unsigned i = 0; fmts[i].access != NULL; i++)
+ if (strncasecmp (fmts[i].access, psz_access, strlen (fmts[i].access)) == 0)
+ {
+ psz_sdp_fmt = fmts[i].fmt;
+ break;
+ }
- var_Get( p_access, "sout-udp-ttl", &val );
- p_session->i_ttl = val.i_int;
- p_session->i_payload = 33;
- p_session->b_rtp = strstr( psz_access, "rtp") ? 1 : 0;
+ src = var_GetNonEmptyString (p_access, "src-addr");
+ dst = var_GetNonEmptyString (p_access, "dst-addr");
+ sport = var_GetInteger (p_access, "src-port");
+ dport = var_GetInteger (p_access, "dst-port");
- msg_Info( p_this, "SAP Enabled");
+ if ((psz_sdp_fmt == NULL)
+ || (asprintf (&fmt, psz_sdp_fmt, payload_type) == -1))
+ fmt = NULL;
- sout_AnnounceRegister( p_sout, p_session, p_method );
- p_stream->p_sys->p_session = p_session;
+ msg_Dbg( p_stream, "SAP advertized format: %s", fmt);
+ if ((fmt == NULL) || ((src == NULL) && (dst == NULL)))
+ {
+ msg_Err (p_access, "SAP announces not supported for access %s",
+ psz_access);
+ goto nosap;
}
- vlc_UrlClean( &url );
- free( p_method );
+ p_session = sout_AnnounceSessionCreate (VLC_OBJECT (p_stream),
+ SOUT_CFG_PREFIX);
+ sout_SessionSetMedia (VLC_OBJECT (p_stream), p_session, fmt,
+ src, sport, dst, dport);
+ sout_AnnounceRegister( p_sout, p_session, p_method );
+ p_stream->p_sys->p_session = p_session;
+ sout_MethodRelease (p_method);
+
+nosap:
+ free (fmt);
+ free (src);
+ free (dst);
}
p_stream->pf_add = Add;