Commit c8d1c51f authored by Pierre Ynard's avatar Pierre Ynard

vod: support for adding tracks after start-up

parent df805945
...@@ -972,7 +972,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -972,7 +972,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
id->i_sequence = id->i_seq_sent_next; id->i_sequence = id->i_seq_sent_next;
} }
/* vod_init_id() may fail either because the ES wasn't found in /* vod_init_id() may fail either because the ES wasn't found in
* the VoD media, or because that track wasn't SETUP. In the * the VoD media, or because the RTSP session is gone. In the
* former case, id->rtp_fmt was left untouched. */ * former case, id->rtp_fmt was left untouched. */
format = (id->rtp_fmt.ptname != NULL); format = (id->rtp_fmt.ptname != NULL);
} }
......
...@@ -443,31 +443,47 @@ int RtspTrackAttach( rtsp_stream_t *rtsp, const char *name, ...@@ -443,31 +443,47 @@ int RtspTrackAttach( rtsp_stream_t *rtsp, const char *name,
if (session == NULL) if (session == NULL)
goto out; goto out;
rtsp_strack_t *tr = NULL;
for (int i = 0; session->trackc; i++) for (int i = 0; session->trackc; i++)
{ {
rtsp_strack_t *tr = session->trackv + i; if (session->trackv[i].id == id)
if (tr->id == id)
{ {
tr->rtp_fd = dup_socket(tr->setup_fd); tr = session->trackv + i;
if (tr->rtp_fd == -1)
break; break;
}
}
if (tr != NULL)
{
tr->sout_id = sout_id; tr->sout_id = sout_id;
tr->rtp_fd = dup_socket(tr->setup_fd);
}
else
{
/* The track was not SETUP. We still create one because we'll
* need the sout_id if we set it up later. */
rtsp_strack_t track = { .id = id, .sout_id = sout_id,
.setup_fd = -1, .rtp_fd = -1 };
vlc_rand_bytes (&track.seq_init, sizeof (track.seq_init));
vlc_rand_bytes (&track.ssrc, sizeof (track.ssrc));
INSERT_ELEM(session->trackv, session->trackc, session->trackc, track);
}
uint16_t seq;
*ssrc = ntohl(tr->ssrc); *ssrc = ntohl(tr->ssrc);
*seq_init = tr->seq_init; *seq_init = tr->seq_init;
if (tr->rtp_fd != -1)
{
uint16_t seq;
rtp_add_sink(tr->sout_id, tr->rtp_fd, false, &seq); rtp_add_sink(tr->sout_id, tr->rtp_fd, false, &seq);
/* To avoid race conditions, sout_id->i_seq_sent_next must /* To avoid race conditions, sout_id->i_seq_sent_next must
* be set here and now. Make sure the caller did its job * be set here and now. Make sure the caller did its job
* properly when passing seq_init. */ * properly when passing seq_init. */
assert(tr->seq_init == seq); assert(tr->seq_init == seq);
val = VLC_SUCCESS;
break;
}
} }
val = VLC_SUCCESS;
out: out:
vlc_mutex_unlock(&rtsp->lock); vlc_mutex_unlock(&rtsp->lock);
return val; return val;
...@@ -491,9 +507,21 @@ void RtspTrackDetach( rtsp_stream_t *rtsp, const char *name, ...@@ -491,9 +507,21 @@ void RtspTrackDetach( rtsp_stream_t *rtsp, const char *name,
rtsp_strack_t *tr = session->trackv + i; rtsp_strack_t *tr = session->trackv + i;
if (tr->sout_id == sout_id) if (tr->sout_id == sout_id)
{ {
tr->sout_id = NULL; if (tr->setup_fd == -1)
rtp_del_sink(sout_id, tr->rtp_fd); {
/* No (more) SETUP information: better get rid of the
* track so that we can have new random ssrc and
* seq_init next time. */
REMOVE_ELEM( session->trackv, session->trackc, i );
break;
}
/* We keep the SETUP information of the track, but stop it */
if (tr->rtp_fd != -1)
{
rtp_del_sink(tr->sout_id, tr->rtp_fd);
tr->rtp_fd = -1; tr->rtp_fd = -1;
}
tr->sout_id = NULL;
break; break;
} }
} }
...@@ -506,9 +534,16 @@ out: ...@@ -506,9 +534,16 @@ out:
/** rtsp must be locked */ /** rtsp must be locked */
static void RtspTrackClose( rtsp_strack_t *tr ) static void RtspTrackClose( rtsp_strack_t *tr )
{ {
if (tr->setup_fd != -1)
{
if (tr->rtp_fd != -1) if (tr->rtp_fd != -1)
{
rtp_del_sink(tr->sout_id, tr->rtp_fd); rtp_del_sink(tr->sout_id, tr->rtp_fd);
tr->rtp_fd = -1;
}
net_Close(tr->setup_fd); net_Close(tr->setup_fd);
tr->setup_fd = -1;
}
} }
...@@ -799,18 +834,6 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -799,18 +834,6 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
sizeof (int)); sizeof (int));
net_GetSockAddress( fd, src, &sport ); net_GetSockAddress( fd, src, &sport );
rtsp_strack_t track = { .id = id, .sout_id = id->sout_id,
.setup_fd = fd, .rtp_fd = -1 };
if (vod)
{
vlc_rand_bytes (&track.seq_init, sizeof (track.seq_init));
vlc_rand_bytes (&track.ssrc, sizeof (track.ssrc));
ssrc = track.ssrc;
}
else
ssrc = id->ssrc;
vlc_mutex_lock( &rtsp->lock ); vlc_mutex_lock( &rtsp->lock );
if( psz_session == NULL ) if( psz_session == NULL )
{ {
...@@ -832,28 +855,53 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -832,28 +855,53 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
} }
RtspClientAlive(ses); RtspClientAlive(ses);
/* Bail if the track is already set up: we don't rtsp_strack_t *tr = NULL;
* support changing the transport parameters on the
* fly */
bool setup = false;
for (int i = 0; i < ses->trackc; i++) for (int i = 0; i < ses->trackc; i++)
{ {
if (ses->trackv[i].id == id) if (ses->trackv[i].id == id)
{ {
setup = true; tr = ses->trackv + i;
break; break;
} }
} }
if (setup)
if (tr == NULL)
{
/* Set up a new track */
rtsp_strack_t track = { .id = id,
.sout_id = id->sout_id,
.setup_fd = fd,
.rtp_fd = -1 };
if (vod)
{
vlc_rand_bytes (&track.seq_init,
sizeof (track.seq_init));
vlc_rand_bytes (&track.ssrc, sizeof (track.ssrc));
ssrc = track.ssrc;
}
else
ssrc = id->ssrc;
INSERT_ELEM( ses->trackv, ses->trackc, ses->trackc,
track );
}
else if (tr->setup_fd == -1)
{
/* The track was not SETUP, but it exists
* because there is a sout_id running for it */
tr->setup_fd = fd;
}
else
{ {
/* The track is already set up, and we don't
* support changing the transport parameters on
* the fly */
vlc_mutex_unlock( &rtsp->lock ); vlc_mutex_unlock( &rtsp->lock );
answer->i_status = 455; answer->i_status = 455;
net_Close( fd ); net_Close( fd );
break; break;
} }
INSERT_ELEM( ses->trackv, ses->trackc, ses->trackc,
track );
vlc_mutex_unlock( &rtsp->lock ); vlc_mutex_unlock( &rtsp->lock );
httpd_ServerIP( cl, ip ); httpd_ServerIP( cl, ip );
...@@ -915,10 +963,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -915,10 +963,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
if (vod) if (vod)
{ {
/* We don't keep a reference to the sout_stream_t, /* We don't keep a reference to the sout_stream_t,
* so we check if a sout_id is available instead. * so we check if a sout_id is available instead. */
* FIXME: this is broken if the stream is still
* running but with no track set up; but this case
* is already broken anyway (see below). */
for (int i = 0; i < ses->trackc; i++) for (int i = 0; i < ses->trackc; i++)
{ {
sout_id = ses->trackv[i].sout_id; sout_id = ses->trackv[i].sout_id;
...@@ -934,17 +979,20 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -934,17 +979,20 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
rtsp_strack_t *tr = ses->trackv + i; rtsp_strack_t *tr = ses->trackv + i;
if( ( id == NULL ) || ( tr->id == id ) ) if( ( id == NULL ) || ( tr->id == id ) )
{ {
if (tr->setup_fd == -1)
/* Track not SETUP */
continue;
uint16_t seq; uint16_t seq;
if( tr->rtp_fd == -1 ) if( tr->rtp_fd == -1 )
{ {
if (vod) /* Track not PLAYing yet */
/* TODO: if the RTP stream output is already if (tr->sout_id == NULL)
* started, it won't pick up newly set-up /* Instance not running yet (VoD) */
* tracks, so we need to call rtp_add_sink()
* or something. */
seq = tr->seq_init; seq = tr->seq_init;
else else
{ {
/* Instance running, add a sink to it */
tr->rtp_fd = dup_socket(tr->setup_fd); tr->rtp_fd = dup_socket(tr->setup_fd);
if (tr->rtp_fd == -1) if (tr->rtp_fd == -1)
continue; continue;
...@@ -955,6 +1003,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -955,6 +1003,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
} }
else else
{ {
/* Track already playing */
assert( tr->sout_id != NULL ); assert( tr->sout_id != NULL );
seq = rtp_get_seq( tr->sout_id ); seq = rtp_get_seq( tr->sout_id );
} }
...@@ -1029,12 +1078,15 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -1029,12 +1078,15 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
rtsp_strack_t *tr = ses->trackv + i;; rtsp_strack_t *tr = ses->trackv + i;;
if (tr->id == id) if (tr->id == id)
{ {
if (tr->setup_fd == -1)
break;
found = true;
if (tr->rtp_fd != -1) if (tr->rtp_fd != -1)
{ {
rtp_del_sink(tr->sout_id, tr->rtp_fd); rtp_del_sink(tr->sout_id, tr->rtp_fd);
tr->rtp_fd = -1; tr->rtp_fd = -1;
} }
found = true;
break; break;
} }
} }
...@@ -1089,6 +1141,9 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -1089,6 +1141,9 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
if( ses->trackv[i].id == id ) if( ses->trackv[i].id == id )
{ {
RtspTrackClose( &ses->trackv[i] ); RtspTrackClose( &ses->trackv[i] );
/* Keep VoD tracks whose instance is still
* running */
if (!(vod && ses->trackv[i].sout_id != NULL))
REMOVE_ELEM( ses->trackv, ses->trackc, i ); REMOVE_ELEM( ses->trackv, ses->trackc, i );
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment