Commit de7c72de authored by Wim Taymans's avatar Wim Taymans

rtsp: massive refactoring

Make GObjects from the remaining simple structures.
Remove GstRTSPSessionStream, it's not needed.
Rename GstRTSPMediaStream -> GstRTSPStream: It is shorter
Rename GstRTSPMediaTrans -> GstRTSPStreamTransport: It describes how
  a GstRTSPStream should be transported to a client.
Rename GstRTSPMediaFactory::get_element -> create_element because that
  more accurately describes what it does.
Make nice methods instead of poking in the structures.
Move some methods inside the relevant object source code.
Use GPtrArray to store objects instead of plain arrays, it is more
  natural and allows us to more easily clean up.
Move the allocation of udp ports to the Stream object. The Stream object
  contains the elements needed to stream the media to a client.
Improve the prepare and unprepare methods. Unprepare should now undo
  everything prepare did. Improve also async unprepare when doing EOS on
  shutdown. Make sure we always unprepare correctly.
parent 0de6262d
......@@ -6,7 +6,10 @@ public_headers = \
rtsp-media-factory.h \
rtsp-media-factory-uri.h \
rtsp-media-mapping.h \
rtsp-stream.h \
rtsp-stream-transport.h \
rtsp-session.h \
rtsp-session-media.h \
rtsp-session-pool.h \
rtsp-client.h \
rtsp-server.h
......@@ -19,7 +22,10 @@ c_sources = \
rtsp-media-factory.c \
rtsp-media-factory-uri.c \
rtsp-media-mapping.c \
rtsp-stream.c \
rtsp-stream-transport.c \
rtsp-session.c \
rtsp-session-media.c \
rtsp-session-pool.c \
rtsp-client.c \
rtsp-server.c
......
......@@ -69,7 +69,7 @@ static void gst_rtsp_client_finalize (GObject * obj);
static GstSDPMessage *create_sdp (GstRTSPClient * client, GstRTSPMedia * media);
static void client_session_finalized (GstRTSPClient * client,
GstRTSPSession * session);
static void unlink_session_streams (GstRTSPClient * client,
static void unlink_session_transports (GstRTSPClient * client,
GstRTSPSession * session, GstRTSPSessionMedia * media);
G_DEFINE_TYPE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT);
......@@ -184,7 +184,7 @@ client_unlink_session (GstRTSPClient * client, GstRTSPSession * session)
GstRTSPSessionMedia *media = g_list_first (session->medias)->data;
gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
unlink_session_streams (client, session, media);
unlink_session_transports (client, session, media);
/* unmanage the media in the session. this will modify session->medias */
gst_rtsp_session_release_media (session, media);
}
......@@ -480,6 +480,7 @@ do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
gst_rtsp_message_init_data (&message, channel);
/* FIXME, need some sort of iovec RTSPMessage here */
if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ))
return FALSE;
......@@ -498,48 +499,49 @@ do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
}
static void
link_stream (GstRTSPClient * client, GstRTSPSession * session,
GstRTSPSessionStream * stream)
link_transport (GstRTSPClient * client, GstRTSPSession * session,
GstRTSPStreamTransport * trans)
{
GST_DEBUG ("client %p: linking stream %p", client, stream);
gst_rtsp_session_stream_set_callbacks (stream, (GstRTSPSendFunc) do_send_data,
GST_DEBUG ("client %p: linking transport %p", client, trans);
gst_rtsp_stream_transport_set_callbacks (trans,
(GstRTSPSendFunc) do_send_data,
(GstRTSPSendFunc) do_send_data, client, NULL);
client->streams = g_list_prepend (client->streams, stream);
client->transports = g_list_prepend (client->transports, trans);
/* make sure our session can't expire */
gst_rtsp_session_prevent_expire (session);
}
static void
unlink_stream (GstRTSPClient * client, GstRTSPSession * session,
GstRTSPSessionStream * stream)
unlink_transport (GstRTSPClient * client, GstRTSPSession * session,
GstRTSPStreamTransport * trans)
{
GST_DEBUG ("client %p: unlinking stream %p", client, stream);
gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL);
client->streams = g_list_remove (client->streams, stream);
GST_DEBUG ("client %p: unlinking transport %p", client, trans);
gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
client->transports = g_list_remove (client->transports, trans);
/* our session can now expire */
gst_rtsp_session_allow_expire (session);
}
static void
unlink_session_streams (GstRTSPClient * client, GstRTSPSession * session,
unlink_session_transports (GstRTSPClient * client, GstRTSPSession * session,
GstRTSPSessionMedia * media)
{
guint n_streams, i;
n_streams = gst_rtsp_media_n_streams (media->media);
for (i = 0; i < n_streams; i++) {
GstRTSPSessionStream *sstream;
GstRTSPStreamTransport *trans;
GstRTSPTransport *tr;
/* get the stream as configured in the session */
sstream = gst_rtsp_session_media_get_stream (media, i);
trans = gst_rtsp_session_media_get_transport (media, i);
/* get the transport, if there is no transport configured, skip this stream */
if (!(tr = sstream->trans.transport))
if (!(tr = trans->transport))
continue;
if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
/* for TCP, unlink the stream from the TCP connection of the client */
unlink_stream (client, session, sstream);
unlink_transport (client, session, trans);
}
}
}
......@@ -581,7 +583,7 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
state->sessmedia = media;
/* unlink the all TCP callbacks */
unlink_session_streams (client, session, media);
unlink_session_transports (client, session, media);
/* remove the session from the watched sessions */
g_object_weak_unref (G_OBJECT (session),
......@@ -722,7 +724,7 @@ handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
goto invalid_state;
/* unlink the all TCP callbacks */
unlink_session_streams (client, session, media);
unlink_session_transports (client, session, media);
/* then pause sending */
gst_rtsp_session_media_set_state (media, GST_STATE_PAUSED);
......@@ -769,7 +771,6 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
GstRTSPStatusCode code;
GString *rtpinfo;
guint n_streams, i, infocount;
guint timestamp, seqnum;
gchar *str;
GstRTSPTimeRange *range;
GstRTSPResult res;
......@@ -805,44 +806,31 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
n_streams = gst_rtsp_media_n_streams (media->media);
for (i = 0, infocount = 0; i < n_streams; i++) {
GstRTSPSessionStream *sstream;
GstRTSPMediaStream *stream;
GstRTSPStreamTransport *trans;
GstRTSPTransport *tr;
GObjectClass *payobjclass;
gchar *uristr;
guint rtptime, seq;
/* get the stream as configured in the session */
sstream = gst_rtsp_session_media_get_stream (media, i);
trans = gst_rtsp_session_media_get_transport (media, i);
/* get the transport, if there is no transport configured, skip this stream */
if (!(tr = sstream->trans.transport)) {
if (!(tr = trans->transport)) {
GST_INFO ("stream %d is not configured", i);
continue;
}
if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
/* for TCP, link the stream to the TCP connection of the client */
link_stream (client, session, sstream);
link_transport (client, session, trans);
}
stream = sstream->media_stream;
payobjclass = G_OBJECT_GET_CLASS (stream->payloader);
if (g_object_class_find_property (payobjclass, "seqnum") &&
g_object_class_find_property (payobjclass, "timestamp")) {
GObject *payobj;
payobj = G_OBJECT (stream->payloader);
/* only add RTP-Info for streams with seqnum and timestamp */
g_object_get (payobj, "seqnum", &seqnum, "timestamp", &timestamp, NULL);
if (gst_rtsp_stream_get_rtpinfo (trans->stream, &rtptime, &seq)) {
if (infocount > 0)
g_string_append (rtpinfo, ", ");
uristr = gst_rtsp_url_get_request_uri (state->uri);
g_string_append_printf (rtpinfo, "url=%s/stream=%d;seq=%u;rtptime=%u",
uristr, i, seqnum, timestamp);
uristr, i, seq, rtptime);
g_free (uristr);
infocount++;
......@@ -944,7 +932,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
GstRTSPLowerTrans supported;
GstRTSPStatusCode code;
GstRTSPSession *session;
GstRTSPSessionStream *stream;
GstRTSPStreamTransport *trans;
gchar *trans_str, *pos;
guint streamid;
GstRTSPSessionMedia *media;
......@@ -1086,14 +1074,14 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
}
}
/* get a handle to the stream in the media */
if (!(stream = gst_rtsp_session_media_get_stream (media, streamid)))
goto no_stream;
/* get a handle to the transport of the media in this session */
if (!(trans = gst_rtsp_session_media_get_transport (media, streamid)))
goto no_stream_transport;
st = gst_rtsp_session_stream_set_transport (stream, ct);
st = gst_rtsp_stream_transport_set_transport (trans, ct);
/* configure keepalive for this transport */
gst_rtsp_session_stream_set_keepalive (stream,
gst_rtsp_stream_transport_set_keepalive (trans,
(GstRTSPKeepAliveFunc) do_keepalive, session, NULL);
/* serialize the server transport */
......@@ -1149,7 +1137,7 @@ invalid_blocksize:
gst_rtsp_transport_free (ct);
return FALSE;
}
no_stream:
no_stream_transport:
{
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
g_object_unref (session);
......@@ -1265,7 +1253,6 @@ handle_describe_request (GstRTSPClient * client, GstRTSPClientState * state)
if (!(media = find_media (client, state)))
goto no_media;
/* create an SDP for the media object on this client */
if (!(sdp = klass->create_sdp (client, media)))
goto no_sdp;
......@@ -1567,28 +1554,28 @@ handle_data (GstRTSPClient * client, GstRTSPMessage * message)
buffer = gst_buffer_new_wrapped (data, size);
handled = FALSE;
for (walk = client->streams; walk; walk = g_list_next (walk)) {
GstRTSPSessionStream *stream = (GstRTSPSessionStream *) walk->data;
GstRTSPMediaStream *mstream;
for (walk = client->transports; walk; walk = g_list_next (walk)) {
GstRTSPStreamTransport *trans = (GstRTSPStreamTransport *) walk->data;
GstRTSPStream *stream;
GstRTSPTransport *tr;
/* get the transport, if there is no transport configured, skip this stream */
if (!(tr = stream->trans.transport))
if (!(tr = trans->transport))
continue;
/* we also need a media stream */
if (!(mstream = stream->media_stream))
if (!(stream = trans->stream))
continue;
/* check for TCP transport */
if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
/* dispatch to the stream based on the channel number */
if (tr->interleaved.min == channel) {
gst_rtsp_media_stream_rtp (mstream, buffer);
gst_rtsp_stream_recv_rtp (stream, buffer);
handled = TRUE;
break;
} else if (tr->interleaved.max == channel) {
gst_rtsp_media_stream_rtcp (mstream, buffer);
gst_rtsp_stream_recv_rtcp (stream, buffer);
handled = TRUE;
break;
}
......
......@@ -33,6 +33,7 @@ typedef struct _GstRTSPClientState GstRTSPClientState;
#include "rtsp-media.h"
#include "rtsp-media-mapping.h"
#include "rtsp-session-pool.h"
#include "rtsp-session-media.h"
#include "rtsp-auth.h"
#include "rtsp-sdp.h"
......@@ -58,7 +59,7 @@ typedef struct _GstRTSPClientState GstRTSPClientState;
*
* Information passed around containing the client state of a request.
*/
struct _GstRTSPClientState{
struct _GstRTSPClientState {
GstRTSPMessage *request;
GstRTSPUrl *uri;
GstRTSPMethod method;
......@@ -81,7 +82,7 @@ struct _GstRTSPClientState{
* @media_mapping: handle to the media mapping used by the client.
* @uri: cached uri
* @media: cached media
* @streams: a list of streams using @connection.
* @transports: a list of #GstRTSPStreamTransport using @connection.
* @sessions: a list of sessions managed by @connection.
*
* The client structure.
......@@ -104,7 +105,7 @@ struct _GstRTSPClient {
GstRTSPUrl *uri;
GstRTSPMedia *media;
GList *streams;
GList *transports;
GList *sessions;
};
......
......@@ -66,7 +66,7 @@ static void gst_rtsp_media_factory_uri_set_property (GObject * object,
guint propid, const GValue * value, GParamSpec * pspec);
static void gst_rtsp_media_factory_uri_finalize (GObject * obj);
static GstElement *rtsp_media_factory_uri_get_element (GstRTSPMediaFactory *
static GstElement *rtsp_media_factory_uri_create_element (GstRTSPMediaFactory *
factory, const GstRTSPUrl * url);
G_DEFINE_TYPE (GstRTSPMediaFactoryURI, gst_rtsp_media_factory_uri,
......@@ -105,7 +105,7 @@ gst_rtsp_media_factory_uri_class_init (GstRTSPMediaFactoryURIClass * klass)
"Use the gstpay payloader to avoid decoding", DEFAULT_USE_GSTPAY,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
mediafactory_class->get_element = rtsp_media_factory_uri_get_element;
mediafactory_class->create_element = rtsp_media_factory_uri_create_element;
GST_DEBUG_CATEGORY_INIT (rtsp_media_factory_uri_debug, "rtspmediafactoryuri",
0, "GstRTSPMediaFactoryUri");
......@@ -528,7 +528,7 @@ no_more_pads_cb (GstElement * uribin, GstElement * element)
}
static GstElement *
rtsp_media_factory_uri_get_element (GstRTSPMediaFactory * factory,
rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url)
{
GstElement *topbin, *element, *uribin;
......
......@@ -58,7 +58,7 @@ static void gst_rtsp_media_factory_finalize (GObject * obj);
static gchar *default_gen_key (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url);
static GstElement *default_get_element (GstRTSPMediaFactory * factory,
static GstElement *default_create_element (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url);
static GstRTSPMedia *default_construct (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url);
......@@ -139,7 +139,7 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
G_TYPE_NONE, 1, GST_TYPE_RTSP_MEDIA);
klass->gen_key = default_gen_key;
klass->get_element = default_get_element;
klass->create_element = default_create_element;
klass->construct = default_construct;
klass->configure = default_configure;
klass->create_pipeline = default_create_pipeline;
......@@ -578,13 +578,15 @@ media_unprepared (GstRTSPMedia * media, GstRTSPMediaFactory * factory)
* @factory: a #GstRTSPMediaFactory
* @url: the url used
*
* Prepare the media object and create its streams. Implementations
* Construct the media object and create its streams. Implementations
* should create the needed gstreamer elements and add them to the result
* object. No state changes should be performed on them yet.
*
* One or more GstRTSPMediaStream objects should be added to the result with
* the srcpad member set to a source pad that produces buffer of type
* application/x-rtp.
* One or more GstRTSPStream objects should be created from the result
* with gst_rtsp_media_create_stream ().
*
* After the media is constructed, it can be configured and then prepared
* with gst_rtsp_media_prepare ().
*
* Returns: (transfer full): a new #GstRTSPMedia if the media could be prepared.
*/
......@@ -596,6 +598,9 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
GstRTSPMedia *media;
GstRTSPMediaFactoryClass *klass;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
g_return_val_if_fail (url != NULL, NULL);
klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
/* convert the url to a key for the hashtable. NULL return or a NULL function
......@@ -676,7 +681,7 @@ default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
}
static GstElement *
default_get_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
default_create_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
{
GstElement *element;
GError *error = NULL;
......@@ -718,63 +723,6 @@ parse_error:
}
}
/* try to find all the payloader elements, they should be named 'pay%d'. for
* each of the payloaders we will create a stream and collect the source pad. */
void
gst_rtsp_media_factory_collect_streams (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url, GstRTSPMedia * media)
{
GstElement *element, *elem;
GstPad *pad;
gint i;
GstRTSPMediaStream *stream;
gboolean have_elem;
element = media->element;
have_elem = TRUE;
for (i = 0; have_elem; i++) {
gchar *name;
have_elem = FALSE;
name = g_strdup_printf ("pay%d", i);
if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
/* create the stream */
stream = g_new0 (GstRTSPMediaStream, 1);
stream->payloader = elem;
GST_INFO ("found stream %d with payloader %p", i, elem);
pad = gst_element_get_static_pad (elem, "src");
/* ghost the pad of the payloader to the element */
stream->srcpad = gst_ghost_pad_new (name, pad);
g_object_unref (pad);
gst_pad_set_active (stream->srcpad, TRUE);
gst_element_add_pad (media->element, stream->srcpad);
gst_object_unref (elem);
/* add stream now */
g_array_append_val (media->streams, stream);
have_elem = TRUE;
}
g_free (name);
name = g_strdup_printf ("dynpay%d", i);
if ((elem = gst_bin_get_by_name (GST_BIN (element), name))) {
/* a stream that will dynamically create pads to provide RTP packets */
GST_INFO ("found dynamic element %d, %p", i, elem);
media->dynamic = g_list_prepend (media->dynamic, elem);
have_elem = TRUE;
}
g_free (name);
}
}
static GstRTSPMedia *
default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
{
......@@ -787,10 +735,7 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
if (!klass->create_pipeline)
goto no_create;
if (klass->get_element)
element = klass->get_element (factory, url);
else
element = NULL;
element = gst_rtsp_media_factory_create_element (factory, url);
if (element == NULL)
goto no_element;
......@@ -798,12 +743,12 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
media = gst_rtsp_media_new ();
media->element = element;
gst_rtsp_media_collect_streams (media);
media->pipeline = klass->create_pipeline (factory, media);
if (media->pipeline == NULL)
goto no_pipeline;
gst_rtsp_media_factory_collect_streams (factory, url, media);
return media;
/* ERRORS */
......@@ -879,16 +824,34 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
}
/**
* gst_rtsp_media_factory_get_element:
* gst_rtsp_media_factory_create_element:
* @factory: a #GstRTSPMediaFactory
* @url: the url used
*
* Construct and return a #GstElement that is a #GstBin containing
* the elements to use for streaming the media.
*
* The bin should contain payloaders pay%d for each stream. The default
* implementation of this function returns the bin created from the
* launch parameter.
*
* Returns: (transfer floating) a new #GstElement.
*/
GstElement *
gst_rtsp_media_factory_get_element (GstRTSPMediaFactory * factory,
gst_rtsp_media_factory_create_element (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url)
{
GstRTSPMediaFactoryClass *klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
return klass->get_element (factory, url);
GstRTSPMediaFactoryClass *klass;
GstElement *result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
if (klass->create_element)
result = klass->create_element (factory, url);
else
result = NULL;
return result;
}
......@@ -82,13 +82,13 @@ struct _GstRTSPMediaFactory {
* @gen_key: convert @url to a key for caching shared #GstRTSPMedia objects.
* The default implementation of this function will use the complete URL
* including the query parameters to return a key.
* @get_element: Construct and return a #GstElement that is a #GstBin containing
* @create_element: Construct and return a #GstElement that is a #GstBin containing
* the elements to use for streaming the media. The bin should contain
* payloaders pay%d for each stream. The default implementation of this
* function returns the bin created from the launch parameter.
* @construct: the vmethod that will be called when the factory has to create the
* #GstRTSPMedia for @url. The default implementation of this
* function calls get_element to retrieve an element and then looks for
* function calls create_element to retrieve an element and then looks for
* pay%d to create the streams.
* @configure: configure the media created with @construct. The default
* implementation will configure the 'shared' property of the media.
......@@ -104,7 +104,7 @@ struct _GstRTSPMediaFactoryClass {
gchar * (*gen_key) (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
GstElement * (*get_element) (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
GstElement * (*create_element) (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
GstRTSPMedia * (*construct) (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
void (*configure) (GstRTSPMediaFactory *factory, GstRTSPMedia *media);
GstElement * (*create_pipeline) (GstRTSPMediaFactory *factory, GstRTSPMedia *media);
......@@ -145,14 +145,11 @@ void gst_rtsp_media_factory_set_multicast_group (GstRTSPMediaFa
gchar * gst_rtsp_media_factory_get_multicast_group (GstRTSPMediaFactory * factory);
/* creating the media from the factory and a url */
GstRTSPMedia * gst_rtsp_media_factory_construct (GstRTSPMediaFactory *factory,
const GstRTSPUrl *url);
void gst_rtsp_media_factory_collect_streams (GstRTSPMediaFactory *factory,
const GstRTSPUrl *url,
GstRTSPMedia *media);
GstElement * gst_rtsp_media_factory_get_element (GstRTSPMediaFactory *factory, const GstRTSPUrl *url);
GstRTSPMedia * gst_rtsp_media_factory_construct (GstRTSPMediaFactory *factory,
const GstRTSPUrl *url);
GstElement * gst_rtsp_media_factory_create_element (GstRTSPMediaFactory *factory,
const GstRTSPUrl *url);
G_END_DECLS
......
This diff is collapsed.
......@@ -36,115 +36,17 @@ G_BEGIN_DECLS
#define GST_RTSP_MEDIA_CAST(obj) ((GstRTSPMedia*)(obj))
#define GST_RTSP_MEDIA_CLASS_CAST(klass) ((GstRTSPMediaClass*)(klass))
typedef struct _GstRTSPMediaStream GstRTSPMediaStream;
typedef struct _GstRTSPMedia GstRTSPMedia;
typedef struct _GstRTSPMediaClass GstRTSPMediaClass;
typedef struct _GstRTSPMediaTrans GstRTSPMediaTrans;
typedef gboolean (*GstRTSPSendFunc) (GstBuffer *buffer, guint8 channel, gpointer user_data);
typedef void (*GstRTSPKeepAliveFunc) (gpointer user_data);
/**
* GstRTSPMediaTrans:
* @idx: a stream index
* @send_rtp: callback for sending RTP messages
* @send_rtcp: callback for sending RTCP messages
* @send_rtp_list: callback for sending RTP messages
* @send_rtcp_list: callback for sending RTCP messages
* @user_data: user data passed in the callbacks
* @notify: free function for the user_data.
* @keep_alive: keep alive callback
* @ka_user_data: data passed to @keep_alive
* @ka_notify: called when @ka_user_data is freed
* @active: if we are actively sending
* @timeout: if we timed out
* @transport: a transport description
* @rtpsource: the receiver rtp source object
*
* A Transport description for stream @idx
*/
struct _GstRTSPMediaTrans {
guint idx;
GstRTSPSendFunc send_rtp;
GstRTSPSendFunc send_rtcp;
gpointer user_data;
GDestroyNotify notify;
GstRTSPKeepAliveFunc keep_alive;
gpointer ka_user_data;
GDestroyNotify ka_notify;
gboolean active;
gboolean timeout;
GstRTSPTransport *transport;
GObject *rtpsource;
};
#include "rtsp-stream.h"
#include "rtsp-auth.h"
/**
* GstRTSPMediaStream:
* @srcpad: the srcpad of the stream
* @payloader: the payloader of the format
* @prepared: if the stream is prepared for streaming
* @recv_rtp_sink: sinkpad for RTP buffers
* @recv_rtcp_sink: sinkpad for RTCP buffers
* @send_rtp_src: srcpad for RTP buffers
* @send_rtcp_src: srcpad for RTCP buffers
* @udpsrc: the udp source elements for RTP/RTCP
* @udpsink: the udp sink elements for RTP/RTCP
* @appsrc: the app source elements for RTP/RTCP
* @appsink: the app sink elements for RTP/RTCP
* @server_port: the server ports for this stream
* @caps_sig: the signal id for detecting caps
* @caps: the caps of the stream
* @tranports: the current transports being streamed
*
* The definition of a media stream. The streams are identified by @id.
*/
struct _GstRTSPMediaStream {
GstPad *srcpad;
GstElement *payloader;
gboolean prepared;
/* pads on the rtpbin */
GstPad *recv_rtcp_sink;
GstPad *recv_rtp_sink;
GstPad *send_rtp_sink;
GstPad *send_rtp_src;
GstPad *send_rtcp_src;
/* the RTPSession object */
GObject *session;
/* sinks used for sending and receiving RTP and RTCP, they share
* sockets */
GstElement *udpsrc[2];
GstElement *udpsink[2];
/* for TCP transport */
GstElement *appsrc[2];
GstElement *appqueue[2];
GstElement *appsink[2];
GstElement *tee[2];
GstElement *selector[2];
/* server ports for sending/receiving */
GstRTSPRange server_port;
/* the caps of the stream */
gulong caps_sig;
GstCaps *caps;
/* transports we stream to */
GList *transports;
};
/**
* GstRTSPMediaStatus:
* @GST_RTSP_MEDIA_STATUS_UNPREPARED: media pipeline not prerolled
* @GST_RTSP_MEDIA_STATUS_UNPREPARING: media pipeline is busy doing a clean
* shutdown.
* @GST_RTSP_MEDIA_STATUS_PREPARING: media pipeline is prerolling
* @GST_RTSP_MEDIA_STATUS_PREPARED: media pipeline is prerolled
* @GST_RTSP_MEDIA_STATUS_ERROR: media pipeline is in error
......@@ -152,10 +54,11 @@ struct _GstRTSPMediaStream {
* The state of the media pipeline.
*/
typedef enum {
GST_RTSP_MEDIA_STATUS_UNPREPARED = 0,
GST_RTSP_MEDIA_STATUS_PREPARING = 1,
GST_RTSP_MEDIA_STATUS_PREPARED = 2,
GST_RTSP_MEDIA_STATUS_ERROR = 3
GST_RTSP_MEDIA_STATUS_UNPREPARED = 0,
GST_RTSP_MEDIA_STATUS_UNPREPARING = 1,
GST_RTSP_MEDIA_STATUS_PREPARING = 2,
GST_RTSP_MEDIA_STATUS_PREPARED = 3,
GST_RTSP_MEDIA_STATUS_ERROR = 4
} GstRTSPMediaStatus;
/**
......@@ -168,10 +71,10 @@ typedef enum {
* @reused: if this media has been reused
* @is_ipv6: if this media is using ipv6
* @element: the data providing element
* @streams: the different streams provided by @element
* @streams: the different #GstRTSPStream provided by @element
* @dynamic: list of dynamic elements managed by @element
* @status: the status of the media pipeline
* @active: the number of active connections
* @n_active: the number of active connections
* @pipeline: the toplevel pipeline
* @fakesink: for making state changes async
* @source: the bus watch for pipeline messages.
......@@ -184,7 +87,7 @@ typedef enum {
* @range: the range of the media being streamed
*
* A class that contains the GStreamer element along with a list of
* #GstRTSPMediaStream objects that can produce data.
* #GstRTSPStream objects that can produce data.
*
* This object is usually created from a #GstRTSPMediaFactory.
*/
......@@ -205,11 +108,10 @@ struct _GstRTSPMedia {
gchar *multicast_group;
GstElement *element;
GArray *streams;
GPtrArray *streams;
GList *dynamic;
GstRTSPMediaStatus status;
gint active;
gboolean eos_pending;
gint n_active;
gboolean adding;
/* the pipeline for the media */
......@@ -251,15 +153,15 @@ struct _GstRTSPMediaClass {
GThread *thread;
/* vmethods */
gboolean (*handle_message) (GstRTSPMedia *media, GstMessage *message);
<