rtsp: make object details private

Make all object details private
Add methods to access private bits
This commit is contained in:
Wim Taymans 2012-11-29 11:11:05 +01:00
parent 8665c3b494
commit ad00c5e792
28 changed files with 2238 additions and 1284 deletions

View file

@ -313,6 +313,7 @@ gst_rtsp_stream_set_mtu
gst_rtsp_stream_join_bin
gst_rtsp_stream_leave_bin
gst_rtsp_stream_get_rtpinfo
gst_rtsp_stream_get_caps
gst_rtsp_stream_recv_rtcp
gst_rtsp_stream_recv_rtp
gst_rtsp_stream_add_transport

View file

@ -35,8 +35,8 @@ remove_sessions (GstRTSPServer * server)
g_print ("removing all sessions\n");
pool = gst_rtsp_server_get_session_pool (server);
gst_rtsp_session_pool_filter (pool, (GstRTSPSessionFilterFunc) remove_func,
server);
gst_rtsp_session_pool_filter (pool,
(GstRTSPSessionPoolFilterFunc) remove_func, server);
g_object_unref (pool);
return FALSE;

View file

@ -21,6 +21,16 @@
#include "rtsp-auth.h"
#define GST_RTSP_AUTH_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuthPrivate))
struct _GstRTSPAuthPrivate
{
GMutex lock;
gchar *basic;
GstRTSPMethod methods;
};
enum
{
PROP_0,
@ -48,6 +58,8 @@ gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPAuthPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gst_rtsp_auth_get_property;
@ -63,9 +75,11 @@ gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
static void
gst_rtsp_auth_init (GstRTSPAuth * auth)
{
g_mutex_init (&auth->lock);
auth->priv = GST_RTSP_AUTH_GET_PRIVATE (auth);
g_mutex_init (&auth->priv->lock);
/* bitwise or of all methods that need authentication */
auth->methods = GST_RTSP_DESCRIBE |
auth->priv->methods = GST_RTSP_DESCRIBE |
GST_RTSP_ANNOUNCE |
GST_RTSP_GET_PARAMETER |
GST_RTSP_SET_PARAMETER |
@ -77,10 +91,11 @@ static void
gst_rtsp_auth_finalize (GObject * obj)
{
GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
GstRTSPAuthPrivate *priv = auth->priv;
GST_INFO ("finalize auth %p", auth);
g_free (auth->basic);
g_mutex_clear (&auth->lock);
g_free (priv->basic);
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
}
@ -132,12 +147,16 @@ gst_rtsp_auth_new (void)
void
gst_rtsp_auth_set_basic (GstRTSPAuth * auth, const gchar * basic)
{
GstRTSPAuthPrivate *priv;
g_return_if_fail (GST_IS_RTSP_AUTH (auth));
g_mutex_lock (&auth->lock);
g_free (auth->basic);
auth->basic = g_strdup (basic);
g_mutex_unlock (&auth->lock);
priv = auth->priv;
g_mutex_lock (&priv->lock);
g_free (priv->basic);
priv->basic = g_strdup (basic);
g_mutex_unlock (&priv->lock);
}
static gboolean
@ -190,10 +209,11 @@ static gboolean
default_check_method (GstRTSPAuth * auth, GstRTSPClient * client,
GQuark hint, GstRTSPClientState * state)
{
GstRTSPAuthPrivate *priv = auth->priv;
gboolean result = TRUE;
GstRTSPResult res;
if ((state->method & auth->methods) != 0) {
if ((state->method & priv->methods) != 0) {
gchar *authorization;
result = FALSE;
@ -207,10 +227,10 @@ default_check_method (GstRTSPAuth * auth, GstRTSPClient * client,
/* parse type */
if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) {
GST_DEBUG_OBJECT (auth, "check Basic auth");
g_mutex_lock (&auth->lock);
if (auth->basic && strcmp (&authorization[6], auth->basic) == 0)
g_mutex_lock (&priv->lock);
if (priv->basic && strcmp (&authorization[6], priv->basic) == 0)
result = TRUE;
g_mutex_unlock (&auth->lock);
g_mutex_unlock (&priv->lock);
} else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) {
GST_DEBUG_OBJECT (auth, "check Digest auth");
/* not implemented yet */

View file

@ -24,6 +24,7 @@
typedef struct _GstRTSPAuth GstRTSPAuth;
typedef struct _GstRTSPAuthClass GstRTSPAuthClass;
typedef struct _GstRTSPAuthPrivate GstRTSPAuthPrivate;
#include "rtsp-client.h"
@ -46,10 +47,7 @@ G_BEGIN_DECLS
struct _GstRTSPAuth {
GObject parent;
/*< private >*/
GMutex lock;
gchar *basic;
GstRTSPMethod methods;
GstRTSPAuthPrivate *priv;
};
struct _GstRTSPAuthClass {

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@ G_BEGIN_DECLS
typedef struct _GstRTSPClient GstRTSPClient;
typedef struct _GstRTSPClientClass GstRTSPClientClass;
typedef struct _GstRTSPClientState GstRTSPClientState;
typedef struct _GstRTSPClientPrivate GstRTSPClientPrivate;
#include "rtsp-media.h"
#include "rtsp-mount-points.h"
@ -90,51 +91,13 @@ typedef gboolean (*GstRTSPClientSendFunc) (GstRTSPClient *client,
/**
* GstRTSPClient:
* @lock: lock protecting the client object
* @connection: the connection object handling the client request.
* @watch: watch for the connection
* @close_seq: sequence number of message with close header
* @server_ip: ip address of the server
* @is_ipv6: if we are IPv6
* @use_client_settings: whether to allow client transport settings for multicast
* @send_func: a #GstRTSPClientSendFunc called when an RTSP message needs to be
* sent to the client.
* @send_data: user data passed to @send_func
* @send_notify: notify called when @send_data is no longer used.
* @session_pool: handle to the session pool used by the client.
* @mount_points: handle to the mount points used by the client.
* @auth: authorization object
* @uri: cached uri
* @media: cached media
* @transports: a list of #GstRTSPStreamTransport using @connection.
* @sessions: a list of sessions managed by @connection.
*
* The client structure.
*/
struct _GstRTSPClient {
GObject parent;
GMutex lock;
GstRTSPConnection *connection;
GstRTSPWatch *watch;
guint close_seq;
gchar *server_ip;
gboolean is_ipv6;
gboolean use_client_settings;
GstRTSPClientSendFunc send_func;
gpointer send_data;
GDestroyNotify send_notify;
GstRTSPSessionPool *session_pool;
GstRTSPMountPoints *mount_points;
GstRTSPAuth *auth;
GstRTSPUrl *uri;
GstRTSPMedia *media;
GList *transports;
GList *sessions;
GstRTSPClientPrivate *priv;
};
struct _GstRTSPClientClass {

View file

@ -21,6 +21,22 @@
#include "rtsp-media-factory-uri.h"
#define GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_URI, GstRTSPMediaFactoryURIPrivate))
struct _GstRTSPMediaFactoryURIPrivate
{
GMutex lock;
gchar *uri;
gboolean use_gstpay;
GstCaps *raw_vcaps;
GstCaps *raw_acaps;
GList *demuxers;
GList *payloaders;
GList *decoders;
};
#define DEFAULT_URI NULL
#define DEFAULT_USE_GSTPAY FALSE
@ -156,41 +172,48 @@ payloader_filter (GstPluginFeature * feature, FilterData * data)
static void
gst_rtsp_media_factory_uri_init (GstRTSPMediaFactoryURI * factory)
{
GstRTSPMediaFactoryURIPrivate *priv =
GST_RTSP_MEDIA_FACTORY_URI_GET_PRIVATE (factory);
FilterData data = { NULL, NULL, NULL };
GST_DEBUG_OBJECT (factory, "new");
factory->uri = g_strdup (DEFAULT_URI);
factory->use_gstpay = DEFAULT_USE_GSTPAY;
factory->priv = priv;
priv->uri = g_strdup (DEFAULT_URI);
priv->use_gstpay = DEFAULT_USE_GSTPAY;
g_mutex_init (&priv->lock);
/* get the feature list using the filter */
gst_registry_feature_filter (gst_registry_get (), (GstPluginFeatureFilter)
payloader_filter, FALSE, &data);
/* sort */
factory->demuxers =
priv->demuxers =
g_list_sort (data.demux, gst_plugin_feature_rank_compare_func);
factory->payloaders =
priv->payloaders =
g_list_sort (data.payload, gst_plugin_feature_rank_compare_func);
factory->decoders =
priv->decoders =
g_list_sort (data.decode, gst_plugin_feature_rank_compare_func);
factory->raw_vcaps = gst_static_caps_get (&raw_video_caps);
factory->raw_acaps = gst_static_caps_get (&raw_audio_caps);
priv->raw_vcaps = gst_static_caps_get (&raw_video_caps);
priv->raw_acaps = gst_static_caps_get (&raw_audio_caps);
}
static void
gst_rtsp_media_factory_uri_finalize (GObject * obj)
{
GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (obj);
GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
GST_DEBUG_OBJECT (factory, "finalize");
g_free (factory->uri);
gst_plugin_feature_list_free (factory->demuxers);
gst_plugin_feature_list_free (factory->payloaders);
gst_plugin_feature_list_free (factory->decoders);
gst_caps_unref (factory->raw_vcaps);
gst_caps_unref (factory->raw_acaps);
g_free (priv->uri);
gst_plugin_feature_list_free (priv->demuxers);
gst_plugin_feature_list_free (priv->payloaders);
gst_plugin_feature_list_free (priv->decoders);
gst_caps_unref (priv->raw_vcaps);
gst_caps_unref (priv->raw_acaps);
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_rtsp_media_factory_uri_parent_class)->finalize (obj);
}
@ -200,13 +223,14 @@ gst_rtsp_media_factory_uri_get_property (GObject * object, guint propid,
GValue * value, GParamSpec * pspec)
{
GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object);
GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
switch (propid) {
case PROP_URI:
g_value_take_string (value, gst_rtsp_media_factory_uri_get_uri (factory));
break;
case PROP_USE_GSTPAY:
g_value_set_boolean (value, factory->use_gstpay);
g_value_set_boolean (value, priv->use_gstpay);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
@ -218,13 +242,14 @@ gst_rtsp_media_factory_uri_set_property (GObject * object, guint propid,
const GValue * value, GParamSpec * pspec)
{
GstRTSPMediaFactoryURI *factory = GST_RTSP_MEDIA_FACTORY_URI (object);
GstRTSPMediaFactoryURIPrivate *priv = factory->priv;
switch (propid) {
case PROP_URI:
gst_rtsp_media_factory_uri_set_uri (factory, g_value_get_string (value));
break;
case PROP_USE_GSTPAY:
factory->use_gstpay = g_value_get_boolean (value);
priv->use_gstpay = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
@ -259,13 +284,17 @@ void
gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI * factory,
const gchar * uri)
{
GstRTSPMediaFactoryURIPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory));
g_return_if_fail (uri != NULL);
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
g_free (factory->uri);
factory->uri = g_strdup (uri);
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
priv = factory->priv;
g_mutex_lock (&priv->lock);
g_free (priv->uri);
priv->uri = g_strdup (uri);
g_mutex_unlock (&priv->lock);
}
/**
@ -279,13 +308,16 @@ gst_rtsp_media_factory_uri_set_uri (GstRTSPMediaFactoryURI * factory,
gchar *
gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI * factory)
{
GstRTSPMediaFactoryURIPrivate *priv;
gchar *result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY_URI (factory), NULL);
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
result = g_strdup (factory->uri);
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
priv = factory->priv;
g_mutex_lock (&priv->lock);
result = g_strdup (priv->uri);
g_mutex_unlock (&priv->lock);
return result;
}
@ -293,12 +325,13 @@ gst_rtsp_media_factory_uri_get_uri (GstRTSPMediaFactoryURI * factory)
static GstElementFactory *
find_payloader (GstRTSPMediaFactoryURI * urifact, GstCaps * caps)
{
GstRTSPMediaFactoryURIPrivate *priv = urifact->priv;
GList *list;
GstElementFactory *factory = NULL;
gboolean autoplug_more = FALSE;
/* first find a demuxer that can link */
list = gst_element_factory_list_filter (urifact->demuxers, caps,
list = gst_element_factory_list_filter (priv->demuxers, caps,
GST_PAD_SINK, FALSE);
if (list) {
@ -340,17 +373,17 @@ find_payloader (GstRTSPMediaFactoryURI * urifact, GstCaps * caps)
return NULL;
/* no demuxer try a depayloader */
list = gst_element_factory_list_filter (urifact->payloaders, caps,
list = gst_element_factory_list_filter (priv->payloaders, caps,
GST_PAD_SINK, FALSE);
if (list == NULL) {
if (urifact->use_gstpay) {
if (priv->use_gstpay) {
/* no depayloader or parser/demuxer, use gstpay when allowed */
factory = gst_element_factory_find ("rtpgstpay");
} else {
/* no depayloader, try a decoder, we'll get to a payloader for a decoded
* video or audio format, worst case. */
list = gst_element_factory_list_filter (urifact->decoders, caps,
list = gst_element_factory_list_filter (priv->decoders, caps,
GST_PAD_SINK, FALSE);
if (list != NULL) {
@ -405,6 +438,7 @@ static void
pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element)
{
GstRTSPMediaFactoryURI *urifact;
GstRTSPMediaFactoryURIPrivate *priv;
FactoryData *data;
GstElementFactory *factory;
GstElement *payloader;
@ -418,6 +452,7 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element)
/* link the element now and expose the pad */
data = g_object_get_data (G_OBJECT (element), factory_key);
urifact = data->factory;
priv = urifact->priv;
/* ref to make refcounting easier later */
gst_object_ref (pad);
@ -429,10 +464,10 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element)
goto no_caps;
/* check for raw caps */
if (gst_caps_can_intersect (caps, urifact->raw_vcaps)) {
if (gst_caps_can_intersect (caps, priv->raw_vcaps)) {
/* we have raw video caps, insert converter */
convert = gst_element_factory_make ("videoconvert", NULL);
} else if (gst_caps_can_intersect (caps, urifact->raw_acaps)) {
} else if (gst_caps_can_intersect (caps, priv->raw_acaps)) {
/* we have raw audio caps, insert converter */
convert = gst_element_factory_make ("audioconvert", NULL);
} else {
@ -536,11 +571,13 @@ static GstElement *
rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url)
{
GstRTSPMediaFactoryURIPrivate *priv;
GstElement *topbin, *element, *uribin;
GstRTSPMediaFactoryURI *urifact;
FactoryData *data;
urifact = GST_RTSP_MEDIA_FACTORY_URI_CAST (factory);
priv = urifact->priv;
GST_LOG ("creating element");
@ -555,7 +592,7 @@ rtsp_media_factory_uri_create_element (GstRTSPMediaFactory * factory,
if (uribin == NULL)
goto no_uridecodebin;
g_object_set (uribin, "uri", urifact->uri, NULL);
g_object_set (uribin, "uri", priv->uri, NULL);
/* keep factory data around */
data = g_new0 (FactoryData, 1);

View file

@ -38,24 +38,17 @@ G_BEGIN_DECLS
typedef struct _GstRTSPMediaFactoryURI GstRTSPMediaFactoryURI;
typedef struct _GstRTSPMediaFactoryURIClass GstRTSPMediaFactoryURIClass;
typedef struct _GstRTSPMediaFactoryURIPrivate GstRTSPMediaFactoryURIPrivate;
/**
* GstRTSPMediaFactoryURI:
* @uri: the uri
*
* A media factory that creates a pipeline to play and uri.
*/
struct _GstRTSPMediaFactoryURI {
GstRTSPMediaFactory parent;
gchar *uri;
gboolean use_gstpay;
GstCaps *raw_vcaps;
GstCaps *raw_acaps;
GList *demuxers;
GList *payloaders;
GList *decoders;
GstRTSPMediaFactoryURIPrivate *priv;
};
/**

View file

@ -19,6 +19,28 @@
#include "rtsp-media-factory.h"
#define GST_RTSP_MEDIA_FACTORY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY, GstRTSPMediaFactoryPrivate))
#define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f) (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->priv->lock))
#define GST_RTSP_MEDIA_FACTORY_LOCK(f) (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
#define GST_RTSP_MEDIA_FACTORY_UNLOCK(f) (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
struct _GstRTSPMediaFactoryPrivate
{
GMutex lock;
gchar *launch;
gboolean shared;
gboolean eos_shutdown;
GstRTSPLowerTrans protocols;
GstRTSPAuth *auth;
guint buffer_size;
GstRTSPAddressPool *pool;
GMutex medias_lock;
GHashTable *medias;
};
#define DEFAULT_LAUNCH NULL
#define DEFAULT_SHARED FALSE
#define DEFAULT_EOS_SHUTDOWN FALSE
@ -72,6 +94,8 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gst_rtsp_media_factory_get_property;
@ -144,15 +168,19 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
static void
gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
{
factory->launch = g_strdup (DEFAULT_LAUNCH);
factory->shared = DEFAULT_SHARED;
factory->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
factory->protocols = DEFAULT_PROTOCOLS;
factory->buffer_size = DEFAULT_BUFFER_SIZE;
GstRTSPMediaFactoryPrivate *priv =
GST_RTSP_MEDIA_FACTORY_GET_PRIVATE (factory);
factory->priv = priv;
g_mutex_init (&factory->lock);
g_mutex_init (&factory->medias_lock);
factory->medias = g_hash_table_new_full (g_str_hash, g_str_equal,
priv->launch = g_strdup (DEFAULT_LAUNCH);
priv->shared = DEFAULT_SHARED;
priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
priv->protocols = DEFAULT_PROTOCOLS;
priv->buffer_size = DEFAULT_BUFFER_SIZE;
g_mutex_init (&priv->lock);
g_mutex_init (&priv->medias_lock);
priv->medias = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
}
@ -160,15 +188,16 @@ static void
gst_rtsp_media_factory_finalize (GObject * obj)
{
GstRTSPMediaFactory *factory = GST_RTSP_MEDIA_FACTORY (obj);
GstRTSPMediaFactoryPrivate *priv = factory->priv;
g_hash_table_unref (factory->medias);
g_mutex_clear (&factory->medias_lock);
g_free (factory->launch);
g_mutex_clear (&factory->lock);
if (factory->auth)
g_object_unref (factory->auth);
if (factory->pool)
g_object_unref (factory->pool);
g_hash_table_unref (priv->medias);
g_mutex_clear (&priv->medias_lock);
g_free (priv->launch);
g_mutex_clear (&priv->lock);
if (priv->auth)
g_object_unref (priv->auth);
if (priv->pool)
g_object_unref (priv->pool);
G_OBJECT_CLASS (gst_rtsp_media_factory_parent_class)->finalize (obj);
}
@ -268,12 +297,16 @@ void
gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory,
const gchar * launch)
{
GstRTSPMediaFactoryPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
g_return_if_fail (launch != NULL);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
g_free (factory->launch);
factory->launch = g_strdup (launch);
g_free (priv->launch);
priv->launch = g_strdup (launch);
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
}
@ -289,12 +322,15 @@ gst_rtsp_media_factory_set_launch (GstRTSPMediaFactory * factory,
gchar *
gst_rtsp_media_factory_get_launch (GstRTSPMediaFactory * factory)
{
GstRTSPMediaFactoryPrivate *priv;
gchar *result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
result = g_strdup (factory->launch);
result = g_strdup (priv->launch);
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
return result;
@ -311,10 +347,14 @@ void
gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory,
gboolean shared)
{
GstRTSPMediaFactoryPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
factory->shared = shared;
priv->shared = shared;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
}
@ -329,12 +369,15 @@ gst_rtsp_media_factory_set_shared (GstRTSPMediaFactory * factory,
gboolean
gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory * factory)
{
GstRTSPMediaFactoryPrivate *priv;
gboolean result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
result = factory->shared;
result = priv->shared;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
return result;
@ -352,10 +395,14 @@ void
gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory,
gboolean eos_shutdown)
{
GstRTSPMediaFactoryPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
factory->eos_shutdown = eos_shutdown;
priv->eos_shutdown = eos_shutdown;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
}
@ -371,12 +418,15 @@ gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory * factory,
gboolean
gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory * factory)
{
GstRTSPMediaFactoryPrivate *priv;
gboolean result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
result = factory->eos_shutdown;
result = priv->eos_shutdown;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
return result;
@ -393,10 +443,14 @@ void
gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory,
guint size)
{
GstRTSPMediaFactoryPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
factory->buffer_size = size;
priv->buffer_size = size;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
}
@ -411,12 +465,15 @@ gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFactory * factory,
guint
gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory)
{
GstRTSPMediaFactoryPrivate *priv;
guint result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
result = factory->buffer_size;
result = priv->buffer_size;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
return result;
@ -433,13 +490,16 @@ void
gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory,
GstRTSPAddressPool * pool)
{
GstRTSPMediaFactoryPrivate *priv;
GstRTSPAddressPool *old;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
if ((old = factory->pool) != pool)
factory->pool = pool ? g_object_ref (pool) : NULL;
if ((old = priv->pool) != pool)
priv->pool = pool ? g_object_ref (pool) : NULL;
else
old = NULL;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
@ -460,12 +520,15 @@ gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory,
GstRTSPAddressPool *
gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory)
{
GstRTSPMediaFactoryPrivate *priv;
GstRTSPAddressPool *result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
if ((result = factory->pool))
if ((result = priv->pool))
g_object_ref (result);
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
@ -483,13 +546,16 @@ void
gst_rtsp_media_factory_set_auth (GstRTSPMediaFactory * factory,
GstRTSPAuth * auth)
{
GstRTSPMediaFactoryPrivate *priv;
GstRTSPAuth *old;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
if ((old = factory->auth) != auth)
factory->auth = auth ? g_object_ref (auth) : NULL;
if ((old = priv->auth) != auth)
priv->auth = auth ? g_object_ref (auth) : NULL;
else
old = NULL;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
@ -510,12 +576,15 @@ gst_rtsp_media_factory_set_auth (GstRTSPMediaFactory * factory,
GstRTSPAuth *
gst_rtsp_media_factory_get_auth (GstRTSPMediaFactory * factory)
{
GstRTSPMediaFactoryPrivate *priv;
GstRTSPAuth *result;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
if ((result = factory->auth))
if ((result = priv->auth))
g_object_ref (result);
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
@ -533,10 +602,14 @@ void
gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory,
GstRTSPLowerTrans protocols)
{
GstRTSPMediaFactoryPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
factory->protocols = protocols;
priv->protocols = protocols;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
}
@ -551,13 +624,16 @@ gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory * factory,
GstRTSPLowerTrans
gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory * factory)
{
GstRTSPMediaFactoryPrivate *priv;
GstRTSPLowerTrans res;
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory),
GST_RTSP_LOWER_TRANS_UNKNOWN);
priv = factory->priv;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
res = factory->protocols;
res = priv->protocols;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
return res;
@ -572,9 +648,11 @@ compare_media (gpointer key, GstRTSPMedia * media1, GstRTSPMedia * media2)
static void
media_unprepared (GstRTSPMedia * media, GstRTSPMediaFactory * factory)
{
g_mutex_lock (&factory->medias_lock);
g_hash_table_foreach_remove (factory->medias, (GHRFunc) compare_media, media);
g_mutex_unlock (&factory->medias_lock);
GstRTSPMediaFactoryPrivate *priv = factory->priv;;
g_mutex_lock (&priv->medias_lock);
g_hash_table_foreach_remove (priv->medias, (GHRFunc) compare_media, media);
g_mutex_unlock (&priv->medias_lock);
}
/**
@ -598,6 +676,7 @@ GstRTSPMedia *
gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url)
{
GstRTSPMediaFactoryPrivate *priv;
gchar *key;
GstRTSPMedia *media;
GstRTSPMediaFactoryClass *klass;
@ -605,6 +684,7 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL);
g_return_val_if_fail (url != NULL, NULL);
priv = factory->priv;;
klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
/* convert the url to a key for the hashtable. NULL return or a NULL function
@ -614,10 +694,10 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
else
key = NULL;
g_mutex_lock (&factory->medias_lock);
g_mutex_lock (&priv->medias_lock);
if (key) {
/* we have a key, see if we find a cached media */
media = g_hash_table_lookup (factory->medias, key);
media = g_hash_table_lookup (priv->medias, key);
if (media)
g_object_ref (media);
} else
@ -647,7 +727,7 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
if (gst_rtsp_media_is_shared (media)) {
/* insert in the hashtable, takes ownership of the key */
g_object_ref (media);
g_hash_table_insert (factory->medias, key, media);
g_hash_table_insert (priv->medias, key, media);
key = NULL;
}
if (!gst_rtsp_media_is_reusable (media)) {
@ -658,7 +738,7 @@ gst_rtsp_media_factory_construct (GstRTSPMediaFactory * factory,
}
}
}
g_mutex_unlock (&factory->medias_lock);
g_mutex_unlock (&priv->medias_lock);
if (key)
g_free (key);
@ -687,16 +767,17 @@ default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
static GstElement *
default_create_element (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
{
GstRTSPMediaFactoryPrivate *priv = factory->priv;
GstElement *element;
GError *error = NULL;
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
/* we need a parse syntax */
if (factory->launch == NULL)
if (priv->launch == NULL)
goto no_launch;
/* parse the user provided launch line */
element = gst_parse_launch (factory->launch, &error);
element = gst_parse_launch (priv->launch, &error);
if (element == NULL)
goto parse_error;
@ -719,7 +800,7 @@ no_launch:
parse_error:
{
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
g_critical ("could not parse launch syntax (%s): %s", factory->launch,
g_critical ("could not parse launch syntax (%s): %s", priv->launch,
(error ? error->message : "unknown reason"));
if (error)
g_error_free (error);
@ -731,7 +812,7 @@ static GstRTSPMedia *
default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
{
GstRTSPMedia *media;
GstElement *element;
GstElement *element, *pipeline;
GstRTSPMediaFactoryClass *klass;
klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
@ -744,13 +825,12 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
goto no_element;
/* create a new empty media */
media = gst_rtsp_media_new ();
media->element = element;
media = gst_rtsp_media_new (element);
gst_rtsp_media_collect_streams (media);
media->pipeline = klass->create_pipeline (factory, media);
if (media->pipeline == NULL)
pipeline = klass->create_pipeline (factory, media);
if (pipeline == NULL)
goto no_pipeline;
return media;
@ -779,25 +859,16 @@ default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
{
GstElement *pipeline;
if (media->element == NULL)
goto no_element;
pipeline = gst_pipeline_new ("media-pipeline");
gst_bin_add (GST_BIN_CAST (pipeline), media->element);
gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
return pipeline;
/* ERRORS */
no_element:
{
g_critical ("no element");
return NULL;
}
}
static void
default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
{
GstRTSPMediaFactoryPrivate *priv = factory->priv;
gboolean shared, eos_shutdown;
guint size;
GstRTSPAuth *auth;
@ -806,10 +877,10 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
/* configure the sharedness */
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
shared = factory->shared;
eos_shutdown = factory->eos_shutdown;
size = factory->buffer_size;
protocols = factory->protocols;
shared = priv->shared;
eos_shutdown = priv->eos_shutdown;
size = priv->buffer_size;
protocols = priv->protocols;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
gst_rtsp_media_set_shared (media, shared);

View file

@ -41,24 +41,11 @@ G_BEGIN_DECLS
typedef struct _GstRTSPMediaFactory GstRTSPMediaFactory;
typedef struct _GstRTSPMediaFactoryClass GstRTSPMediaFactoryClass;
#define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f) (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->lock))
#define GST_RTSP_MEDIA_FACTORY_LOCK(f) (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
#define GST_RTSP_MEDIA_FACTORY_UNLOCK(f) (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_GET_LOCK(f)))
typedef struct _GstRTSPMediaFactoryPrivate GstRTSPMediaFactoryPrivate;
/**
* GstRTSPMediaFactory:
* @parent: the parent GObject
* @lock: mutex protecting the datastructure.
* @launch: the launch description
* @shared: if media from this factory can be shared between clients
* @eos_shutdown: if shutdown should first send EOS to the pipeline
* @protocols: allowed transport protocols
* @auth: the authentication manager
* @buffer_size: the kernel udp buffer size
* @pool: the multicast address pool to use
* @medias_lock: mutex protecting the medias.
* @medias: hashtable of shared media
*
* The definition and logic for constructing the pipeline for a media. The media
* can contain multiple streams like audio and video.
@ -66,17 +53,7 @@ typedef struct _GstRTSPMediaFactoryClass GstRTSPMediaFactoryClass;
struct _GstRTSPMediaFactory {
GObject parent;
GMutex lock;
gchar *launch;
gboolean shared;
gboolean eos_shutdown;
GstRTSPLowerTrans protocols;
GstRTSPAuth *auth;
guint buffer_size;
GstRTSPAddressPool *pool;
GMutex medias_lock;
GHashTable *medias;
GstRTSPMediaFactoryPrivate *priv;
};
/**

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,7 @@ G_BEGIN_DECLS
typedef struct _GstRTSPMedia GstRTSPMedia;
typedef struct _GstRTSPMediaClass GstRTSPMediaClass;
typedef struct _GstRTSPMediaPrivate GstRTSPMediaPrivate;
#include "rtsp-stream.h"
#include "rtsp-auth.h"
@ -64,36 +65,6 @@ typedef enum {
/**
* GstRTSPMedia:
* @parent: parent GObject
* @lock: for protecting the object
* @cond: for signaling the object
* @shared: if this media can be shared between clients
* @reusable: if this media can be reused after an unprepare
* @protocols: the allowed lower transport for this stream
* @reused: if this media has been reused
* @is_ipv6: if this media is using ipv6
* @eos_shutdown: if EOS should be sent on shutdown
* @buffer_size: The UDP buffer size
* @auth: the authentication service in use
* @multicast_group: the multicast group to use
* @element: the data providing element, owned by @pipeline
* @streams: the different #GstRTSPStream provided by @element
* @dynamic: list of dynamic elements managed by @element
* @status: the status of the media pipeline
* @n_active: the number of active connections
* @adding: when elements are added to the pipeline
* @pipeline: the toplevel pipeline
* @fakesink: for making state changes async
* @source: the bus watch for pipeline messages.
* @id: the id of the watch
* @is_live: if the pipeline is live
* @seekable: if the pipeline can perform a seek
* @buffering: if the pipeline is buffering
* @target_state: the desired target state of the pipeline
* @rtpbin: the rtpbin
* @range: the range of the media being streamed
* @range_start: range start in #GstClockTime
* @range_stop: range stop in #GstClockTime
*
* A class that contains the GStreamer element along with a list of
* #GstRTSPStream objects that can produce data.
@ -103,45 +74,7 @@ typedef enum {
struct _GstRTSPMedia {
GObject parent;
GMutex lock;
GCond cond;
gboolean shared;
gboolean reusable;
GstRTSPLowerTrans protocols;
gboolean reused;
gboolean is_ipv6;
gboolean eos_shutdown;
guint buffer_size;
GstRTSPAuth *auth;
GstRTSPAddressPool*pool;
GstElement *element;
GRecMutex state_lock;
GPtrArray *streams;
GList *dynamic;
GstRTSPMediaStatus status;
gint n_active;
gboolean adding;
/* the pipeline for the media */
GstElement *pipeline;
GstElement *fakesink;
GSource *source;
guint id;
gboolean is_live;
gboolean seekable;
gboolean buffering;
GstState target_state;
/* RTP session manager */
GstElement *rtpbin;
/* the range of media */
GstRTSPTimeRange range;
GstClockTime range_start;
GstClockTime range_stop;
GstRTSPMediaPrivate *priv;
};
/**
@ -179,7 +112,11 @@ struct _GstRTSPMediaClass {
GType gst_rtsp_media_get_type (void);
/* creating the media */
GstRTSPMedia * gst_rtsp_media_new (void);
GstRTSPMedia * gst_rtsp_media_new (GstElement *element);
void gst_rtsp_media_take_pipeline (GstRTSPMedia *media, GstPipeline *pipeline);
GstRTSPMediaStatus gst_rtsp_media_get_status (GstRTSPMedia *media);
void gst_rtsp_media_set_shared (GstRTSPMedia *media, gboolean shared);
gboolean gst_rtsp_media_is_shared (GstRTSPMedia *media);

View file

@ -19,6 +19,15 @@
#include "rtsp-mount-points.h"
#define GST_RTSP_MOUNT_POINTS_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MOUNT_POINTS, GstRTSPMountPointsPrivate))
struct _GstRTSPMountPointsPrivate
{
GMutex lock;
GHashTable *mounts;
};
G_DEFINE_TYPE (GstRTSPMountPoints, gst_rtsp_mount_points, G_TYPE_OBJECT);
GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
@ -34,6 +43,8 @@ gst_rtsp_mount_points_class_init (GstRTSPMountPointsClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPMountPointsPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gst_rtsp_mount_points_finalize;
@ -47,10 +58,14 @@ gst_rtsp_mount_points_class_init (GstRTSPMountPointsClass * klass)
static void
gst_rtsp_mount_points_init (GstRTSPMountPoints * mounts)
{
GstRTSPMountPointsPrivate *priv = GST_RTSP_MOUNT_POINTS_GET_PRIVATE (mounts);
GST_DEBUG_OBJECT (mounts, "created");
g_mutex_init (&mounts->lock);
mounts->mounts = g_hash_table_new_full (g_str_hash, g_str_equal,
mounts->priv = priv;
g_mutex_init (&priv->lock);
priv->mounts = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
}
@ -58,11 +73,12 @@ static void
gst_rtsp_mount_points_finalize (GObject * obj)
{
GstRTSPMountPoints *mounts = GST_RTSP_MOUNT_POINTS (obj);
GstRTSPMountPointsPrivate *priv = mounts->priv;
GST_DEBUG_OBJECT (mounts, "finalized");
g_hash_table_unref (mounts->mounts);
g_mutex_clear (&mounts->lock);
g_hash_table_unref (priv->mounts);
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_rtsp_mount_points_parent_class)->finalize (obj);
}
@ -87,16 +103,17 @@ gst_rtsp_mount_points_new (void)
static GstRTSPMediaFactory *
find_factory (GstRTSPMountPoints * mounts, const GstRTSPUrl * url)
{
GstRTSPMountPointsPrivate *priv = mounts->priv;
GstRTSPMediaFactory *result;
g_mutex_lock (&mounts->lock);
g_mutex_lock (&priv->lock);
/* find the location of the media in the hashtable we only use the absolute
* path of the uri to find a media factory. If the factory depends on other
* properties found in the url, this method should be overridden. */
result = g_hash_table_lookup (mounts->mounts, url->abspath);
result = g_hash_table_lookup (priv->mounts, url->abspath);
if (result)
g_object_ref (result);
g_mutex_unlock (&mounts->lock);
g_mutex_unlock (&priv->lock);
GST_INFO ("found media factory %p for url abspath %s", result, url->abspath);
@ -150,13 +167,17 @@ void
gst_rtsp_mount_points_add_factory (GstRTSPMountPoints * mounts,
const gchar * path, GstRTSPMediaFactory * factory)
{
GstRTSPMountPointsPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts));
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
g_return_if_fail (path != NULL);
g_mutex_lock (&mounts->lock);
g_hash_table_insert (mounts->mounts, g_strdup (path), factory);
g_mutex_unlock (&mounts->lock);
priv = mounts->priv;
g_mutex_lock (&priv->lock);
g_hash_table_insert (priv->mounts, g_strdup (path), factory);
g_mutex_unlock (&priv->lock);
}
/**
@ -170,10 +191,14 @@ void
gst_rtsp_mount_points_remove_factory (GstRTSPMountPoints * mounts,
const gchar * path)
{
GstRTSPMountPointsPrivate *priv;
g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts));
g_return_if_fail (path != NULL);
g_mutex_lock (&mounts->lock);
g_hash_table_remove (mounts->mounts, path);
g_mutex_unlock (&mounts->lock);
priv = mounts->priv;
g_mutex_lock (&priv->lock);
g_hash_table_remove (priv->mounts, path);
g_mutex_unlock (&priv->lock);
}

View file

@ -39,6 +39,7 @@ G_BEGIN_DECLS
typedef struct _GstRTSPMountPoints GstRTSPMountPoints;
typedef struct _GstRTSPMountPointsClass GstRTSPMountPointsClass;
typedef struct _GstRTSPMountPointsPrivate GstRTSPMountPointsPrivate;
/**
* GstRTSPMountPoints:
@ -50,8 +51,7 @@ typedef struct _GstRTSPMountPointsClass GstRTSPMountPointsClass;
struct _GstRTSPMountPoints {
GObject parent;
GMutex lock;
GHashTable *mounts;
GstRTSPMountPointsPrivate *priv;
};
/**

View file

@ -38,12 +38,12 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
guint i, n_streams;
gchar *rangestr;
if (media->status != GST_RTSP_MEDIA_STATUS_PREPARED)
goto not_prepared;
n_streams = gst_rtsp_media_n_streams (media);
rangestr = gst_rtsp_media_get_range_string (media, FALSE);
if (rangestr == NULL)
goto not_prepared;
gst_sdp_message_add_attribute (sdp, "range", rangestr);
g_free (rangestr);
@ -57,16 +57,19 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
guint n_fields, j;
gboolean first;
GString *fmtp;
GstCaps *caps;
stream = gst_rtsp_media_get_stream (media, i);
caps = gst_rtsp_stream_get_caps (stream);
if (stream->caps == NULL) {
if (caps == NULL) {
g_warning ("ignoring stream %d without media type", i);
continue;
}
s = gst_caps_get_structure (stream->caps, 0);
s = gst_caps_get_structure (caps, 0);
if (s == NULL) {
gst_caps_unref (caps);
g_warning ("ignoring stream %d without media type", i);
continue;
}
@ -152,6 +155,7 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
}
gst_sdp_message_add_media (sdp, smedia);
gst_sdp_media_free (smedia);
gst_caps_unref (caps);
}
return TRUE;

View file

@ -23,6 +23,38 @@
#include "rtsp-server.h"
#include "rtsp-client.h"
#define GST_RTSP_SERVER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SERVER, GstRTSPServerPrivate))
#define GST_RTSP_SERVER_GET_LOCK(server) (&(GST_RTSP_SERVER_CAST(server)->priv->lock))
#define GST_RTSP_SERVER_LOCK(server) (g_mutex_lock(GST_RTSP_SERVER_GET_LOCK(server)))
#define GST_RTSP_SERVER_UNLOCK(server) (g_mutex_unlock(GST_RTSP_SERVER_GET_LOCK(server)))
struct _GstRTSPServerPrivate
{
GMutex lock;
/* server information */
gchar *address;
gchar *service;
gint backlog;
gint max_threads;
GSocket *socket;
/* sessions on this server */
GstRTSPSessionPool *session_pool;
/* mount points for this server */
GstRTSPMountPoints *mount_points;
/* authentication manager */
GstRTSPAuth *auth;
/* the clients that are connected */
GList *clients;
};
#define DEFAULT_ADDRESS "0.0.0.0"
#define DEFAULT_BOUND_PORT -1
/* #define DEFAULT_ADDRESS "::0" */
@ -80,6 +112,8 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPServerPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gst_rtsp_server_get_property;
@ -185,36 +219,41 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
static void
gst_rtsp_server_init (GstRTSPServer * server)
{
g_mutex_init (&server->lock);
server->address = g_strdup (DEFAULT_ADDRESS);
server->service = g_strdup (DEFAULT_SERVICE);
server->socket = NULL;
server->backlog = DEFAULT_BACKLOG;
server->session_pool = gst_rtsp_session_pool_new ();
server->mount_points = gst_rtsp_mount_points_new ();
server->max_threads = DEFAULT_MAX_THREADS;
GstRTSPServerPrivate *priv = GST_RTSP_SERVER_GET_PRIVATE (server);
server->priv = priv;
g_mutex_init (&priv->lock);
priv->address = g_strdup (DEFAULT_ADDRESS);
priv->service = g_strdup (DEFAULT_SERVICE);
priv->socket = NULL;
priv->backlog = DEFAULT_BACKLOG;
priv->session_pool = gst_rtsp_session_pool_new ();
priv->mount_points = gst_rtsp_mount_points_new ();
priv->max_threads = DEFAULT_MAX_THREADS;
}
static void
gst_rtsp_server_finalize (GObject * object)
{
GstRTSPServer *server = GST_RTSP_SERVER (object);
GstRTSPServerPrivate *priv = server->priv;
GST_DEBUG_OBJECT (server, "finalize server");
g_free (server->address);
g_free (server->service);
g_free (priv->address);
g_free (priv->service);
if (server->socket)
g_object_unref (server->socket);
if (priv->socket)
g_object_unref (priv->socket);
g_object_unref (server->session_pool);
g_object_unref (server->mount_points);
g_object_unref (priv->session_pool);
g_object_unref (priv->mount_points);
if (server->auth)
g_object_unref (server->auth);
if (priv->auth)
g_object_unref (priv->auth);
g_mutex_clear (&server->lock);
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_rtsp_server_parent_class)->finalize (object);
}
@ -246,12 +285,16 @@ gst_rtsp_server_new (void)
void
gst_rtsp_server_set_address (GstRTSPServer * server, const gchar * address)
{
GstRTSPServerPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
g_return_if_fail (address != NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
g_free (server->address);
server->address = g_strdup (address);
g_free (priv->address);
priv->address = g_strdup (address);
GST_RTSP_SERVER_UNLOCK (server);
}
@ -266,11 +309,15 @@ gst_rtsp_server_set_address (GstRTSPServer * server, const gchar * address)
gchar *
gst_rtsp_server_get_address (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
gchar *result;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
result = g_strdup (server->address);
result = g_strdup (priv->address);
GST_RTSP_SERVER_UNLOCK (server);
return result;
@ -287,16 +334,19 @@ gst_rtsp_server_get_address (GstRTSPServer * server)
int
gst_rtsp_server_get_bound_port (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
GSocketAddress *address;
int result = -1;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), result);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
if (server->socket == NULL)
if (priv->socket == NULL)
goto out;
address = g_socket_get_local_address (server->socket, NULL);
address = g_socket_get_local_address (priv->socket, NULL);
result = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
g_object_unref (address);
@ -320,12 +370,16 @@ out:
void
gst_rtsp_server_set_service (GstRTSPServer * server, const gchar * service)
{
GstRTSPServerPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
g_return_if_fail (service != NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
g_free (server->service);
server->service = g_strdup (service);
g_free (priv->service);
priv->service = g_strdup (service);
GST_RTSP_SERVER_UNLOCK (server);
}
@ -340,12 +394,15 @@ gst_rtsp_server_set_service (GstRTSPServer * server, const gchar * service)
gchar *
gst_rtsp_server_get_service (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
gchar *result;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
result = g_strdup (server->service);
result = g_strdup (priv->service);
GST_RTSP_SERVER_UNLOCK (server);
return result;
@ -364,10 +421,14 @@ gst_rtsp_server_get_service (GstRTSPServer * server)
void
gst_rtsp_server_set_backlog (GstRTSPServer * server, gint backlog)
{
GstRTSPServerPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
server->backlog = backlog;
priv->backlog = backlog;
GST_RTSP_SERVER_UNLOCK (server);
}
@ -382,12 +443,15 @@ gst_rtsp_server_set_backlog (GstRTSPServer * server, gint backlog)
gint
gst_rtsp_server_get_backlog (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
gint result;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), -1);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
result = server->backlog;
result = priv->backlog;
GST_RTSP_SERVER_UNLOCK (server);
return result;
@ -404,16 +468,19 @@ void
gst_rtsp_server_set_session_pool (GstRTSPServer * server,
GstRTSPSessionPool * pool)
{
GstRTSPServerPrivate *priv;
GstRTSPSessionPool *old;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
priv = server->priv;
if (pool)
g_object_ref (pool);
GST_RTSP_SERVER_LOCK (server);
old = server->session_pool;
server->session_pool = pool;
old = priv->session_pool;
priv->session_pool = pool;
GST_RTSP_SERVER_UNLOCK (server);
if (old)
@ -432,12 +499,15 @@ gst_rtsp_server_set_session_pool (GstRTSPServer * server,
GstRTSPSessionPool *
gst_rtsp_server_get_session_pool (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
GstRTSPSessionPool *result;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
if ((result = server->session_pool))
if ((result = priv->session_pool))
g_object_ref (result);
GST_RTSP_SERVER_UNLOCK (server);
@ -455,16 +525,19 @@ void
gst_rtsp_server_set_mount_points (GstRTSPServer * server,
GstRTSPMountPoints * mounts)
{
GstRTSPServerPrivate *priv;
GstRTSPMountPoints *old;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
priv = server->priv;
if (mounts)
g_object_ref (mounts);
GST_RTSP_SERVER_LOCK (server);
old = server->mount_points;
server->mount_points = mounts;
old = priv->mount_points;
priv->mount_points = mounts;
GST_RTSP_SERVER_UNLOCK (server);
if (old)
@ -484,12 +557,15 @@ gst_rtsp_server_set_mount_points (GstRTSPServer * server,
GstRTSPMountPoints *
gst_rtsp_server_get_mount_points (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
GstRTSPMountPoints *result;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
if ((result = server->mount_points))
if ((result = priv->mount_points))
g_object_ref (result);
GST_RTSP_SERVER_UNLOCK (server);
@ -506,16 +582,19 @@ gst_rtsp_server_get_mount_points (GstRTSPServer * server)
void
gst_rtsp_server_set_auth (GstRTSPServer * server, GstRTSPAuth * auth)
{
GstRTSPServerPrivate *priv;
GstRTSPAuth *old;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
priv = server->priv;
if (auth)
g_object_ref (auth);
GST_RTSP_SERVER_LOCK (server);
old = server->auth;
server->auth = auth;
old = priv->auth;
priv->auth = auth;
GST_RTSP_SERVER_UNLOCK (server);
if (old)
@ -535,12 +614,15 @@ gst_rtsp_server_set_auth (GstRTSPServer * server, GstRTSPAuth * auth)
GstRTSPAuth *
gst_rtsp_server_get_auth (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
GstRTSPAuth *result;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
if ((result = server->auth))
if ((result = priv->auth))
g_object_ref (result);
GST_RTSP_SERVER_UNLOCK (server);
@ -559,10 +641,14 @@ gst_rtsp_server_get_auth (GstRTSPServer * server)
void
gst_rtsp_server_set_max_threads (GstRTSPServer * server, gint max_threads)
{
GstRTSPServerPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
server->max_threads = max_threads;
priv->max_threads = max_threads;
GST_RTSP_SERVER_UNLOCK (server);
}
@ -578,12 +664,15 @@ gst_rtsp_server_set_max_threads (GstRTSPServer * server, gint max_threads)
gint
gst_rtsp_server_get_max_threads (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
gint res;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), -1);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
res = server->max_threads;
res = priv->max_threads;
GST_RTSP_SERVER_UNLOCK (server);
return res;
@ -668,6 +757,7 @@ GSocket *
gst_rtsp_server_create_socket (GstRTSPServer * server,
GCancellable * cancellable, GError ** error)
{
GstRTSPServerPrivate *priv;
GSocketConnectable *conn;
GSocketAddressEnumerator *enumerator;
GSocket *socket = NULL;
@ -680,16 +770,18 @@ gst_rtsp_server_create_socket (GstRTSPServer * server,
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
GST_DEBUG_OBJECT (server, "getting address info of %s/%s", server->address,
server->service);
GST_DEBUG_OBJECT (server, "getting address info of %s/%s", priv->address,
priv->service);
/* resolve the server IP address */
port = atoi (server->service);
if (port != 0 || !strcmp (server->service, "0"))
conn = g_network_address_new (server->address, port);
port = atoi (priv->service);
if (port != 0 || !strcmp (priv->service, "0"))
conn = g_network_address_new (priv->address, port);
else
conn = g_network_service_new (server->service, "tcp", server->address);
conn = g_network_service_new (priv->service, "tcp", priv->address);
enumerator = g_socket_connectable_enumerate (conn);
g_object_unref (conn);
@ -764,13 +856,13 @@ gst_rtsp_server_create_socket (GstRTSPServer * server,
g_socket_set_blocking (socket, FALSE);
/* set listen backlog */
g_socket_set_listen_backlog (socket, server->backlog);
g_socket_set_listen_backlog (socket, priv->backlog);
if (!g_socket_listen (socket, error))
goto listen_failed;
GST_DEBUG_OBJECT (server, "listening on server socket %p with queue of %d",
socket, server->backlog);
socket, priv->backlog);
GST_RTSP_SERVER_UNLOCK (server);
@ -854,13 +946,14 @@ static void
unmanage_client (GstRTSPClient * client, ClientContext * ctx)
{
GstRTSPServer *server = ctx->server;
GstRTSPServerPrivate *priv = server->priv;
GST_DEBUG_OBJECT (server, "unmanage client %p", client);
g_object_ref (server);
GST_RTSP_SERVER_LOCK (server);
server->clients = g_list_remove (server->clients, ctx);
priv->clients = g_list_remove (priv->clients, ctx);
GST_RTSP_SERVER_UNLOCK (server);
if (ctx->loop)
@ -877,13 +970,14 @@ static void
manage_client (GstRTSPServer * server, GstRTSPClient * client)
{
ClientContext *ctx;
GstRTSPServerPrivate *priv = server->priv;
GST_DEBUG_OBJECT (server, "manage client %p", client);
ctx = g_slice_new0 (ClientContext);
ctx->server = server;
ctx->client = client;
if (server->max_threads == 0) {
if (priv->max_threads == 0) {
GSource *source;
/* find the context to add the watch */
@ -899,7 +993,7 @@ manage_client (GstRTSPServer * server, GstRTSPClient * client)
GST_RTSP_SERVER_LOCK (server);
g_signal_connect (client, "closed", (GCallback) unmanage_client, ctx);
server->clients = g_list_prepend (server->clients, ctx);
priv->clients = g_list_prepend (priv->clients, ctx);
GST_RTSP_SERVER_UNLOCK (server);
if (ctx->loop) {
@ -913,17 +1007,18 @@ static GstRTSPClient *
default_create_client (GstRTSPServer * server)
{
GstRTSPClient *client;
GstRTSPServerPrivate *priv = server->priv;
/* a new client connected, create a session to handle the client. */
client = gst_rtsp_client_new ();
/* set the session pool that this client should use */
GST_RTSP_SERVER_LOCK (server);
gst_rtsp_client_set_session_pool (client, server->session_pool);
gst_rtsp_client_set_session_pool (client, priv->session_pool);
/* set the mount points that this client should use */
gst_rtsp_client_set_mount_points (client, server->mount_points);
gst_rtsp_client_set_mount_points (client, priv->mount_points);
/* set authentication manager */
gst_rtsp_client_set_auth (client, server->auth);
gst_rtsp_client_set_auth (client, priv->auth);
GST_RTSP_SERVER_UNLOCK (server);
return client;
@ -1073,9 +1168,12 @@ accept_failed:
static void
watch_destroyed (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv = server->priv;
GST_DEBUG_OBJECT (server, "source destroyed");
g_object_unref (server->socket);
server->socket = NULL;
g_object_unref (priv->socket);
priv->socket = NULL;
g_object_unref (server);
}
@ -1100,18 +1198,21 @@ GSource *
gst_rtsp_server_create_source (GstRTSPServer * server,
GCancellable * cancellable, GError ** error)
{
GstRTSPServerPrivate *priv;
GSocket *socket, *old;
GSource *source;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
priv = server->priv;
socket = gst_rtsp_server_create_socket (server, NULL, error);
if (socket == NULL)
goto no_socket;
GST_RTSP_SERVER_LOCK (server);
old = server->socket;
server->socket = g_object_ref (socket);
old = priv->socket;
priv->socket = g_object_ref (socket);
GST_RTSP_SERVER_UNLOCK (server);
if (old)

View file

@ -26,6 +26,7 @@ G_BEGIN_DECLS
typedef struct _GstRTSPServer GstRTSPServer;
typedef struct _GstRTSPServerClass GstRTSPServerClass;
typedef struct _GstRTSPServerPrivate GstRTSPServerPrivate;
#include "rtsp-session-pool.h"
#include "rtsp-mount-points.h"
@ -41,10 +42,6 @@ typedef struct _GstRTSPServerClass GstRTSPServerClass;
#define GST_RTSP_SERVER_CAST(obj) ((GstRTSPServer*)(obj))
#define GST_RTSP_SERVER_CLASS_CAST(klass) ((GstRTSPServerClass*)(klass))
#define GST_RTSP_SERVER_GET_LOCK(server) (&(GST_RTSP_SERVER_CAST(server)->lock))
#define GST_RTSP_SERVER_LOCK(server) (g_mutex_lock(GST_RTSP_SERVER_GET_LOCK(server)))
#define GST_RTSP_SERVER_UNLOCK(server) (g_mutex_unlock(GST_RTSP_SERVER_GET_LOCK(server)))
/**
* GstRTSPServer:
*
@ -54,27 +51,7 @@ typedef struct _GstRTSPServerClass GstRTSPServerClass;
struct _GstRTSPServer {
GObject parent;
GMutex lock;
/* server information */
gchar *address;
gchar *service;
gint backlog;
gint max_threads;
GSocket *socket;
/* sessions on this server */
GstRTSPSessionPool *session_pool;
/* mount points for this server */
GstRTSPMountPoints *mount_points;
/* authentication manager */
GstRTSPAuth *auth;
/* the clients that are connected */
GList *clients;
GstRTSPServerPrivate *priv;
};
/**

View file

@ -20,6 +20,20 @@
#include "rtsp-session.h"
#define GST_RTSP_SESSION_MEDIA_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION_MEDIA, GstRTSPSessionMediaPrivate))
struct _GstRTSPSessionMediaPrivate
{
GMutex lock;
GstRTSPUrl *url;
GstRTSPMedia *media;
GstRTSPState state;
guint counter;
GPtrArray *transports;
};
enum
{
PROP_0,
@ -38,6 +52,8 @@ gst_rtsp_session_media_class_init (GstRTSPSessionMediaClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPSessionMediaPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gst_rtsp_session_media_finalize;
@ -49,26 +65,32 @@ gst_rtsp_session_media_class_init (GstRTSPSessionMediaClass * klass)
static void
gst_rtsp_session_media_init (GstRTSPSessionMedia * media)
{
g_mutex_init (&media->lock);
media->state = GST_RTSP_STATE_INIT;
GstRTSPSessionMediaPrivate *priv = GST_RTSP_SESSION_MEDIA_GET_PRIVATE (media);
media->priv = priv;
g_mutex_init (&priv->lock);
priv->state = GST_RTSP_STATE_INIT;
}
static void
gst_rtsp_session_media_finalize (GObject * obj)
{
GstRTSPSessionMedia *media;
GstRTSPSessionMediaPrivate *priv;
media = GST_RTSP_SESSION_MEDIA (obj);
priv = media->priv;
GST_INFO ("free session media %p", media);
gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
g_ptr_array_unref (media->transports);
g_ptr_array_unref (priv->transports);
gst_rtsp_url_free (media->url);
g_object_unref (media->media);
g_mutex_clear (&media->lock);
gst_rtsp_url_free (priv->url);
g_object_unref (priv->media);
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_rtsp_session_media_parent_class)->finalize (obj);
}
@ -95,25 +117,65 @@ free_session_media (gpointer data)
GstRTSPSessionMedia *
gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media)
{
GstRTSPSessionMediaPrivate *priv;
GstRTSPSessionMedia *result;
guint n_streams;
g_return_val_if_fail (url != NULL, NULL);
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
g_return_val_if_fail (media->status == GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
g_return_val_if_fail (gst_rtsp_media_get_status (media) ==
GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
result = g_object_new (GST_TYPE_RTSP_SESSION_MEDIA, NULL);
result->url = gst_rtsp_url_copy ((GstRTSPUrl *) url);
result->media = media;
priv = result->priv;
priv->url = gst_rtsp_url_copy ((GstRTSPUrl *) url);
priv->media = media;
/* prealloc the streams now, filled with NULL */
n_streams = gst_rtsp_media_n_streams (media);
result->transports = g_ptr_array_new_full (n_streams, free_session_media);
g_ptr_array_set_size (result->transports, n_streams);
priv->transports = g_ptr_array_new_full (n_streams, free_session_media);
g_ptr_array_set_size (priv->transports, n_streams);
return result;
}
/**
* gst_rtsp_session_media_matches_url:
* @media: a #GstRTSPSessionMedia
* @url: a #GstRTSPUrl
*
* Check if the url of @media matches @url.
*
* Returns: %TRUE when @url matches the url of @media.
*/
gboolean
gst_rtsp_session_media_matches_url (GstRTSPSessionMedia * media,
const GstRTSPUrl * url)
{
g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
g_return_val_if_fail (url != NULL, FALSE);
return g_str_equal (media->priv->url->abspath, url->abspath);
}
/**
* gst_rtsp_session_media_get_media:
* @media: a #GstRTSPSessionMedia
*
* Get the #GstRTSPMedia that was used when constructing @media
*
* Returns: (transfer none): the #GstRTSPMedia of @media. Remains valid as long
* as @media is valid.
*/
GstRTSPMedia *
gst_rtsp_session_media_get_media (GstRTSPSessionMedia * media)
{
g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
return media->priv->media;
}
/**
* gst_rtsp_session_media_set_transport:
* @media: a #GstRTSPSessionMedia
@ -128,21 +190,26 @@ GstRTSPStreamTransport *
gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
GstRTSPStream * stream, GstRTSPTransport * tr)
{
GstRTSPSessionMediaPrivate *priv;
GstRTSPStreamTransport *result;
guint idx;
g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
g_return_val_if_fail (stream->idx < media->transports->len, NULL);
g_return_val_if_fail (tr != NULL, NULL);
priv = media->priv;
idx = gst_rtsp_stream_get_index (stream);
g_return_val_if_fail (idx < priv->transports->len, NULL);
g_mutex_lock (&media->lock);
result = g_ptr_array_index (media->transports, stream->idx);
g_mutex_lock (&priv->lock);
result = g_ptr_array_index (priv->transports, idx);
if (result == NULL) {
result = gst_rtsp_stream_transport_new (stream, tr);
g_ptr_array_index (media->transports, stream->idx) = result;
g_mutex_unlock (&media->lock);
g_ptr_array_index (priv->transports, idx) = result;
g_mutex_unlock (&priv->lock);
} else {
gst_rtsp_stream_transport_set_transport (result, tr);
g_mutex_unlock (&media->lock);
g_mutex_unlock (&priv->lock);
}
return result;
@ -161,14 +228,16 @@ gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
GstRTSPStreamTransport *
gst_rtsp_session_media_get_transport (GstRTSPSessionMedia * media, guint idx)
{
GstRTSPSessionMediaPrivate *priv;
GstRTSPStreamTransport *result;
g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), NULL);
g_return_val_if_fail (idx < media->transports->len, NULL);
priv = media->priv;
g_return_val_if_fail (idx < priv->transports->len, NULL);
g_mutex_lock (&media->lock);
result = g_ptr_array_index (media->transports, idx);
g_mutex_unlock (&media->lock);
g_mutex_lock (&priv->lock);
result = g_ptr_array_index (priv->transports, idx);
g_mutex_unlock (&priv->lock);
return result;
}
@ -187,12 +256,16 @@ gboolean
gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia * media,
GstRTSPRange * range)
{
GstRTSPSessionMediaPrivate *priv;
g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
g_mutex_lock (&media->lock);
range->min = media->counter++;
range->max = media->counter++;
g_mutex_unlock (&media->lock);
priv = media->priv;
g_mutex_lock (&priv->lock);
range->min = priv->counter++;
range->max = priv->counter++;
g_mutex_unlock (&priv->lock);
return TRUE;
}
@ -209,13 +282,64 @@ gst_rtsp_session_media_alloc_channels (GstRTSPSessionMedia * media,
gboolean
gst_rtsp_session_media_set_state (GstRTSPSessionMedia * media, GstState state)
{
GstRTSPSessionMediaPrivate *priv;
gboolean ret;
g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE);
g_mutex_lock (&media->lock);
ret = gst_rtsp_media_set_state (media->media, state, media->transports);
g_mutex_unlock (&media->lock);
priv = media->priv;
g_mutex_lock (&priv->lock);
ret = gst_rtsp_media_set_state (priv->media, state, priv->transports);
g_mutex_unlock (&priv->lock);
return ret;
}
/**
* gst_rtsp_session_media_set_rtsp_state:
* @media: a #GstRTSPSessionMedia
* @state: a #GstRTSPState
*
* Set the RTSP state of @media to @state.
*/
void
gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia * media,
GstRTSPState state)
{
GstRTSPSessionMediaPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SESSION_MEDIA (media));
priv = media->priv;
g_mutex_lock (&priv->lock);
priv->state = state;
g_mutex_unlock (&priv->lock);
}
/**
* gst_rtsp_session_media_set_rtsp_state:
* @media: a #GstRTSPSessionMedia
*
* Get the current RTSP state of @media.
*
* Returns: the current RTSP state of @media.
*/
GstRTSPState
gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia * media)
{
GstRTSPSessionMediaPrivate *priv;
GstRTSPState ret;
g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media),
GST_RTSP_STATE_INVALID);
priv = media->priv;
g_mutex_lock (&priv->lock);
ret = priv->state;
g_mutex_unlock (&priv->lock);
return ret;
}

View file

@ -37,6 +37,7 @@ G_BEGIN_DECLS
typedef struct _GstRTSPSessionMedia GstRTSPSessionMedia;
typedef struct _GstRTSPSessionMediaClass GstRTSPSessionMediaClass;
typedef struct _GstRTSPSessionMediaPrivate GstRTSPSessionMediaPrivate;
/**
* GstRTSPSessionMedia:
@ -53,13 +54,7 @@ struct _GstRTSPSessionMedia
{
GObject parent;
GMutex lock;
GstRTSPUrl *url;
GstRTSPMedia *media;
GstRTSPState state;
guint counter;
GPtrArray *transports;
GstRTSPSessionMediaPrivate *priv;
};
struct _GstRTSPSessionMediaClass
@ -71,10 +66,20 @@ GType gst_rtsp_session_media_get_type (void);
GstRTSPSessionMedia * gst_rtsp_session_media_new (const GstRTSPUrl *url,
GstRTSPMedia *media);
gboolean gst_rtsp_session_media_matches_url (GstRTSPSessionMedia *media,
const GstRTSPUrl *url);
GstRTSPMedia * gst_rtsp_session_media_get_media (GstRTSPSessionMedia *media);
/* control media */
gboolean gst_rtsp_session_media_set_state (GstRTSPSessionMedia *media,
GstState state);
void gst_rtsp_session_media_set_rtsp_state (GstRTSPSessionMedia *media,
GstRTSPState state);
GstRTSPState gst_rtsp_session_media_get_rtsp_state (GstRTSPSessionMedia *media);
/* get stream transport config */
GstRTSPStreamTransport * gst_rtsp_session_media_set_transport (GstRTSPSessionMedia *media,
GstRTSPStream *stream,

View file

@ -19,6 +19,17 @@
#include "rtsp-session-pool.h"
#define GST_RTSP_SESSION_POOL_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION_POOL, GstRTSPSessionPoolPrivate))
struct _GstRTSPSessionPoolPrivate
{
guint max_sessions;
GMutex lock;
GHashTable *sessions;
};
#define DEFAULT_MAX_SESSIONS 0
enum
@ -54,6 +65,8 @@ gst_rtsp_session_pool_class_init (GstRTSPSessionPoolClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPSessionPoolPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gst_rtsp_session_pool_get_property;
@ -75,19 +88,24 @@ gst_rtsp_session_pool_class_init (GstRTSPSessionPoolClass * klass)
static void
gst_rtsp_session_pool_init (GstRTSPSessionPool * pool)
{
g_mutex_init (&pool->lock);
pool->sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
GstRTSPSessionPoolPrivate *priv = GST_RTSP_SESSION_POOL_GET_PRIVATE (pool);
pool->priv = priv;
g_mutex_init (&priv->lock);
priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, g_object_unref);
pool->max_sessions = DEFAULT_MAX_SESSIONS;
priv->max_sessions = DEFAULT_MAX_SESSIONS;
}
static void
gst_rtsp_session_pool_finalize (GObject * object)
{
GstRTSPSessionPool *pool = GST_RTSP_SESSION_POOL (object);
GstRTSPSessionPoolPrivate *priv = pool->priv;
g_mutex_clear (&pool->lock);
g_hash_table_unref (pool->sessions);
g_mutex_clear (&priv->lock);
g_hash_table_unref (priv->sessions);
G_OBJECT_CLASS (gst_rtsp_session_pool_parent_class)->finalize (object);
}
@ -152,11 +170,15 @@ gst_rtsp_session_pool_new (void)
void
gst_rtsp_session_pool_set_max_sessions (GstRTSPSessionPool * pool, guint max)
{
GstRTSPSessionPoolPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SESSION_POOL (pool));
g_mutex_lock (&pool->lock);
pool->max_sessions = max;
g_mutex_unlock (&pool->lock);
priv = pool->priv;
g_mutex_lock (&priv->lock);
priv->max_sessions = max;
g_mutex_unlock (&priv->lock);
}
/**
@ -171,13 +193,16 @@ gst_rtsp_session_pool_set_max_sessions (GstRTSPSessionPool * pool, guint max)
guint
gst_rtsp_session_pool_get_max_sessions (GstRTSPSessionPool * pool)
{
GstRTSPSessionPoolPrivate *priv;
guint result;
g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0);
g_mutex_lock (&pool->lock);
result = pool->max_sessions;
g_mutex_unlock (&pool->lock);
priv = pool->priv;
g_mutex_lock (&priv->lock);
result = priv->max_sessions;
g_mutex_unlock (&priv->lock);
return result;
}
@ -193,13 +218,16 @@ gst_rtsp_session_pool_get_max_sessions (GstRTSPSessionPool * pool)
guint
gst_rtsp_session_pool_get_n_sessions (GstRTSPSessionPool * pool)
{
GstRTSPSessionPoolPrivate *priv;
guint result;
g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0);
g_mutex_lock (&pool->lock);
result = g_hash_table_size (pool->sessions);
g_mutex_unlock (&pool->lock);
priv = pool->priv;
g_mutex_lock (&priv->lock);
result = g_hash_table_size (priv->sessions);
g_mutex_unlock (&priv->lock);
return result;
}
@ -218,18 +246,21 @@ gst_rtsp_session_pool_get_n_sessions (GstRTSPSessionPool * pool)
GstRTSPSession *
gst_rtsp_session_pool_find (GstRTSPSessionPool * pool, const gchar * sessionid)
{
GstRTSPSessionPoolPrivate *priv;
GstRTSPSession *result;
g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
g_return_val_if_fail (sessionid != NULL, NULL);
g_mutex_lock (&pool->lock);
result = g_hash_table_lookup (pool->sessions, sessionid);
priv = pool->priv;
g_mutex_lock (&priv->lock);
result = g_hash_table_lookup (priv->sessions, sessionid);
if (result) {
g_object_ref (result);
gst_rtsp_session_touch (result);
}
g_mutex_unlock (&pool->lock);
g_mutex_unlock (&priv->lock);
return result;
}
@ -260,6 +291,7 @@ create_session_id (GstRTSPSessionPool * pool)
GstRTSPSession *
gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
{
GstRTSPSessionPoolPrivate *priv;
GstRTSPSession *result = NULL;
GstRTSPSessionPoolClass *klass;
gchar *id = NULL;
@ -267,6 +299,8 @@ gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
priv = pool->priv;
klass = GST_RTSP_SESSION_POOL_GET_CLASS (pool);
retry = 0;
@ -281,14 +315,14 @@ gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
if (id == NULL)
goto no_session;
g_mutex_lock (&pool->lock);
g_mutex_lock (&priv->lock);
/* check session limit */
if (pool->max_sessions > 0) {
if (g_hash_table_size (pool->sessions) >= pool->max_sessions)
if (priv->max_sessions > 0) {
if (g_hash_table_size (priv->sessions) >= priv->max_sessions)
goto too_many_sessions;
}
/* check if the sessionid existed */
result = g_hash_table_lookup (pool->sessions, id);
result = g_hash_table_lookup (priv->sessions, id);
if (result) {
/* found, retry with a different session id */
result = NULL;
@ -300,9 +334,10 @@ gst_rtsp_session_pool_create (GstRTSPSessionPool * pool)
result = gst_rtsp_session_new (id);
/* take additional ref for the pool */
g_object_ref (result);
g_hash_table_insert (pool->sessions, result->sessionid, result);
g_hash_table_insert (priv->sessions,
(gchar *) gst_rtsp_session_get_sessionid (result), result);
}
g_mutex_unlock (&pool->lock);
g_mutex_unlock (&priv->lock);
g_free (id);
} while (result == NULL);
@ -323,14 +358,14 @@ no_session:
collision:
{
GST_WARNING ("can't find unique sessionid for GstRTSPSessionPool %p", pool);
g_mutex_unlock (&pool->lock);
g_mutex_unlock (&priv->lock);
g_free (id);
return NULL;
}
too_many_sessions:
{
GST_WARNING ("session pool reached max sessions of %d", pool->max_sessions);
g_mutex_unlock (&pool->lock);
GST_WARNING ("session pool reached max sessions of %d", priv->max_sessions);
g_mutex_unlock (&priv->lock);
g_free (id);
return NULL;
}
@ -348,14 +383,19 @@ too_many_sessions:
gboolean
gst_rtsp_session_pool_remove (GstRTSPSessionPool * pool, GstRTSPSession * sess)
{
GstRTSPSessionPoolPrivate *priv;
gboolean found;
g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), FALSE);
g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE);
g_mutex_lock (&pool->lock);
found = g_hash_table_remove (pool->sessions, sess->sessionid);
g_mutex_unlock (&pool->lock);
priv = pool->priv;
g_mutex_lock (&priv->lock);
found =
g_hash_table_remove (priv->sessions,
gst_rtsp_session_get_sessionid (sess));
g_mutex_unlock (&priv->lock);
return found;
}
@ -378,18 +418,21 @@ cleanup_func (gchar * sessionid, GstRTSPSession * sess, GTimeVal * now)
guint
gst_rtsp_session_pool_cleanup (GstRTSPSessionPool * pool)
{
GstRTSPSessionPoolPrivate *priv;
guint result;
GTimeVal now;
g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0);
priv = pool->priv;
g_get_current_time (&now);
g_mutex_lock (&pool->lock);
g_mutex_lock (&priv->lock);
result =
g_hash_table_foreach_remove (pool->sessions, (GHRFunc) cleanup_func,
g_hash_table_foreach_remove (priv->sessions, (GHRFunc) cleanup_func,
&now);
g_mutex_unlock (&pool->lock);
g_mutex_unlock (&priv->lock);
return result;
}
@ -397,7 +440,7 @@ gst_rtsp_session_pool_cleanup (GstRTSPSessionPool * pool)
typedef struct
{
GstRTSPSessionPool *pool;
GstRTSPSessionFilterFunc func;
GstRTSPSessionPoolFilterFunc func;
gpointer user_data;
GList *list;
} FilterData;
@ -443,21 +486,24 @@ filter_func (gchar * sessionid, GstRTSPSession * sess, FilterData * data)
*/
GList *
gst_rtsp_session_pool_filter (GstRTSPSessionPool * pool,
GstRTSPSessionFilterFunc func, gpointer user_data)
GstRTSPSessionPoolFilterFunc func, gpointer user_data)
{
GstRTSPSessionPoolPrivate *priv;
FilterData data;
g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
g_return_val_if_fail (func != NULL, NULL);
priv = pool->priv;
data.pool = pool;
data.func = func;
data.user_data = user_data;
data.list = NULL;
g_mutex_lock (&pool->lock);
g_hash_table_foreach_remove (pool->sessions, (GHRFunc) filter_func, &data);
g_mutex_unlock (&pool->lock);
g_mutex_lock (&priv->lock);
g_hash_table_foreach_remove (priv->sessions, (GHRFunc) filter_func, &data);
g_mutex_unlock (&priv->lock);
return data.list;
}
@ -489,15 +535,17 @@ collect_timeout (gchar * sessionid, GstRTSPSession * sess, GstPoolSource * psrc)
static gboolean
gst_pool_source_prepare (GSource * source, gint * timeout)
{
GstRTSPSessionPoolPrivate *priv;
GstPoolSource *psrc;
gboolean result;
psrc = (GstPoolSource *) source;
psrc->timeout = -1;
priv = psrc->pool->priv;
g_mutex_lock (&psrc->pool->lock);
g_hash_table_foreach (psrc->pool->sessions, (GHFunc) collect_timeout, psrc);
g_mutex_unlock (&psrc->pool->lock);
g_mutex_lock (&priv->lock);
g_hash_table_foreach (priv->sessions, (GHFunc) collect_timeout, psrc);
g_mutex_unlock (&priv->lock);
if (timeout)
*timeout = psrc->timeout;

View file

@ -27,6 +27,7 @@ G_BEGIN_DECLS
typedef struct _GstRTSPSessionPool GstRTSPSessionPool;
typedef struct _GstRTSPSessionPoolClass GstRTSPSessionPoolClass;
typedef struct _GstRTSPSessionPoolPrivate GstRTSPSessionPoolPrivate;
#include "rtsp-session.h"
@ -51,10 +52,7 @@ typedef struct _GstRTSPSessionPoolClass GstRTSPSessionPoolClass;
struct _GstRTSPSessionPool {
GObject parent;
guint max_sessions;
GMutex lock;
GHashTable *sessions;
GstRTSPSessionPoolPrivate *priv;
};
/**
@ -83,22 +81,7 @@ struct _GstRTSPSessionPoolClass {
typedef gboolean (*GstRTSPSessionPoolFunc) (GstRTSPSessionPool *pool, gpointer user_data);
/**
* GstRTSPFilterResult:
* @GST_RTSP_FILTER_REMOVE: Remove session
* @GST_RTSP_FILTER_KEEP: Keep session in the pool
* @GST_RTSP_FILTER_REF: Ref session in the result list
*
* Possible return values for gst_rtsp_session_pool_filter().
*/
typedef enum
{
GST_RTSP_FILTER_REMOVE,
GST_RTSP_FILTER_KEEP,
GST_RTSP_FILTER_REF,
} GstRTSPFilterResult;
/**
* GstRTSPSessionFilterFunc:
* GstRTSPSessionPoolFilterFunc:
* @pool: a #GstRTSPSessionPool object
* @session: a #GstRTSPSession in @pool
* @user_data: user data that has been given to gst_rtsp_session_pool_filter()
@ -117,9 +100,9 @@ typedef enum
*
* Returns: a #GstRTSPFilterResult.
*/
typedef GstRTSPFilterResult (*GstRTSPSessionFilterFunc) (GstRTSPSessionPool *pool,
GstRTSPSession *session,
gpointer user_data);
typedef GstRTSPFilterResult (*GstRTSPSessionPoolFilterFunc) (GstRTSPSessionPool *pool,
GstRTSPSession *session,
gpointer user_data);
GType gst_rtsp_session_pool_get_type (void);
@ -142,7 +125,7 @@ gboolean gst_rtsp_session_pool_remove (GstRTSPSessionPoo
/* perform session maintenance */
GList * gst_rtsp_session_pool_filter (GstRTSPSessionPool *pool,
GstRTSPSessionFilterFunc func,
GstRTSPSessionPoolFilterFunc func,
gpointer user_data);
guint gst_rtsp_session_pool_cleanup (GstRTSPSessionPool *pool);
GSource * gst_rtsp_session_pool_create_watch (GstRTSPSessionPool *pool);

View file

@ -20,6 +20,22 @@
#include "rtsp-session.h"
#define GST_RTSP_SESSION_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_SESSION, GstRTSPSessionPrivate))
struct _GstRTSPSessionPrivate
{
GMutex lock;
gchar *sessionid;
guint timeout;
GTimeVal create_time;
GTimeVal last_access;
gint expire_count;
GList *medias;
};
#undef DEBUG
#define DEFAULT_TIMEOUT 60
@ -48,6 +64,8 @@ gst_rtsp_session_class_init (GstRTSPSessionClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPSessionPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gst_rtsp_session_get_property;
@ -71,9 +89,13 @@ gst_rtsp_session_class_init (GstRTSPSessionClass * klass)
static void
gst_rtsp_session_init (GstRTSPSession * session)
{
g_mutex_init (&session->lock);
session->timeout = DEFAULT_TIMEOUT;
g_get_current_time (&session->create_time);
GstRTSPSessionPrivate *priv = GST_RTSP_SESSION_GET_PRIVATE (session);
session->priv = priv;
g_mutex_init (&priv->lock);
priv->timeout = DEFAULT_TIMEOUT;
g_get_current_time (&priv->create_time);
gst_rtsp_session_touch (session);
}
@ -81,17 +103,19 @@ static void
gst_rtsp_session_finalize (GObject * obj)
{
GstRTSPSession *session;
GstRTSPSessionPrivate *priv;
session = GST_RTSP_SESSION (obj);
priv = session->priv;
GST_INFO ("finalize session %p", session);
/* free all media */
g_list_free_full (session->medias, g_object_unref);
g_list_free_full (priv->medias, g_object_unref);
/* free session id */
g_free (session->sessionid);
g_mutex_clear (&session->lock);
g_free (priv->sessionid);
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_rtsp_session_parent_class)->finalize (obj);
}
@ -101,10 +125,11 @@ gst_rtsp_session_get_property (GObject * object, guint propid,
GValue * value, GParamSpec * pspec)
{
GstRTSPSession *session = GST_RTSP_SESSION (object);
GstRTSPSessionPrivate *priv = session->priv;
switch (propid) {
case PROP_SESSIONID:
g_value_set_string (value, session->sessionid);
g_value_set_string (value, priv->sessionid);
break;
case PROP_TIMEOUT:
g_value_set_uint (value, gst_rtsp_session_get_timeout (session));
@ -119,11 +144,12 @@ gst_rtsp_session_set_property (GObject * object, guint propid,
const GValue * value, GParamSpec * pspec)
{
GstRTSPSession *session = GST_RTSP_SESSION (object);
GstRTSPSessionPrivate *priv = session->priv;
switch (propid) {
case PROP_SESSIONID:
g_free (session->sessionid);
session->sessionid = g_value_dup_string (value);
g_free (priv->sessionid);
priv->sessionid = g_value_dup_string (value);
break;
case PROP_TIMEOUT:
gst_rtsp_session_set_timeout (session, g_value_get_uint (value));
@ -150,18 +176,22 @@ GstRTSPSessionMedia *
gst_rtsp_session_manage_media (GstRTSPSession * sess, const GstRTSPUrl * uri,
GstRTSPMedia * media)
{
GstRTSPSessionPrivate *priv;
GstRTSPSessionMedia *result;
g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
g_return_val_if_fail (media->status == GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
g_return_val_if_fail (gst_rtsp_media_get_status (media) ==
GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
priv = sess->priv;
result = gst_rtsp_session_media_new (uri, media);
g_mutex_lock (&sess->lock);
sess->medias = g_list_prepend (sess->medias, result);
g_mutex_unlock (&sess->lock);
g_mutex_lock (&priv->lock);
priv->medias = g_list_prepend (priv->medias, result);
g_mutex_unlock (&priv->lock);
GST_INFO ("manage new media %p in session %p", media, result);
@ -181,18 +211,21 @@ gboolean
gst_rtsp_session_release_media (GstRTSPSession * sess,
GstRTSPSessionMedia * media)
{
GstRTSPSessionPrivate *priv;
GList *find;
gboolean more;
g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE);
g_return_val_if_fail (media != NULL, FALSE);
g_mutex_lock (&sess->lock);
find = g_list_find (sess->medias, media);
priv = sess->priv;
g_mutex_lock (&priv->lock);
find = g_list_find (priv->medias, media);
if (find)
sess->medias = g_list_delete_link (sess->medias, find);
more = (sess->medias != NULL);
g_mutex_unlock (&sess->lock);
priv->medias = g_list_delete_link (priv->medias, find);
more = (priv->medias != NULL);
g_mutex_unlock (&priv->lock);
if (find)
g_object_unref (media);
@ -212,24 +245,87 @@ gst_rtsp_session_release_media (GstRTSPSession * sess,
GstRTSPSessionMedia *
gst_rtsp_session_get_media (GstRTSPSession * sess, const GstRTSPUrl * url)
{
GstRTSPSessionPrivate *priv;
GstRTSPSessionMedia *result;
GList *walk;
g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
g_return_val_if_fail (url != NULL, NULL);
priv = sess->priv;
result = NULL;
g_mutex_lock (&sess->lock);
for (walk = sess->medias; walk; walk = g_list_next (walk)) {
g_mutex_lock (&priv->lock);
for (walk = priv->medias; walk; walk = g_list_next (walk)) {
result = (GstRTSPSessionMedia *) walk->data;
if (g_str_equal (result->url->abspath, url->abspath))
if (gst_rtsp_session_media_matches_url (result, url))
break;
result = NULL;
}
g_mutex_unlock (&sess->lock);
g_mutex_unlock (&priv->lock);
return result;
}
/**
* gst_rtsp_session_filter:
* @sess: a #GstRTSPSession
* @func: (scope call): a callback
* @user_data: user data passed to @func
*
* Call @func for each media in @sess. The result value of @func determines
* what happens to the media. @func will be called with @sess
* locked so no further actions on @sess can be performed from @func.
*
* If @func returns #GST_RTSP_FILTER_REMOVE, the media will be removed from
* @sess.
*
* If @func returns #GST_RTSP_FILTER_KEEP, the media will remain in @sess.
*
* If @func returns #GST_RTSP_FILTER_REF, the media will remain in @sess but
* will also be added with an additional ref to the result #GList of this
* function..
*
* Returns: (element-type GstRTSPSessionMedia) (transfer full): a GList with all
* media for which @func returned #GST_RTSP_FILTER_REF. After usage, each
* element in the #GList should be unreffed before the list is freed.
*/
GList *
gst_rtsp_session_filter (GstRTSPSession * sess,
GstRTSPSessionFilterFunc func, gpointer user_data)
{
GstRTSPSessionPrivate *priv;
GList *result, *walk, *next;
g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
g_return_val_if_fail (func != NULL, NULL);
priv = sess->priv;
result = NULL;
g_mutex_lock (&priv->lock);
for (walk = priv->medias; walk; walk = next) {
GstRTSPSessionMedia *media = walk->data;
next = g_list_next (walk);
switch (func (sess, media, user_data)) {
case GST_RTSP_FILTER_REMOVE:
g_object_unref (media);
priv->medias = g_list_delete_link (priv->medias, walk);
break;
case GST_RTSP_FILTER_REF:
result = g_list_prepend (result, g_object_ref (media));
break;
case GST_RTSP_FILTER_KEEP:
default:
break;
}
}
g_mutex_unlock (&priv->lock);
return result;
}
@ -266,7 +362,7 @@ gst_rtsp_session_get_sessionid (GstRTSPSession * session)
{
g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL);
return session->sessionid;
return session->priv->sessionid;
}
/**
@ -280,17 +376,19 @@ gst_rtsp_session_get_sessionid (GstRTSPSession * session)
gchar *
gst_rtsp_session_get_header (GstRTSPSession * session)
{
GstRTSPSessionPrivate *priv;
gchar *result;
g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL);
g_mutex_lock (&session->lock);
if (session->timeout != 60)
result = g_strdup_printf ("%s; timeout=%d", session->sessionid,
session->timeout);
priv = session->priv;
g_mutex_lock (&priv->lock);
if (priv->timeout != 60)
result = g_strdup_printf ("%s; timeout=%d", priv->sessionid, priv->timeout);
else
result = g_strdup (session->sessionid);
g_mutex_unlock (&session->lock);
result = g_strdup (priv->sessionid);
g_mutex_unlock (&priv->lock);
return result;
}
@ -306,11 +404,15 @@ gst_rtsp_session_get_header (GstRTSPSession * session)
void
gst_rtsp_session_set_timeout (GstRTSPSession * session, guint timeout)
{
GstRTSPSessionPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SESSION (session));
g_mutex_lock (&session->lock);
session->timeout = timeout;
g_mutex_unlock (&session->lock);
priv = session->priv;
g_mutex_lock (&priv->lock);
priv->timeout = timeout;
g_mutex_unlock (&priv->lock);
}
/**
@ -324,13 +426,16 @@ gst_rtsp_session_set_timeout (GstRTSPSession * session, guint timeout)
guint
gst_rtsp_session_get_timeout (GstRTSPSession * session)
{
GstRTSPSessionPrivate *priv;
guint res;
g_return_val_if_fail (GST_IS_RTSP_SESSION (session), 0);
g_mutex_lock (&session->lock);
res = session->timeout;
g_mutex_unlock (&session->lock);
priv = session->priv;
g_mutex_lock (&priv->lock);
res = priv->timeout;
g_mutex_unlock (&priv->lock);
return res;
}
@ -344,11 +449,15 @@ gst_rtsp_session_get_timeout (GstRTSPSession * session)
void
gst_rtsp_session_touch (GstRTSPSession * session)
{
GstRTSPSessionPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SESSION (session));
g_mutex_lock (&session->lock);
g_get_current_time (&session->last_access);
g_mutex_unlock (&session->lock);
priv = session->priv;
g_mutex_lock (&priv->lock);
g_get_current_time (&priv->last_access);
g_mutex_unlock (&priv->lock);
}
/**
@ -362,7 +471,7 @@ gst_rtsp_session_prevent_expire (GstRTSPSession * session)
{
g_return_if_fail (GST_IS_RTSP_SESSION (session));
g_atomic_int_add (&session->expire_count, 1);
g_atomic_int_add (&session->priv->expire_count, 1);
}
/**
@ -375,7 +484,7 @@ gst_rtsp_session_prevent_expire (GstRTSPSession * session)
void
gst_rtsp_session_allow_expire (GstRTSPSession * session)
{
g_atomic_int_add (&session->expire_count, -1);
g_atomic_int_add (&session->priv->expire_count, -1);
}
/**
@ -390,22 +499,25 @@ gst_rtsp_session_allow_expire (GstRTSPSession * session)
gint
gst_rtsp_session_next_timeout (GstRTSPSession * session, GTimeVal * now)
{
GstRTSPSessionPrivate *priv;
gint res;
GstClockTime last_access, now_ns;
g_return_val_if_fail (GST_IS_RTSP_SESSION (session), -1);
g_return_val_if_fail (now != NULL, -1);
g_mutex_lock (&session->lock);
if (g_atomic_int_get (&session->expire_count) != 0) {
priv = session->priv;
g_mutex_lock (&priv->lock);
if (g_atomic_int_get (&priv->expire_count) != 0) {
/* touch session when the expire count is not 0 */
g_get_current_time (&session->last_access);
g_get_current_time (&priv->last_access);
}
last_access = GST_TIMEVAL_TO_TIME (session->last_access);
last_access = GST_TIMEVAL_TO_TIME (priv->last_access);
/* add timeout allow for 5 seconds of extra time */
last_access += session->timeout * GST_SECOND + (5 * GST_SECOND);
g_mutex_unlock (&session->lock);
last_access += priv->timeout * GST_SECOND + (5 * GST_SECOND);
g_mutex_unlock (&priv->lock);
now_ns = GST_TIMEVAL_TO_TIME (*now);

View file

@ -37,19 +37,28 @@ G_BEGIN_DECLS
typedef struct _GstRTSPSession GstRTSPSession;
typedef struct _GstRTSPSessionClass GstRTSPSessionClass;
typedef struct _GstRTSPSessionPrivate GstRTSPSessionPrivate;
/**
* GstRTSPFilterResult:
* @GST_RTSP_FILTER_REMOVE: Remove session
* @GST_RTSP_FILTER_KEEP: Keep session in the pool
* @GST_RTSP_FILTER_REF: Ref session in the result list
*
* Possible return values for gst_rtsp_session_pool_filter().
*/
typedef enum
{
GST_RTSP_FILTER_REMOVE,
GST_RTSP_FILTER_KEEP,
GST_RTSP_FILTER_REF,
} GstRTSPFilterResult;
#include "rtsp-media.h"
#include "rtsp-session-media.h"
/**
* GstRTSPSession:
* @parent: the parent GObject
* @sessionid: the session id of the session
* @timeout: the timeout of the session
* @create_time: the time when the session was created
* @last_access: the time the session was last accessed
* @expire_count: the expire prevention counter
* @medias: a list of #GstRTSPSessionMedia managed in this session
*
* Session information kept by the server for a specific client.
* One client session, identified with a session id, can handle multiple medias
@ -58,15 +67,7 @@ typedef struct _GstRTSPSessionClass GstRTSPSessionClass;
struct _GstRTSPSession {
GObject parent;
GMutex lock;
gchar *sessionid;
guint timeout;
GTimeVal create_time;
GTimeVal last_access;
gint expire_count;
GList *medias;
GstRTSPSessionPrivate *priv;
};
struct _GstRTSPSessionClass {
@ -102,6 +103,35 @@ gboolean gst_rtsp_session_release_media (GstRTSPSession *se
GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess,
const GstRTSPUrl *url);
/**
* GstRTSPSessionFilterFunc:
* @sess: a #GstRTSPSession object
* @media: a #GstRTSPSessionMedia in @sess
* @user_data: user data that has been given to gst_rtsp_session_filter()
*
* This function will be called by the gst_rtsp_session_filter(). An
* implementation should return a value of #GstRTSPFilterResult.
*
* When this function returns #GST_RTSP_FILTER_REMOVE, @media will be removed
* from @sess.
*
* A return value of #GST_RTSP_FILTER_KEEP will leave @media untouched in
* @sess.
*
* A value of GST_RTSP_FILTER_REF will add @media to the result #GList of
* gst_rtsp_session_filter().
*
* Returns: a #GstRTSPFilterResult.
*/
typedef GstRTSPFilterResult (*GstRTSPSessionFilterFunc) (GstRTSPSession *sess,
GstRTSPSessionMedia *media,
gpointer user_data);
GList * gst_rtsp_session_filter (GstRTSPSession *sess,
GstRTSPSessionFilterFunc func,
gpointer user_data);
G_END_DECLS
#endif /* __GST_RTSP_SESSION_H__ */

View file

@ -20,11 +20,31 @@
#include <string.h>
#include <stdlib.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
#include "rtsp-stream-transport.h"
#define GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM_TRANSPORT, GstRTSPStreamTransportPrivate))
struct _GstRTSPStreamTransportPrivate
{
GstRTSPStream *stream;
GstRTSPSendFunc send_rtp;
GstRTSPSendFunc send_rtcp;
gpointer user_data;
GDestroyNotify notify;
GstRTSPKeepAliveFunc keep_alive;
gpointer ka_user_data;
GDestroyNotify ka_notify;
gboolean active;
gboolean timed_out;
GstRTSPTransport *transport;
GObject *rtpsource;
};
enum
{
PROP_0,
@ -44,6 +64,8 @@ gst_rtsp_stream_transport_class_init (GstRTSPStreamTransportClass * klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GstRTSPStreamTransportPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gst_rtsp_stream_transport_finalize;
@ -55,25 +77,31 @@ gst_rtsp_stream_transport_class_init (GstRTSPStreamTransportClass * klass)
static void
gst_rtsp_stream_transport_init (GstRTSPStreamTransport * trans)
{
GstRTSPStreamTransportPrivate *priv =
GST_RTSP_STREAM_TRANSPORT_GET_PRIVATE (trans);
trans->priv = priv;
}
static void
gst_rtsp_stream_transport_finalize (GObject * obj)
{
GstRTSPStreamTransportPrivate *priv;
GstRTSPStreamTransport *trans;
trans = GST_RTSP_STREAM_TRANSPORT (obj);
priv = trans->priv;
/* remove callbacks now */
gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
gst_rtsp_stream_transport_set_keepalive (trans, NULL, NULL, NULL);
if (trans->transport)
gst_rtsp_transport_free (trans->transport);
if (priv->transport)
gst_rtsp_transport_free (priv->transport);
#if 0
if (trans->rtpsource)
g_object_set_qdata (trans->rtpsource, ssrc_stream_map_key, NULL);
if (priv->rtpsource)
g_object_set_qdata (priv->rtpsource, ssrc_stream_map_key, NULL);
#endif
G_OBJECT_CLASS (gst_rtsp_stream_transport_parent_class)->finalize (obj);
@ -92,18 +120,36 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
GstRTSPStreamTransport *
gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
{
GstRTSPStreamTransportPrivate *priv;
GstRTSPStreamTransport *trans;
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
g_return_val_if_fail (tr != NULL, NULL);
trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL);
trans->stream = stream;
trans->transport = tr;
priv = trans->priv;
priv->stream = stream;
priv->transport = tr;
return trans;
}
/**
* gst_rtsp_stream_transport_get_stream:
* @trans: a #GstRTSPStreamTransport
*
* Get the #GstRTSPStream used when constructing @trans.
*
* Returns: (transfer none): the stream used when constructing @trans.
*/
GstRTSPStream *
gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport * trans)
{
g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
return trans->priv->stream;
}
/**
* gst_rtsp_stream_transport_set_callbacks:
* @trans: a #GstRTSPStreamTransport
@ -120,12 +166,18 @@ gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport * trans,
GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp,
gpointer user_data, GDestroyNotify notify)
{
trans->send_rtp = send_rtp;
trans->send_rtcp = send_rtcp;
if (trans->notify)
trans->notify (trans->user_data);
trans->user_data = user_data;
trans->notify = notify;
GstRTSPStreamTransportPrivate *priv;
g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
priv = trans->priv;
priv->send_rtp = send_rtp;
priv->send_rtcp = send_rtcp;
if (priv->notify)
priv->notify (priv->user_data);
priv->user_data = user_data;
priv->notify = notify;
}
/**
@ -142,11 +194,17 @@ void
gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport * trans,
GstRTSPKeepAliveFunc keep_alive, gpointer user_data, GDestroyNotify notify)
{
trans->keep_alive = keep_alive;
if (trans->ka_notify)
trans->ka_notify (trans->ka_user_data);
trans->ka_user_data = user_data;
trans->ka_notify = notify;
GstRTSPStreamTransportPrivate *priv;
g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
priv = trans->priv;
priv->keep_alive = keep_alive;
if (priv->ka_notify)
priv->ka_notify (priv->ka_user_data);
priv->ka_user_data = user_data;
priv->ka_notify = notify;
}
@ -162,13 +220,100 @@ void
gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
GstRTSPTransport * tr)
{
GstRTSPStreamTransportPrivate *priv;
g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
g_return_if_fail (tr != NULL);
priv = trans->priv;
/* keep track of the transports in the stream. */
if (trans->transport)
gst_rtsp_transport_free (trans->transport);
trans->transport = tr;
if (priv->transport)
gst_rtsp_transport_free (priv->transport);
priv->transport = tr;
}
/**
* gst_rtsp_stream_transport_get_transport:
* @trans: a #GstRTSPStreamTransport
*
* Get the transport configured in @trans.
*
* Returns: (transfer none): the transport configured in @trans. It remains
* valid for as long as @trans is valid.
*/
const GstRTSPTransport *
gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans)
{
g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
return trans->priv->transport;
}
/**
* gst_rtsp_stream_transport_set_active:
* @trans: a #GstRTSPStreamTransport
* @active: new state of @trans
*
* Activate or deactivate datatransfer configured in @trans.
*
* Returns: %TRUE when the state was changed.
*/
gboolean
gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport * trans,
gboolean active)
{
GstRTSPStreamTransportPrivate *priv;
gboolean res;
g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
priv = trans->priv;
if (priv->active == active)
return FALSE;
if (active)
res = gst_rtsp_stream_add_transport (priv->stream, trans);
else
res = gst_rtsp_stream_remove_transport (priv->stream, trans);
if (res)
priv->active = active;
return res;
}
/**
* gst_rtsp_stream_transport_set_timed_out:
* @trans: a #GstRTSPStreamTransport
* @timedout: timed out value
*
* Set the timed out state of @trans to @timedout
*/
void
gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport * trans,
gboolean timedout)
{
g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
trans->priv->timed_out = timedout;
}
/**
* gst_rtsp_stream_transport_is_timed_out:
* @trans: a #GstRTSPStreamTransport
*
* Check if @trans is timed out.
*
* Returns: %TRUE if @trans timed out.
*/
gboolean
gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
{
g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), FALSE);
return trans->priv->timed_out;
}
/**
@ -184,12 +329,15 @@ gboolean
gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
GstBuffer * buffer)
{
GstRTSPStreamTransportPrivate *priv;
gboolean res = FALSE;
if (trans->send_rtp)
priv = trans->priv;
if (priv->send_rtp)
res =
trans->send_rtp (buffer, trans->transport->interleaved.min,
trans->user_data);
priv->send_rtp (buffer, priv->transport->interleaved.min,
priv->user_data);
return res;
}
@ -207,12 +355,15 @@ gboolean
gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
GstBuffer * buffer)
{
GstRTSPStreamTransportPrivate *priv;
gboolean res = FALSE;
if (trans->send_rtcp)
priv = trans->priv;
if (priv->send_rtcp)
res =
trans->send_rtcp (buffer, trans->transport->interleaved.max,
trans->user_data);
priv->send_rtcp (buffer, priv->transport->interleaved.max,
priv->user_data);
return res;
}
@ -226,6 +377,10 @@ gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
void
gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
{
if (trans->keep_alive)
trans->keep_alive (trans->ka_user_data);
GstRTSPStreamTransportPrivate *priv;
priv = trans->priv;
if (priv->keep_alive)
priv->keep_alive (priv->ka_user_data);
}

View file

@ -38,9 +38,9 @@ G_BEGIN_DECLS
typedef struct _GstRTSPStreamTransport GstRTSPStreamTransport;
typedef struct _GstRTSPStreamTransportClass GstRTSPStreamTransportClass;
typedef struct _GstRTSPStreamTransportPrivate GstRTSPStreamTransportPrivate;
#include "rtsp-stream.h"
#include "rtsp-address-pool.h"
typedef gboolean (*GstRTSPSendFunc) (GstBuffer *buffer, guint8 channel, gpointer user_data);
typedef void (*GstRTSPKeepAliveFunc) (gpointer user_data);
@ -48,41 +48,13 @@ typedef void (*GstRTSPKeepAliveFunc) (gpointer user_data);
/**
* GstRTSPStreamTransport:
* @parent: parent instance
* @stream: the GstRTSPStream we manage
* @send_rtp: callback for sending RTP messages
* @send_rtcp: 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
* @addr: an optional address
* @rtpsource: the receiver rtp source object
*
* A Transport description for stream @idx
* A Transport description for a stream
*/
struct _GstRTSPStreamTransport {
GObject parent;
GstRTSPStream *stream;
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;
GstRTSPStreamTransportPrivate *priv;
};
struct _GstRTSPStreamTransportClass {
@ -94,8 +66,11 @@ GType gst_rtsp_stream_transport_get_type (void);
GstRTSPStreamTransport * gst_rtsp_stream_transport_new (GstRTSPStream *stream,
GstRTSPTransport *tr);
GstRTSPStream * gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport *trans);
void gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport *trans,
GstRTSPTransport * tr);
const GstRTSPTransport * gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport *trans);
void gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport *trans,
GstRTSPSendFunc send_rtp,
@ -107,6 +82,15 @@ void gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamT
gpointer user_data,
GDestroyNotify notify);
gboolean gst_rtsp_stream_transport_set_active (GstRTSPStreamTransport *trans,
gboolean active);
void gst_rtsp_stream_transport_set_timed_out (GstRTSPStreamTransport *trans,
gboolean timedout);
gboolean gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport *trans);
gboolean gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport *trans,
GstBuffer *buffer);
gboolean gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport *trans,

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,7 @@ G_BEGIN_DECLS
typedef struct _GstRTSPStream GstRTSPStream;
typedef struct _GstRTSPStreamClass GstRTSPStreamClass;
typedef struct _GstRTSPStreamPrivate GstRTSPStreamPrivate;
#include "rtsp-stream-transport.h"
#include "rtsp-address-pool.h"
@ -45,79 +46,13 @@ typedef struct _GstRTSPStreamClass GstRTSPStreamClass;
/**
* GstRTSPStream:
* @parent: the parent instance
* @lock: mutex protecting the stream
* @idx: the stream index
* @srcpad: the srcpad of the stream
* @payloader: the payloader of the format
* @is_ipv6: should this stream be IPv6
* @buffer_size: the UDP buffer size
* @is_joined: if the stream is joined in a bin
* @send_rtp_sink: sinkpad for sending RTP buffers
* @recv_sink: sinkpad for receiving RTP/RTCP buffers
* @send_src: srcpad for sending RTP/RTCP buffers
* @session: the RTP session object
* @udpsrc: the udp source elements for RTP/RTCP
* @udpsink: the udp sink elements for RTP/RTCP
* @appsrc: the app source elements for RTP/RTCP
* @appqueue: the app queue elements for RTP/RTCP
* @appsink: the app sink elements for RTP/RTCP
* @tee: tee for the sending to udpsink and appsink
* @funnel: tee for the receiving from udpsrc and appsrc
* @server_port: the server ports for this stream
* @pool: the address pool for this stream
* @addr: the address for this stream
* @caps_sig: the signal id for detecting caps
* @caps: the caps of the stream
* @n_active: the number of active transports in @transports
* @transports: list of #GstStreamTransport being streamed to
*
* The definition of a media stream. The streams are identified by @idx.
* The definition of a media stream.
*/
struct _GstRTSPStream {
GObject parent;
GMutex lock;
guint idx;
GstPad *srcpad;
GstElement *payloader;
gboolean is_ipv6;
guint buffer_size;
gboolean is_joined;
/* pads on the rtpbin */
GstPad *send_rtp_sink;
GstPad *recv_sink[2];
GstPad *send_src[2];
/* 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 *funnel[2];
/* server ports for sending/receiving */
GstRTSPRange server_port;
/* multicast addresses */
GstRTSPAddressPool *pool;
GstRTSPAddress *addr;
/* the caps of the stream */
gulong caps_sig;
GstCaps *caps;
/* transports we stream to */
guint n_active;
GList *transports;
GstRTSPStreamPrivate *priv;
};
struct _GstRTSPStreamClass {
@ -128,9 +63,10 @@ GType gst_rtsp_stream_get_type (void);
GstRTSPStream * gst_rtsp_stream_new (guint idx, GstElement *payloader,
GstPad *srcpad);
guint gst_rtsp_stream_get_index (GstRTSPStream *stream);
void gst_rtsp_stream_set_mtu (GstRTSPStream * stream, guint mtu);
guint gst_rtsp_stream_get_mtu (GstRTSPStream * stream);
void gst_rtsp_stream_set_mtu (GstRTSPStream *stream, guint mtu);
guint gst_rtsp_stream_get_mtu (GstRTSPStream *stream);
void gst_rtsp_stream_set_address_pool (GstRTSPStream *stream, GstRTSPAddressPool *pool);
GstRTSPAddressPool *
@ -138,14 +74,20 @@ GstRTSPAddressPool *
GstRTSPAddress * gst_rtsp_stream_get_address (GstRTSPStream *stream);
gboolean gst_rtsp_stream_join_bin (GstRTSPStream * stream,
gboolean gst_rtsp_stream_join_bin (GstRTSPStream *stream,
GstBin *bin, GstElement *rtpbin,
GstState state);
gboolean gst_rtsp_stream_leave_bin (GstRTSPStream * stream,
gboolean gst_rtsp_stream_leave_bin (GstRTSPStream *stream,
GstBin *bin, GstElement *rtpbin);
gboolean gst_rtsp_stream_get_rtpinfo (GstRTSPStream * stream,
guint *rtptime, guint * seq);
void gst_rtsp_stream_get_server_port (GstRTSPStream *stream,
GstRTSPRange *server_port);
void gst_rtsp_stream_get_ssrc (GstRTSPStream *stream,
guint *ssrc);
gboolean gst_rtsp_stream_get_rtpinfo (GstRTSPStream *stream,
guint *rtptime, guint *seq);
GstCaps * gst_rtsp_stream_get_caps (GstRTSPStream *stream);
GstFlowReturn gst_rtsp_stream_recv_rtp (GstRTSPStream *stream,
GstBuffer *buffer);

View file

@ -93,7 +93,7 @@ GST_START_TEST (test_media)
{
GstRTSPMedia *media;
media = gst_rtsp_media_new ();
media = gst_rtsp_media_new (NULL);
fail_unless (GST_IS_RTSP_MEDIA (media));
g_object_unref (media);
}