gst_rtsp_media_signals[SIGNAL_PREPARED] =
g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+ g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+ g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
gst_rtsp_media_signals[SIGNAL_TARGET_STATE] =
g_signal_new ("target-state", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL,
- NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, target_state),
+ NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
gst_rtsp_media_signals[SIGNAL_NEW_STATE] =
g_signal_new ("new-state", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL,
- g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+ g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT);
GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia");
}
}
+typedef struct
+{
+ gint64 position;
+ gboolean ret;
+} DoQueryPositionData;
+
+static void
+do_query_position (GstRTSPStream * stream, DoQueryPositionData * data)
+{
+ gint64 tmp;
+
+ if (gst_rtsp_stream_query_position (stream, &tmp)) {
+ data->position = MAX (data->position, tmp);
+ data->ret = TRUE;
+ }
+}
+
static gboolean
default_query_position (GstRTSPMedia * media, gint64 * position)
{
- return gst_element_query_position (media->priv->pipeline, GST_FORMAT_TIME,
- position);
+ GstRTSPMediaPrivate *priv;
+ DoQueryPositionData data;
+
+ priv = media->priv;
+
+ data.position = -1;
+ data.ret = FALSE;
+
+ g_ptr_array_foreach (priv->streams, (GFunc) do_query_position, &data);
+
+ *position = data.position;
+
+ return data.ret;
+}
+
+typedef struct
+{
+ gint64 stop;
+ gboolean ret;
+} DoQueryStopData;
+
+static void
+do_query_stop (GstRTSPStream * stream, DoQueryStopData * data)
+{
+ gint64 tmp;
+
+ if (gst_rtsp_stream_query_stop (stream, &tmp)) {
+ data->stop = MAX (data->stop, tmp);
+ data->ret = TRUE;
+ }
}
static gboolean
default_query_stop (GstRTSPMedia * media, gint64 * stop)
{
- GstQuery *query;
- gboolean res;
+ GstRTSPMediaPrivate *priv;
+ DoQueryStopData data;
- query = gst_query_new_segment (GST_FORMAT_TIME);
- if ((res = gst_element_query (media->priv->pipeline, query))) {
- GstFormat format;
- gst_query_parse_segment (query, NULL, &format, NULL, stop);
- if (format != GST_FORMAT_TIME)
- *stop = -1;
- }
- gst_query_unref (query);
- return res;
+ priv = media->priv;
+
+ data.stop = -1;
+ data.ret = FALSE;
+
+ g_ptr_array_foreach (priv->streams, (GFunc) do_query_stop, &data);
+
+ *stop = data.stop;
+
+ return data.ret;
}
static GstElement *
collect_media_stats (GstRTSPMedia * media)
{
GstRTSPMediaPrivate *priv = media->priv;
- gint64 position, stop;
+ gint64 position = 0, stop = -1;
if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED &&
priv->status != GST_RTSP_MEDIA_STATUS_PREPARING)
*
* Retrieve the stream with index @idx from @media.
*
- * Returns: (transfer none): the #GstRTSPStream at index @idx or %NULL when a stream with
- * that index did not exist.
+ * Returns: (nullable) (transfer none): the #GstRTSPStream at index
+ * @idx or %NULL when a stream with that index did not exist.
*/
GstRTSPStream *
gst_rtsp_media_get_stream (GstRTSPMedia * media, guint idx)
*
* Find a stream in @media with @control as the control uri.
*
- * Returns: (transfer none): the #GstRTSPStream with control uri @control
- * or %NULL when a stream with that control did not exist.
+ * Returns: (nullable) (transfer none): the #GstRTSPStream with
+ * control uri @control or %NULL when a stream with that control did
+ * not exist.
*/
GstRTSPStream *
gst_rtsp_media_find_stream (GstRTSPMedia * media, const gchar * control)
/**
* gst_rtsp_media_prepare:
* @media: a #GstRTSPMedia
- * @thread: (transfer full): a #GstRTSPThread to run the bus handler or %NULL
+ * @thread: (transfer full) (allow-none): a #GstRTSPThread to run the
+ * bus handler or %NULL
*
* Prepare @media for streaming. This function will create the objects
* to manage the streaming. A pipeline must have been set on @media with
/**
* gst_rtsp_media_get_time_provider:
* @media: a #GstRTSPMedia
- * @address: an address or %NULL
+ * @address: (allow-none): an address or %NULL
* @port: a port or 0
*
* Get the #GstNetTimeProvider for the clock used by @media. The time provider
}
}
+static void
+do_set_seqnum (GstRTSPStream * stream)
+{
+ guint16 seq_num;
+ seq_num = gst_rtsp_stream_get_current_seqnum (stream);
+ gst_rtsp_stream_set_seqnum_offset (stream, seq_num + 1);
+}
+
/* call with state_lock */
gboolean
default_suspend (GstRTSPMedia * media)
ret = set_target_state (media, GST_STATE_NULL, TRUE);
if (ret == GST_STATE_CHANGE_FAILURE)
goto state_failed;
+ /* Because payloader needs to set the sequence number as
+ * monotonic, we need to preserve the sequence number
+ * after pause. (otherwise going from pause to play, which
+ * is actually from NULL to PLAY will create a new sequence
+ * number. */
+ g_ptr_array_foreach (priv->streams, (GFunc) do_set_seqnum, NULL);
break;
default:
break;