mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-09-04 11:14:10 +00:00
basesink: Add processing deadline
The processing deadline is the acceptable amount of time to process the media in a live pipeline before it reaches the sink. This is on top of the algorithmic latency that is normally reported by the latency query. This should make pipelines such as "v4lsrc ! xvimagesink" not claim that all frames are late in the QoS events. Ideally, this should replace max_lateness for most applications. https://bugzilla.gnome.org/show_bug.cgi?id=640610
This commit is contained in:
parent
cd3e55c38e
commit
a7f9c80220
2 changed files with 109 additions and 1 deletions
|
@ -178,6 +178,7 @@ struct _GstBaseSinkPrivate
|
||||||
gboolean async_enabled;
|
gboolean async_enabled;
|
||||||
GstClockTimeDiff ts_offset;
|
GstClockTimeDiff ts_offset;
|
||||||
GstClockTime render_delay;
|
GstClockTime render_delay;
|
||||||
|
GstClockTime processing_deadline;
|
||||||
|
|
||||||
/* start, stop of current buffer, stream time, used to report position */
|
/* start, stop of current buffer, stream time, used to report position */
|
||||||
GstClockTime current_sstart;
|
GstClockTime current_sstart;
|
||||||
|
@ -287,6 +288,7 @@ struct _GstBaseSinkPrivate
|
||||||
#define DEFAULT_THROTTLE_TIME 0
|
#define DEFAULT_THROTTLE_TIME 0
|
||||||
#define DEFAULT_MAX_BITRATE 0
|
#define DEFAULT_MAX_BITRATE 0
|
||||||
#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE
|
#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE
|
||||||
|
#define DEFAULT_PROCESSING_DEADLINE (20 * GST_MSECOND)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -302,6 +304,7 @@ enum
|
||||||
PROP_RENDER_DELAY,
|
PROP_RENDER_DELAY,
|
||||||
PROP_THROTTLE_TIME,
|
PROP_THROTTLE_TIME,
|
||||||
PROP_MAX_BITRATE,
|
PROP_MAX_BITRATE,
|
||||||
|
PROP_PROCESSING_DEADLINE,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -536,6 +539,20 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
|
||||||
"The maximum bits per second to render (0 = disabled)", 0,
|
"The maximum bits per second to render (0 = disabled)", 0,
|
||||||
G_MAXUINT64, DEFAULT_MAX_BITRATE,
|
G_MAXUINT64, DEFAULT_MAX_BITRATE,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
/**
|
||||||
|
* GstBaseSink:processing-deadline:
|
||||||
|
*
|
||||||
|
* Maximum amount of time (in nanoseconds) that the pipeline can take
|
||||||
|
* for processing the buffer. This is added to the latency of live
|
||||||
|
* pipelines.
|
||||||
|
*
|
||||||
|
* Since: 1.16
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PROCESSING_DEADLINE,
|
||||||
|
g_param_spec_uint64 ("processing-deadline", "Processing deadline",
|
||||||
|
"Maximum processing deadline in nanoseconds", 0, G_MAXUINT64,
|
||||||
|
DEFAULT_PROCESSING_DEADLINE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
|
GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
|
||||||
|
@ -662,6 +679,7 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
|
||||||
priv->async_enabled = DEFAULT_ASYNC;
|
priv->async_enabled = DEFAULT_ASYNC;
|
||||||
priv->ts_offset = DEFAULT_TS_OFFSET;
|
priv->ts_offset = DEFAULT_TS_OFFSET;
|
||||||
priv->render_delay = DEFAULT_RENDER_DELAY;
|
priv->render_delay = DEFAULT_RENDER_DELAY;
|
||||||
|
priv->processing_deadline = DEFAULT_PROCESSING_DEADLINE;
|
||||||
priv->blocksize = DEFAULT_BLOCKSIZE;
|
priv->blocksize = DEFAULT_BLOCKSIZE;
|
||||||
priv->cached_clock_id = NULL;
|
priv->cached_clock_id = NULL;
|
||||||
g_atomic_int_set (&priv->enable_last_sample, DEFAULT_ENABLE_LAST_SAMPLE);
|
g_atomic_int_set (&priv->enable_last_sample, DEFAULT_ENABLE_LAST_SAMPLE);
|
||||||
|
@ -1150,7 +1168,7 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
|
||||||
GstClockTime * max_latency)
|
GstClockTime * max_latency)
|
||||||
{
|
{
|
||||||
gboolean l, us_live, res, have_latency;
|
gboolean l, us_live, res, have_latency;
|
||||||
GstClockTime min, max, render_delay;
|
GstClockTime min, max, render_delay, processing_deadline;
|
||||||
GstQuery *query;
|
GstQuery *query;
|
||||||
GstClockTime us_min, us_max;
|
GstClockTime us_min, us_max;
|
||||||
|
|
||||||
|
@ -1159,6 +1177,7 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
|
||||||
l = sink->sync;
|
l = sink->sync;
|
||||||
have_latency = sink->priv->have_latency;
|
have_latency = sink->priv->have_latency;
|
||||||
render_delay = sink->priv->render_delay;
|
render_delay = sink->priv->render_delay;
|
||||||
|
processing_deadline = sink->priv->processing_deadline;
|
||||||
GST_OBJECT_UNLOCK (sink);
|
GST_OBJECT_UNLOCK (sink);
|
||||||
|
|
||||||
/* assume no latency */
|
/* assume no latency */
|
||||||
|
@ -1188,6 +1207,22 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
|
||||||
min += render_delay;
|
min += render_delay;
|
||||||
if (max != -1)
|
if (max != -1)
|
||||||
max += render_delay;
|
max += render_delay;
|
||||||
|
|
||||||
|
if (max == -1 || min + processing_deadline <= max)
|
||||||
|
min += processing_deadline;
|
||||||
|
else {
|
||||||
|
GST_ELEMENT_WARNING (sink, CORE, CLOCK,
|
||||||
|
(_("Pipeline construction is invalid, please add queues.")),
|
||||||
|
("Not enough buffering available for "
|
||||||
|
" the processing deadline of %" GST_TIME_FORMAT
|
||||||
|
", add enough queues to buffer %" GST_TIME_FORMAT
|
||||||
|
" additional data. Shortening processing latency to %"
|
||||||
|
GST_TIME_FORMAT ".",
|
||||||
|
GST_TIME_ARGS (processing_deadline),
|
||||||
|
GST_TIME_ARGS (min + processing_deadline - max),
|
||||||
|
GST_TIME_ARGS (max - min)));
|
||||||
|
min = max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gst_query_unref (query);
|
gst_query_unref (query);
|
||||||
|
@ -1413,6 +1448,66 @@ gst_base_sink_get_max_bitrate (GstBaseSink * sink)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_sink_set_processing_deadline:
|
||||||
|
* @sink: a #GstBaseSink
|
||||||
|
* @delay: the new processing deadline in nanoseconds.
|
||||||
|
*
|
||||||
|
* Maximum amount of time (in nanoseconds) that the pipeline can take
|
||||||
|
* for processing the buffer. This is added to the latency of live
|
||||||
|
* pipelines.
|
||||||
|
*
|
||||||
|
* This function is usually called by subclasses.
|
||||||
|
*
|
||||||
|
* Since: 1.16
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_base_sink_set_processing_deadline (GstBaseSink * sink, GstClockTime delay)
|
||||||
|
{
|
||||||
|
GstClockTime old_processing_deadline;
|
||||||
|
|
||||||
|
g_return_if_fail (GST_IS_BASE_SINK (sink));
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (sink);
|
||||||
|
old_processing_deadline = sink->priv->processing_deadline;
|
||||||
|
sink->priv->processing_deadline = delay;
|
||||||
|
GST_LOG_OBJECT (sink, "set render delay to %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (delay));
|
||||||
|
GST_OBJECT_UNLOCK (sink);
|
||||||
|
|
||||||
|
if (delay != old_processing_deadline) {
|
||||||
|
GST_DEBUG_OBJECT (sink, "posting latency changed");
|
||||||
|
gst_element_post_message (GST_ELEMENT_CAST (sink),
|
||||||
|
gst_message_new_latency (GST_OBJECT_CAST (sink)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_sink_get_processing_deadline:
|
||||||
|
* @sink: a #GstBaseSink
|
||||||
|
*
|
||||||
|
* Get the processing deadline of @sink. see
|
||||||
|
* gst_base_sink_set_processing_deadline() for more information about
|
||||||
|
* the processing deadline.
|
||||||
|
*
|
||||||
|
* Returns: the processing deadline
|
||||||
|
*
|
||||||
|
* Since: 1.16
|
||||||
|
*/
|
||||||
|
GstClockTime
|
||||||
|
gst_base_sink_get_processing_deadline (GstBaseSink * sink)
|
||||||
|
{
|
||||||
|
GstClockTimeDiff res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (sink);
|
||||||
|
res = sink->priv->processing_deadline;
|
||||||
|
GST_OBJECT_UNLOCK (sink);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_base_sink_set_property (GObject * object, guint prop_id,
|
gst_base_sink_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec)
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
@ -1450,6 +1545,9 @@ gst_base_sink_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_MAX_BITRATE:
|
case PROP_MAX_BITRATE:
|
||||||
gst_base_sink_set_max_bitrate (sink, g_value_get_uint64 (value));
|
gst_base_sink_set_max_bitrate (sink, g_value_get_uint64 (value));
|
||||||
break;
|
break;
|
||||||
|
case PROP_PROCESSING_DEADLINE:
|
||||||
|
gst_base_sink_set_processing_deadline (sink, g_value_get_uint64 (value));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -1496,6 +1594,9 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_MAX_BITRATE:
|
case PROP_MAX_BITRATE:
|
||||||
g_value_set_uint64 (value, gst_base_sink_get_max_bitrate (sink));
|
g_value_set_uint64 (value, gst_base_sink_get_max_bitrate (sink));
|
||||||
break;
|
break;
|
||||||
|
case PROP_PROCESSING_DEADLINE:
|
||||||
|
g_value_set_uint64 (value, gst_base_sink_get_processing_deadline (sink));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -310,6 +310,13 @@ void gst_base_sink_set_max_bitrate (GstBaseSink *sink, guint64 max_
|
||||||
GST_BASE_API
|
GST_BASE_API
|
||||||
guint64 gst_base_sink_get_max_bitrate (GstBaseSink *sink);
|
guint64 gst_base_sink_get_max_bitrate (GstBaseSink *sink);
|
||||||
|
|
||||||
|
/* processing deadline */
|
||||||
|
GST_BASE_API
|
||||||
|
void gst_base_sink_set_processing_deadline (GstBaseSink *sink, GstClockTime processing_deadline);
|
||||||
|
|
||||||
|
GST_BASE_API
|
||||||
|
GstClockTime gst_base_sink_get_processing_deadline (GstBaseSink *sink);
|
||||||
|
|
||||||
GST_BASE_API
|
GST_BASE_API
|
||||||
GstClockReturn gst_base_sink_wait_clock (GstBaseSink *sink, GstClockTime time,
|
GstClockReturn gst_base_sink_wait_clock (GstBaseSink *sink, GstClockTime time,
|
||||||
GstClockTimeDiff * jitter);
|
GstClockTimeDiff * jitter);
|
||||||
|
|
Loading…
Reference in a new issue