AM_PROG_LIBTOOL
dnl *** required versions of GStreamer stuff ***
-GST_REQ=0.10.20
-GSTPB_REQ=0.10.20
+GST_REQ=0.10.22.1
+GSTPB_REQ=0.10.22.1
dnl export for .pc files
AC_SUBST([GST_REQ])
if (!media)
goto not_found;
+ /* the session state must be playing or recording */
+ if (media->state != GST_RTSP_STATE_PLAYING &&
+ media->state != GST_RTSP_STATE_RECORDING)
+ goto invalid_state;
+
gst_rtsp_session_media_pause (media);
- g_object_unref (session);
/* construct the response now */
code = GST_RTSP_STS_OK;
send_response (client, &response);
+ /* the state is now READY */
+ media->state = GST_RTSP_STATE_READY;
+ g_object_unref (session);
+
return FALSE;
/* ERRORS */
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
return FALSE;
}
+invalid_state:
+ {
+ send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, request);
+ return FALSE;
+ }
}
static gboolean
if (!media)
goto not_found;
+ /* the session state must be playing or ready */
+ if (media->state != GST_RTSP_STATE_PLAYING &&
+ media->state != GST_RTSP_STATE_READY)
+ goto invalid_state;
+
/* grab RTPInfo from the payloaders now */
rtpinfo = g_string_new ("");
/* start playing after sending the request */
gst_rtsp_session_media_play (media);
+
+ media->state = GST_RTSP_STATE_PLAYING;
g_object_unref (session);
return FALSE;
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
return FALSE;
}
+invalid_state:
+ {
+ send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, request);
+ return FALSE;
+ }
}
static gboolean
gst_rtsp_message_add_header (&response, GST_RTSP_HDR_TRANSPORT, trans_str);
g_free (trans_str);
- g_object_unref (session);
send_response (client, &response);
+ /* update the state */
+ switch (media->state) {
+ case GST_RTSP_STATE_PLAYING:
+ case GST_RTSP_STATE_RECORDING:
+ case GST_RTSP_STATE_READY:
+ /* no state change */
+ break;
+ default:
+ media->state = GST_RTSP_STATE_READY;
+ break;
+ }
+
+ g_object_unref (session);
+
return TRUE;
/* ERRORS */
}
}
-gboolean
-gst_rtsp_media_stream_add (GstRTSPMediaStream *stream, GstRTSPTransport *ct)
-{
- g_return_val_if_fail (stream != NULL, FALSE);
- g_return_val_if_fail (ct != NULL, FALSE);
- g_return_val_if_fail (stream->prepared, FALSE);
-
- g_message ("adding %s:%d", ct->destination, ct->client_port.min);
-
- g_signal_emit_by_name (stream->udpsink[0], "add", ct->destination, ct->client_port.min, NULL);
- g_signal_emit_by_name (stream->udpsink[1], "add", ct->destination, ct->client_port.max, NULL);
-
- return TRUE;
-}
-
-gboolean
-gst_rtsp_media_stream_remove (GstRTSPMediaStream *stream, GstRTSPTransport *ct)
-{
- g_return_val_if_fail (stream != NULL, FALSE);
- g_return_val_if_fail (ct != NULL, FALSE);
- g_return_val_if_fail (stream->prepared, FALSE);
-
- g_message ("removing %s:%d", ct->destination, ct->client_port.min);
-
- g_signal_emit_by_name (stream->udpsink[0], "remove", ct->destination, ct->client_port.min, NULL);
- g_signal_emit_by_name (stream->udpsink[1], "remove", ct->destination, ct->client_port.max, NULL);
-
- return TRUE;
-}
-
/**
* gst_rtsp_media_play:
* @media: a #GstRTSPMedia
+ * @transports: a GArray of #GstRTSPMediaTrans pointers
*
- * Tell the @media to start playing and streaming to the client.
+ * Start playing @media for to the transports in @transports.
*
- * Returns: a #GstStateChangeReturn
+ * Returns: %TRUE on success.
*/
-GstStateChangeReturn
-gst_rtsp_media_play (GstRTSPMedia *media)
+gboolean
+gst_rtsp_media_play (GstRTSPMedia *media, GArray *transports)
{
+ gint i;
GstStateChangeReturn ret;
- g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_STATE_CHANGE_FAILURE);
- g_return_val_if_fail (media->prepared, GST_STATE_CHANGE_FAILURE);
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+ g_return_val_if_fail (transports != NULL, FALSE);
+ g_return_val_if_fail (media->prepared, FALSE);
+
+ for (i = 0; i < transports->len; i++) {
+ GstRTSPMediaTrans *tr;
+ GstRTSPMediaStream *stream;
+ GstRTSPTransport *trans;
+
+ /* we need a non-NULL entry in the array */
+ tr = g_array_index (transports, GstRTSPMediaTrans *, i);
+ if (tr == NULL)
+ continue;
+
+ /* we need a transport */
+ if (!(trans = tr->transport))
+ continue;
+
+ /* get the stream and add the destinations */
+ stream = gst_rtsp_media_get_stream (media, tr->idx);
+
+ g_message ("adding %s:%d-%d", trans->destination, trans->client_port.min, trans->client_port.max);
+
+ g_signal_emit_by_name (stream->udpsink[0], "add", trans->destination, trans->client_port.min, NULL);
+ g_signal_emit_by_name (stream->udpsink[1], "add", trans->destination, trans->client_port.max, NULL);
+ }
g_message ("playing");
ret = gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
- return ret;
+ return TRUE;
}
/**
* gst_rtsp_media_pause:
* @media: a #GstRTSPMedia
+ * @transports: a array of #GstRTSPTransport pointers
*
- * Tell the @media to pause.
+ * Pause playing @media for to the transports in @transports.
*
- * Returns: a #GstStateChangeReturn
+ * Returns: %TRUE on success.
*/
-GstStateChangeReturn
-gst_rtsp_media_pause (GstRTSPMedia *media)
+gboolean
+gst_rtsp_media_pause (GstRTSPMedia *media, GArray *transports)
{
+ gint i;
GstStateChangeReturn ret;
- g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_STATE_CHANGE_FAILURE);
- g_return_val_if_fail (media->prepared, GST_STATE_CHANGE_FAILURE);
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+ g_return_val_if_fail (transports != NULL, FALSE);
+ g_return_val_if_fail (media->prepared, FALSE);
+
+ for (i = 0; i < transports->len; i++) {
+ GstRTSPMediaTrans *tr;
+ GstRTSPMediaStream *stream;
+ GstRTSPTransport *trans;
+
+ /* we need a non-NULL entry in the array */
+ tr = g_array_index (transports, GstRTSPMediaTrans *, i);
+ if (tr == NULL)
+ continue;
- g_message ("paused");
+ /* we need a transport */
+ if (!(trans = tr->transport))
+ continue;
+
+ /* get the stream and add the destinations */
+ stream = gst_rtsp_media_get_stream (media, tr->idx);
+
+ g_message ("removing %s:%d-%d", trans->destination, trans->client_port.min, trans->client_port.max);
+
+ g_signal_emit_by_name (stream->udpsink[0], "remove", trans->destination, trans->client_port.min, NULL);
+ g_signal_emit_by_name (stream->udpsink[1], "remove", trans->destination, trans->client_port.max, NULL);
+ }
+
+ g_message ("pause");
ret = gst_element_set_state (media->pipeline, GST_STATE_PAUSED);
- return ret;
+ return TRUE;
}
/**
- * gst_rtsp_media_stop:
+ * gst_rtsp_media_stream_stop:
* @media: a #GstRTSPMedia
+ * @transports: a GArray of #GstRTSPMediaTrans pointers
*
- * Tell the @media to stop playing. After this call the media
- * cannot be played or paused anymore
+ * Stop playing @media for to the transports in @transports.
*
- * Returns: a #GstStateChangeReturn
+ * Returns: %TRUE on success.
*/
-GstStateChangeReturn
-gst_rtsp_media_stop (GstRTSPMedia *media)
+gboolean
+gst_rtsp_media_stop (GstRTSPMedia *media, GArray *transports)
{
GstStateChangeReturn ret;
- g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), GST_STATE_CHANGE_FAILURE);
- g_return_val_if_fail (media->prepared, GST_STATE_CHANGE_FAILURE);
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+ g_return_val_if_fail (transports != NULL, FALSE);
+ g_return_val_if_fail (media->prepared, FALSE);
+
+ gst_rtsp_media_pause (media, transports);
g_message ("stop");
ret = gst_element_set_state (media->pipeline, GST_STATE_NULL);
- return ret;
+ return TRUE;
}
typedef struct _GstRTSPMediaStream GstRTSPMediaStream;
typedef struct _GstRTSPMedia GstRTSPMedia;
typedef struct _GstRTSPMediaClass GstRTSPMediaClass;
+typedef struct _GstRTSPMediaTrans GstRTSPMediaTrans;
+
+/**
+ * GstRTSPMediaTrans:
+ * @idx: a stream index
+ * @transport: a transport description
+ *
+ * A Transport description for stream @idx
+ */
+struct _GstRTSPMediaTrans {
+ guint idx;
+
+ GstRTSPTransport *transport;
+};
/**
* GstRTSPMediaStream:
guint gst_rtsp_media_n_streams (GstRTSPMedia *media);
GstRTSPMediaStream * gst_rtsp_media_get_stream (GstRTSPMedia *media, guint idx);
-/* add destinations to a stream */
-gboolean gst_rtsp_media_stream_add (GstRTSPMediaStream *stream, GstRTSPTransport *ct);
-gboolean gst_rtsp_media_stream_remove (GstRTSPMediaStream *stream, GstRTSPTransport *ct);
-
-GstStateChangeReturn gst_rtsp_media_play (GstRTSPMedia *media);
-GstStateChangeReturn gst_rtsp_media_pause (GstRTSPMedia *media);
-GstStateChangeReturn gst_rtsp_media_stop (GstRTSPMedia *media);
+gboolean gst_rtsp_media_play (GstRTSPMedia *media, GArray *trans);
+gboolean gst_rtsp_media_pause (GstRTSPMedia *media, GArray *trans);
+gboolean gst_rtsp_media_stop (GstRTSPMedia *media, GArray *trans);
G_END_DECLS
}
static void
-gst_rtsp_session_free_stream (GstRTSPSessionStream *stream, GstRTSPSessionMedia *media)
+gst_rtsp_session_free_stream (GstRTSPSessionStream *stream)
{
- if (stream->client_trans)
- gst_rtsp_transport_free (stream->client_trans);
+ if (stream->trans.transport)
+ gst_rtsp_transport_free (stream->trans.transport);
g_free (stream);
}
static void
gst_rtsp_session_free_media (GstRTSPSessionMedia *media, GstRTSPSession *session)
{
- g_list_foreach (media->streams, (GFunc) gst_rtsp_session_free_stream,
- media);
- g_list_free (media->streams);
+ guint size, i;
+
+ size = media->streams->len;
+
+ for (i = 0; i < size; i++) {
+ GstRTSPSessionStream *stream;
+
+ stream = g_array_index (media->streams, GstRTSPSessionStream *, i);
+
+ if (stream)
+ gst_rtsp_session_free_stream (stream);
+ }
+ g_array_free (media->streams, TRUE);
if (media->url)
gst_rtsp_url_free (media->url);
GstRTSPMedia *media)
{
GstRTSPSessionMedia *result;
+ guint n_streams;
+
+ g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
+ g_return_val_if_fail (uri != NULL, NULL);
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
+ g_return_val_if_fail (media->prepared, NULL);
result = g_new0 (GstRTSPSessionMedia, 1);
result->media = media;
result->url = gst_rtsp_url_copy ((GstRTSPUrl *)uri);
+ result->state = GST_RTSP_STATE_INIT;
+
+ /* prealloc the streams now, filled with NULL */
+ n_streams = gst_rtsp_media_n_streams (media);
+ result->streams = g_array_sized_new (FALSE, TRUE, sizeof (GstRTSPSessionStream *), n_streams);
+ g_array_set_size (result->streams, n_streams);
sess->medias = g_list_prepend (sess->medias, result);
{
GstRTSPSessionStream *result;
GstRTSPMediaStream *media_stream;
- GList *walk;
g_return_val_if_fail (media != NULL, NULL);
g_return_val_if_fail (media->media != NULL, NULL);
- media_stream = gst_rtsp_media_get_stream (media->media, idx);
- if (media_stream == NULL)
- goto no_media;
-
- result = NULL;
- for (walk = media->streams; walk; walk = g_list_next (walk)) {
- result = (GstRTSPSessionStream *) walk->data;
-
- if (result->media_stream == media_stream)
- break;
+ if (idx >= media->streams->len)
+ return NULL;
- result = NULL;
- }
+ result = g_array_index (media->streams, GstRTSPSessionStream *, idx);
if (result == NULL) {
+ media_stream = gst_rtsp_media_get_stream (media->media, idx);
+ if (media_stream == NULL)
+ goto no_media;
+
result = g_new0 (GstRTSPSessionStream, 1);
+ result->trans.idx = idx;
+ result->trans.transport = NULL;
result->media_stream = media_stream;
- media->streams = g_list_prepend (media->streams, result);
+ g_array_insert_val (media->streams, idx, result);
}
return result;
st->client_port = ct->client_port;
/* keep track of the transports */
- if (stream->client_trans)
- gst_rtsp_transport_free (stream->client_trans);
- stream->client_trans = ct;
+ if (stream->trans.transport)
+ gst_rtsp_transport_free (stream->trans.transport);
+ stream->trans.transport = ct;
st->server_port.min = stream->media_stream->server_port.min;
st->server_port.max = stream->media_stream->server_port.max;
return st;
}
-
/**
* gst_rtsp_session_media_play:
* @media: a #GstRTSPSessionMedia
*
* Tell the media object @media to start playing and streaming to the client.
*
- * Returns: a #GstStateChangeReturn
+ * Returns: %TRUE on success.
*/
-GstStateChangeReturn
+gboolean
gst_rtsp_session_media_play (GstRTSPSessionMedia *media)
{
- GstStateChangeReturn ret;
- GstRTSPSessionStream *stream;
- GList *walk;
+ gboolean ret;
- for (walk = media->streams; walk; walk = g_list_next (walk)) {
- stream = (GstRTSPSessionStream *) walk->data;
-
- gst_rtsp_media_stream_add (stream->media_stream, stream->client_trans);
- }
- ret = gst_rtsp_media_play (media->media);
+ ret = gst_rtsp_media_play (media->media, media->streams);
return ret;
}
*
* Tell the media object @media to pause.
*
- * Returns: a #GstStateChangeReturn
+ * Returns: %TRUE on success.
*/
-GstStateChangeReturn
+gboolean
gst_rtsp_session_media_pause (GstRTSPSessionMedia *media)
{
- GstStateChangeReturn ret;
+ gboolean ret;
- ret = gst_rtsp_media_pause (media->media);
+ ret = gst_rtsp_media_pause (media->media, media->streams);
return ret;
}
* Tell the media object @media to stop playing. After this call the media
* cannot be played or paused anymore
*
- * Returns: a #GstStateChangeReturn
+ * Returns: %TRUE on success.
*/
-GstStateChangeReturn
+gboolean
gst_rtsp_session_media_stop (GstRTSPSessionMedia *media)
{
- GstStateChangeReturn ret;
+ gboolean ret;
- ret = gst_rtsp_media_stop (media->media);
+ ret = gst_rtsp_media_stop (media->media, media->streams);
return ret;
}
/**
* GstRTSPSessionStream:
+ * @trans: the media transport
+ * @media_stream: the controlled media stream
*
* Configuration of a stream. A stream is an audio or video stream related to a
* media.
*/
struct _GstRTSPSessionStream
{
+ GstRTSPMediaTrans trans;
+
/* the stream of the media */
GstRTSPMediaStream *media_stream;
-
- /* client and server transports */
- GstRTSPTransport *client_trans;
};
/**
/* the pipeline for the media */
GstRTSPMedia *media;
+ /* the server state */
+ GstRTSPState state;
+
/* configuration for the different streams */
- GList *streams;
+ GArray *streams;
};
/**
GType gst_rtsp_session_get_type (void);
+/* create a new session */
GstRTSPSession * gst_rtsp_session_new (const gchar *sessionid);
+/* handle media in a session */
GstRTSPSessionMedia * gst_rtsp_session_manage_media (GstRTSPSession *sess,
const GstRTSPUrl *uri,
GstRTSPMedia *media);
+/* get media in a session */
GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess,
const GstRTSPUrl *uri);
-GstStateChangeReturn gst_rtsp_session_media_play (GstRTSPSessionMedia *media);
-GstStateChangeReturn gst_rtsp_session_media_pause (GstRTSPSessionMedia *media);
-GstStateChangeReturn gst_rtsp_session_media_stop (GstRTSPSessionMedia *media);
+/* control media */
+gboolean gst_rtsp_session_media_play (GstRTSPSessionMedia *media);
+gboolean gst_rtsp_session_media_pause (GstRTSPSessionMedia *media);
+gboolean gst_rtsp_session_media_stop (GstRTSPSessionMedia *media);
+/* get stream config */
GstRTSPSessionStream * gst_rtsp_session_media_get_stream (GstRTSPSessionMedia *media,
guint idx);
+/* configure transport */
GstRTSPTransport * gst_rtsp_session_stream_set_transport (GstRTSPSessionStream *stream,
GstRTSPTransport *ct);