"Allows you to modify the default caching value for RTSP streams. This " \
"value should be set in millisecond units." )
+#define KASENNA_TEXT N_( "Kasenna RTSP dialect")
+#define KASENNA_LONGTEXT N_( "Kasenna server speaks an old and unstandard dialect of RTSP. " \
+ "When you set this parameter, VLC will try this dialect for communication. In " \
+ "this mode you cannot talk to normal RTSP servers." )
+
vlc_module_begin();
set_description( _("live.com (RTSP/RTP/SDP) demuxer" ) );
set_capability( "demux2", 50 );
+ set_name( "Live.com RTP/RTSP");
set_callbacks( Open, Close );
add_shortcut( "live" );
+ set_category( CAT_INPUT );
+ set_subcategory( SUBCAT_INPUT_DEMUX );
add_submodule();
set_description( _("RTSP/RTP access and demux") );
N_("Use RTP over RTSP (TCP)"), VLC_TRUE );
add_integer( "rtsp-caching", 4 * DEFAULT_PTS_DELAY / 1000, NULL,
CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
+ add_bool( "rtsp-kasenna", VLC_FALSE, NULL, KASENNA_TEXT,
+ KASENNA_LONGTEXT, VLC_TRUE );
vlc_module_end();
/* TODO:
FramedSource *readSource;
vlc_bool_t b_rtcp_sync;
- uint8_t buffer[65536];
+ uint8_t *p_buffer;
+ unsigned int i_buffer;
char waiting;
static int ParseASF( demux_t * );
+static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int i_duration );
+static void StreamClose( void *p_private );
+static void TaskInterrupt( void *p_private );
+
+
/*****************************************************************************
* DemuxOpen:
*****************************************************************************/
if( psz_options )
delete [] psz_options;
- p_sdp = (uint8_t*)p_sys->rtsp->describeURL( psz_url );
+ p_sdp = (uint8_t*)p_sys->rtsp->describeURL( psz_url,
+ NULL, var_CreateGetBool( p_demux, "rtsp-kasenna" ) );
if( p_sdp == NULL )
{
msg_Err( p_demux, "describeURL failed (%s)", p_sys->env->getResultMsg() );
}
p_sys->p_sdp = (char*)p_sdp;
- fprintf( stderr, "sdp=%s\n", p_sys->p_sdp );
+ msg_Dbg( p_demux, "sdp=%s\n", p_sys->p_sdp );
}
if( ( p_sys->ms = MediaSession::createNew(*p_sys->env, p_sys->p_sdp ) ) == NULL )
{
tk->b_rtcp_sync = VLC_FALSE;
tk->p_out_muxed = NULL;
tk->p_es = NULL;
+ tk->i_buffer = 65536;
+ tk->p_buffer = (uint8_t *)malloc( 65536 );
/* Value taken from mplayer */
if( !strcmp( sub->mediumName(), "audio" ) )
delete[] p_extra;
}
}
- else if( !strcmp( sub->codecName(), "X-QT" ) || !strcmp( sub->codecName(), "X-QUICKTIME" ) )
+ else if( !strcmp( sub->codecName(), "X-QT" ) || !strcmp( sub->codecName(), "X-QUICKTIME" ) ||
+ !strcmp( sub->codecName(), "X-QDM" ) || !strcmp( sub->codecName(), "X-SV3V-ES" ) ||
+ !strcmp( sub->codecName(), "X-SORENSONVIDEO" ) )
{
tk->b_quicktime = VLC_TRUE;
}
tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
}
+ if( sub->rtcpInstance() != NULL )
+ {
+ sub->rtcpInstance()->setByeHandler( StreamClose, tk );
+ }
+
if( tk->p_es || tk->b_quicktime || tk->b_muxed || tk->b_asf )
{
tk->readSource = sub->readSource();
{
stream_DemuxDelete( tk->p_out_muxed );
}
-
+ free( tk->p_buffer );
free( tk );
}
if( p_sys->i_track )
free( p_sys );
}
-
-static void StreamRead( void *p_private, unsigned int i_size, struct timeval pts );
-static void StreamClose( void *p_private );
-static void TaskInterrupt( void *p_private );
-
/*****************************************************************************
* Demux:
*****************************************************************************/
if( tk->waiting == 0 )
{
tk->waiting = 1;
- tk->readSource->getNextFrame( tk->buffer, 65536,
+ tk->readSource->getNextFrame( tk->p_buffer, tk->i_buffer,
StreamRead, tk,
StreamClose, tk );
}
p_sys->i_start = (mtime_t)(f * (double)p_sys->i_length);
p_sys->i_pcr_start = 0;
p_sys->i_pcr = 0;
+
for( i = 0; i < p_sys->i_track; i++ )
{
p_sys->track[i]->i_pts = 0;
}
return VLC_SUCCESS;
}
- return VLC_EGENERIC;
+ return VLC_SUCCESS;
}
/* Special for access_demux */
case DEMUX_CAN_PAUSE:
pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
- if( p_sys->rtsp )
+ if( p_sys->rtsp && p_sys->i_length )
*pb = VLC_TRUE; /* Not always true, but will be handled in SET_PAUSE_STATE */
else
*pb = VLC_FALSE;
return VLC_SUCCESS;
case DEMUX_SET_PAUSE_STATE:
+ double d_npt;
MediaSubsessionIterator *iter;
MediaSubsession *sub;
+ d_npt = ( (double)( p_sys->i_pcr - p_sys->i_pcr_start + p_sys->i_start ) ) / 1000000.00;
+
b_bool = (vlc_bool_t)va_arg( args, vlc_bool_t );
if( p_sys->rtsp == NULL )
return VLC_EGENERIC;
while( ( sub = iter->next() ) != NULL )
{
if( ( b_bool && !p_sys->rtsp->pauseMediaSubsession( *sub ) ) ||
- ( !b_bool && !p_sys->rtsp->playMediaSubsession( *sub, -1 ) ) )
+ ( !b_bool && !p_sys->rtsp->playMediaSubsession( *sub, d_npt > 0 ? d_npt : -1 ) ) )
{
delete iter;
return VLC_EGENERIC;
}
}
delete iter;
-
+#if 0
/* reset PCR and PCR start, mmh won't work well for multi-stream I fear */
for( i = 0; i < p_sys->i_track; i++ )
{
- live_track_t *tk = p_sys->track[i];
- tk->i_pts = 0;
+ p_sys->track[i]->i_pts = 0;
}
p_sys->i_pcr_start = 0; /* FIXME Wrong */
p_sys->i_pcr = 0;
-
+#endif
return VLC_SUCCESS;
case DEMUX_GET_TITLE_INFO:
/*****************************************************************************
*
*****************************************************************************/
-static void StreamRead( void *p_private, unsigned int i_size, struct timeval pts )
+static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int duration )
{
live_track_t *tk = (live_track_t*)p_private;
demux_t *p_demux = tk->p_demux;
i_size,
pts.tv_sec * 1000000LL + pts.tv_usec );
#endif
- if( i_size > 65536 )
+
+ /* grow buffer if it looks like buffer is too small, but don't eat
+ * up all the memory on strange streams */
+ if( i_truncated_bytes > 0 && tk->i_buffer < 2000000 )
+ {
+ void *p_tmp;
+ msg_Dbg( p_demux, "lost %d bytes", i_truncated_bytes );
+ msg_Dbg( p_demux, "increasing buffer size to %d", tk->i_buffer * 2 );
+ tk->i_buffer *= 2;
+ p_tmp = realloc( tk->p_buffer, tk->i_buffer );
+ if (p_tmp == NULL)
+ {
+ msg_Warn( p_demux, "realloc failed" );
+ }
+ else
+ {
+ tk->p_buffer = (uint8_t*)p_tmp;
+ }
+ }
+ if( i_size > tk->i_buffer )
{
msg_Warn( p_demux, "buffer overflow" );
}
#endif
p_block = block_New( p_demux, i_size + 4 );
memcpy( p_block->p_buffer, &header, 4 );
- memcpy( p_block->p_buffer + 4, tk->buffer, i_size );
+ memcpy( p_block->p_buffer + 4, tk->p_buffer, i_size );
}
else if( tk->b_asf )
{
int i_copy = __MIN( p_sys->asfh.i_min_data_packet_size, i_size );
p_block = block_New( p_demux, p_sys->asfh.i_min_data_packet_size );
- memcpy( p_block->p_buffer, tk->buffer, i_copy );
+ memcpy( p_block->p_buffer, tk->p_buffer, i_copy );
}
else
{
p_block = block_New( p_demux, i_size );
- memcpy( p_block->p_buffer, tk->buffer, i_size );
+ memcpy( p_block->p_buffer, tk->p_buffer, i_size );
}
if( tk->fmt.i_codec == VLC_FOURCC('h','2','6','1') &&
tk->rtpSource->curPacketMarkerBit() )