mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
Cleanup of sessions and more
Fix the refcounting of media and sessions in the client. Properly clean up the session data when the client performs a teardown. Add Server header to responses. Allow for multiple uri setups in one session. Add Range header to the PLAY response and add the range attribute to the SDP message. Fix the session pool remove method, it used the wrong key in the hashtable. Also give the ownership of the sessionid to the session object.
This commit is contained in:
parent
d5a00f1f23
commit
e789a8fdf3
7 changed files with 137 additions and 19 deletions
|
@ -49,6 +49,8 @@ gst_rtsp_client_finalize (GObject * obj)
|
|||
{
|
||||
GstRTSPClient *client = GST_RTSP_CLIENT (obj);
|
||||
|
||||
g_message ("finalize client %p", client);
|
||||
|
||||
gst_rtsp_connection_free (client->connection);
|
||||
if (client->session_pool)
|
||||
g_object_unref (client->session_pool);
|
||||
|
@ -81,6 +83,8 @@ gst_rtsp_client_new (void)
|
|||
static void
|
||||
send_response (GstRTSPClient *client, GstRTSPMessage *response)
|
||||
{
|
||||
gst_rtsp_message_add_header (response, GST_RTSP_HDR_SERVER, "GStreamer RTSP server");
|
||||
|
||||
#ifdef DEBUG
|
||||
gst_rtsp_message_dump (response);
|
||||
#endif
|
||||
|
@ -149,14 +153,17 @@ find_media (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage *request)
|
|||
|
||||
/* now keep track of the uri and the media */
|
||||
client->uri = gst_rtsp_url_copy (uri);
|
||||
client->media = g_object_ref (media);
|
||||
client->media = media;
|
||||
}
|
||||
else {
|
||||
/* we have seen this uri before, used cached media */
|
||||
media = g_object_ref (client->media);
|
||||
media = client->media;
|
||||
g_message ("reusing cached media %p", media);
|
||||
}
|
||||
|
||||
if (media)
|
||||
g_object_ref (media);
|
||||
|
||||
return media;
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -243,12 +250,17 @@ handle_teardown_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage
|
|||
|
||||
gst_rtsp_session_media_stop (media);
|
||||
|
||||
gst_rtsp_session_pool_remove (client->session_pool, session);
|
||||
g_object_unref (session);
|
||||
/* unmanage the media in the session, returns false if all media session
|
||||
* are torn down. */
|
||||
if (!gst_rtsp_session_release_media (session, media)) {
|
||||
/* remove the session */
|
||||
gst_rtsp_session_pool_remove (client->session_pool, session);
|
||||
|
||||
/* remove the session id from the request, which will also remove it from the
|
||||
* response */
|
||||
gst_rtsp_message_remove_header (request, GST_RTSP_HDR_SESSION, -1);
|
||||
/* remove the session id from the request, which will also remove it from the
|
||||
* response */
|
||||
gst_rtsp_message_remove_header (request, GST_RTSP_HDR_SESSION, -1);
|
||||
}
|
||||
g_object_unref (session);
|
||||
|
||||
/* construct the response now */
|
||||
code = GST_RTSP_STS_OK;
|
||||
|
@ -314,11 +326,13 @@ no_session:
|
|||
not_found:
|
||||
{
|
||||
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
|
||||
g_object_unref (session);
|
||||
return FALSE;
|
||||
}
|
||||
invalid_state:
|
||||
{
|
||||
send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, request);
|
||||
g_object_unref (session);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -333,6 +347,7 @@ handle_play_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage *req
|
|||
GString *rtpinfo;
|
||||
guint n_streams, i;
|
||||
guint timestamp, seqnum;
|
||||
gchar *str;
|
||||
|
||||
if (!(session = ensure_session (client, request)))
|
||||
goto no_session;
|
||||
|
@ -373,8 +388,12 @@ handle_play_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage *req
|
|||
gst_rtsp_message_init_response (&response, code, gst_rtsp_status_as_text (code), request);
|
||||
|
||||
/* add the RTP-Info header */
|
||||
gst_rtsp_message_add_header (&response, GST_RTSP_HDR_RTP_INFO, rtpinfo->str);
|
||||
g_string_free (rtpinfo, TRUE);
|
||||
str = g_string_free (rtpinfo, FALSE);
|
||||
gst_rtsp_message_take_header (&response, GST_RTSP_HDR_RTP_INFO, str);
|
||||
|
||||
/* add the range */
|
||||
str = gst_rtsp_range_to_string (&media->media->range);
|
||||
gst_rtsp_message_take_header (&response, GST_RTSP_HDR_RANGE, str);
|
||||
|
||||
send_response (client, &response);
|
||||
|
||||
|
@ -395,11 +414,13 @@ no_session:
|
|||
not_found:
|
||||
{
|
||||
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
|
||||
g_object_unref (session);
|
||||
return FALSE;
|
||||
}
|
||||
invalid_state:
|
||||
{
|
||||
send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, request);
|
||||
g_object_unref (session);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -490,6 +511,11 @@ handle_setup_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage *re
|
|||
/* we had a session in the request, find it again */
|
||||
if (!(session = gst_rtsp_session_pool_find (client->session_pool, sessid)))
|
||||
goto session_not_found;
|
||||
|
||||
/* get a handle to the configuration of the media in the session, this can
|
||||
* return NULL if this is a new url to manage in this session. */
|
||||
media = gst_rtsp_session_get_media (session, uri);
|
||||
|
||||
need_session = FALSE;
|
||||
}
|
||||
else {
|
||||
|
@ -497,10 +523,15 @@ handle_setup_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage *re
|
|||
* something. */
|
||||
if (!(session = gst_rtsp_session_pool_create (client->session_pool)))
|
||||
goto service_unavailable;
|
||||
|
||||
/* we need a new media configuration in this session */
|
||||
media = NULL;
|
||||
|
||||
need_session = TRUE;
|
||||
}
|
||||
|
||||
if (need_session) {
|
||||
/* we have no media, find one and manage it */
|
||||
if (media == NULL) {
|
||||
GstRTSPMedia *m;
|
||||
|
||||
/* get a handle to the configuration of the media in the session */
|
||||
|
@ -509,8 +540,9 @@ handle_setup_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage *re
|
|||
media = gst_rtsp_session_manage_media (session, uri, m);
|
||||
}
|
||||
}
|
||||
/* get a handle to the configuration of the media in the session */
|
||||
if (!(media = gst_rtsp_session_get_media (session, uri)))
|
||||
|
||||
/* if we stil have no media, error */
|
||||
if (media == NULL)
|
||||
goto not_found;
|
||||
|
||||
/* get a handle to the stream in the media */
|
||||
|
@ -528,6 +560,7 @@ handle_setup_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage *re
|
|||
code = GST_RTSP_STS_OK;
|
||||
gst_rtsp_message_init_response (&response, code, gst_rtsp_status_as_text (code), request);
|
||||
|
||||
/* add the new session header for new session ids */
|
||||
if (need_session)
|
||||
gst_rtsp_message_add_header (&response, GST_RTSP_HDR_SESSION, session->sessionid);
|
||||
|
||||
|
@ -566,6 +599,7 @@ not_found:
|
|||
no_stream:
|
||||
{
|
||||
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
|
||||
g_object_unref (media);
|
||||
return FALSE;
|
||||
}
|
||||
session_not_found:
|
||||
|
@ -628,6 +662,8 @@ handle_describe_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPMessage
|
|||
if (!(sdp = gst_rtsp_sdp_from_media (media)))
|
||||
goto no_sdp;
|
||||
|
||||
g_object_unref (media);
|
||||
|
||||
gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK,
|
||||
gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
|
||||
|
||||
|
|
|
@ -76,6 +76,8 @@ gst_rtsp_media_finalize (GObject * obj)
|
|||
|
||||
media = GST_RTSP_MEDIA (obj);
|
||||
|
||||
g_message ("finalize media %p", media);
|
||||
|
||||
for (i = 0; i < media->streams->len; i++) {
|
||||
GstRTSPMediaStream *stream;
|
||||
|
||||
|
@ -447,6 +449,31 @@ setup_stream (GstRTSPMediaStream *stream, guint idx, GstRTSPMedia *media)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
collect_media_stats (GstRTSPMedia *media)
|
||||
{
|
||||
GstFormat format;
|
||||
gint64 duration;
|
||||
|
||||
media->range.unit = GST_RTSP_RANGE_NPT;
|
||||
media->range.min.type = GST_RTSP_TIME_SECONDS;
|
||||
media->range.min.seconds = 0.0;
|
||||
|
||||
/* get the duration */
|
||||
format = GST_FORMAT_TIME;
|
||||
if (!gst_element_query_duration (media->pipeline, &format, &duration))
|
||||
duration = -1;
|
||||
|
||||
if (duration == -1) {
|
||||
media->range.max.type = GST_RTSP_TIME_END;
|
||||
media->range.max.seconds = -1;
|
||||
}
|
||||
else {
|
||||
media->range.max.type = GST_RTSP_TIME_SECONDS;
|
||||
media->range.max.seconds = ((gdouble)duration) / GST_SECOND;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_prepare:
|
||||
* @obj: a #GstRTSPMedia
|
||||
|
@ -509,6 +536,9 @@ gst_rtsp_media_prepare (GstRTSPMedia *media)
|
|||
/* and back to PAUSED for live pipelines */
|
||||
ret = gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
|
||||
|
||||
/* collect stats about the media */
|
||||
collect_media_stats (media);
|
||||
|
||||
/* unlock the udp src elements */
|
||||
n_streams = gst_rtsp_media_n_streams (media);
|
||||
for (i = 0; i < n_streams; i++) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/rtsp/gstrtsprange.h>
|
||||
#include <gst/rtsp/gstrtspurl.h>
|
||||
|
||||
#ifndef __GST_RTSP_MEDIA_H__
|
||||
|
@ -129,6 +130,9 @@ struct _GstRTSPMedia {
|
|||
|
||||
/* for TCP transport */
|
||||
GstElement *multifdsink;
|
||||
|
||||
/* the range of media */
|
||||
GstRTSPTimeRange range;
|
||||
};
|
||||
|
||||
struct _GstRTSPMediaClass {
|
||||
|
|
|
@ -33,6 +33,7 @@ gst_rtsp_sdp_from_media (GstRTSPMedia *media)
|
|||
{
|
||||
GstSDPMessage *sdp;
|
||||
guint i, n_streams;
|
||||
gchar *rangestr;
|
||||
|
||||
n_streams = gst_rtsp_media_n_streams (media);
|
||||
|
||||
|
@ -46,6 +47,9 @@ gst_rtsp_sdp_from_media (GstRTSPMedia *media)
|
|||
gst_sdp_message_add_time (sdp, "0", "0", NULL);
|
||||
gst_sdp_message_add_attribute (sdp, "tool", "GStreamer");
|
||||
gst_sdp_message_add_attribute (sdp, "type", "broadcast");
|
||||
rangestr = gst_rtsp_range_to_string (&media->range);
|
||||
gst_sdp_message_add_attribute (sdp, "range", rangestr);
|
||||
g_free (rangestr);
|
||||
|
||||
for (i = 0; i < n_streams; i++) {
|
||||
GstRTSPMediaStream *stream;
|
||||
|
|
|
@ -44,7 +44,7 @@ gst_rtsp_session_pool_init (GstRTSPSessionPool * pool)
|
|||
{
|
||||
pool->lock = g_mutex_new ();
|
||||
pool->sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
NULL, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -197,7 +197,7 @@ gst_rtsp_session_pool_remove (GstRTSPSessionPool *pool, GstRTSPSession *sess)
|
|||
g_return_if_fail (GST_IS_RTSP_SESSION (sess));
|
||||
|
||||
g_mutex_lock (pool->lock);
|
||||
found = g_hash_table_remove (pool->sessions, sess);
|
||||
found = g_hash_table_remove (pool->sessions, sess->sessionid);
|
||||
g_mutex_unlock (pool->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ gst_rtsp_session_init (GstRTSPSession * session)
|
|||
static void
|
||||
gst_rtsp_session_free_stream (GstRTSPSessionStream *stream)
|
||||
{
|
||||
g_message ("free session stream %p", stream);
|
||||
|
||||
if (stream->trans.transport)
|
||||
gst_rtsp_transport_free (stream->trans.transport);
|
||||
|
||||
|
@ -57,6 +59,8 @@ gst_rtsp_session_free_media (GstRTSPSessionMedia *media, GstRTSPSession *session
|
|||
|
||||
size = media->streams->len;
|
||||
|
||||
g_message ("free session media %p", media);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
GstRTSPSessionStream *stream;
|
||||
|
||||
|
@ -83,6 +87,8 @@ gst_rtsp_session_finalize (GObject * obj)
|
|||
|
||||
session = GST_RTSP_SESSION (obj);
|
||||
|
||||
g_message ("finalize session %p", session);
|
||||
|
||||
/* free all media */
|
||||
g_list_foreach (session->medias, (GFunc) gst_rtsp_session_free_media,
|
||||
session);
|
||||
|
@ -98,10 +104,12 @@ gst_rtsp_session_finalize (GObject * obj)
|
|||
* gst_rtsp_session_manage_media:
|
||||
* @sess: a #GstRTSPSession
|
||||
* @url: the url for the media
|
||||
* @obj: a #GstRTSPMediaObject
|
||||
* @media: a #GstRTSPMediaObject
|
||||
*
|
||||
* Manage the media object @obj in @sess. @url will be used to retrieve this
|
||||
* media object from the session with gst_rtsp_session_get_media().
|
||||
* media from the session with gst_rtsp_session_get_media().
|
||||
*
|
||||
* Ownership is taken from @media.
|
||||
*
|
||||
* Returns: a new @GstRTSPSessionMedia object.
|
||||
*/
|
||||
|
@ -129,11 +137,46 @@ gst_rtsp_session_manage_media (GstRTSPSession *sess, const GstRTSPUrl *uri,
|
|||
|
||||
sess->medias = g_list_prepend (sess->medias, result);
|
||||
|
||||
g_message ("manage new media %p in session %p", media, sess);
|
||||
g_message ("manage new media %p in session %p", media, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_session_release_media:
|
||||
* @sess: a #GstRTSPSession
|
||||
* @media: a #GstRTSPMediaObject
|
||||
*
|
||||
* Release the managed @media in @sess, freeing the memory allocated by it.
|
||||
*
|
||||
* Returns: %TRUE if there are more media session left in @sess.
|
||||
*/
|
||||
gboolean
|
||||
gst_rtsp_session_release_media (GstRTSPSession *sess,
|
||||
GstRTSPSessionMedia *media)
|
||||
{
|
||||
GList *walk, *next;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE);
|
||||
g_return_val_if_fail (media != NULL, FALSE);
|
||||
|
||||
for (walk = sess->medias; walk;) {
|
||||
GstRTSPSessionMedia *find;
|
||||
|
||||
find = (GstRTSPSessionMedia *) walk->data;
|
||||
next = g_list_next (walk);
|
||||
|
||||
if (find == media) {
|
||||
sess->medias = g_list_delete_link (sess->medias, walk);
|
||||
|
||||
gst_rtsp_session_free_media (find, sess);
|
||||
break;
|
||||
}
|
||||
walk = next;
|
||||
}
|
||||
return (sess->medias != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_session_get_media:
|
||||
* @sess: a #GstRTSPSession
|
||||
|
@ -141,7 +184,7 @@ gst_rtsp_session_manage_media (GstRTSPSession *sess, const GstRTSPUrl *uri,
|
|||
*
|
||||
* Get the session media of the @url.
|
||||
*
|
||||
* Returns: the configuration for @url in @sess.
|
||||
* Returns: the configuration for @url in @sess.
|
||||
*/
|
||||
GstRTSPSessionMedia *
|
||||
gst_rtsp_session_get_media (GstRTSPSession *sess, const GstRTSPUrl *url)
|
||||
|
|
|
@ -107,10 +107,11 @@ GstRTSPSession * gst_rtsp_session_new (const gchar *sessi
|
|||
GstRTSPSessionMedia * gst_rtsp_session_manage_media (GstRTSPSession *sess,
|
||||
const GstRTSPUrl *uri,
|
||||
GstRTSPMedia *media);
|
||||
gboolean gst_rtsp_session_release_media (GstRTSPSession *sess,
|
||||
GstRTSPSessionMedia *media);
|
||||
/* get media in a session */
|
||||
GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess,
|
||||
const GstRTSPUrl *uri);
|
||||
|
||||
/* control media */
|
||||
gboolean gst_rtsp_session_media_play (GstRTSPSessionMedia *media);
|
||||
gboolean gst_rtsp_session_media_pause (GstRTSPSessionMedia *media);
|
||||
|
|
Loading…
Reference in a new issue