/*****************************************************************************
* Preamble
*****************************************************************************/
+#define _GNU_SOURCE
#include <stdlib.h>
#include <errno.h>
#define THROTLE_LONGTEXT N_( "This limits the maximum number of clients " \
"that can connect to the RTSP VOD. 0 means no limit." )
+#define RAWMUX_TEXT N_( "MUX for RAW RTSP transport" )
+
vlc_module_begin();
set_shortname( _("RTSP VoD" ) );
set_description( _("RTSP VoD server") );
set_callbacks( Open, Close );
add_shortcut( "rtsp" );
add_string ( "rtsp-host", NULL, NULL, HOST_TEXT, HOST_LONGTEXT, VLC_TRUE );
+ add_string( "rtsp-raw-mux", "ts", NULL, RAWMUX_TEXT, RAWMUX_TEXT, VLC_TRUE );
add_integer( "rtsp-throttle-users", 0, NULL, THROTLE_TEXT,
THROTLE_LONGTEXT, VLC_TRUE );
vlc_module_end();
int i_throttle_users;
int i_connections;
+ char *psz_raw_mux;
+
/* List of media */
int i_media;
vod_media_t **media;
msg_Dbg( p_this, "allowing up to %d connections", p_sys->i_throttle_users );
p_sys->i_connections = 0;
+ var_Create( p_this, "rtsp-raw-mux", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
+ p_sys->psz_raw_mux = var_GetString( p_this, "rtsp-raw-mux" );
+
p_sys->p_rtsp_host =
httpd_HostNew( VLC_OBJECT(p_vod), url.psz_host, url.i_port );
if( !p_sys->p_rtsp_host )
error:
if( p_sys && p_sys->p_rtsp_host ) httpd_HostDelete( p_sys->p_rtsp_host );
+ if( p_sys && p_sys->psz_raw_mux ) free( p_sys->psz_raw_mux );
if( p_sys ) free( p_sys );
vlc_UrlClean( &url );
httpd_HostDelete( p_sys->p_rtsp_host );
var_Destroy( p_this, "rtsp-throttle-users" );
+ var_Destroy( p_this, "rtsp-raw-mux" );
/* TODO delete medias */
free( p_sys->psz_path );
+ free( p_sys->psz_raw_mux );
free( p_sys );
}
RtspCallback, (void*)p_media );
httpd_UrlCatch( p_media->p_rtsp_url, HTTPD_MSG_PAUSE,
RtspCallback, (void*)p_media );
+ httpd_UrlCatch( p_media->p_rtsp_url, HTTPD_MSG_GETPARAMETER,
+ RtspCallback, (void*)p_media );
httpd_UrlCatch( p_media->p_rtsp_url, HTTPD_MSG_TEARDOWN,
RtspCallback, (void*)p_media );
p_es->i_payload_type = p_media->i_payload_type++;
p_es->psz_rtpmap = strdup( "H263-1998/90000" );
break;
+ case VLC_FOURCC( 'h', '2', '6', '4' ):
+ p_es->i_payload_type = p_media->i_payload_type++;
+ p_es->psz_rtpmap = strdup( "H264/90000" );
+ p_es->psz_fmtp = strdup( "packetization-mode=1" );
+ break;
case VLC_FOURCC( 'm', 'p', '4', 'v' ):
p_es->i_payload_type = p_media->i_payload_type++;
p_es->psz_rtpmap = strdup( "MP4V-ES/90000" );
if( strstr( psz_transport, "MP2T/H2221/UDP" ) ||
strstr( psz_transport, "RAW/RAW/UDP" ) )
{
+ p_media->psz_mux = p_vod->p_sys->psz_raw_mux;
p_media->b_raw = VLC_TRUE;
}
p_rtsp = RtspClientGet( p_media, psz_session );
if( !p_rtsp ) break;
+ if( p_rtsp->b_playing )
+ {
+ char *psz_position = httpd_MsgGet( query, "Range" );
+ char *psz_scale = httpd_MsgGet( query, "Scale" );
+ if( psz_position ) psz_position = strstr( psz_position, "npt=" );
+ if( psz_position && !psz_scale )
+ {
+ double f_pos;
+ char *end;
+
+ msg_Dbg( p_vod, "seeking request: %s", psz_position );
+ psz_position += 4;
+ /* FIXME: npt= is not necessarily formatted as a float */
+ f_pos = us_strtod( psz_position, &end );
+ if( end > psz_position )
+ {
+ f_pos /= ((double)(p_media->i_length))/1000 /1000 / 100;
+ vod_MediaControl( p_vod, p_media, psz_session,
+ VOD_MEDIA_SEEK, f_pos );
+ }
+ break;
+ }
+ if( psz_scale )
+ {
+ double f_scale = 0.0;
+ char *end;
+
+ f_scale = us_strtod( psz_scale, &end );
+ if( end > psz_scale )
+ {
+ f_scale = (f_scale * 30.0);
+ if( psz_scale[0] == '-' ) /* rewind */
+ {
+ msg_Dbg( p_vod, "rewind request: %s", psz_scale );
+ vod_MediaControl( p_vod, p_media, psz_session,
+ VOD_MEDIA_REWIND, f_scale );
+ }
+ else if(psz_scale[0] != '1' ) /* fast-forward */
+ {
+ msg_Dbg( p_vod, "fastforward request: %s", psz_scale );
+ vod_MediaControl( p_vod, p_media, psz_session,
+ VOD_MEDIA_FORWARD, f_scale );
+ }
+
+ if( p_rtsp->b_paused == VLC_TRUE )
+ {
+ p_rtsp->b_paused = VLC_FALSE;
+ vod_MediaControl( p_vod, p_media, psz_session,
+ VOD_MEDIA_PAUSE, psz_output );
+ }
+ }
+ break;
+ }
+ }
+
if( p_rtsp->b_playing && p_rtsp->b_paused )
{
vod_MediaControl( p_vod, p_media, psz_session,
RtspClientDel( p_media, p_rtsp );
break;
+ case HTTPD_MSG_GETPARAMETER:
+ answer->i_status = 200;
+ answer->psz_status = strdup( "OK" );
+ answer->i_body = 0;
+ answer->p_body = NULL;
+ break;
+
default:
return VLC_EGENERIC;
}
httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
psz_cseq = httpd_MsgGet( query, "Cseq" );
psz_cseq ? i_cseq = atoi( psz_cseq ) : 0;
- httpd_MsgAdd( answer, "Cseq", "%d", i_cseq );
+ httpd_MsgAdd( answer, "CSeq", "%d", i_cseq );
httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );
if( psz_session )
sizeof( "i=*\r\n" ) + strlen( p_media->psz_session_description ) +
sizeof( "u=*\r\n" ) + strlen( p_media->psz_session_url ) +
sizeof( "e=*\r\n" ) + strlen( p_media->psz_session_email ) +
+ sizeof( "c=IN IP4 0.0.0.0\r\n" ) + 20 + 10 +
sizeof( "t=0 0\r\n" ) + /* FIXME */
sizeof( "a=tool:"PACKAGE_STRING"\r\n" ) +
- sizeof( "c=IN IP4 0.0.0.0\r\n" ) + 20 + 10 +
sizeof( "a=range:npt=0-1000000000.000\r\n" );
psz_control = (ipv == '6') ? p_media->psz_rtsp_control_v6
if( *p_media->psz_session_email )
p += sprintf( p, "e=%s\r\n", p_media->psz_session_email );
+ p += sprintf( p, "c=IN IP%c %s\r\n", ipv, ipv == '6' ? "::" : "0.0.0.0" );
p += sprintf( p, "t=0 0\r\n" ); /* FIXME */
p += sprintf( p, "a=tool:"PACKAGE_STRING"\r\n" );
- p += sprintf( p, "c=IN IP%c %s\r\n", ipv, ipv == '6' ? "::" : "0.0.0.0" );
-
if( p_media->i_length > 0 )
{
lldiv_t d = lldiv( p_media->i_length / 1000, 1000 );
- p += sprintf( p, "a=range:npt=0-"I64Fd".%03u\r\n", d.quot,
+ p += sprintf( p, "a=range:npt=0-%lld.%03u\r\n", d.quot,
(unsigned)d.rem );
}