mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
rtsp: make address-pool return an address object
Return a boxed GstRTSPAddress from the GstRTSPAddressPool. This allows us to store more info in the structure and allows us to more easily return the address to the right pool when no longer needed. Pass the address to the StreamTransport so that we can return it to the pool when the stream transport is freed or changed.
This commit is contained in:
parent
fde8c01a85
commit
45b6693b39
8 changed files with 143 additions and 70 deletions
|
@ -22,6 +22,43 @@
|
|||
|
||||
#include "rtsp-address-pool.h"
|
||||
|
||||
GstRTSPAddress *
|
||||
gst_rtsp_address_copy (GstRTSPAddress * addr)
|
||||
{
|
||||
GstRTSPAddress *copy;
|
||||
|
||||
g_return_val_if_fail (addr != NULL, NULL);
|
||||
|
||||
copy = g_slice_dup (GstRTSPAddress, addr);
|
||||
/* only release to the pool when the original is freed. It's a bit
|
||||
* weird but this will do for now as it avoid us to use refcounting. */
|
||||
copy->pool = NULL;
|
||||
copy->address = g_strdup (copy->address);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static void gst_rtsp_address_pool_release_address (GstRTSPAddressPool * pool,
|
||||
GstRTSPAddress * addr);
|
||||
|
||||
void
|
||||
gst_rtsp_address_free (GstRTSPAddress * addr)
|
||||
{
|
||||
g_return_if_fail (addr != NULL);
|
||||
|
||||
if (addr->pool) {
|
||||
/* unrefs the pool and sets it to NULL */
|
||||
gst_rtsp_address_pool_release_address (addr->pool, addr);
|
||||
}
|
||||
g_free (addr->address);
|
||||
g_slice_free (GstRTSPAddress, addr);
|
||||
}
|
||||
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstRTSPAddress, gst_rtsp_address,
|
||||
(GBoxedCopyFunc) gst_rtsp_address_copy,
|
||||
(GBoxedFreeFunc) gst_rtsp_address_free);
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (rtsp_address_pool_debug);
|
||||
#define GST_CAT_DEFAULT rtsp_address_pool_debug
|
||||
|
||||
|
@ -298,35 +335,29 @@ split_range (GstRTSPAddressPool * pool, AddrRange * range, gint skip,
|
|||
* @pool: a #GstRTSPAddressPool
|
||||
* @flags: flags
|
||||
* @n_ports: the amount of ports
|
||||
* @address: result address
|
||||
* @port: result port
|
||||
* @ttl: result TTL
|
||||
*
|
||||
* Take an address and ports from @pool. @flags can be used to control the
|
||||
* allocation. @n_ports consecutive ports will be allocated of which the first
|
||||
* one can be found in @port.
|
||||
*
|
||||
* Returns: a pointer that should be used to release the address with
|
||||
* gst_rtsp_address_pool_release_address() after usage or %NULL when no
|
||||
* address could be acquired.
|
||||
* Returns: a #GstRTSPAddress that should be freed with gst_rtsp_address_free
|
||||
* after use or %NULL when no address could be acquired.
|
||||
*/
|
||||
gpointer
|
||||
GstRTSPAddress *
|
||||
gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool,
|
||||
GstRTSPAddressFlags flags, gint n_ports, gchar ** address,
|
||||
guint16 * port, guint8 * ttl)
|
||||
GstRTSPAddressFlags flags, gint n_ports)
|
||||
{
|
||||
GstRTSPAddressPoolPrivate *priv;
|
||||
GList *walk, *next;
|
||||
AddrRange *result;
|
||||
GstRTSPAddress *addr;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool), NULL);
|
||||
g_return_val_if_fail (n_ports > 0, NULL);
|
||||
g_return_val_if_fail (address != NULL, NULL);
|
||||
g_return_val_if_fail (port != NULL, NULL);
|
||||
g_return_val_if_fail (ttl != NULL, NULL);
|
||||
|
||||
priv = pool->priv;
|
||||
result = NULL;
|
||||
addr = NULL;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
/* go over available ranges */
|
||||
|
@ -363,13 +394,19 @@ gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool,
|
|||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
if (result) {
|
||||
*address = get_address_string (&result->min);
|
||||
*port = result->min.port;
|
||||
*ttl = result->ttl;
|
||||
addr = g_slice_new0 (GstRTSPAddress);
|
||||
addr->pool = g_object_ref (pool);
|
||||
addr->address = get_address_string (&result->min);
|
||||
addr->n_ports = n_ports;
|
||||
addr->port = result->min.port;
|
||||
addr->ttl = result->ttl;
|
||||
addr->priv = result;
|
||||
|
||||
GST_DEBUG_OBJECT (pool, "got address %s:%u ttl %u", *address, *port, *ttl);
|
||||
GST_DEBUG_OBJECT (pool, "got address %s:%u ttl %u", addr->address,
|
||||
addr->port, addr->ttl);
|
||||
}
|
||||
return result;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -380,34 +417,44 @@ gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool,
|
|||
* Release a previously acquired address (with
|
||||
* gst_rtsp_address_pool_acquire_address()) back into @pool.
|
||||
*/
|
||||
void
|
||||
gst_rtsp_address_pool_release_address (GstRTSPAddressPool * pool, gpointer id)
|
||||
static void
|
||||
gst_rtsp_address_pool_release_address (GstRTSPAddressPool * pool,
|
||||
GstRTSPAddress * addr)
|
||||
{
|
||||
GstRTSPAddressPoolPrivate *priv;
|
||||
GList *find;
|
||||
AddrRange *range;
|
||||
|
||||
g_return_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool));
|
||||
g_return_if_fail (id != NULL);
|
||||
g_return_if_fail (addr != NULL);
|
||||
g_return_if_fail (addr->pool == pool);
|
||||
|
||||
priv = pool->priv;
|
||||
range = addr->priv;
|
||||
|
||||
/* we don't want to free twice */
|
||||
addr->priv = NULL;
|
||||
addr->pool = NULL;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
find = g_list_find (priv->allocated, id);
|
||||
find = g_list_find (priv->allocated, range);
|
||||
if (find == NULL)
|
||||
goto not_found;
|
||||
|
||||
priv->allocated = g_list_delete_link (priv->allocated, find);
|
||||
|
||||
/* FIXME, merge and do something clever */
|
||||
priv->addresses = g_list_prepend (priv->addresses, id);
|
||||
priv->addresses = g_list_prepend (priv->addresses, range);
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
g_object_unref (pool);
|
||||
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
not_found:
|
||||
{
|
||||
g_warning ("Released unknown id %p", id);
|
||||
g_warning ("Released unknown address %p", addr);
|
||||
g_mutex_unlock (&priv->lock);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -33,10 +33,29 @@ G_BEGIN_DECLS
|
|||
#define GST_RTSP_ADDRESS_POOL_CAST(obj) ((GstRTSPAddressPool*)(obj))
|
||||
#define GST_RTSP_ADDRESS_POOL_CLASS_CAST(klass) ((GstRTSPAddressPoolClass*)(klass))
|
||||
|
||||
typedef struct _GstRTSPAddress GstRTSPAddress;
|
||||
typedef struct _GstRTSPAddressClass GstRTSPAddressClass;
|
||||
|
||||
typedef struct _GstRTSPAddressPool GstRTSPAddressPool;
|
||||
typedef struct _GstRTSPAddressPoolClass GstRTSPAddressPoolClass;
|
||||
typedef struct _GstRTSPAddressPoolPrivate GstRTSPAddressPoolPrivate;
|
||||
|
||||
struct _GstRTSPAddress {
|
||||
GstRTSPAddressPool *pool;
|
||||
|
||||
gchar *address;
|
||||
guint16 port;
|
||||
gint n_ports;
|
||||
guint8 ttl;
|
||||
|
||||
gpointer priv;
|
||||
};
|
||||
|
||||
GType gst_rtsp_address_get_type (void);
|
||||
|
||||
GstRTSPAddress * gst_rtsp_address_copy (GstRTSPAddress *addr);
|
||||
void gst_rtsp_address_free (GstRTSPAddress *addr);
|
||||
|
||||
typedef enum {
|
||||
GST_RTSP_ADDRESS_FLAG_NONE = 0,
|
||||
GST_RTSP_ADDRESS_FLAG_IPV4 = (1 << 0),
|
||||
|
@ -74,13 +93,9 @@ gboolean gst_rtsp_address_pool_add_range (GstRTSPAddressPool
|
|||
guint16 max_port,
|
||||
guint8 ttl);
|
||||
|
||||
gpointer gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool,
|
||||
GstRTSPAddress * gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool,
|
||||
GstRTSPAddressFlags flags,
|
||||
gint n_ports,
|
||||
gchar **address,
|
||||
guint16 *port, guint8 *ttl);
|
||||
void gst_rtsp_address_pool_release_address (GstRTSPAddressPool * pool,
|
||||
gpointer);
|
||||
gint n_ports);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_RTSP_ADDRESS_POOL_H__ */
|
||||
|
|
|
@ -973,31 +973,30 @@ handle_blocksize (GstRTSPMedia * media, GstRTSPMessage * request)
|
|||
|
||||
static gboolean
|
||||
configure_client_transport (GstRTSPClient * client, GstRTSPClientState * state,
|
||||
GstRTSPTransport * ct)
|
||||
GstRTSPTransport * ct, GstRTSPAddress ** addr)
|
||||
{
|
||||
/* we have a valid transport now, set the destination of the client. */
|
||||
if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
|
||||
if (ct->destination == NULL || !client->use_client_settings) {
|
||||
GstRTSPAddressPool *pool;
|
||||
gchar *address;
|
||||
guint16 port;
|
||||
guint8 ttl;
|
||||
gpointer id;
|
||||
GstRTSPAddress *ad;
|
||||
|
||||
pool = gst_rtsp_media_get_address_pool (state->media);
|
||||
if (pool == NULL)
|
||||
goto no_pool;
|
||||
|
||||
id = gst_rtsp_address_pool_acquire_address (pool,
|
||||
GST_RTSP_ADDRESS_FLAG_EVEN_PORT, 2, &address, &port, &ttl);
|
||||
if (id == NULL)
|
||||
ad = gst_rtsp_address_pool_acquire_address (pool,
|
||||
GST_RTSP_ADDRESS_FLAG_EVEN_PORT, 2);
|
||||
if (ad == NULL)
|
||||
goto no_address;
|
||||
|
||||
g_free (ct->destination);
|
||||
ct->destination = address;
|
||||
ct->port.min = port;
|
||||
ct->port.max = port + 1;
|
||||
ct->ttl = ttl;
|
||||
ct->destination = g_strdup (ad->address);
|
||||
ct->port.min = ad->port;
|
||||
ct->port.max = ad->port + 1;
|
||||
ct->ttl = ad->ttl;
|
||||
|
||||
*addr = ad;
|
||||
}
|
||||
} else {
|
||||
GstRTSPUrl *url;
|
||||
|
@ -1019,10 +1018,12 @@ configure_client_transport (GstRTSPClient * client, GstRTSPClientState * state,
|
|||
/* ERRORS */
|
||||
no_pool:
|
||||
{
|
||||
GST_ERROR_OBJECT (client, "no address pool specified");
|
||||
return FALSE;
|
||||
}
|
||||
no_address:
|
||||
{
|
||||
GST_ERROR_OBJECT (client, "failed to acquire address from pool");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -1078,6 +1079,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
|
|||
GstRTSPSessionMedia *sessmedia;
|
||||
GstRTSPMedia *media;
|
||||
GstRTSPStream *stream;
|
||||
GstRTSPAddress *addr;
|
||||
|
||||
uri = state->uri;
|
||||
|
||||
|
@ -1166,11 +1168,12 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
|
|||
goto invalid_blocksize;
|
||||
|
||||
/* update the client transport */
|
||||
if (!configure_client_transport (client, state, ct))
|
||||
addr = NULL;
|
||||
if (!configure_client_transport (client, state, ct, &addr))
|
||||
goto unsupported_client_transport;
|
||||
|
||||
/* set in the session media transport */
|
||||
trans = gst_rtsp_session_media_set_transport (sessmedia, stream, ct);
|
||||
trans = gst_rtsp_session_media_set_transport (sessmedia, stream, ct, addr);
|
||||
|
||||
/* configure keepalive for this transport */
|
||||
gst_rtsp_stream_transport_set_keepalive (trans,
|
||||
|
|
|
@ -123,6 +123,7 @@ gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media)
|
|||
* @media: a #GstRTSPSessionMedia
|
||||
* @stream: a #GstRTSPStream
|
||||
* @tr: a #GstRTSPTransport
|
||||
* @addr: (transfer full) (allow none): an optional #GstRTSPAddress
|
||||
*
|
||||
* Configure the transport for @stream to @tr in @media.
|
||||
*
|
||||
|
@ -130,7 +131,7 @@ gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media)
|
|||
*/
|
||||
GstRTSPStreamTransport *
|
||||
gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
|
||||
GstRTSPStream * stream, GstRTSPTransport * tr)
|
||||
GstRTSPStream * stream, GstRTSPTransport * tr, GstRTSPAddress * addr)
|
||||
{
|
||||
GstRTSPStreamTransport *result;
|
||||
|
||||
|
@ -141,11 +142,11 @@ gst_rtsp_session_media_set_transport (GstRTSPSessionMedia * media,
|
|||
g_mutex_lock (&media->lock);
|
||||
result = g_ptr_array_index (media->transports, stream->idx);
|
||||
if (result == NULL) {
|
||||
result = gst_rtsp_stream_transport_new (stream, tr);
|
||||
result = gst_rtsp_stream_transport_new (stream, tr, addr);
|
||||
g_ptr_array_index (media->transports, stream->idx) = result;
|
||||
g_mutex_unlock (&media->lock);
|
||||
} else {
|
||||
gst_rtsp_stream_transport_set_transport (result, tr);
|
||||
gst_rtsp_stream_transport_set_transport (result, tr, addr);
|
||||
g_mutex_unlock (&media->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,8 @@ gboolean gst_rtsp_session_media_set_state (GstRTSPSessionMe
|
|||
/* get stream transport config */
|
||||
GstRTSPStreamTransport * gst_rtsp_session_media_set_transport (GstRTSPSessionMedia *media,
|
||||
GstRTSPStream *stream,
|
||||
GstRTSPTransport *tr);
|
||||
GstRTSPTransport *tr,
|
||||
GstRTSPAddress *addr);
|
||||
GstRTSPStreamTransport * gst_rtsp_session_media_get_transport (GstRTSPSessionMedia *media,
|
||||
guint idx);
|
||||
|
||||
|
|
|
@ -70,6 +70,8 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
|
|||
|
||||
if (trans->transport)
|
||||
gst_rtsp_transport_free (trans->transport);
|
||||
if (trans->addr)
|
||||
gst_rtsp_address_free (trans->addr);
|
||||
|
||||
#if 0
|
||||
if (trans->rtpsource)
|
||||
|
@ -83,6 +85,7 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
|
|||
* gst_rtsp_stream_transport_new:
|
||||
* @stream: a #GstRTSPStream
|
||||
* @tr: (transfer full): a GstRTSPTransport
|
||||
* @addr: (transfer full) (allow none): an optional GstRTSPAddress
|
||||
*
|
||||
* Create a new #GstRTSPStreamTransport that can be used to manage
|
||||
* @stream with transport @tr.
|
||||
|
@ -90,7 +93,8 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
|
|||
* Returns: a new #GstRTSPStreamTransport
|
||||
*/
|
||||
GstRTSPStreamTransport *
|
||||
gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
|
||||
gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr,
|
||||
GstRTSPAddress * addr)
|
||||
{
|
||||
GstRTSPStreamTransport *trans;
|
||||
|
||||
|
@ -100,6 +104,7 @@ gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
|
|||
trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL);
|
||||
trans->stream = stream;
|
||||
trans->transport = tr;
|
||||
trans->addr = addr;
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
@ -154,13 +159,14 @@ gst_rtsp_stream_transport_set_keepalive (GstRTSPStreamTransport * trans,
|
|||
* gst_rtsp_stream_transport_set_transport:
|
||||
* @trans: a #GstRTSPStreamTransport
|
||||
* @tr: (transfer full): a client #GstRTSPTransport
|
||||
* @addr: (transfer full) (allow none): a ##GstRTSPAddress
|
||||
*
|
||||
* Set @ct as the client transport. This function takes ownership of
|
||||
* the passed @tr.
|
||||
* Set @tr and the optional @addr as the client transport. This function
|
||||
* takes ownership of the passed @tr and @addr.
|
||||
*/
|
||||
void
|
||||
gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
|
||||
GstRTSPTransport * tr)
|
||||
GstRTSPTransport * tr, GstRTSPAddress * addr)
|
||||
{
|
||||
g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
|
||||
g_return_if_fail (tr != NULL);
|
||||
|
@ -169,6 +175,9 @@ gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
|
|||
if (trans->transport)
|
||||
gst_rtsp_transport_free (trans->transport);
|
||||
trans->transport = tr;
|
||||
if (trans->addr)
|
||||
gst_rtsp_address_free (trans->addr);
|
||||
trans->addr = addr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,7 @@ typedef struct _GstRTSPStreamTransport GstRTSPStreamTransport;
|
|||
typedef struct _GstRTSPStreamTransportClass GstRTSPStreamTransportClass;
|
||||
|
||||
#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);
|
||||
|
@ -58,6 +59,7 @@ typedef void (*GstRTSPKeepAliveFunc) (gpointer user_data);
|
|||
* @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
|
||||
|
@ -79,6 +81,7 @@ struct _GstRTSPStreamTransport {
|
|||
gboolean timeout;
|
||||
|
||||
GstRTSPTransport *transport;
|
||||
GstRTSPAddress *addr;
|
||||
|
||||
GObject *rtpsource;
|
||||
};
|
||||
|
@ -90,10 +93,12 @@ struct _GstRTSPStreamTransportClass {
|
|||
GType gst_rtsp_stream_transport_get_type (void);
|
||||
|
||||
GstRTSPStreamTransport * gst_rtsp_stream_transport_new (GstRTSPStream *stream,
|
||||
GstRTSPTransport *tr);
|
||||
GstRTSPTransport *tr,
|
||||
GstRTSPAddress *addr);
|
||||
|
||||
void gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport *trans,
|
||||
GstRTSPTransport * tr);
|
||||
GstRTSPTransport * tr,
|
||||
GstRTSPAddress *addr);
|
||||
|
||||
void gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport *trans,
|
||||
GstRTSPSendFunc send_rtp,
|
||||
|
|
|
@ -23,11 +23,8 @@
|
|||
|
||||
GST_START_TEST (test_pool)
|
||||
{
|
||||
gpointer id;
|
||||
GstRTSPAddressPool *pool;
|
||||
gchar *address;
|
||||
guint16 port;
|
||||
guint8 ttl;
|
||||
GstRTSPAddress *addr;
|
||||
|
||||
pool = gst_rtsp_address_pool_new ();
|
||||
|
||||
|
@ -44,23 +41,18 @@ GST_START_TEST (test_pool)
|
|||
"233.255.0.0", "233.255.0.0", 5020, 5020, 1));
|
||||
|
||||
/* should fail, we can't allocate a block of 256 ports */
|
||||
id = gst_rtsp_address_pool_acquire_address (pool,
|
||||
0, 256, &address, &port, &ttl);
|
||||
fail_unless (id == NULL);
|
||||
addr = gst_rtsp_address_pool_acquire_address (pool, 0, 256);
|
||||
fail_unless (addr == NULL);
|
||||
|
||||
id = gst_rtsp_address_pool_acquire_address (pool,
|
||||
0, 2, &address, &port, &ttl);
|
||||
fail_unless (id != NULL);
|
||||
addr = gst_rtsp_address_pool_acquire_address (pool, 0, 2);
|
||||
fail_unless (addr != NULL);
|
||||
|
||||
gst_rtsp_address_pool_release_address (pool, id);
|
||||
g_free (address);
|
||||
gst_rtsp_address_free (addr);
|
||||
|
||||
id = gst_rtsp_address_pool_acquire_address (pool,
|
||||
0, 4, &address, &port, &ttl);
|
||||
fail_unless (id != NULL);
|
||||
addr = gst_rtsp_address_pool_acquire_address (pool, 0, 4);
|
||||
fail_unless (addr != NULL);
|
||||
|
||||
gst_rtsp_address_pool_release_address (pool, id);
|
||||
g_free (address);
|
||||
gst_rtsp_address_free (addr);
|
||||
|
||||
g_object_unref (pool);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue