guint buffer_size;
GstRTSPAddressPool *pool;
gboolean blocked;
- gboolean record;
+ GstRTSPTransportMode transport_mode;
GstElement *element;
GRecMutex state_lock; /* locking order: state lock, lock */
GList *payloads; /* protected by lock */
GstClockTime rtx_time; /* protected by lock */
+ guint latency; /* protected by lock */
};
#define DEFAULT_SHARED FALSE
#define DEFAULT_EOS_SHUTDOWN FALSE
#define DEFAULT_BUFFER_SIZE 0x80000
#define DEFAULT_TIME_PROVIDER FALSE
-#define DEFAULT_RECORD FALSE
+#define DEFAULT_LATENCY 200
+#define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
/* define to dump received RTCP packets */
#undef DUMP_STATS
PROP_BUFFER_SIZE,
PROP_ELEMENT,
PROP_TIME_PROVIDER,
- PROP_RECORD,
+ PROP_LATENCY,
+ PROP_TRANSPORT_MODE,
PROP_LAST
};
#define C_ENUM(v) ((gint) v)
-#define GST_TYPE_RTSP_SUSPEND_MODE (gst_rtsp_suspend_mode_get_type())
GType
gst_rtsp_suspend_mode_get_type (void)
{
return (GType) id;
}
+#define C_FLAGS(v) ((guint) v)
+
+GType
+gst_rtsp_transport_mode_get_type (void)
+{
+ static gsize id = 0;
+ static const GFlagsValue values[] = {
+ {C_FLAGS (GST_RTSP_TRANSPORT_MODE_PLAY), "GST_RTSP_TRANSPORT_MODE_PLAY",
+ "play"},
+ {C_FLAGS (GST_RTSP_TRANSPORT_MODE_RECORD), "GST_RTSP_TRANSPORT_MODE_RECORD",
+ "record"},
+ {0, NULL, NULL}
+ };
+
+ if (g_once_init_enter (&id)) {
+ GType tmp = g_flags_register_static ("GstRTSPTransportMode", values);
+ g_once_init_leave (&id, tmp);
+ }
+ return (GType) id;
+}
+
G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
static void
"Use a NetTimeProvider for clients",
DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_RECORD,
- g_param_spec_boolean ("record", "Record",
+ g_object_class_install_property (gobject_class, PROP_LATENCY,
+ g_param_spec_uint ("latency", "Latency",
+ "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
+ DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
+ g_param_spec_flags ("transport-mode", "Transport Mode",
"If this media pipeline can be used for PLAY or RECORD",
- DEFAULT_RECORD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
priv->buffer_size = DEFAULT_BUFFER_SIZE;
priv->time_provider = DEFAULT_TIME_PROVIDER;
- priv->record = DEFAULT_RECORD;
+ priv->transport_mode = DEFAULT_TRANSPORT_MODE;
}
static void
case PROP_TIME_PROVIDER:
g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
break;
- case PROP_RECORD:
- g_value_set_boolean (value, gst_rtsp_media_is_record (media));
+ case PROP_LATENCY:
+ g_value_set_uint (value, gst_rtsp_media_get_latency (media));
+ break;
+ case PROP_TRANSPORT_MODE:
+ g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
case PROP_TIME_PROVIDER:
gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
break;
- case PROP_RECORD:
- gst_rtsp_media_set_record (media, g_value_get_boolean (value));
+ case PROP_LATENCY:
+ gst_rtsp_media_set_latency (media, g_value_get_uint (value));
+ break;
+ case PROP_TRANSPORT_MODE:
+ gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
/**
+ * gst_rtsp_media_set_latncy:
+ * @media: a #GstRTSPMedia
+ * @latency: latency in milliseconds
+ *
+ * Configure the latency used for receiving media.
+ */
+void
+gst_rtsp_media_set_latency (GstRTSPMedia * media, guint latency)
+{
+ GstRTSPMediaPrivate *priv;
+
+ g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+
+ GST_LOG_OBJECT (media, "set latency %ums", latency);
+
+ priv = media->priv;
+
+ g_mutex_lock (&priv->lock);
+ priv->latency = latency;
+ if (priv->rtpbin)
+ g_object_set (priv->rtpbin, "latency", latency, NULL);
+ g_mutex_unlock (&priv->lock);
+}
+
+/**
+ * gst_rtsp_media_get_latency:
+ * @media: a #GstRTSPMedia
+ *
+ * Get the latency that is used for receiving media.
+ *
+ * Returns: latency in milliseconds
+ */
+guint
+gst_rtsp_media_get_latency (GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv;
+ guint res;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+
+ priv = media->priv;
+
+ g_mutex_unlock (&priv->lock);
+ res = priv->latency;
+ g_mutex_unlock (&priv->lock);
+
+ return res;
+}
+
+/**
* gst_rtsp_media_use_time_provider:
* @media: a #GstRTSPMedia
* @time_provider: if a #GstNetTimeProvider should be used
GstPad *pad;
gint i;
gboolean have_elem;
+ GstRTSPTransportMode mode = 0;
g_return_if_fail (GST_IS_RTSP_MEDIA (media));
gst_object_unref (elem);
have_elem = TRUE;
+ mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
}
g_free (name);
g_mutex_unlock (&priv->lock);
have_elem = TRUE;
+ mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
}
g_free (name);
gst_object_unref (elem);
have_elem = TRUE;
+ mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
}
g_free (name);
}
+
+ if (have_elem) {
+ if (priv->transport_mode != mode)
+ GST_WARNING ("found different mode than expected (0x%02x != 0x%02d)",
+ priv->transport_mode, mode);
+ }
}
/**
goto not_prepared;
/* Update the seekable state of the pipeline in case it changed */
- if (gst_rtsp_media_is_record (media)) {
+ if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
/* TODO: Seeking for RECORD? */
priv->seekable = FALSE;
} else {
GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
gst_element_state_get_name (old), gst_element_state_get_name (new),
gst_element_state_get_name (pending));
- if (gst_rtsp_media_is_record (media)
+ if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)
&& old == GST_STATE_READY && new == GST_STATE_PAUSED) {
GST_INFO ("%p: went to PAUSED, prepared now", media);
collect_media_stats (media);
* seeking query in preroll instead */
priv->seekable = FALSE;
priv->is_live = TRUE;
- if (!gst_rtsp_media_is_record (media)) {
+ if (!(priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
/* start blocked to make sure nothing goes to the sink */
media_streams_set_blocked (media, TRUE);
}
if (priv->rtpbin != NULL) {
gboolean success = TRUE;
+ g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
+
if (klass->setup_rtpbin)
success = klass->setup_rtpbin (media, priv->rtpbin);
}
/**
- * gst_rtsp_media_set_record:
+ * gst_rtsp_media_set_transport_mode:
* @media: a #GstRTSPMedia
- * @record: the new value
+ * @mode: the new value
*
- * Set or unset if the pipeline for @media can be used for PLAY or RECORD
- * methods.
+ * Sets if the media pipeline can work in PLAY or RECORD mode
*/
void
-gst_rtsp_media_set_record (GstRTSPMedia * media, gboolean record)
+gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
+ GstRTSPTransportMode mode)
{
GstRTSPMediaPrivate *priv;
priv = media->priv;
g_mutex_lock (&priv->lock);
- priv->record = record;
+ priv->transport_mode = mode;
g_mutex_unlock (&priv->lock);
}
/**
- * gst_rtsp_media_is_record:
+ * gst_rtsp_media_get_transport_mode:
* @media: a #GstRTSPMedia
*
* Check if the pipeline for @media can be used for PLAY or RECORD methods.
*
- * Returns: %TRUE if the media can be record between clients.
+ * Returns: The transport mode.
*/
-gboolean
-gst_rtsp_media_is_record (GstRTSPMedia * media)
+GstRTSPTransportMode
+gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
{
GstRTSPMediaPrivate *priv;
- gboolean res;
+ GstRTSPTransportMode res;
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
priv = media->priv;
g_mutex_lock (&priv->lock);
- res = priv->record;
+ res = priv->transport_mode;
g_mutex_unlock (&priv->lock);
return res;