enum vod_query_e
{
- VOD_MEDIA_PLAY, /* arg1= char * res= */
- VOD_MEDIA_PAUSE, /* arg1= res= */
+ VOD_MEDIA_PLAY, /* arg1= char *, arg2= int64_t *, res= */
+ VOD_MEDIA_PAUSE, /* arg1= int64_t * res= */
VOD_MEDIA_STOP, /* arg1= res=can fail */
VOD_MEDIA_SEEK, /* arg1= double res= */
VOD_MEDIA_REWIND, /* arg1= double res= */
switch( cmd.i_type )
{
case RTSP_CMD_TYPE_PLAY:
+ cmd.i_arg = -1;
vod_MediaControl( p_vod, p_media, cmd.psz_session,
- VOD_MEDIA_PLAY, cmd.psz_arg );
+ VOD_MEDIA_PLAY, cmd.psz_arg, &cmd.i_arg );
break;
case RTSP_CMD_TYPE_PAUSE:
+ cmd.i_arg = -1;
vod_MediaControl( p_vod, p_media, cmd.psz_session,
- VOD_MEDIA_PAUSE );
+ VOD_MEDIA_PAUSE, &cmd.i_arg );
break;
case RTSP_CMD_TYPE_STOP:
/* Return a timestamp corresponding to packets being sent now, and that
* can be passed to rtp_compute_ts() to get rtptime values for each ES.
- * If the stream output is not started, the initial timestamp that will
- * be used with the first packets is returned instead. */
+ * Also return the NPT corresponding to this timestamp. If the stream
+ * output is not started, the initial timestamp that will be used with
+ * the first packets for NPT=0 is returned instead. */
int64_t rtp_get_ts( const sout_stream_t *p_stream, const sout_stream_id_t *id,
- const vod_media_t *p_media, const char *psz_vod_session )
+ const vod_media_t *p_media, const char *psz_vod_session,
+ int64_t *p_npt )
{
+ if (p_npt != NULL)
+ *p_npt = 0;
+
if (id != NULL)
p_stream = id->p_stream;
if( now < i_npt_zero )
return p_sys->i_pts_zero;
- return p_sys->i_pts_zero + (now - i_npt_zero);
+ int64_t npt = now - i_npt_zero;
+ if (p_npt != NULL)
+ *p_npt = npt;
+
+ return p_sys->i_pts_zero + npt;
}
void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
void rtp_del_sink( sout_stream_id_t *id, int fd );
uint16_t rtp_get_seq( sout_stream_id_t *id );
int64_t rtp_get_ts( const sout_stream_t *p_stream, const sout_stream_id_t *id,
- const vod_media_t *p_media, const char *psz_vod_session );
+ const vod_media_t *p_media, const char *psz_vod_session,
+ int64_t *p_npt );
/* RTP packetization */
void rtp_packetize_common (sout_stream_id_t *id, block_t *out,
int vod_check_range(vod_media_t *p_media, const char *psz_session,
int64_t start, int64_t end);
void vod_play(vod_media_t *p_media, const char *psz_session,
- int64_t start, int64_t end, bool running);
-void vod_pause(vod_media_t *p_media, const char *psz_session);
+ int64_t *start, int64_t end);
+void vod_pause(vod_media_t *p_media, const char *psz_session, int64_t *npt);
void vod_stop(vod_media_t *p_media, const char *psz_session);
const char *vod_get_mux(const vod_media_t *p_media);
answer->i_status = 200;
psz_session = httpd_MsgGet( query, "Session" );
- int64_t start = -1, end = -1;
+ int64_t start = -1, end = -1, npt;
const char *range = httpd_MsgGet (query, "Range");
if (range != NULL)
{
}
}
int64_t ts = rtp_get_ts(vod ? NULL : (sout_stream_t *)owner,
- sout_id, rtsp->vod_media, psz_session);
+ sout_id, rtsp->vod_media, psz_session,
+ vod ? NULL : &npt);
for( int i = 0; i < ses->trackc; i++ )
{
}
if (vod)
{
- bool running = (sout_id != NULL);
- vod_play(rtsp->vod_media, psz_session, start, end, running);
+ vod_play(rtsp->vod_media, psz_session, &start, end);
+ npt = start;
}
}
vlc_mutex_unlock( &rtsp->lock );
+ if (ses != NULL)
+ {
+ double f_npt = (double) npt / CLOCK_FREQ;
+ httpd_MsgAdd( answer, "Range", "npt=%f-", f_npt );
+ }
+
if( httpd_MsgGet( query, "Scale" ) != NULL )
httpd_MsgAdd( answer, "Scale", "1." );
break;
{
if (id == NULL)
{
- if (vod)
- vod_pause(rtsp->vod_media, psz_session);
+ assert(vod);
+ int64_t npt;
+ vod_pause(rtsp->vod_media, psz_session, &npt);
+ double f_npt = (double) npt / CLOCK_FREQ;
+ httpd_MsgAdd( answer, "Range", "npt=%f-", f_npt );
}
else /* "Mute" the selected track */
{
{
RTSP_CMD_TYPE_NONE, /* Exit requested */
+#if 0
RTSP_CMD_TYPE_PLAY,
RTSP_CMD_TYPE_PAUSE,
+#endif
RTSP_CMD_TYPE_STOP,
- RTSP_CMD_TYPE_SEEK,
#if 0
+ RTSP_CMD_TYPE_SEEK,
RTSP_CMD_TYPE_REWIND,
RTSP_CMD_TYPE_FORWARD,
#endif
/* */
switch( cmd.i_type )
{
+#if 0
case RTSP_CMD_TYPE_PLAY:
vod_MediaControl( p_vod, p_media, cmd.psz_session,
VOD_MEDIA_PLAY, cmd.psz_arg );
vod_MediaControl( p_vod, p_media, cmd.psz_session,
VOD_MEDIA_PAUSE );
break;
+#endif
case RTSP_CMD_TYPE_STOP:
vod_MediaControl( p_vod, p_media, cmd.psz_session, VOD_MEDIA_STOP );
break;
+#if 0
case RTSP_CMD_TYPE_SEEK:
vod_MediaControl( p_vod, p_media, cmd.psz_session,
VOD_MEDIA_SEEK, cmd.i_arg );
break;
-#if 0
case RTSP_CMD_TYPE_REWIND:
vod_MediaControl( p_vod, p_media, cmd.psz_session,
VOD_MEDIA_REWIND, cmd.f_arg );
/* TODO: add support in the VLM for queueing proper PLAY requests with
* start and end times, fetch whether the input is seekable... and then
- * clean this up and remove the running argument */
+ * clean this up */
void vod_play(vod_media_t *p_media, const char *psz_session,
- int64_t start, int64_t end, bool running)
+ int64_t *start, int64_t end)
{
- if (vod_check_range(p_media, psz_session, start, end) != VLC_SUCCESS)
+ if (vod_check_range(p_media, psz_session, *start, end) != VLC_SUCCESS)
return;
- /* We want to seek before unpausing, but it won't
- * work if the instance is not running yet. */
-
- if (!running)
- /* We're passing the #vod{} sout chain here */
- CommandPush(p_media->p_vod, RTSP_CMD_TYPE_PLAY, p_media,
- psz_session, 0, "vod");
- if (start >= 0)
- CommandPush(p_media->p_vod, RTSP_CMD_TYPE_SEEK, p_media,
- psz_session, start, NULL);
- if (running)
- /* This is the thing to do to unpause... */
- CommandPush(p_media->p_vod, RTSP_CMD_TYPE_PLAY, p_media,
- psz_session, 0, "vod");
+ /* We're passing the #vod{} sout chain here */
+ vod_MediaControl(p_media->p_vod, p_media, psz_session,
+ VOD_MEDIA_PLAY, "vod", start);
}
-void vod_pause(vod_media_t *p_media, const char *psz_session)
+void vod_pause(vod_media_t *p_media, const char *psz_session, int64_t *npt)
{
- CommandPush(p_media->p_vod, RTSP_CMD_TYPE_PAUSE, p_media,
- psz_session, 0, NULL);
+ vod_MediaControl(p_media->p_vod, p_media, psz_session,
+ VOD_MEDIA_PAUSE, npt);
}
void vod_stop(vod_media_t *p_media, const char *psz_session)
switch( i_query )
{
case VOD_MEDIA_PLAY:
+ {
psz = (const char *)va_arg( args, const char * );
+ int64_t *i_time = (int64_t *)va_arg( args, int64_t *);
+ bool b_retry = false;
+ if (*i_time < 0)
+ {
+ /* No start time requested: return the current NPT */
+ i_ret = vlm_ControlInternal( vlm, VLM_GET_MEDIA_INSTANCE_TIME, id, psz_id, i_time );
+ /* The instance is not running yet, it will start at 0 */
+ if (i_ret)
+ *i_time = 0;
+ }
+ else
+ {
+ /* We want to seek before unpausing, but it won't
+ * work if the instance is not running yet. */
+ b_retry = vlm_ControlInternal( vlm, VLM_SET_MEDIA_INSTANCE_TIME, id, psz_id, *i_time );
+ }
+
i_ret = vlm_ControlInternal( vlm, VLM_START_MEDIA_VOD_INSTANCE, id, psz_id, 0, psz );
+
+ if (!i_ret && b_retry)
+ i_ret = vlm_ControlInternal( vlm, VLM_SET_MEDIA_INSTANCE_TIME, id, psz_id, *i_time );
break;
+ }
case VOD_MEDIA_PAUSE:
+ {
+ int64_t *i_time = (int64_t *)va_arg( args, int64_t *);
i_ret = vlm_ControlInternal( vlm, VLM_PAUSE_MEDIA_INSTANCE, id, psz_id );
+ if (!i_ret)
+ i_ret = vlm_ControlInternal( vlm, VLM_GET_MEDIA_INSTANCE_TIME, id, psz_id, i_time );
break;
+ }
case VOD_MEDIA_STOP:
i_ret = vlm_ControlInternal( vlm, VLM_STOP_MEDIA_INSTANCE, id, psz_id );