mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
Add a new last-buffer property that contains the last buffer used in basesink for preroll or rendering. useful for ma...
Original commit message from CVS: * docs/libs/gstreamer-libs-sections.txt: * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), (gst_base_sink_get_last_buffer), (gst_base_sink_set_last_buffer), (gst_base_sink_get_property), (gst_base_sink_render_object), (gst_base_sink_preroll_object), (gst_base_sink_queue_object_unlocked), (gst_base_sink_event), (gst_base_sink_change_state): * libs/gst/base/gstbasesink.h: Add a new last-buffer property that contains the last buffer used in basesink for preroll or rendering. useful for making snapshots. API: gst_base_sink_get_last_buffer() API: GstBaseSink::last-buffer
This commit is contained in:
parent
7da5577459
commit
2715cf6e28
4 changed files with 120 additions and 25 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
||||||
|
2007-10-30 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
|
||||||
|
* docs/libs/gstreamer-libs-sections.txt:
|
||||||
|
* libs/gst/base/gstbasesink.c: (gst_base_sink_class_init),
|
||||||
|
(gst_base_sink_get_last_buffer), (gst_base_sink_set_last_buffer),
|
||||||
|
(gst_base_sink_get_property), (gst_base_sink_render_object),
|
||||||
|
(gst_base_sink_preroll_object),
|
||||||
|
(gst_base_sink_queue_object_unlocked), (gst_base_sink_event),
|
||||||
|
(gst_base_sink_change_state):
|
||||||
|
* libs/gst/base/gstbasesink.h:
|
||||||
|
Add a new last-buffer property that contains the last buffer used in
|
||||||
|
basesink for preroll or rendering. useful for making snapshots.
|
||||||
|
API: gst_base_sink_get_last_buffer()
|
||||||
|
API: GstBaseSink::last-buffer
|
||||||
|
|
||||||
2007-10-29 Stefan Kost <ensonic@users.sf.net>
|
2007-10-29 Stefan Kost <ensonic@users.sf.net>
|
||||||
|
|
||||||
* docs/gst/running.xml:
|
* docs/gst/running.xml:
|
||||||
|
|
|
@ -271,6 +271,7 @@ gst_base_sink_set_async_enabled
|
||||||
gst_base_sink_is_async_enabled
|
gst_base_sink_is_async_enabled
|
||||||
gst_base_sink_set_ts_offset
|
gst_base_sink_set_ts_offset
|
||||||
gst_base_sink_get_ts_offset
|
gst_base_sink_get_ts_offset
|
||||||
|
gst_base_sink_get_last_buffer
|
||||||
|
|
||||||
GST_BASE_SINK_PAD
|
GST_BASE_SINK_PAD
|
||||||
|
|
||||||
|
|
|
@ -207,6 +207,9 @@ struct _GstBaseSinkPrivate
|
||||||
|
|
||||||
/* when we are prerolled and able to report latency */
|
/* when we are prerolled and able to report latency */
|
||||||
gboolean have_latency;
|
gboolean have_latency;
|
||||||
|
|
||||||
|
/* the last buffer we prerolled or rendered. Useful for making snapshots */
|
||||||
|
GstBuffer *last_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
|
#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
|
||||||
|
@ -241,7 +244,9 @@ enum
|
||||||
PROP_MAX_LATENESS,
|
PROP_MAX_LATENESS,
|
||||||
PROP_QOS,
|
PROP_QOS,
|
||||||
PROP_ASYNC,
|
PROP_ASYNC,
|
||||||
PROP_TS_OFFSET
|
PROP_TS_OFFSET,
|
||||||
|
PROP_LAST_BUFFER,
|
||||||
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
static GstElementClass *parent_class = NULL;
|
||||||
|
@ -383,6 +388,19 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
|
||||||
"Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64,
|
"Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64,
|
||||||
DEFAULT_TS_OFFSET, G_PARAM_READWRITE));
|
DEFAULT_TS_OFFSET, G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstBaseSink:last-buffer
|
||||||
|
*
|
||||||
|
* The last buffer that arrived in the sink and was used for preroll or for
|
||||||
|
* rendering. This property can be used to generate thumbnails.
|
||||||
|
*
|
||||||
|
* Since: 0.10.15
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_LAST_BUFFER,
|
||||||
|
gst_param_spec_mini_object ("last-buffer", "Last Buffer",
|
||||||
|
"The last buffer received in the sink", GST_TYPE_BUFFER,
|
||||||
|
G_PARAM_READABLE));
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
|
GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
|
||||||
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event);
|
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event);
|
||||||
|
@ -783,6 +801,44 @@ gst_base_sink_get_ts_offset (GstBaseSink * sink)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_sink_get_last_buffer:
|
||||||
|
* @sink: the sink
|
||||||
|
*
|
||||||
|
* Get the last buffer that arrived in the sink and was used for preroll or for
|
||||||
|
* rendering. This property can be used to generate thumbnails.
|
||||||
|
*
|
||||||
|
* The #GstCaps on the buffer can be used to determine the type of the buffer.
|
||||||
|
*
|
||||||
|
* Returns: a #GstBuffer. gst_buffer_unref() after usage. This function returns
|
||||||
|
* NULL when no buffer has arrived in the sink yet or when the sink is not in
|
||||||
|
* PAUSED or PLAYING.
|
||||||
|
*
|
||||||
|
* Since: 0.10.15
|
||||||
|
*/
|
||||||
|
GstBuffer *
|
||||||
|
gst_base_sink_get_last_buffer (GstBaseSink * sink)
|
||||||
|
{
|
||||||
|
GstBuffer *res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_BASE_SINK (sink), NULL);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (sink);
|
||||||
|
if ((res = sink->priv->last_buffer))
|
||||||
|
gst_buffer_ref (res);
|
||||||
|
GST_OBJECT_UNLOCK (sink);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_base_sink_set_last_buffer (GstBaseSink * sink, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GST_OBJECT_LOCK (sink);
|
||||||
|
gst_buffer_replace (&sink->priv->last_buffer, buffer);
|
||||||
|
GST_OBJECT_UNLOCK (sink);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_base_sink_get_latency:
|
* gst_base_sink_get_latency:
|
||||||
* @sink: the sink
|
* @sink: the sink
|
||||||
|
@ -963,6 +1019,9 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_TS_OFFSET:
|
case PROP_TS_OFFSET:
|
||||||
g_value_set_int64 (value, gst_base_sink_get_ts_offset (sink));
|
g_value_set_int64 (value, gst_base_sink_get_ts_offset (sink));
|
||||||
break;
|
break;
|
||||||
|
case PROP_LAST_BUFFER:
|
||||||
|
gst_value_take_buffer (value, gst_base_sink_get_last_buffer (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;
|
||||||
|
@ -1938,10 +1997,16 @@ gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,
|
||||||
|
|
||||||
/* and now render, event or buffer. */
|
/* and now render, event or buffer. */
|
||||||
if (G_LIKELY (GST_IS_BUFFER (obj))) {
|
if (G_LIKELY (GST_IS_BUFFER (obj))) {
|
||||||
|
GstBuffer *buf;
|
||||||
|
|
||||||
/* drop late buffers unconditionally, let's hope it's unlikely */
|
/* drop late buffers unconditionally, let's hope it's unlikely */
|
||||||
if (G_UNLIKELY (late))
|
if (G_UNLIKELY (late))
|
||||||
goto dropped;
|
goto dropped;
|
||||||
|
|
||||||
|
buf = GST_BUFFER_CAST (obj);
|
||||||
|
|
||||||
|
gst_base_sink_set_last_buffer (basesink, buf);
|
||||||
|
|
||||||
bclass = GST_BASE_SINK_GET_CLASS (basesink);
|
bclass = GST_BASE_SINK_GET_CLASS (basesink);
|
||||||
|
|
||||||
if (G_LIKELY (bclass->render)) {
|
if (G_LIKELY (bclass->render)) {
|
||||||
|
@ -1956,7 +2021,7 @@ gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,
|
||||||
if (do_qos)
|
if (do_qos)
|
||||||
gst_base_sink_do_render_stats (basesink, TRUE);
|
gst_base_sink_do_render_stats (basesink, TRUE);
|
||||||
|
|
||||||
ret = bclass->render (basesink, GST_BUFFER_CAST (obj));
|
ret = bclass->render (basesink, buf);
|
||||||
|
|
||||||
priv->rendered++;
|
priv->rendered++;
|
||||||
|
|
||||||
|
@ -2045,11 +2110,15 @@ gst_base_sink_preroll_object (GstBaseSink * basesink, GstPad * pad,
|
||||||
/* if it's a buffer, we need to call the preroll method */
|
/* if it's a buffer, we need to call the preroll method */
|
||||||
if (G_LIKELY (GST_IS_BUFFER (obj))) {
|
if (G_LIKELY (GST_IS_BUFFER (obj))) {
|
||||||
GstBaseSinkClass *bclass;
|
GstBaseSinkClass *bclass;
|
||||||
GstBuffer *buf = GST_BUFFER_CAST (obj);
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
buf = GST_BUFFER_CAST (obj);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (basesink, "preroll buffer %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (basesink, "preroll buffer %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
|
||||||
|
|
||||||
|
gst_base_sink_set_last_buffer (basesink, buf);
|
||||||
|
|
||||||
bclass = GST_BASE_SINK_GET_CLASS (basesink);
|
bclass = GST_BASE_SINK_GET_CLASS (basesink);
|
||||||
if (bclass->preroll)
|
if (bclass->preroll)
|
||||||
if ((ret = bclass->preroll (basesink, buf)) != GST_FLOW_OK)
|
if ((ret = bclass->preroll (basesink, buf)) != GST_FLOW_OK)
|
||||||
|
@ -2111,7 +2180,8 @@ gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad,
|
||||||
/* need to recheck if we need preroll, commmit state during preroll
|
/* need to recheck if we need preroll, commmit state during preroll
|
||||||
* could have made us not need more preroll. */
|
* could have made us not need more preroll. */
|
||||||
if (G_UNLIKELY (basesink->need_preroll)) {
|
if (G_UNLIKELY (basesink->need_preroll)) {
|
||||||
/* see if we can render now. */
|
/* see if we can render now, if we can't add the object to the preroll
|
||||||
|
* queue. */
|
||||||
if (G_UNLIKELY (length <= basesink->preroll_queue_max_len))
|
if (G_UNLIKELY (length <= basesink->preroll_queue_max_len))
|
||||||
goto more_preroll;
|
goto more_preroll;
|
||||||
}
|
}
|
||||||
|
@ -2304,6 +2374,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
|
||||||
basesink->priv->have_latency = TRUE;
|
basesink->priv->have_latency = TRUE;
|
||||||
basesink->need_preroll = FALSE;
|
basesink->need_preroll = FALSE;
|
||||||
}
|
}
|
||||||
|
gst_base_sink_set_last_buffer (basesink, NULL);
|
||||||
GST_PAD_STREAM_UNLOCK (pad);
|
GST_PAD_STREAM_UNLOCK (pad);
|
||||||
|
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
@ -3122,6 +3193,9 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
||||||
GstBaseSink *basesink = GST_BASE_SINK (element);
|
GstBaseSink *basesink = GST_BASE_SINK (element);
|
||||||
GstBaseSinkClass *bclass;
|
GstBaseSinkClass *bclass;
|
||||||
|
GstBaseSinkPrivate *priv;
|
||||||
|
|
||||||
|
priv = basesink->priv;
|
||||||
|
|
||||||
bclass = GST_BASE_SINK_GET_CLASS (basesink);
|
bclass = GST_BASE_SINK_GET_CLASS (basesink);
|
||||||
|
|
||||||
|
@ -3144,15 +3218,15 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
basesink->have_preroll = FALSE;
|
basesink->have_preroll = FALSE;
|
||||||
basesink->need_preroll = TRUE;
|
basesink->need_preroll = TRUE;
|
||||||
basesink->playing_async = TRUE;
|
basesink->playing_async = TRUE;
|
||||||
basesink->priv->current_sstart = 0;
|
priv->current_sstart = 0;
|
||||||
basesink->priv->current_sstop = 0;
|
priv->current_sstop = 0;
|
||||||
basesink->priv->eos_rtime = -1;
|
priv->eos_rtime = -1;
|
||||||
basesink->priv->latency = 0;
|
priv->latency = 0;
|
||||||
basesink->eos = FALSE;
|
basesink->eos = FALSE;
|
||||||
basesink->priv->received_eos = FALSE;
|
priv->received_eos = FALSE;
|
||||||
gst_base_sink_reset_qos (basesink);
|
gst_base_sink_reset_qos (basesink);
|
||||||
basesink->priv->commited = FALSE;
|
priv->commited = FALSE;
|
||||||
if (basesink->priv->async_enabled) {
|
if (priv->async_enabled) {
|
||||||
GST_DEBUG_OBJECT (basesink, "doing async state change");
|
GST_DEBUG_OBJECT (basesink, "doing async state change");
|
||||||
/* when async enabled, post async-start message and return ASYNC from
|
/* when async enabled, post async-start message and return ASYNC from
|
||||||
* the state change function */
|
* the state change function */
|
||||||
|
@ -3160,7 +3234,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
||||||
gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE));
|
gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE));
|
||||||
} else {
|
} else {
|
||||||
basesink->priv->have_latency = TRUE;
|
priv->have_latency = TRUE;
|
||||||
}
|
}
|
||||||
GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
|
GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
|
||||||
break;
|
break;
|
||||||
|
@ -3184,8 +3258,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, we are not prerolled");
|
GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, we are not prerolled");
|
||||||
basesink->need_preroll = TRUE;
|
basesink->need_preroll = TRUE;
|
||||||
basesink->playing_async = TRUE;
|
basesink->playing_async = TRUE;
|
||||||
basesink->priv->commited = FALSE;
|
priv->commited = FALSE;
|
||||||
if (basesink->priv->async_enabled) {
|
if (priv->async_enabled) {
|
||||||
GST_DEBUG_OBJECT (basesink, "doing async state change");
|
GST_DEBUG_OBJECT (basesink, "doing async state change");
|
||||||
ret = GST_STATE_CHANGE_ASYNC;
|
ret = GST_STATE_CHANGE_ASYNC;
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
||||||
|
@ -3255,8 +3329,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
GST_DEBUG_OBJECT (basesink,
|
GST_DEBUG_OBJECT (basesink,
|
||||||
"PLAYING to PAUSED, we are not prerolled");
|
"PLAYING to PAUSED, we are not prerolled");
|
||||||
basesink->playing_async = TRUE;
|
basesink->playing_async = TRUE;
|
||||||
basesink->priv->commited = FALSE;
|
priv->commited = FALSE;
|
||||||
if (basesink->priv->async_enabled) {
|
if (priv->async_enabled) {
|
||||||
GST_DEBUG_OBJECT (basesink, "doing async state change");
|
GST_DEBUG_OBJECT (basesink, "doing async state change");
|
||||||
ret = GST_STATE_CHANGE_ASYNC;
|
ret = GST_STATE_CHANGE_ASYNC;
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
||||||
|
@ -3266,16 +3340,15 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (basesink, "rendered: %" G_GUINT64_FORMAT
|
GST_DEBUG_OBJECT (basesink, "rendered: %" G_GUINT64_FORMAT
|
||||||
", dropped: %" G_GUINT64_FORMAT, basesink->priv->rendered,
|
", dropped: %" G_GUINT64_FORMAT, priv->rendered, priv->dropped);
|
||||||
basesink->priv->dropped);
|
|
||||||
|
|
||||||
gst_base_sink_reset_qos (basesink);
|
gst_base_sink_reset_qos (basesink);
|
||||||
GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
|
GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
GST_PAD_PREROLL_LOCK (basesink->sinkpad);
|
GST_PAD_PREROLL_LOCK (basesink->sinkpad);
|
||||||
if (!basesink->priv->commited) {
|
if (!priv->commited) {
|
||||||
if (basesink->priv->async_enabled) {
|
if (priv->async_enabled) {
|
||||||
GST_DEBUG_OBJECT (basesink, "PAUSED to READY, posting async-done");
|
GST_DEBUG_OBJECT (basesink, "PAUSED to READY, posting async-done");
|
||||||
|
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
||||||
|
@ -3285,20 +3358,23 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
gst_element_post_message (GST_ELEMENT_CAST (basesink),
|
||||||
gst_message_new_async_done (GST_OBJECT_CAST (basesink)));
|
gst_message_new_async_done (GST_OBJECT_CAST (basesink)));
|
||||||
}
|
}
|
||||||
basesink->priv->commited = TRUE;
|
priv->commited = TRUE;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (basesink, "PAUSED to READY, don't need_preroll");
|
GST_DEBUG_OBJECT (basesink, "PAUSED to READY, don't need_preroll");
|
||||||
}
|
}
|
||||||
basesink->priv->current_sstart = 0;
|
priv->current_sstart = 0;
|
||||||
basesink->priv->current_sstop = 0;
|
priv->current_sstop = 0;
|
||||||
basesink->priv->have_latency = FALSE;
|
priv->have_latency = FALSE;
|
||||||
|
gst_base_sink_set_last_buffer (basesink, NULL);
|
||||||
GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
|
GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
if (bclass->stop)
|
if (bclass->stop) {
|
||||||
if (!bclass->stop (basesink)) {
|
if (!bclass->stop (basesink)) {
|
||||||
GST_WARNING_OBJECT (basesink, "failed to stop");
|
GST_WARNING_OBJECT (basesink, "failed to stop");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
gst_base_sink_set_last_buffer (basesink, NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -209,6 +209,9 @@ gboolean gst_base_sink_is_async_enabled (GstBaseSink *sink);
|
||||||
void gst_base_sink_set_ts_offset (GstBaseSink *sink, GstClockTimeDiff offset);
|
void gst_base_sink_set_ts_offset (GstBaseSink *sink, GstClockTimeDiff offset);
|
||||||
GstClockTimeDiff gst_base_sink_get_ts_offset (GstBaseSink *sink);
|
GstClockTimeDiff gst_base_sink_get_ts_offset (GstBaseSink *sink);
|
||||||
|
|
||||||
|
/* last buffer */
|
||||||
|
GstBuffer * gst_base_sink_get_last_buffer (GstBaseSink *sink);
|
||||||
|
|
||||||
/* latency */
|
/* latency */
|
||||||
gboolean gst_base_sink_query_latency (GstBaseSink *sink, gboolean *live, gboolean *upstream_live,
|
gboolean gst_base_sink_query_latency (GstBaseSink *sink, gboolean *live, gboolean *upstream_live,
|
||||||
GstClockTime *min_latency, GstClockTime *max_latency);
|
GstClockTime *min_latency, GstClockTime *max_latency);
|
||||||
|
|
Loading…
Reference in a new issue