gst_rtsp_media_set_retransmission_time
gst_rtsp_media_get_retransmission_time
+gst_rtsp_media_set_do_retransmission
+gst_rtsp_media_get_do_retransmission
+
gst_rtsp_media_set_latency
gst_rtsp_media_get_latency
gst_rtsp_media_factory_set_retransmission_time
gst_rtsp_media_factory_get_retransmission_time
+gst_rtsp_media_factory_set_do_retransmission
+gst_rtsp_media_factory_get_do_retransmission
+
gst_rtsp_media_factory_set_latency
gst_rtsp_media_factory_get_latency
gst_rtsp_stream_set_pt_map
gst_rtsp_stream_request_aux_sender
+gst_rtsp_stream_request_aux_receiver
gst_rtsp_stream_seekable
GstClockTime rtx_time;
guint latency;
+ gboolean do_retransmission;
GMutex medias_lock;
GHashTable *medias; /* protected by medias_lock */
#define DEFAULT_LATENCY 200
#define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
#define DEFAULT_STOP_ON_DISCONNECT TRUE
+#define DEFAULT_DO_RETRANSMISSION FALSE
enum
{
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
+ priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
g_mutex_init (&priv->lock);
g_mutex_init (&priv->medias_lock);
}
/**
+ * gst_rtsp_media_factory_set_do_retransmission:
+ *
+ * Set whether retransmission requests will be sent for
+ * receiving media
+ *
+ * Since: 1.16
+ */
+void
+gst_rtsp_media_factory_set_do_retransmission (GstRTSPMediaFactory * factory,
+ gboolean do_retransmission)
+{
+ GstRTSPMediaFactoryPrivate *priv;
+
+ g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
+
+ priv = factory->priv;
+
+ GST_DEBUG_OBJECT (factory, "Do retransmission %d", do_retransmission);
+
+ GST_RTSP_MEDIA_FACTORY_LOCK (factory);
+ priv->do_retransmission = do_retransmission;
+ GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+}
+
+/**
+ * gst_rtsp_media_factory_get_do_retransmission:
+ *
+ * Returns: Whether retransmission requests will be sent for receiving media
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_rtsp_media_factory_get_do_retransmission (GstRTSPMediaFactory * factory)
+{
+ GstRTSPMediaFactoryPrivate *priv;
+ gboolean res;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), 0);
+
+ priv = factory->priv;
+
+ GST_RTSP_MEDIA_FACTORY_LOCK (factory);
+ res = priv->do_retransmission;
+ GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+
+ return res;
+}
+
+/**
* gst_rtsp_media_factory_set_latency:
* @factory: a #GstRTSPMediaFactory
* @latency: latency in milliseconds
gst_rtsp_media_set_profiles (media, profiles);
gst_rtsp_media_set_protocols (media, protocols);
gst_rtsp_media_set_retransmission_time (media, rtx_time);
+ gst_rtsp_media_set_do_retransmission (media, priv->do_retransmission);
gst_rtsp_media_set_latency (media, latency);
gst_rtsp_media_set_transport_mode (media, transport_mode);
gst_rtsp_media_set_stop_on_disconnect (media, stop_on_disconnect);
GstClockTime gst_rtsp_media_factory_get_retransmission_time (GstRTSPMediaFactory * factory);
GST_RTSP_SERVER_API
+void gst_rtsp_media_factory_set_do_retransmission (GstRTSPMediaFactory * factory,
+ gboolean do_retransmission);
+
+GST_RTSP_SERVER_API
+gboolean gst_rtsp_media_factory_get_do_retransmission (GstRTSPMediaFactory * factory);
+
+GST_RTSP_SERVER_API
void gst_rtsp_media_factory_set_latency (GstRTSPMediaFactory * factory,
guint latency);
GList *payloads; /* protected by lock */
GstClockTime rtx_time; /* protected by lock */
+ gboolean do_retransmission; /* protected by lock */
guint latency; /* protected by lock */
GstClock *clock; /* protected by lock */
GstRTSPPublishClockMode publish_clock_mode;
#define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
#define DEFAULT_STOP_ON_DISCONNECT TRUE
+#define DEFAULT_DO_RETRANSMISSION FALSE
+
/* define to dump received RTCP packets */
#undef DUMP_STATS
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
+ priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
}
static void
gst_rtsp_stream_set_retransmission_time (stream, time);
}
-
- if (priv->rtpbin)
- g_object_set (priv->rtpbin, "do-retransmission", time > 0, NULL);
g_mutex_unlock (&priv->lock);
}
}
/**
+ * gst_rtsp_media_set_do_retransmission:
+ *
+ * Set whether retransmission requests will be sent
+ *
+ * Since: 1.16
+ */
+void
+gst_rtsp_media_set_do_retransmission (GstRTSPMedia * media, gboolean do_retransmission)
+{
+ GstRTSPMediaPrivate *priv;
+
+ g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+
+ priv = media->priv;
+
+ g_mutex_lock (&priv->lock);
+ priv->do_retransmission = do_retransmission;
+
+ if (priv->rtpbin)
+ g_object_set (priv->rtpbin, "do-retransmission", do_retransmission, NULL);
+ g_mutex_unlock (&priv->lock);
+}
+
+/**
+ * gst_rtsp_media_get_do_retransmission:
+ *
+ * Returns: Whether retransmission requests will be sent
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_rtsp_media_get_do_retransmission (GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv;
+ gboolean res;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
+
+ priv = media->priv;
+
+ g_mutex_lock (&priv->lock);
+ res = priv->do_retransmission;
+ g_mutex_unlock (&priv->lock);
+
+ return res;
+}
+
+/**
* gst_rtsp_media_set_latency:
* @media: a #GstRTSPMedia
* @latency: latency in milliseconds
GstRTSPMediaPrivate *priv = media->priv;
GstRTSPStream *stream = NULL;
guint i;
+ GstElement *res = NULL;
+
+ g_mutex_lock (&priv->lock);
+ for (i = 0; i < priv->streams->len; i++) {
+ stream = g_ptr_array_index (priv->streams, i);
+
+ if (sessid == gst_rtsp_stream_get_index (stream))
+ break;
+
+ stream = NULL;
+ }
+ g_mutex_unlock (&priv->lock);
+
+ if (stream)
+ res = gst_rtsp_stream_request_aux_sender (stream, sessid);
+
+ return res;
+}
+
+static GstElement *
+request_aux_receiver (GstElement * rtpbin, guint sessid, GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv = media->priv;
+ GstRTSPStream *stream = NULL;
+ guint i;
+ GstElement *res = NULL;
g_mutex_lock (&priv->lock);
for (i = 0; i < priv->streams->len; i++) {
if (sessid == gst_rtsp_stream_get_index (stream))
break;
+
+ stream = NULL;
}
g_mutex_unlock (&priv->lock);
- return gst_rtsp_stream_request_aux_sender (stream, sessid);
+ if (stream)
+ res = gst_rtsp_stream_request_aux_receiver (stream, sessid);
+
+ return res;
}
static gboolean
(GCallback) request_aux_sender, media);
}
+ if (priv->do_retransmission) {
+ g_signal_connect (priv->rtpbin, "request-aux-receiver",
+ (GCallback) request_aux_receiver, media);
+ }
+
if (!gst_rtsp_stream_join_bin (stream, GST_BIN (priv->pipeline),
priv->rtpbin, GST_STATE_NULL)) {
goto join_bin_failed;
}
if (priv->rtpbin)
- g_object_set (priv->rtpbin, "do-retransmission", priv->rtx_time > 0, NULL);
+ g_object_set (priv->rtpbin, "do-retransmission", priv->do_retransmission, NULL);
for (walk = priv->dynamic; walk; walk = g_list_next (walk)) {
GstElement *elem = walk->data;
GstClockTime gst_rtsp_media_get_retransmission_time (GstRTSPMedia *media);
GST_RTSP_SERVER_API
+void gst_rtsp_media_set_do_retransmission (GstRTSPMedia * media,
+ gboolean do_retransmission);
+
+GST_RTSP_SERVER_API
+gboolean gst_rtsp_media_get_do_retransmission (GstRTSPMedia * media);
+
+GST_RTSP_SERVER_API
void gst_rtsp_media_set_latency (GstRTSPMedia *media, guint latency);
GST_RTSP_SERVER_API
/* retransmission */
GstElement *rtxsend;
+ GstElement *rtxreceive;
guint rtx_pt;
GstClockTime rtx_time;
g_object_unref (priv->pool);
if (priv->rtxsend)
g_object_unref (priv->rtxsend);
+ if (priv->rtxreceive)
+ g_object_unref (priv->rtxreceive);
for (i = 0; i < 2; i++) {
if (priv->socket_v4[i])
return bin;
}
+static void
+add_rtx_pt (gpointer key, GstCaps *caps, GstStructure *pt_map)
+{
+ guint pt = GPOINTER_TO_INT (key);
+ const GstStructure *s = gst_caps_get_structure (caps, 0);
+ const gchar *apt;
+
+ if (!g_strcmp0 (gst_structure_get_string (s, "encoding-name"), "RTX") &&
+ (apt = gst_structure_get_string (s, "apt"))) {
+ gst_structure_set (pt_map, apt, G_TYPE_UINT, pt, NULL);
+ }
+}
+
+/* Call with priv->lock taken */
+static void
+update_rtx_receive_pt_map (GstRTSPStream * stream)
+{
+ GstStructure *pt_map;
+
+ if (!stream->priv->rtxreceive)
+ goto done;
+
+ pt_map = gst_structure_new_empty ("application/x-rtp-pt-map");
+ g_hash_table_foreach (stream->priv->ptmap, (GHFunc) add_rtx_pt, pt_map);
+ g_object_set (stream->priv->rtxreceive, "payload-type-map", pt_map, NULL);
+ gst_structure_free (pt_map);
+
+done:
+ return;
+}
+
+/**
+ * gst_rtsp_stream_request_aux_receiver:
+ * @stream: a #GstRTSPStream
+ * @sessid: the session id
+ *
+ * Creating a rtxreceive bin
+ *
+ * Returns: (transfer full) (nullable): a #GstElement.
+ *
+ * Since: 1.16
+ */
+GstElement *
+gst_rtsp_stream_request_aux_receiver (GstRTSPStream * stream, guint sessid)
+{
+ GstElement *bin;
+ GstPad *pad;
+ gchar *name;
+
+ g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL);
+
+ g_mutex_lock (&stream->priv->lock);
+
+ bin = gst_bin_new (NULL);
+ stream->priv->rtxreceive = gst_element_factory_make ("rtprtxreceive", NULL);
+ update_rtx_receive_pt_map (stream);
+ gst_bin_add (GST_BIN (bin), gst_object_ref (stream->priv->rtxreceive));
+
+ pad = gst_element_get_static_pad (stream->priv->rtxreceive, "src");
+ name = g_strdup_printf ("src_%u", sessid);
+ gst_element_add_pad (bin, gst_ghost_pad_new (name, pad));
+ g_free (name);
+ gst_object_unref (pad);
+
+ pad = gst_element_get_static_pad (stream->priv->rtxreceive, "sink");
+ name = g_strdup_printf ("sink_%u", sessid);
+ gst_element_add_pad (bin, gst_ghost_pad_new (name, pad));
+ g_free (name);
+ gst_object_unref (pad);
+
+ g_mutex_unlock (&stream->priv->lock);
+
+ return bin;
+}
+
/**
* gst_rtsp_stream_set_pt_map:
* @stream: a #GstRTSPStream
g_mutex_lock (&priv->lock);
g_hash_table_insert (priv->ptmap, GINT_TO_POINTER (pt), gst_caps_ref (caps));
+ update_rtx_receive_pt_map (stream);
g_mutex_unlock (&priv->lock);
}
GstElement * gst_rtsp_stream_request_aux_sender (GstRTSPStream * stream, guint sessid);
GST_RTSP_SERVER_API
+GstElement * gst_rtsp_stream_request_aux_receiver (GstRTSPStream * stream, guint sessid);
+
+GST_RTSP_SERVER_API
gboolean gst_rtsp_stream_allocate_udp_sockets (GstRTSPStream * stream, GSocketFamily family,
GstRTSPTransport *transport, gboolean use_client_settings);