mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-29 23:32:33 +00:00
Make the server handle arbitrary pipelines
Make GstMediaFactory an object that can instantiate GstMediaBin objects. The GstMediaBin object has a handle to a bin with elements and to a list of GstMediaStream objects that this bin produces. Add GstMediaMapper that can map url mountpoints to GstMediaFactory objects along with methods to register and remove those mappings. Add methods and a property to GstRTSPServer to manage the GstMediaMapper object used by the server instance. Modify the example application so that it shows how to create custom pipelines attached to a specific mount point. Various misc cleanps.
This commit is contained in:
parent
ddf17f338b
commit
4b1c190a5f
14 changed files with 758 additions and 380 deletions
|
@ -26,6 +26,8 @@ main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
GstRTSPServer *server;
|
GstRTSPServer *server;
|
||||||
|
GstRTSPMediaMapping *mapping;
|
||||||
|
GstRTSPMediaFactory *factory;
|
||||||
|
|
||||||
gst_init (&argc, &argv);
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
@ -34,9 +36,41 @@ main (int argc, char *argv[])
|
||||||
/* create a server instance */
|
/* create a server instance */
|
||||||
server = gst_rtsp_server_new ();
|
server = gst_rtsp_server_new ();
|
||||||
|
|
||||||
|
/* get the mapping for this server, every server has a default mapper object
|
||||||
|
* that be used to map uri mount points to media factories */
|
||||||
|
mapping = gst_rtsp_server_get_media_mapping (server);
|
||||||
|
|
||||||
|
/* make a media factory for a webcam. The default media factory can use
|
||||||
|
* gst-launch syntax to create pipelines. */
|
||||||
|
factory = gst_rtsp_media_factory_new ();
|
||||||
|
#if 0
|
||||||
|
gst_rtsp_media_factory_set_launch (factory, "( "
|
||||||
|
"v4l2src ! video/x-raw-yuv,width=352,height=288,framerate=15/1 ! "
|
||||||
|
"queue ! videorate ! ffmpegcolorspace ! "
|
||||||
|
"x264enc bitrate=300 ! rtph264pay name=pay0 pt=96 "
|
||||||
|
"alsasrc ! audio/x-raw-int,rate=8000 ! queue ! "
|
||||||
|
"amrnbenc ! rtpamrpay name=pay1 pt=97 "
|
||||||
|
")");
|
||||||
|
#endif
|
||||||
|
/* any launch line works as long as it contains elements named pay%d. Each
|
||||||
|
* element with pay%d names will be a stream */
|
||||||
|
gst_rtsp_media_factory_set_launch (factory, "( "
|
||||||
|
"videotestsrc ! video/x-raw-yuv,width=352,height=288,framerate=15/1 ! "
|
||||||
|
"x264enc bitrate=300 ! rtph264pay name=pay0 pt=96 "
|
||||||
|
"audiotestsrc ! audio/x-raw-int,rate=8000 ! "
|
||||||
|
"alawenc ! rtppcmapay name=pay1 pt=97 "
|
||||||
|
")");
|
||||||
|
|
||||||
|
/* attach the factory to the /camera url */
|
||||||
|
gst_rtsp_media_mapping_add_factory (mapping, "/camera", factory);
|
||||||
|
|
||||||
|
/* don't need the ref to the mapper anymore */
|
||||||
|
g_object_unref (mapping);
|
||||||
|
|
||||||
/* attach the server to the default maincontext */
|
/* attach the server to the default maincontext */
|
||||||
gst_rtsp_server_attach (server, NULL);
|
gst_rtsp_server_attach (server, NULL);
|
||||||
|
|
||||||
|
/* start serving */
|
||||||
g_main_loop_run (loop);
|
g_main_loop_run (loop);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -3,6 +3,7 @@ public_headers = \
|
||||||
rtsp-client.h \
|
rtsp-client.h \
|
||||||
rtsp-media.h \
|
rtsp-media.h \
|
||||||
rtsp-media-factory.h \
|
rtsp-media-factory.h \
|
||||||
|
rtsp-media-mapping.h \
|
||||||
rtsp-session-pool.h \
|
rtsp-session-pool.h \
|
||||||
rtsp-session.h
|
rtsp-session.h
|
||||||
|
|
||||||
|
@ -10,7 +11,8 @@ c_sources = \
|
||||||
rtsp-server.c \
|
rtsp-server.c \
|
||||||
rtsp-client.c \
|
rtsp-client.c \
|
||||||
rtsp-media.c \
|
rtsp-media.c \
|
||||||
rtsp-media-factory.c \
|
rtsp-media-factory.c \
|
||||||
|
rtsp-media-mapping.c \
|
||||||
rtsp-session-pool.c \
|
rtsp-session-pool.c \
|
||||||
rtsp-session.c
|
rtsp-session.c
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
|
||||||
|
static void gst_rtsp_client_finalize (GObject * obj);
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -33,6 +35,8 @@ gst_rtsp_client_class_init (GstRTSPClientClass * klass)
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
|
|
||||||
gobject_class = G_OBJECT_CLASS (klass);
|
gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_rtsp_client_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -40,6 +44,12 @@ gst_rtsp_client_init (GstRTSPClient * client)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtsp_client_finalize (GObject * obj)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (gst_rtsp_client_parent_class)->finalize (obj);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_client_new:
|
* gst_rtsp_client_new:
|
||||||
*
|
*
|
||||||
|
@ -87,7 +97,7 @@ handle_teardown_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessag
|
||||||
goto service_unavailable;
|
goto service_unavailable;
|
||||||
|
|
||||||
/* get a handle to the configuration of the media in the session */
|
/* get a handle to the configuration of the media in the session */
|
||||||
media = gst_rtsp_session_get_media (session, client->media);
|
media = gst_rtsp_session_get_media (session, uri, client->factory);
|
||||||
if (!media)
|
if (!media)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
|
|
||||||
|
@ -116,6 +126,7 @@ session_not_found:
|
||||||
}
|
}
|
||||||
service_unavailable:
|
service_unavailable:
|
||||||
{
|
{
|
||||||
|
handle_generic_response (client, GST_RTSP_STS_OK, request);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
not_found:
|
not_found:
|
||||||
|
@ -145,7 +156,7 @@ handle_pause_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *
|
||||||
goto service_unavailable;
|
goto service_unavailable;
|
||||||
|
|
||||||
/* get a handle to the configuration of the media in the session */
|
/* get a handle to the configuration of the media in the session */
|
||||||
media = gst_rtsp_session_get_media (session, client->media);
|
media = gst_rtsp_session_get_media (session, uri, client->factory);
|
||||||
if (!media)
|
if (!media)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
|
|
||||||
|
@ -201,7 +212,7 @@ handle_play_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *r
|
||||||
goto service_unavailable;
|
goto service_unavailable;
|
||||||
|
|
||||||
/* get a handle to the configuration of the media in the session */
|
/* get a handle to the configuration of the media in the session */
|
||||||
media = gst_rtsp_session_get_media (session, client->media);
|
media = gst_rtsp_session_get_media (session, uri, client->factory);
|
||||||
if (!media)
|
if (!media)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
|
|
||||||
|
@ -222,11 +233,11 @@ handle_play_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *r
|
||||||
|
|
||||||
/* grab RTPInfo from the payloaders now */
|
/* grab RTPInfo from the payloaders now */
|
||||||
rtpinfo = g_string_new ("");
|
rtpinfo = g_string_new ("");
|
||||||
n_streams = gst_rtsp_media_n_streams (client->media);
|
n_streams = gst_rtsp_media_bin_n_streams (media->mediabin);
|
||||||
for (i = 0; i < n_streams; i++) {
|
for (i = 0; i < n_streams; i++) {
|
||||||
GstRTSPMediaStream *stream;
|
GstRTSPMediaStream *stream;
|
||||||
|
|
||||||
stream = gst_rtsp_media_get_stream (client->media, i);
|
stream = gst_rtsp_media_bin_get_stream (media->mediabin, i);
|
||||||
|
|
||||||
g_object_get (G_OBJECT (stream->payloader), "seqnum", &seqnum, NULL);
|
g_object_get (G_OBJECT (stream->payloader), "seqnum", &seqnum, NULL);
|
||||||
g_object_get (G_OBJECT (stream->payloader), "timestamp", ×tamp, NULL);
|
g_object_get (G_OBJECT (stream->payloader), "timestamp", ×tamp, NULL);
|
||||||
|
@ -271,7 +282,7 @@ not_found:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_setup_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *request)
|
handle_setup_response (GstRTSPClient *client, const gchar *location, GstRTSPMessage *request)
|
||||||
{
|
{
|
||||||
GstRTSPResult res;
|
GstRTSPResult res;
|
||||||
gchar *sessid;
|
gchar *sessid;
|
||||||
|
@ -279,6 +290,7 @@ handle_setup_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *
|
||||||
gchar **transports;
|
gchar **transports;
|
||||||
gboolean have_transport;
|
gboolean have_transport;
|
||||||
GstRTSPTransport *ct, *st;
|
GstRTSPTransport *ct, *st;
|
||||||
|
GstRTSPUrl *uri;
|
||||||
GstRTSPSession *session;
|
GstRTSPSession *session;
|
||||||
gint i;
|
gint i;
|
||||||
GstRTSPLowerTrans supported;
|
GstRTSPLowerTrans supported;
|
||||||
|
@ -290,9 +302,28 @@ handle_setup_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *
|
||||||
GstRTSPSessionMedia *media;
|
GstRTSPSessionMedia *media;
|
||||||
gboolean need_session;
|
gboolean need_session;
|
||||||
|
|
||||||
|
/* the uri contains the stream number we added in the SDP config, which is
|
||||||
|
* always /stream=%d so we need to strip that off */
|
||||||
|
if ((res = gst_rtsp_url_parse (location, &uri)) != GST_RTSP_OK)
|
||||||
|
goto bad_url;
|
||||||
|
|
||||||
|
/* parse the stream we need to configure, look for the stream in the abspath
|
||||||
|
* first and then in the query. */
|
||||||
|
if (!(pos = strstr (uri->abspath, "/stream="))) {
|
||||||
|
if (!(pos = strstr (uri->query, "/stream=")))
|
||||||
|
goto bad_request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we can mofify the parse uri in place */
|
||||||
|
*pos = '\0';
|
||||||
|
|
||||||
|
pos += strlen ("/stream=");
|
||||||
|
if (sscanf (pos, "%u", &streamid) != 1)
|
||||||
|
goto bad_request;
|
||||||
|
|
||||||
/* find the media associated with the uri */
|
/* find the media associated with the uri */
|
||||||
if (client->media == NULL) {
|
if (client->factory == NULL) {
|
||||||
if ((client->media = gst_rtsp_media_new (uri)) == NULL)
|
if ((client->factory = gst_rtsp_media_mapping_find_factory (client->mapping, uri)) == NULL)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,20 +382,12 @@ handle_setup_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a handle to the configuration of the media in the session */
|
/* get a handle to the configuration of the media in the session */
|
||||||
media = gst_rtsp_session_get_media (session, client->media);
|
media = gst_rtsp_session_get_media (session, uri->abspath, client->factory);
|
||||||
if (!media)
|
if (!media)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
|
|
||||||
/* parse the stream we need to configure */
|
|
||||||
if (!(pos = strstr (uri, "stream=")))
|
|
||||||
goto bad_request;
|
|
||||||
|
|
||||||
pos += strlen ("stream=");
|
|
||||||
if (sscanf (pos, "%u", &streamid) != 1)
|
|
||||||
goto bad_request;
|
|
||||||
|
|
||||||
/* get a handle to the stream in the media */
|
/* get a handle to the stream in the media */
|
||||||
stream = gst_rtsp_session_get_stream (media, streamid);
|
stream = gst_rtsp_session_media_get_stream (media, streamid);
|
||||||
|
|
||||||
/* setup the server transport from the client transport */
|
/* setup the server transport from the client transport */
|
||||||
st = gst_rtsp_session_stream_set_transport (stream, inet_ntoa (client->address.sin_addr), ct);
|
st = gst_rtsp_session_stream_set_transport (stream, inet_ntoa (client->address.sin_addr), ct);
|
||||||
|
@ -387,9 +410,9 @@ handle_setup_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
not_found:
|
bad_url:
|
||||||
{
|
{
|
||||||
handle_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
|
handle_generic_response (client, GST_RTSP_STS_BAD_REQUEST, request);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
bad_request:
|
bad_request:
|
||||||
|
@ -397,6 +420,11 @@ bad_request:
|
||||||
handle_generic_response (client, GST_RTSP_STS_BAD_REQUEST, request);
|
handle_generic_response (client, GST_RTSP_STS_BAD_REQUEST, request);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
not_found:
|
||||||
|
{
|
||||||
|
handle_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
session_not_found:
|
session_not_found:
|
||||||
{
|
{
|
||||||
handle_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, request);
|
handle_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, request);
|
||||||
|
@ -414,46 +442,58 @@ service_unavailable:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for the describe we must generate an SDP */
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_describe_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessage *request)
|
handle_describe_response (GstRTSPClient *client, const gchar *location, GstRTSPMessage *request)
|
||||||
{
|
{
|
||||||
GstRTSPMessage response = { 0 };
|
GstRTSPMessage response = { 0 };
|
||||||
|
GstRTSPResult res;
|
||||||
GstSDPMessage *sdp;
|
GstSDPMessage *sdp;
|
||||||
|
GstRTSPUrl *uri;
|
||||||
guint n_streams, i;
|
guint n_streams, i;
|
||||||
gchar *sdptext;
|
gchar *sdptext;
|
||||||
GstRTSPMedia *media;
|
GstRTSPMediaFactory *factory;
|
||||||
GstElement *pipeline = NULL;
|
GstRTSPMediaBin *mediabin;
|
||||||
|
GstElement *pipeline;
|
||||||
|
|
||||||
|
/* the uri contains the stream number we added in the SDP config, which is
|
||||||
|
* always /stream=%d so we need to strip that off */
|
||||||
|
if ((res = gst_rtsp_url_parse (location, &uri)) != GST_RTSP_OK)
|
||||||
|
goto bad_url;
|
||||||
|
|
||||||
|
/* find the factory for the uri first */
|
||||||
|
if (!(factory = gst_rtsp_media_mapping_find_factory (client->mapping, uri)))
|
||||||
|
goto no_factory;
|
||||||
|
|
||||||
/* check what kind of format is accepted */
|
/* check what kind of format is accepted */
|
||||||
|
|
||||||
|
/* create a pipeline to preroll the media */
|
||||||
|
pipeline = gst_pipeline_new ("client-describe-pipeline");
|
||||||
|
|
||||||
/* for the describe we must generate an SDP */
|
/* prepare the media and add it to the pipeline */
|
||||||
if (!(media = gst_rtsp_media_new (uri)))
|
if (!(mediabin = gst_rtsp_media_factory_construct (factory, uri->abspath)))
|
||||||
goto no_media;
|
goto no_media_bin;
|
||||||
|
|
||||||
/* create a pipeline if we have to */
|
gst_bin_add (GST_BIN_CAST (pipeline), mediabin->element);
|
||||||
if (pipeline == NULL) {
|
|
||||||
pipeline = gst_pipeline_new ("client-pipeline");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prepare the media into the pipeline */
|
|
||||||
if (!gst_rtsp_media_prepare (media, GST_BIN (pipeline)))
|
|
||||||
goto no_media;
|
|
||||||
|
|
||||||
/* link fakesink to all stream pads and set the pipeline to PLAYING */
|
/* link fakesink to all stream pads and set the pipeline to PLAYING */
|
||||||
n_streams = gst_rtsp_media_n_streams (media);
|
n_streams = gst_rtsp_media_bin_n_streams (mediabin);
|
||||||
for (i = 0; i < n_streams; i++) {
|
for (i = 0; i < n_streams; i++) {
|
||||||
GstRTSPMediaStream *stream;
|
GstRTSPMediaStream *stream;
|
||||||
GstElement *sink;
|
GstElement *sink;
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
|
GstPadLinkReturn lret;
|
||||||
|
|
||||||
stream = gst_rtsp_media_get_stream (media, i);
|
stream = gst_rtsp_media_bin_get_stream (mediabin, i);
|
||||||
|
|
||||||
sink = gst_element_factory_make ("fakesink", NULL);
|
sink = gst_element_factory_make ("fakesink", NULL);
|
||||||
gst_bin_add (GST_BIN (pipeline), sink);
|
gst_bin_add (GST_BIN (pipeline), sink);
|
||||||
|
|
||||||
sinkpad = gst_element_get_static_pad (sink, "sink");
|
sinkpad = gst_element_get_static_pad (sink, "sink");
|
||||||
gst_pad_link (stream->srcpad, sinkpad);
|
lret = gst_pad_link (stream->srcpad, sinkpad);
|
||||||
|
if (lret != GST_PAD_LINK_OK) {
|
||||||
|
g_warning ("failed to link pad to sink: %d", lret);
|
||||||
|
}
|
||||||
gst_object_unref (sinkpad);
|
gst_object_unref (sinkpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +527,7 @@ handle_describe_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessag
|
||||||
gboolean first;
|
gboolean first;
|
||||||
GString *fmtp;
|
GString *fmtp;
|
||||||
|
|
||||||
stream = gst_rtsp_media_get_stream (media, i);
|
stream = gst_rtsp_media_bin_get_stream (mediabin, i);
|
||||||
gst_sdp_media_new (&smedia);
|
gst_sdp_media_new (&smedia);
|
||||||
|
|
||||||
s = gst_caps_get_structure (stream->caps, 0);
|
s = gst_caps_get_structure (stream->caps, 0);
|
||||||
|
@ -572,7 +612,7 @@ handle_describe_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessag
|
||||||
/* go back to NULL */
|
/* go back to NULL */
|
||||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
|
||||||
g_object_unref (media);
|
g_object_unref (factory);
|
||||||
|
|
||||||
gst_object_unref (pipeline);
|
gst_object_unref (pipeline);
|
||||||
pipeline = NULL;
|
pipeline = NULL;
|
||||||
|
@ -590,11 +630,22 @@ handle_describe_response (GstRTSPClient *client, const gchar *uri, GstRTSPMessag
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
no_media:
|
bad_url:
|
||||||
|
{
|
||||||
|
handle_generic_response (client, GST_RTSP_STS_BAD_REQUEST, request);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
no_factory:
|
||||||
{
|
{
|
||||||
handle_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
|
handle_generic_response (client, GST_RTSP_STS_NOT_FOUND, request);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
no_media_bin:
|
||||||
|
{
|
||||||
|
handle_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, request);
|
||||||
|
g_object_unref (factory);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -713,7 +764,8 @@ handle_client (GstRTSPClient *client)
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
receive_failed:
|
receive_failed:
|
||||||
{
|
{
|
||||||
g_print ("receive failed, disconnect client %p\n", client);
|
g_message ("receive failed %d (%s), disconnect client %p", res,
|
||||||
|
gst_rtsp_strresult (res), client);
|
||||||
gst_rtsp_connection_close (client->connection);
|
gst_rtsp_connection_close (client->connection);
|
||||||
g_object_unref (client);
|
g_object_unref (client);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -747,7 +799,7 @@ client_accept (GstRTSPClient *client, GIOChannel *channel)
|
||||||
* connections */
|
* connections */
|
||||||
gst_poll_add_fd (conn->fdset, &conn->fd);
|
gst_poll_add_fd (conn->fdset, &conn->fd);
|
||||||
|
|
||||||
g_print ("added new client %p ip %s with fd %d\n", client,
|
g_message ("added new client %p ip %s with fd %d", client,
|
||||||
inet_ntoa (client->address.sin_addr), conn->fd.fd);
|
inet_ntoa (client->address.sin_addr), conn->fd.fd);
|
||||||
|
|
||||||
client->connection = conn;
|
client->connection = conn;
|
||||||
|
@ -769,7 +821,8 @@ accept_failed:
|
||||||
* @pool: a #GstRTSPSessionPool
|
* @pool: a #GstRTSPSessionPool
|
||||||
*
|
*
|
||||||
* Set @pool as the sessionpool for @client which it will use to find
|
* Set @pool as the sessionpool for @client which it will use to find
|
||||||
* or allocate sessions.
|
* or allocate sessions. the sessionpool is usually inherited from the server
|
||||||
|
* that created the client but can be overridden later.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_rtsp_client_set_session_pool (GstRTSPClient *client, GstRTSPSessionPool *pool)
|
gst_rtsp_client_set_session_pool (GstRTSPClient *client, GstRTSPSessionPool *pool)
|
||||||
|
@ -777,11 +830,13 @@ gst_rtsp_client_set_session_pool (GstRTSPClient *client, GstRTSPSessionPool *poo
|
||||||
GstRTSPSessionPool *old;
|
GstRTSPSessionPool *old;
|
||||||
|
|
||||||
old = client->pool;
|
old = client->pool;
|
||||||
if (pool)
|
if (old != pool) {
|
||||||
g_object_ref (pool);
|
if (pool)
|
||||||
client->pool = pool;
|
g_object_ref (pool);
|
||||||
if (old)
|
client->pool = pool;
|
||||||
g_object_unref (old);
|
if (old)
|
||||||
|
g_object_unref (old);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -804,43 +859,44 @@ gst_rtsp_client_get_session_pool (GstRTSPClient *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_client_set_media_factory:
|
* gst_rtsp_client_set_media_mapping:
|
||||||
* @client: a #GstRTSPClient
|
* @client: a #GstRTSPClient
|
||||||
* @factory: a #GstRTSPMediaFactory
|
* @mapping: a #GstRTSPMediaMapping
|
||||||
*
|
*
|
||||||
* Set @factory as the media factory for @client which it will use to map urls
|
* Set @mapping as the media mapping for @client which it will use to map urls
|
||||||
* to media streams.
|
* to media streams. These mapping is usually inherited from the server that
|
||||||
|
* created the client but can be overriden later.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_rtsp_client_set_media_factory (GstRTSPClient *client, GstRTSPMediaFactory *factory)
|
gst_rtsp_client_set_media_mapping (GstRTSPClient *client, GstRTSPMediaMapping *mapping)
|
||||||
{
|
{
|
||||||
GstRTSPMediaFactory *old;
|
GstRTSPMediaMapping *old;
|
||||||
|
|
||||||
old = client->factory;
|
old = client->mapping;
|
||||||
|
|
||||||
if (old != factory) {
|
if (old != mapping) {
|
||||||
if (factory)
|
if (mapping)
|
||||||
g_object_ref (factory);
|
g_object_ref (mapping);
|
||||||
client->factory = factory;
|
client->mapping = mapping;
|
||||||
if (old)
|
if (old)
|
||||||
g_object_unref (old);
|
g_object_unref (old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_client_get_media_factory:
|
* gst_rtsp_client_get_media_mapping:
|
||||||
* @client: a #GstRTSPClient
|
* @client: a #GstRTSPClient
|
||||||
*
|
*
|
||||||
* Get the #GstRTSPMediaFactory object that @client uses to manage its sessions.
|
* Get the #GstRTSPMediaMapping object that @client uses to manage its sessions.
|
||||||
*
|
*
|
||||||
* Returns: a #GstRTSPMediaFactory, unref after usage.
|
* Returns: a #GstRTSPMediaMapping, unref after usage.
|
||||||
*/
|
*/
|
||||||
GstRTSPMediaFactory *
|
GstRTSPMediaMapping *
|
||||||
gst_rtsp_client_get_media_factory (GstRTSPClient *client)
|
gst_rtsp_client_get_media_mapping (GstRTSPClient *client)
|
||||||
{
|
{
|
||||||
GstRTSPMediaFactory *result;
|
GstRTSPMediaMapping *result;
|
||||||
|
|
||||||
if ((result = client->factory))
|
if ((result = client->mapping))
|
||||||
g_object_ref (result);
|
g_object_ref (result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#define __GST_RTSP_CLIENT_H__
|
#define __GST_RTSP_CLIENT_H__
|
||||||
|
|
||||||
#include "rtsp-media.h"
|
#include "rtsp-media.h"
|
||||||
#include "rtsp-media-factory.h"
|
#include "rtsp-media-mapping.h"
|
||||||
#include "rtsp-session-pool.h"
|
#include "rtsp-session-pool.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
@ -75,9 +75,8 @@ struct _GstRTSPClient {
|
||||||
|
|
||||||
GstRTSPSessionPool *pool;
|
GstRTSPSessionPool *pool;
|
||||||
|
|
||||||
GstRTSPMedia *media;
|
GstRTSPMediaFactory *factory;
|
||||||
GstRTSPMediaFactory *factory;
|
GstRTSPMediaMapping *mapping;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRTSPClientClass {
|
struct _GstRTSPClientClass {
|
||||||
|
@ -92,9 +91,9 @@ void gst_rtsp_client_set_session_pool (GstRTSPClient *client,
|
||||||
GstRTSPSessionPool *pool);
|
GstRTSPSessionPool *pool);
|
||||||
GstRTSPSessionPool * gst_rtsp_client_get_session_pool (GstRTSPClient *client);
|
GstRTSPSessionPool * gst_rtsp_client_get_session_pool (GstRTSPClient *client);
|
||||||
|
|
||||||
void gst_rtsp_client_set_media_factory (GstRTSPClient *client,
|
void gst_rtsp_client_set_media_mapping (GstRTSPClient *client,
|
||||||
GstRTSPMediaFactory *factory);
|
GstRTSPMediaMapping *mapping);
|
||||||
GstRTSPMediaFactory * gst_rtsp_client_get_media_factory (GstRTSPClient *client);
|
GstRTSPMediaMapping * gst_rtsp_client_get_media_mapping (GstRTSPClient *client);
|
||||||
|
|
||||||
gboolean gst_rtsp_client_accept (GstRTSPClient *client,
|
gboolean gst_rtsp_client_accept (GstRTSPClient *client,
|
||||||
GIOChannel *channel);
|
GIOChannel *channel);
|
||||||
|
|
|
@ -19,11 +19,24 @@
|
||||||
|
|
||||||
#include "rtsp-media-factory.h"
|
#include "rtsp-media-factory.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstRTSPMediaFactory, gst_rtsp_media_factory, G_TYPE_OBJECT);
|
#define DEFAULT_LAUNCH NULL
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_LAUNCH,
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gst_rtsp_media_factory_get_property (GObject *object, guint propid,
|
||||||
|
GValue *value, GParamSpec *pspec);
|
||||||
|
static void gst_rtsp_media_factory_set_property (GObject *object, guint propid,
|
||||||
|
const GValue *value, GParamSpec *pspec);
|
||||||
static void gst_rtsp_media_factory_finalize (GObject * obj);
|
static void gst_rtsp_media_factory_finalize (GObject * obj);
|
||||||
|
|
||||||
static GstRTSPMedia * create_media (GstRTSPMediaFactory *factory, const gchar *url);
|
static GstRTSPMediaBin * default_construct (GstRTSPMediaFactory *factory, const gchar *location);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GstRTSPMediaFactory, gst_rtsp_media_factory, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
|
gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
|
||||||
|
@ -32,9 +45,28 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
|
||||||
|
|
||||||
gobject_class = G_OBJECT_CLASS (klass);
|
gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->get_property = gst_rtsp_media_factory_get_property;
|
||||||
|
gobject_class->set_property = gst_rtsp_media_factory_set_property;
|
||||||
gobject_class->finalize = gst_rtsp_media_factory_finalize;
|
gobject_class->finalize = gst_rtsp_media_factory_finalize;
|
||||||
|
|
||||||
klass->create_media = create_media;
|
/**
|
||||||
|
* GstRTSPMediaFactory::launch
|
||||||
|
*
|
||||||
|
* The gst_parse_launch() line to use for constructing the pipeline in the
|
||||||
|
* default prepare vmethod.
|
||||||
|
*
|
||||||
|
* The pipeline description should return a GstBin as the toplevel element
|
||||||
|
* which can be accomplished by enclosing the dscription with brackets '('
|
||||||
|
* ')'.
|
||||||
|
*
|
||||||
|
* The description should return a pipeline with payloaders named pay0, pay1,
|
||||||
|
* etc.. Each of the payloaders will result in a stream.
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_LAUNCH,
|
||||||
|
g_param_spec_string ("launch", "Launch", "A launch description of the pipeline",
|
||||||
|
DEFAULT_LAUNCH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
klass->construct = default_construct;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -45,9 +77,51 @@ gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
|
||||||
static void
|
static void
|
||||||
gst_rtsp_media_factory_finalize (GObject * obj)
|
gst_rtsp_media_factory_finalize (GObject * obj)
|
||||||
{
|
{
|
||||||
|
GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (obj);
|
||||||
|
|
||||||
|
g_free (factory->launch);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtsp_media_factory_get_property (GObject *object, guint propid,
|
||||||
|
GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
|
||||||
|
|
||||||
|
switch (propid) {
|
||||||
|
case PROP_LAUNCH:
|
||||||
|
g_value_take_string (value, gst_rtsp_media_factory_get_launch (factory));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtsp_media_factory_set_property (GObject *object, guint propid,
|
||||||
|
const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (object);
|
||||||
|
|
||||||
|
switch (propid) {
|
||||||
|
case PROP_LAUNCH:
|
||||||
|
gst_rtsp_media_factory_set_launch (factory, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtsp_media_factory_new:
|
||||||
|
*
|
||||||
|
* Create a new #GstRTSPMediaFactory instance.
|
||||||
|
*
|
||||||
|
* Returns: a new #GstRTSPMediaFactory object or %NULL when location did not contain a
|
||||||
|
* valid or understood URL.
|
||||||
|
*/
|
||||||
GstRTSPMediaFactory *
|
GstRTSPMediaFactory *
|
||||||
gst_rtsp_media_factory_new (void)
|
gst_rtsp_media_factory_new (void)
|
||||||
{
|
{
|
||||||
|
@ -58,40 +132,172 @@ gst_rtsp_media_factory_new (void)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstRTSPMedia *
|
/**
|
||||||
create_media (GstRTSPMediaFactory *factory, const gchar *url)
|
* gst_rtsp_media_factory_set_launch:
|
||||||
|
* @factory: a #GstRTSPMediaFactory
|
||||||
|
* @launch: the launch description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The gst_parse_launch() line to use for constructing the pipeline in the
|
||||||
|
* default prepare vmethod.
|
||||||
|
*
|
||||||
|
* The pipeline description should return a GstBin as the toplevel element
|
||||||
|
* which can be accomplished by enclosing the dscription with brackets '('
|
||||||
|
* ')'.
|
||||||
|
*
|
||||||
|
* The description should return a pipeline with payloaders named pay0, pay1,
|
||||||
|
* etc.. Each of the payloaders will result in a stream.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory *factory, const gchar *launch)
|
||||||
{
|
{
|
||||||
GstRTSPMedia *result;
|
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
|
||||||
|
g_return_if_fail (launch != NULL);
|
||||||
|
|
||||||
result = gst_rtsp_media_new (url);
|
factory->launch = g_strdup (launch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtsp_media_factory_get_launch:
|
||||||
|
* @factory: a #GstRTSPMediaFactory
|
||||||
|
*
|
||||||
|
* Get the gst_parse_launch() pipeline description that will be used in the
|
||||||
|
* default prepare vmethod.
|
||||||
|
*
|
||||||
|
* Returns: the configured launch description. g_free() after usage.
|
||||||
|
*/
|
||||||
|
gchar *
|
||||||
|
gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory *factory)
|
||||||
|
{
|
||||||
|
gchar *result;
|
||||||
|
|
||||||
|
result = g_strdup (factory->launch);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
GstRTSPMedia *
|
/**
|
||||||
gst_rtsp_media_factory_create (GstRTSPMediaFactory *factory, const gchar *url)
|
* gst_rtsp_media_factory_construct:
|
||||||
|
* @factory: a #GstRTSPMediaFactory
|
||||||
|
* @location: the url used
|
||||||
|
*
|
||||||
|
* Prepare the media bin 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.
|
||||||
|
*
|
||||||
|
* Returns: a new #GstRTSPMediaBin if the media could be prepared.
|
||||||
|
*/
|
||||||
|
GstRTSPMediaBin *
|
||||||
|
gst_rtsp_media_factory_construct (GstRTSPMediaFactory *factory, const gchar *location)
|
||||||
{
|
{
|
||||||
GstRTSPMedia *result = NULL;
|
GstRTSPMediaBin *res;
|
||||||
GstRTSPMediaFactoryClass *klass;
|
GstRTSPMediaFactoryClass *klass;
|
||||||
|
|
||||||
klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
|
klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
|
||||||
|
|
||||||
if (klass->create_media)
|
if (klass->construct)
|
||||||
result = klass->create_media (factory, url);
|
res = klass->construct (factory, location);
|
||||||
|
else
|
||||||
|
res = NULL;
|
||||||
|
|
||||||
return result;
|
g_message ("constructed mediabin %p for location %s", res, location);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
gst_rtsp_media_factory_add (GstRTSPMediaFactory *factory, const gchar *path,
|
caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPMediaStream * stream)
|
||||||
GType type)
|
|
||||||
{
|
{
|
||||||
g_warning ("gst_rtsp_media_factory_add: not implemented");
|
if (stream->caps)
|
||||||
}
|
gst_caps_unref (stream->caps);
|
||||||
void
|
if ((stream->caps = GST_PAD_CAPS (pad)))
|
||||||
gst_rtsp_media_factory_remove (GstRTSPMediaFactory *factory, const gchar *path,
|
gst_caps_ref (stream->caps);
|
||||||
GType type)
|
|
||||||
{
|
|
||||||
g_warning ("gst_rtsp_media_factory_remove: not implemented");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstRTSPMediaBin *
|
||||||
|
default_construct (GstRTSPMediaFactory *factory, const gchar *location)
|
||||||
|
{
|
||||||
|
GstRTSPMediaBin *bin;
|
||||||
|
GstRTSPMediaStream *stream;
|
||||||
|
GstElement *pay, *element;
|
||||||
|
GstPad * pad;
|
||||||
|
gint i;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
/* we need a parse syntax */
|
||||||
|
if (factory->launch == NULL)
|
||||||
|
goto no_launch;
|
||||||
|
|
||||||
|
/* parse the user provided launch line */
|
||||||
|
element = gst_parse_launch (factory->launch, &error);
|
||||||
|
if (element == NULL)
|
||||||
|
goto parse_error;
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
/* a recoverable error was encountered */
|
||||||
|
g_warning ("recoverable parsing error: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bin = g_object_new (GST_TYPE_RTSP_MEDIA_BIN, NULL);
|
||||||
|
bin->element = element;
|
||||||
|
|
||||||
|
/* try to find all the payloader elements, they should be named 'pay%d'. for
|
||||||
|
* each of the payloaders we will create a stream, collect the source pad and
|
||||||
|
* add a notify::caps on the pad. */
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
name = g_strdup_printf ("pay%d", i);
|
||||||
|
|
||||||
|
if (!(pay = gst_bin_get_by_name (GST_BIN (element), name))) {
|
||||||
|
/* no more payloaders found, we have found all the streams and we can
|
||||||
|
* end the loop */
|
||||||
|
g_free (name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the stream */
|
||||||
|
stream = g_new0 (GstRTSPMediaStream, 1);
|
||||||
|
stream->mediabin = bin;
|
||||||
|
stream->element = element;
|
||||||
|
stream->payloader = pay;
|
||||||
|
stream->idx = bin->streams->len;
|
||||||
|
|
||||||
|
pad = gst_element_get_static_pad (pay, "src");
|
||||||
|
|
||||||
|
/* ghost the pad of the payloader to the element */
|
||||||
|
stream->srcpad = gst_ghost_pad_new (name, pad);
|
||||||
|
gst_element_add_pad (stream->element, stream->srcpad);
|
||||||
|
|
||||||
|
stream->caps_sig = g_signal_connect (pad, "notify::caps", (GCallback) caps_notify, stream);
|
||||||
|
gst_object_unref (pad);
|
||||||
|
|
||||||
|
/* add stream now */
|
||||||
|
g_array_append_val (bin->streams, stream);
|
||||||
|
gst_object_unref (pay);
|
||||||
|
|
||||||
|
g_free (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bin;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_launch:
|
||||||
|
{
|
||||||
|
g_critical ("no launch line specified");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
parse_error:
|
||||||
|
{
|
||||||
|
g_critical ("could not parse launch syntax (%s): %s", factory->launch,
|
||||||
|
(error ? error->message : "unknown reason"));
|
||||||
|
if (error)
|
||||||
|
g_error_free (error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#include <gst/rtsp/gstrtspurl.h>
|
#include <gst/rtsp/gstrtspurl.h>
|
||||||
|
|
||||||
#include "rtsp-media.h"
|
#include "rtsp-media.h"
|
||||||
|
@ -28,7 +27,8 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GST_TYPE_RTSP_MEDIA_FACTORY (gst_rtsp_media_get_type ())
|
/* types for the media factory */
|
||||||
|
#define GST_TYPE_RTSP_MEDIA_FACTORY (gst_rtsp_media_factory_get_type ())
|
||||||
#define GST_IS_RTSP_MEDIA_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY))
|
#define GST_IS_RTSP_MEDIA_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY))
|
||||||
#define GST_IS_RTSP_MEDIA_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_FACTORY))
|
#define GST_IS_RTSP_MEDIA_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_FACTORY))
|
||||||
#define GST_RTSP_MEDIA_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryClass))
|
#define GST_RTSP_MEDIA_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryClass))
|
||||||
|
@ -42,33 +42,41 @@ typedef struct _GstRTSPMediaFactoryClass GstRTSPMediaFactoryClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstRTSPMediaFactory:
|
* GstRTSPMediaFactory:
|
||||||
|
* @launch: the launch description
|
||||||
|
* @streams: the array of #GstRTSPMediaStream objects for this media.
|
||||||
*
|
*
|
||||||
* Creates a #GstRTSPMedia object for a given url.
|
* The definition and logic for constructing the pipeline for a media. The media
|
||||||
|
* can contain multiple streams like audio and video.
|
||||||
*/
|
*/
|
||||||
struct _GstRTSPMediaFactory {
|
struct _GstRTSPMediaFactory {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
|
||||||
|
gchar *launch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstRTSPMediaFactoryClass:
|
||||||
|
* @construct: the vmethod that will be called when the factory has to create the
|
||||||
|
* #GstRTSPMediaBin for @location.
|
||||||
|
*
|
||||||
|
* the #GstRTSPMediaFactory class structure.
|
||||||
|
*/
|
||||||
struct _GstRTSPMediaFactoryClass {
|
struct _GstRTSPMediaFactoryClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
GstRTSPMedia * (*create_media) (GstRTSPMediaFactory *factory, const gchar *url);
|
GstRTSPMediaBin * (*construct) (GstRTSPMediaFactory *factory, const gchar *location);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_rtsp_media_factory_get_type (void);
|
GType gst_rtsp_media_factory_get_type (void);
|
||||||
|
|
||||||
/* creating a factory */
|
/* configuring the factory */
|
||||||
GstRTSPMediaFactory * gst_rtsp_media_factory_new (void);
|
GstRTSPMediaFactory * gst_rtsp_media_factory_new (void);
|
||||||
|
|
||||||
/* creating a media */
|
void gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory *factory, const gchar *launch);
|
||||||
GstRTSPMedia * gst_rtsp_media_factory_create (GstRTSPMediaFactory *factory, const gchar *url);
|
gchar * gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory *factory);
|
||||||
|
|
||||||
|
/* creating the media bin from the factory */
|
||||||
/* managing media GTypes to a path */
|
GstRTSPMediaBin * gst_rtsp_media_factory_construct (GstRTSPMediaFactory *factory, const gchar *location);
|
||||||
void gst_rtsp_media_factory_add (GstRTSPMediaFactory *factory, const gchar *path,
|
|
||||||
GType type);
|
|
||||||
void gst_rtsp_media_factory_remove (GstRTSPMediaFactory *factory, const gchar *path,
|
|
||||||
GType type);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
146
gst/rtsp-server/rtsp-media-mapping.c
Normal file
146
gst/rtsp-server/rtsp-media-mapping.c
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rtsp-media-mapping.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GstRTSPMediaMapping, gst_rtsp_media_mapping, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void gst_rtsp_media_mapping_finalize (GObject * obj);
|
||||||
|
|
||||||
|
static GstRTSPMediaFactory * find_media (GstRTSPMediaMapping *mapping, const GstRTSPUrl *url);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtsp_media_mapping_class_init (GstRTSPMediaMappingClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_rtsp_media_mapping_finalize;
|
||||||
|
|
||||||
|
klass->find_media = find_media;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtsp_media_mapping_init (GstRTSPMediaMapping * mapping)
|
||||||
|
{
|
||||||
|
mapping->mappings = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtsp_media_mapping_finalize (GObject * obj)
|
||||||
|
{
|
||||||
|
GstRTSPMediaMapping *mapping = GST_RTSP_MEDIA_MAPPING (obj);
|
||||||
|
|
||||||
|
g_hash_table_unref (mapping->mappings);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_rtsp_media_mapping_parent_class)->finalize (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
GstRTSPMediaMapping *
|
||||||
|
gst_rtsp_media_mapping_new (void)
|
||||||
|
{
|
||||||
|
GstRTSPMediaMapping *result;
|
||||||
|
|
||||||
|
result = g_object_new (GST_TYPE_RTSP_MEDIA_MAPPING, NULL);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstRTSPMediaFactory *
|
||||||
|
find_media (GstRTSPMediaMapping *mapping, const GstRTSPUrl *url)
|
||||||
|
{
|
||||||
|
GstRTSPMediaFactory *result;
|
||||||
|
|
||||||
|
/* find the location of the media in the hashtable */
|
||||||
|
result = g_hash_table_lookup (mapping->mappings, url->abspath);
|
||||||
|
if (result)
|
||||||
|
g_object_ref (result);
|
||||||
|
|
||||||
|
g_message ("found media %p for url abspath %s", result, url->abspath);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtsp_media_mapping_find_factory:
|
||||||
|
* @mapping: a #GstRTSPMediaMapping
|
||||||
|
* @url: a url
|
||||||
|
*
|
||||||
|
* Find the #GstRTSPMediaFactory for @url from the mappings registered in @mapping.
|
||||||
|
*
|
||||||
|
* Returns: the #GstRTSPMediaFactory for @url. g_object_unref() after usage.
|
||||||
|
*/
|
||||||
|
GstRTSPMediaFactory *
|
||||||
|
gst_rtsp_media_mapping_find_factory (GstRTSPMediaMapping *mapping, const GstRTSPUrl *url)
|
||||||
|
{
|
||||||
|
GstRTSPMediaFactory *result;
|
||||||
|
GstRTSPMediaMappingClass *klass;
|
||||||
|
|
||||||
|
klass = GST_RTSP_MEDIA_MAPPING_GET_CLASS (mapping);
|
||||||
|
|
||||||
|
if (klass->find_media)
|
||||||
|
result = klass->find_media (mapping, url);
|
||||||
|
else
|
||||||
|
result = NULL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtsp_media_mapping_add_factory:
|
||||||
|
* @mapping: a #GstRTSPMediaMapping
|
||||||
|
* @path: a mount point
|
||||||
|
* @factory: a #GstRTSPMediaFactory
|
||||||
|
*
|
||||||
|
* Attach @factory to the mount point @path in @mapping.
|
||||||
|
*
|
||||||
|
* @path is of the form (/node)+. Any previous mapping will be freed.
|
||||||
|
*
|
||||||
|
* Ownership is taken of the reference on @factory so that @factory should not be
|
||||||
|
* used after calling this function.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_rtsp_media_mapping_add_factory (GstRTSPMediaMapping *mapping, const gchar *path,
|
||||||
|
GstRTSPMediaFactory *factory)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GST_IS_RTSP_MEDIA_MAPPING (mapping));
|
||||||
|
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
|
||||||
|
g_return_if_fail (path != NULL);
|
||||||
|
|
||||||
|
g_hash_table_insert (mapping->mappings, g_strdup (path), factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtsp_media_mapping_remove_factory:
|
||||||
|
* @mapping: a #GstRTSPMediaMapping
|
||||||
|
* @path: a mount point
|
||||||
|
*
|
||||||
|
* Remove the #GstRTSPMediaFactory associated with @path in @mapping.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_rtsp_media_mapping_remove_factory (GstRTSPMediaMapping *mapping, const gchar *path)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GST_IS_RTSP_MEDIA_MAPPING (mapping));
|
||||||
|
g_return_if_fail (path != NULL);
|
||||||
|
|
||||||
|
g_hash_table_remove (mapping->mappings, path);
|
||||||
|
}
|
||||||
|
|
76
gst/rtsp-server/rtsp-media-mapping.h
Normal file
76
gst/rtsp-server/rtsp-media-mapping.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include <gst/rtsp/gstrtspurl.h>
|
||||||
|
|
||||||
|
#include "rtsp-media-factory.h"
|
||||||
|
|
||||||
|
#ifndef __GST_RTSP_MEDIA_MAPPING_H__
|
||||||
|
#define __GST_RTSP_MEDIA_MAPPING_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_RTSP_MEDIA_MAPPING (gst_rtsp_media_mapping_get_type ())
|
||||||
|
#define GST_IS_RTSP_MEDIA_MAPPING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_MAPPING))
|
||||||
|
#define GST_IS_RTSP_MEDIA_MAPPING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_MAPPING))
|
||||||
|
#define GST_RTSP_MEDIA_MAPPING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_MAPPING, GstRTSPMediaMappingClass))
|
||||||
|
#define GST_RTSP_MEDIA_MAPPING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA_MAPPING, GstRTSPMediaMapping))
|
||||||
|
#define GST_RTSP_MEDIA_MAPPING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA_MAPPING, GstRTSPMediaMappingClass))
|
||||||
|
#define GST_RTSP_MEDIA_MAPPING_CAST(obj) ((GstRTSPMediaMapping*)(obj))
|
||||||
|
#define GST_RTSP_MEDIA_MAPPING_CLASS_CAST(klass) ((GstRTSPMediaMappingClass*)(klass))
|
||||||
|
|
||||||
|
typedef struct _GstRTSPMediaMapping GstRTSPMediaMapping;
|
||||||
|
typedef struct _GstRTSPMediaMappingClass GstRTSPMediaMappingClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstRTSPMediaMapping:
|
||||||
|
* @mappings: the mountpoint to media mappings
|
||||||
|
*
|
||||||
|
* Creates a #GstRTSPMedia object for a given url.
|
||||||
|
*/
|
||||||
|
struct _GstRTSPMediaMapping {
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
GHashTable *mappings;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstRTSPMediaMappingClass {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
GstRTSPMediaFactory * (*find_media) (GstRTSPMediaMapping *mapping, const GstRTSPUrl *url);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_rtsp_media_mapping_get_type (void);
|
||||||
|
|
||||||
|
/* creating a mapping */
|
||||||
|
GstRTSPMediaMapping * gst_rtsp_media_mapping_new (void);
|
||||||
|
|
||||||
|
/* finding a media factory */
|
||||||
|
GstRTSPMediaFactory * gst_rtsp_media_mapping_find_factory (GstRTSPMediaMapping *mapping, const GstRTSPUrl *url);
|
||||||
|
|
||||||
|
/* managing media to a path */
|
||||||
|
void gst_rtsp_media_mapping_add_factory (GstRTSPMediaMapping *mapping, const gchar *path,
|
||||||
|
GstRTSPMediaFactory *factory);
|
||||||
|
void gst_rtsp_media_mapping_remove_factory (GstRTSPMediaMapping *mapping, const gchar *path);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_RTSP_MEDIA_MAPPING_H__ */
|
|
@ -19,24 +19,24 @@
|
||||||
|
|
||||||
#include "rtsp-media.h"
|
#include "rtsp-media.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
|
static void gst_rtsp_media_bin_finalize (GObject * obj);
|
||||||
|
|
||||||
static void gst_rtsp_media_finalize (GObject * obj);
|
G_DEFINE_TYPE (GstRTSPMediaBin, gst_rtsp_media_bin, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
|
gst_rtsp_media_bin_class_init (GstRTSPMediaBinClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
|
|
||||||
gobject_class = G_OBJECT_CLASS (klass);
|
gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
gobject_class->finalize = gst_rtsp_media_finalize;
|
gobject_class->finalize = gst_rtsp_media_bin_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtsp_media_init (GstRTSPMedia * media)
|
gst_rtsp_media_bin_init (GstRTSPMediaBin * bin)
|
||||||
{
|
{
|
||||||
media->streams = g_array_new (FALSE, TRUE, sizeof (GstRTSPMediaStream *));
|
bin->streams = g_array_new (FALSE, TRUE, sizeof (GstRTSPMediaStream *));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -45,218 +45,59 @@ gst_rtsp_media_stream_free (GstRTSPMediaStream *stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtsp_media_finalize (GObject * obj)
|
gst_rtsp_media_bin_finalize (GObject * obj)
|
||||||
{
|
{
|
||||||
GstRTSPMedia *media;
|
GstRTSPMediaBin *bin;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
media = GST_RTSP_MEDIA (obj);
|
bin = GST_RTSP_MEDIA_BIN (obj);
|
||||||
|
|
||||||
g_free (media->location);
|
for (i = 0; i < bin->streams->len; i++) {
|
||||||
gst_rtsp_url_free (media->url);
|
|
||||||
|
|
||||||
for (i = 0; i < media->streams->len; i++) {
|
|
||||||
GstRTSPMediaStream *stream;
|
GstRTSPMediaStream *stream;
|
||||||
|
|
||||||
stream = g_array_index (media->streams, GstRTSPMediaStream *, i);
|
stream = g_array_index (bin->streams, GstRTSPMediaStream *, i);
|
||||||
|
|
||||||
gst_rtsp_media_stream_free (stream);
|
gst_rtsp_media_stream_free (stream);
|
||||||
}
|
}
|
||||||
g_array_free (media->streams, TRUE);
|
g_array_free (bin->streams, TRUE);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (gst_rtsp_media_bin_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_media_new:
|
* gst_rtsp_media_bin_n_streams:
|
||||||
* @location: the URL of the media
|
* @media: a #GstRTSPMediaBin
|
||||||
*
|
*
|
||||||
* Create a new #GstRTSPMedia instance.
|
* Get the number of streams in this mediabin.
|
||||||
*
|
|
||||||
* Returns: a new #GstRTSPMedia object or %NULL when location did not contain a
|
|
||||||
* valid or understood URL.
|
|
||||||
*/
|
|
||||||
GstRTSPMedia *
|
|
||||||
gst_rtsp_media_new (const gchar *location)
|
|
||||||
{
|
|
||||||
GstRTSPMedia *result;
|
|
||||||
GstRTSPUrl *url;
|
|
||||||
|
|
||||||
url = NULL;
|
|
||||||
|
|
||||||
if (gst_rtsp_url_parse (location, &url) != GST_RTSP_OK)
|
|
||||||
goto invalid_url;
|
|
||||||
|
|
||||||
result = g_object_new (GST_TYPE_RTSP_MEDIA, NULL);
|
|
||||||
result->location = g_strdup (location);
|
|
||||||
result->url = url;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
/* ERRORS */
|
|
||||||
invalid_url:
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPMediaStream * stream)
|
|
||||||
{
|
|
||||||
if (stream->caps)
|
|
||||||
gst_caps_unref (stream->caps);
|
|
||||||
if ((stream->caps = GST_PAD_CAPS (pad)))
|
|
||||||
gst_caps_ref (stream->caps);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gst_rtsp_media_prepare:
|
|
||||||
* @media: a #GstRTSPMedia
|
|
||||||
* @bin: the parent bin to create the elements in.
|
|
||||||
*
|
|
||||||
* Prepare the media object so that it creates its streams. Implementations
|
|
||||||
* should crate the needed gstreamer elements and add them to @bin. No state
|
|
||||||
* changes should be performed on them yet.
|
|
||||||
*
|
|
||||||
* One or more GstRTSPMediaStream objects should be added to @media with the
|
|
||||||
* srcpad member set to a source pad that produces buffer of type
|
|
||||||
* application/x-rtp.
|
|
||||||
*
|
|
||||||
* Returns: %TRUE if the media could be prepared.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
gst_rtsp_media_prepare (GstRTSPMedia *media, GstBin *bin)
|
|
||||||
{
|
|
||||||
GstRTSPMediaStream *stream;
|
|
||||||
GstElement *pay, *element;
|
|
||||||
GstPad * pad;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
/* if we're already prepared we must exit */
|
|
||||||
g_return_val_if_fail (media->prepared == FALSE, FALSE);
|
|
||||||
|
|
||||||
g_print ("%s\n", media->url->abspath);
|
|
||||||
|
|
||||||
if (g_str_has_prefix (media->url->abspath, "/camera")) {
|
|
||||||
/* live */
|
|
||||||
element = gst_parse_launch ("( "
|
|
||||||
"v4l2src ! video/x-raw-yuv,width=352,height=288,framerate=15/1 ! "
|
|
||||||
"queue ! videorate ! ffmpegcolorspace ! "
|
|
||||||
"x264enc bitrate=300 ! rtph264pay name=pay0 pt=96 "
|
|
||||||
"alsasrc ! audio/x-raw-int,rate=8000 ! queue ! "
|
|
||||||
"amrnbenc ! rtpamrpay name=pay1 pt=97 "
|
|
||||||
")", NULL);
|
|
||||||
}
|
|
||||||
else if (g_str_has_prefix (media->url->abspath, "/h264")) {
|
|
||||||
/* transcode h264 */
|
|
||||||
element = gst_parse_launch ("( uridecodebin "
|
|
||||||
"uri=file:///home/cschalle/Videos/mi2.avi ! "
|
|
||||||
"x264enc bitrate=300 ! rtph264pay name=pay0 )", NULL);
|
|
||||||
}
|
|
||||||
else if (g_str_has_prefix (media->url->abspath, "/theora")) {
|
|
||||||
/* transcode theora */
|
|
||||||
element = gst_parse_launch ("( uridecodebin "
|
|
||||||
"uri=file:///home/wim/data/mi2.avi ! "
|
|
||||||
"theoraenc ! rtptheorapay name=pay0 )", NULL);
|
|
||||||
}
|
|
||||||
else if (g_str_has_prefix (media->url->abspath, "/macpclinux")) {
|
|
||||||
/* theora/vorbis */
|
|
||||||
element = gst_parse_launch ("( filesrc "
|
|
||||||
"location=/home/cschalle/Videos/mac_pc_linux_2.ogg ! oggdemux name=d ! "
|
|
||||||
"queue ! theoraparse ! rtptheorapay name=pay0 "
|
|
||||||
"d. ! queue ! vorbisparse ! rtpvorbispay name=pay1 )", NULL);
|
|
||||||
}
|
|
||||||
else if (g_str_has_prefix (media->url->abspath, "/rtspproxy")) {
|
|
||||||
/* proxy RTSP transcode */
|
|
||||||
element = gst_parse_launch ("( uridecodebin "
|
|
||||||
"uri=rtsp://ia300135.us.archive.org:554/0/items/uncovered_interviews/uncovered_interviews_3_256kb.mp4 ! "
|
|
||||||
"x264enc bitrate=1800 ! rtph264pay name=pay0 )", NULL);
|
|
||||||
}
|
|
||||||
else if (g_str_has_prefix (media->url->abspath, "/httpproxy")) {
|
|
||||||
/* proxy HTTP transcode */
|
|
||||||
element = gst_parse_launch ("( uridecodebin "
|
|
||||||
"uri=http://movies.apple.com/movies/fox/maxpayne/maxpayne-tlre_h480.mov name=d "
|
|
||||||
"d. ! queue ! x264enc bitrate=1800 ! rtph264pay name=pay0 pt=96 "
|
|
||||||
"d. ! queue ! faac ! rtpmp4gpay name=pay1 pt=97 )", NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
gst_bin_add (bin, element);
|
|
||||||
|
|
||||||
for (i = 0; ; i++) {
|
|
||||||
gchar *name;
|
|
||||||
|
|
||||||
name = g_strdup_printf ("pay%d", i);
|
|
||||||
|
|
||||||
if (!(pay = gst_bin_get_by_name (GST_BIN (element), name))) {
|
|
||||||
g_free (name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the stream */
|
|
||||||
stream = g_new0 (GstRTSPMediaStream, 1);
|
|
||||||
stream->media = media;
|
|
||||||
stream->element = element;
|
|
||||||
stream->payloader = pay;
|
|
||||||
stream->idx = media->streams->len;
|
|
||||||
|
|
||||||
pad = gst_element_get_static_pad (pay, "src");
|
|
||||||
|
|
||||||
stream->srcpad = gst_ghost_pad_new (name, pad);
|
|
||||||
gst_element_add_pad (stream->element, stream->srcpad);
|
|
||||||
|
|
||||||
stream->caps_sig = g_signal_connect (pad, "notify::caps", (GCallback) caps_notify, stream);
|
|
||||||
gst_object_unref (pad);
|
|
||||||
|
|
||||||
/* add stream now */
|
|
||||||
g_array_append_val (media->streams, stream);
|
|
||||||
gst_object_unref (pay);
|
|
||||||
|
|
||||||
g_free (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
media->prepared = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gst_rtsp_media_n_streams:
|
|
||||||
* @media: a #GstRTSPMedia
|
|
||||||
*
|
|
||||||
* Get the number of streams in this media.
|
|
||||||
*
|
*
|
||||||
* Returns: The number of streams.
|
* Returns: The number of streams.
|
||||||
*/
|
*/
|
||||||
guint
|
guint
|
||||||
gst_rtsp_media_n_streams (GstRTSPMedia *media)
|
gst_rtsp_media_bin_n_streams (GstRTSPMediaBin *bin)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
|
g_return_val_if_fail (GST_IS_RTSP_MEDIA_BIN (bin), 0);
|
||||||
g_return_val_if_fail (media->prepared, 0);
|
|
||||||
|
|
||||||
return media->streams->len;
|
return bin->streams->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_media_get_stream:
|
* gst_rtsp_media_bin_get_stream:
|
||||||
* @media: a #GstRTSPMedia
|
* @bin: a #GstRTSPMediaBin
|
||||||
* @idx: the stream index
|
* @idx: the stream index
|
||||||
*
|
*
|
||||||
* Retrieve the stream with index @idx from @media.
|
* Retrieve the stream with index @idx from @bin.
|
||||||
*
|
*
|
||||||
* Returns: the #GstRTSPMediaStream at index @idx.
|
* Returns: the #GstRTSPMediaStream at index @idx.
|
||||||
*/
|
*/
|
||||||
GstRTSPMediaStream *
|
GstRTSPMediaStream *
|
||||||
gst_rtsp_media_get_stream (GstRTSPMedia *media, guint idx)
|
gst_rtsp_media_bin_get_stream (GstRTSPMediaBin *bin, guint idx)
|
||||||
{
|
{
|
||||||
GstRTSPMediaStream *res;
|
GstRTSPMediaStream *res;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
|
g_return_val_if_fail (GST_IS_RTSP_MEDIA_BIN (bin), NULL);
|
||||||
g_return_val_if_fail (media->prepared, 0);
|
g_return_val_if_fail (idx < bin->streams->len, NULL);
|
||||||
g_return_val_if_fail (idx < media->streams->len, NULL);
|
|
||||||
|
|
||||||
res = g_array_index (media->streams, GstRTSPMediaStream *, idx);
|
res = g_array_index (bin->streams, GstRTSPMediaStream *, idx);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,18 +25,19 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GST_TYPE_RTSP_MEDIA (gst_rtsp_media_get_type ())
|
/* types for the media bin */
|
||||||
#define GST_IS_RTSP_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA))
|
#define GST_TYPE_RTSP_MEDIA_BIN (gst_rtsp_media_bin_get_type ())
|
||||||
#define GST_IS_RTSP_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA))
|
#define GST_IS_RTSP_MEDIA_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_BIN))
|
||||||
#define GST_RTSP_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMediaClass))
|
#define GST_IS_RTSP_MEDIA_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_BIN))
|
||||||
#define GST_RTSP_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA, GstRTSPMedia))
|
#define GST_RTSP_MEDIA_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_BIN, GstRTSPMediaBinClass))
|
||||||
#define GST_RTSP_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA, GstRTSPMediaClass))
|
#define GST_RTSP_MEDIA_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA_BIN, GstRTSPMediaBin))
|
||||||
#define GST_RTSP_MEDIA_CAST(obj) ((GstRTSPMedia*)(obj))
|
#define GST_RTSP_MEDIA_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA_BIN, GstRTSPMediaBinClass))
|
||||||
#define GST_RTSP_MEDIA_CLASS_CAST(klass) ((GstRTSPMediaClass*)(klass))
|
#define GST_RTSP_MEDIA_BIN_CAST(obj) ((GstRTSPMediaBin*)(obj))
|
||||||
|
#define GST_RTSP_MEDIA_BIN_CLASS_CAST(klass) ((GstRTSPMediaBinClass*)(klass))
|
||||||
|
|
||||||
typedef struct _GstRTSPMedia GstRTSPMedia;
|
|
||||||
typedef struct _GstRTSPMediaStream GstRTSPMediaStream;
|
typedef struct _GstRTSPMediaStream GstRTSPMediaStream;
|
||||||
typedef struct _GstRTSPMediaClass GstRTSPMediaClass;
|
typedef struct _GstRTSPMediaBin GstRTSPMediaBin;
|
||||||
|
typedef struct _GstRTSPMediaBinClass GstRTSPMediaBinClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstRTSPMediaStream:
|
* GstRTSPMediaStream:
|
||||||
|
@ -51,7 +52,7 @@ typedef struct _GstRTSPMediaClass GstRTSPMediaClass;
|
||||||
* The definition of a media stream. The streams are identified by @id.
|
* The definition of a media stream. The streams are identified by @id.
|
||||||
*/
|
*/
|
||||||
struct _GstRTSPMediaStream {
|
struct _GstRTSPMediaStream {
|
||||||
GstRTSPMedia *media;
|
GstRTSPMediaBin *mediabin;
|
||||||
|
|
||||||
guint idx;
|
guint idx;
|
||||||
|
|
||||||
|
@ -63,33 +64,28 @@ struct _GstRTSPMediaStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstRTSPMedia:
|
* GstRTSPMediaBin:
|
||||||
|
* @media: the owner #GstRTSPMedia
|
||||||
*
|
*
|
||||||
* The definition and logic for constructing the pipeline for a media. The media
|
* A class that contains the elements to handle the media
|
||||||
* can contain multiple streams like audio and video.
|
* provided by @media.
|
||||||
*/
|
*/
|
||||||
struct _GstRTSPMedia {
|
struct _GstRTSPMediaBin {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
|
||||||
gchar *location;
|
GstElement *element;
|
||||||
GstRTSPUrl *url;
|
|
||||||
|
|
||||||
gboolean prepared;
|
|
||||||
GArray *streams;
|
GArray *streams;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRTSPMediaClass {
|
struct _GstRTSPMediaBinClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_rtsp_media_get_type (void);
|
GType gst_rtsp_media_bin_get_type (void);
|
||||||
|
|
||||||
GstRTSPMedia * gst_rtsp_media_new (const gchar *name);
|
/* dealing with the media bin */
|
||||||
|
guint gst_rtsp_media_bin_n_streams (GstRTSPMediaBin *bin);
|
||||||
gboolean gst_rtsp_media_prepare (GstRTSPMedia *media, GstBin *bin);
|
GstRTSPMediaStream * gst_rtsp_media_bin_get_stream (GstRTSPMediaBin *bin, guint idx);
|
||||||
|
|
||||||
guint gst_rtsp_media_n_streams (GstRTSPMedia *media);
|
|
||||||
GstRTSPMediaStream * gst_rtsp_media_get_stream (GstRTSPMedia *media, guint idx);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ enum
|
||||||
PROP_BACKLOG,
|
PROP_BACKLOG,
|
||||||
PROP_PORT,
|
PROP_PORT,
|
||||||
PROP_POOL,
|
PROP_POOL,
|
||||||
PROP_FACTORY,
|
PROP_MAPPING,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,14 +88,14 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
|
||||||
g_param_spec_object ("pool", "Pool", "The session pool to use for client session",
|
g_param_spec_object ("pool", "Pool", "The session pool to use for client session",
|
||||||
GST_TYPE_RTSP_SESSION_POOL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
GST_TYPE_RTSP_SESSION_POOL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
/**
|
/**
|
||||||
* GstRTSPServer::factory
|
* GstRTSPServer::mapping
|
||||||
*
|
*
|
||||||
* The media factory to use for this server. By default the server has no
|
* The media mapping to use for this server. By default the server has no
|
||||||
* media factories and thus cannot map urls to media streams.
|
* media mapping and thus cannot map urls to media streams.
|
||||||
*/
|
*/
|
||||||
g_object_class_install_property (gobject_class, PROP_POOL,
|
g_object_class_install_property (gobject_class, PROP_MAPPING,
|
||||||
g_param_spec_object ("factory", "Factory", "The media factory to use for client session",
|
g_param_spec_object ("mapping", "Mapping", "The media mapping to use for client session",
|
||||||
GST_TYPE_RTSP_MEDIA_FACTORY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
GST_TYPE_RTSP_MEDIA_MAPPING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
klass->accept_client = gst_rtsp_server_accept_client;
|
klass->accept_client = gst_rtsp_server_accept_client;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ gst_rtsp_server_init (GstRTSPServer * server)
|
||||||
server->server_port = DEFAULT_PORT;
|
server->server_port = DEFAULT_PORT;
|
||||||
server->backlog = DEFAULT_BACKLOG;
|
server->backlog = DEFAULT_BACKLOG;
|
||||||
server->pool = gst_rtsp_session_pool_new ();
|
server->pool = gst_rtsp_session_pool_new ();
|
||||||
|
server->mapping = gst_rtsp_media_mapping_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,13 +203,19 @@ gst_rtsp_server_get_backlog (GstRTSPServer *server)
|
||||||
void
|
void
|
||||||
gst_rtsp_server_set_session_pool (GstRTSPServer *server, GstRTSPSessionPool *pool)
|
gst_rtsp_server_set_session_pool (GstRTSPServer *server, GstRTSPSessionPool *pool)
|
||||||
{
|
{
|
||||||
|
GstRTSPSessionPool *old;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_RTSP_SERVER (server));
|
g_return_if_fail (GST_IS_RTSP_SERVER (server));
|
||||||
|
|
||||||
if (server->pool)
|
old = server->pool;
|
||||||
g_object_unref (server->pool);
|
|
||||||
if (pool)
|
if (old != pool) {
|
||||||
g_object_ref (pool);
|
if (pool)
|
||||||
server->pool = pool;
|
g_object_ref (pool);
|
||||||
|
server->pool = pool;
|
||||||
|
if (old)
|
||||||
|
g_object_unref (old);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,25 +242,25 @@ gst_rtsp_server_get_session_pool (GstRTSPServer *server)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_server_set_media_factory:
|
* gst_rtsp_server_set_media_mapping:
|
||||||
* @server: a #GstRTSPServer
|
* @server: a #GstRTSPServer
|
||||||
* @factory: a #GstRTSPMediaFactory
|
* @mapping: a #GstRTSPMediaMapping
|
||||||
*
|
*
|
||||||
* configure @factory to be used as the media factory of @server.
|
* configure @mapping to be used as the media mapping of @server.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_rtsp_server_set_media_factory (GstRTSPServer *server, GstRTSPMediaFactory *factory)
|
gst_rtsp_server_set_media_mapping (GstRTSPServer *server, GstRTSPMediaMapping *mapping)
|
||||||
{
|
{
|
||||||
GstRTSPMediaFactory *old;
|
GstRTSPMediaMapping *old;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_RTSP_SERVER (server));
|
g_return_if_fail (GST_IS_RTSP_SERVER (server));
|
||||||
|
|
||||||
old = server->factory;
|
old = server->mapping;
|
||||||
|
|
||||||
if (old != factory) {
|
if (old != mapping) {
|
||||||
if (factory)
|
if (mapping)
|
||||||
g_object_ref (factory);
|
g_object_ref (mapping);
|
||||||
server->factory = factory;
|
server->mapping = mapping;
|
||||||
if (old)
|
if (old)
|
||||||
g_object_unref (old);
|
g_object_unref (old);
|
||||||
}
|
}
|
||||||
|
@ -261,22 +268,22 @@ gst_rtsp_server_set_media_factory (GstRTSPServer *server, GstRTSPMediaFactory *f
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_server_get_media_factory:
|
* gst_rtsp_server_get_media_mapping:
|
||||||
* @server: a #GstRTSPServer
|
* @server: a #GstRTSPServer
|
||||||
*
|
*
|
||||||
* Get the #GstRTSPMediaFactory used as the media factory of @server.
|
* Get the #GstRTSPMediaMapping used as the media mapping of @server.
|
||||||
*
|
*
|
||||||
* Returns: the #GstRTSPMediaFactory of @server. g_object_unref() after
|
* Returns: the #GstRTSPMediaMapping of @server. g_object_unref() after
|
||||||
* usage.
|
* usage.
|
||||||
*/
|
*/
|
||||||
GstRTSPMediaFactory *
|
GstRTSPMediaMapping *
|
||||||
gst_rtsp_server_get_media_factory (GstRTSPServer *server)
|
gst_rtsp_server_get_media_mapping (GstRTSPServer *server)
|
||||||
{
|
{
|
||||||
GstRTSPMediaFactory *result;
|
GstRTSPMediaMapping *result;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
|
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
|
||||||
|
|
||||||
if ((result = server->factory))
|
if ((result = server->mapping))
|
||||||
g_object_ref (result);
|
g_object_ref (result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -298,8 +305,8 @@ gst_rtsp_server_get_property (GObject *object, guint propid,
|
||||||
case PROP_POOL:
|
case PROP_POOL:
|
||||||
g_value_take_object (value, gst_rtsp_server_get_session_pool (server));
|
g_value_take_object (value, gst_rtsp_server_get_session_pool (server));
|
||||||
break;
|
break;
|
||||||
case PROP_FACTORY:
|
case PROP_MAPPING:
|
||||||
g_value_take_object (value, gst_rtsp_server_get_media_factory (server));
|
g_value_take_object (value, gst_rtsp_server_get_media_mapping (server));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
||||||
|
@ -322,8 +329,8 @@ gst_rtsp_server_set_property (GObject *object, guint propid,
|
||||||
case PROP_POOL:
|
case PROP_POOL:
|
||||||
gst_rtsp_server_set_session_pool (server, g_value_get_object (value));
|
gst_rtsp_server_set_session_pool (server, g_value_get_object (value));
|
||||||
break;
|
break;
|
||||||
case PROP_FACTORY:
|
case PROP_MAPPING:
|
||||||
gst_rtsp_server_set_media_factory (server, g_value_get_object (value));
|
gst_rtsp_server_set_media_mapping (server, g_value_get_object (value));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
||||||
|
@ -440,7 +447,7 @@ gst_rtsp_server_accept_client (GstRTSPServer *server, GIOChannel *channel)
|
||||||
gst_rtsp_client_set_session_pool (client, server->pool);
|
gst_rtsp_client_set_session_pool (client, server->pool);
|
||||||
|
|
||||||
/* set the session pool that this client should use */
|
/* set the session pool that this client should use */
|
||||||
gst_rtsp_client_set_media_factory (client, server->factory);
|
gst_rtsp_client_set_media_mapping (client, server->mapping);
|
||||||
|
|
||||||
/* accept connections for that client, this function returns after accepting
|
/* accept connections for that client, this function returns after accepting
|
||||||
* the connection and will run the remainder of the communication with the
|
* the connection and will run the remainder of the communication with the
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#include "rtsp-session-pool.h"
|
#include "rtsp-session-pool.h"
|
||||||
#include "rtsp-media-factory.h"
|
#include "rtsp-media-mapping.h"
|
||||||
#include "rtsp-client.h"
|
#include "rtsp-client.h"
|
||||||
|
|
||||||
#ifndef __GST_RTSP_SERVER_H__
|
#ifndef __GST_RTSP_SERVER_H__
|
||||||
|
@ -72,8 +72,8 @@ struct _GstRTSPServer {
|
||||||
/* sessions on this server */
|
/* sessions on this server */
|
||||||
GstRTSPSessionPool *pool;
|
GstRTSPSessionPool *pool;
|
||||||
|
|
||||||
/* media factory for this server */
|
/* media mapper for this server */
|
||||||
GstRTSPMediaFactory *factory;
|
GstRTSPMediaMapping *mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,8 +103,8 @@ gint gst_rtsp_server_get_backlog (GstRTSPServer *serve
|
||||||
void gst_rtsp_server_set_session_pool (GstRTSPServer *server, GstRTSPSessionPool *pool);
|
void gst_rtsp_server_set_session_pool (GstRTSPServer *server, GstRTSPSessionPool *pool);
|
||||||
GstRTSPSessionPool * gst_rtsp_server_get_session_pool (GstRTSPServer *server);
|
GstRTSPSessionPool * gst_rtsp_server_get_session_pool (GstRTSPServer *server);
|
||||||
|
|
||||||
void gst_rtsp_server_set_media_factory (GstRTSPServer *server, GstRTSPMediaFactory *factory);
|
void gst_rtsp_server_set_media_mapping (GstRTSPServer *server, GstRTSPMediaMapping *mapping);
|
||||||
GstRTSPMediaFactory * gst_rtsp_server_get_media_factory (GstRTSPServer *server);
|
GstRTSPMediaMapping * gst_rtsp_server_get_media_mapping (GstRTSPServer *server);
|
||||||
|
|
||||||
gboolean gst_rtsp_server_io_func (GIOChannel *channel, GIOCondition condition,
|
gboolean gst_rtsp_server_io_func (GIOChannel *channel, GIOCondition condition,
|
||||||
GstRTSPServer *server);
|
GstRTSPServer *server);
|
||||||
|
|
|
@ -62,8 +62,8 @@ gst_rtsp_session_free_media (GstRTSPSessionMedia *media)
|
||||||
|
|
||||||
gst_element_set_state (media->pipeline, GST_STATE_NULL);
|
gst_element_set_state (media->pipeline, GST_STATE_NULL);
|
||||||
|
|
||||||
if (media->media)
|
if (media->factory)
|
||||||
g_object_unref (media->media);
|
g_object_unref (media->factory);
|
||||||
|
|
||||||
for (walk = media->streams; walk; walk = g_list_next (walk)) {
|
for (walk = media->streams; walk; walk = g_list_next (walk)) {
|
||||||
GstRTSPSessionStream *stream = (GstRTSPSessionStream *) walk->data;
|
GstRTSPSessionStream *stream = (GstRTSPSessionStream *) walk->data;
|
||||||
|
@ -98,14 +98,15 @@ gst_rtsp_session_finalize (GObject * obj)
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_session_get_media:
|
* gst_rtsp_session_get_media:
|
||||||
* @sess: a #GstRTSPSession
|
* @sess: a #GstRTSPSession
|
||||||
* @media: a #GstRTSPSessionMedia
|
* @location: the url for the media
|
||||||
|
* @factory: a #GstRTSPMediaFactory
|
||||||
*
|
*
|
||||||
* Get or create the session information for @media.
|
* Get or create the session information for @factory.
|
||||||
*
|
*
|
||||||
* Returns: the configuration for @media in @sess.
|
* Returns: the configuration for @factory in @sess.
|
||||||
*/
|
*/
|
||||||
GstRTSPSessionMedia *
|
GstRTSPSessionMedia *
|
||||||
gst_rtsp_session_get_media (GstRTSPSession *sess, GstRTSPMedia *media)
|
gst_rtsp_session_get_media (GstRTSPSession *sess, const gchar *location, GstRTSPMediaFactory *factory)
|
||||||
{
|
{
|
||||||
GstRTSPSessionMedia *result;
|
GstRTSPSessionMedia *result;
|
||||||
GList *walk;
|
GList *walk;
|
||||||
|
@ -115,19 +116,22 @@ gst_rtsp_session_get_media (GstRTSPSession *sess, GstRTSPMedia *media)
|
||||||
for (walk = sess->medias; walk; walk = g_list_next (walk)) {
|
for (walk = sess->medias; walk; walk = g_list_next (walk)) {
|
||||||
result = (GstRTSPSessionMedia *) walk->data;
|
result = (GstRTSPSessionMedia *) walk->data;
|
||||||
|
|
||||||
if (result->media == media)
|
if (result->factory == factory)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
result = NULL;
|
result = NULL;
|
||||||
}
|
}
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
result = g_new0 (GstRTSPSessionMedia, 1);
|
result = g_new0 (GstRTSPSessionMedia, 1);
|
||||||
result->media = media;
|
result->factory = factory;
|
||||||
result->pipeline = gst_pipeline_new ("pipeline");
|
result->pipeline = gst_pipeline_new ("pipeline");
|
||||||
|
|
||||||
/* prepare media into the pipeline */
|
/* construct media and add to the pipeline */
|
||||||
if (!gst_rtsp_media_prepare (media, GST_BIN (result->pipeline)))
|
result->mediabin = gst_rtsp_media_factory_construct (factory, location);
|
||||||
|
if (result->mediabin == NULL)
|
||||||
goto no_media;
|
goto no_media;
|
||||||
|
|
||||||
|
gst_bin_add (GST_BIN_CAST (result->pipeline), result->mediabin->element);
|
||||||
|
|
||||||
result->rtpbin = gst_element_factory_make ("gstrtpbin", "rtpbin");
|
result->rtpbin = gst_element_factory_make ("gstrtpbin", "rtpbin");
|
||||||
|
|
||||||
|
@ -149,7 +153,7 @@ no_media:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_session_get_stream:
|
* gst_rtsp_session_media_get_stream:
|
||||||
* @media: a #GstRTSPSessionMedia
|
* @media: a #GstRTSPSessionMedia
|
||||||
* @idx: the stream index
|
* @idx: the stream index
|
||||||
*
|
*
|
||||||
|
@ -159,7 +163,7 @@ no_media:
|
||||||
* is unreffed.
|
* is unreffed.
|
||||||
*/
|
*/
|
||||||
GstRTSPSessionStream *
|
GstRTSPSessionStream *
|
||||||
gst_rtsp_session_get_stream (GstRTSPSessionMedia *media, guint idx)
|
gst_rtsp_session_media_get_stream (GstRTSPSessionMedia *media, guint idx)
|
||||||
{
|
{
|
||||||
GstRTSPSessionStream *result;
|
GstRTSPSessionStream *result;
|
||||||
GList *walk;
|
GList *walk;
|
||||||
|
@ -178,7 +182,7 @@ gst_rtsp_session_get_stream (GstRTSPSessionMedia *media, guint idx)
|
||||||
result = g_new0 (GstRTSPSessionStream, 1);
|
result = g_new0 (GstRTSPSessionStream, 1);
|
||||||
result->idx = idx;
|
result->idx = idx;
|
||||||
result->media = media;
|
result->media = media;
|
||||||
result->media_stream = gst_rtsp_media_get_stream (media->media, idx);
|
result->media_stream = gst_rtsp_media_bin_get_stream (media->mediabin, idx);
|
||||||
|
|
||||||
media->streams = g_list_prepend (media->streams, result);
|
media->streams = g_list_prepend (media->streams, result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <gst/rtsp/gstrtsptransport.h>
|
#include <gst/rtsp/gstrtsptransport.h>
|
||||||
|
|
||||||
#include "rtsp-media.h"
|
#include "rtsp-media.h"
|
||||||
|
#include "rtsp-media-factory.h"
|
||||||
|
|
||||||
#ifndef __GST_RTSP_SESSION_H__
|
#ifndef __GST_RTSP_SESSION_H__
|
||||||
#define __GST_RTSP_SESSION_H__
|
#define __GST_RTSP_SESSION_H__
|
||||||
|
@ -87,10 +88,11 @@ struct _GstRTSPSessionMedia
|
||||||
GstRTSPSession *session;
|
GstRTSPSession *session;
|
||||||
|
|
||||||
/* the media we are handling */
|
/* the media we are handling */
|
||||||
GstRTSPMedia *media;
|
GstRTSPMediaFactory *factory;
|
||||||
|
|
||||||
/* the pipeline for the media */
|
/* the pipeline for the media */
|
||||||
GstElement *pipeline;
|
GstElement *pipeline;
|
||||||
|
GstRTSPMediaBin *mediabin;
|
||||||
|
|
||||||
/* RTP session manager */
|
/* RTP session manager */
|
||||||
GstElement *rtpbin;
|
GstElement *rtpbin;
|
||||||
|
@ -125,15 +127,16 @@ GType gst_rtsp_session_get_type (void);
|
||||||
|
|
||||||
GstRTSPSession * gst_rtsp_session_new (const gchar *sessionid);
|
GstRTSPSession * gst_rtsp_session_new (const gchar *sessionid);
|
||||||
|
|
||||||
GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess,
|
GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess, const gchar *location,
|
||||||
GstRTSPMedia *media);
|
GstRTSPMediaFactory *factory);
|
||||||
GstRTSPSessionStream * gst_rtsp_session_get_stream (GstRTSPSessionMedia *media,
|
|
||||||
guint idx);
|
|
||||||
|
|
||||||
GstStateChangeReturn gst_rtsp_session_media_play (GstRTSPSessionMedia *media);
|
GstStateChangeReturn gst_rtsp_session_media_play (GstRTSPSessionMedia *media);
|
||||||
GstStateChangeReturn gst_rtsp_session_media_pause (GstRTSPSessionMedia *media);
|
GstStateChangeReturn gst_rtsp_session_media_pause (GstRTSPSessionMedia *media);
|
||||||
GstStateChangeReturn gst_rtsp_session_media_stop (GstRTSPSessionMedia *media);
|
GstStateChangeReturn gst_rtsp_session_media_stop (GstRTSPSessionMedia *media);
|
||||||
|
|
||||||
|
GstRTSPSessionStream * gst_rtsp_session_media_get_stream (GstRTSPSessionMedia *media,
|
||||||
|
guint idx);
|
||||||
|
|
||||||
GstRTSPTransport * gst_rtsp_session_stream_set_transport (GstRTSPSessionStream *stream,
|
GstRTSPTransport * gst_rtsp_session_stream_set_transport (GstRTSPSessionStream *stream,
|
||||||
const gchar *destination,
|
const gchar *destination,
|
||||||
GstRTSPTransport *ct);
|
GstRTSPTransport *ct);
|
||||||
|
|
Loading…
Reference in a new issue