mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
libs/gst/base/gstbasesrc.*: Add property to make the basesrc timestamp buffers based on the current running time.
Original commit message from CVS: * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), (gst_base_src_init), (gst_base_src_set_do_timestamp), (gst_base_src_get_do_timestamp), (gst_base_src_set_property), (gst_base_src_get_property), (gst_base_src_do_sync): * libs/gst/base/gstbasesrc.h: Add property to make the basesrc timestamp buffers based on the current running time. API: GstBaseSrc::do-timestamp API: gst_base_src_set_do_timestamp() API: gst_base_src_get_do_timestamp()
This commit is contained in:
parent
08708360fd
commit
5d57d96af6
3 changed files with 107 additions and 10 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2007-09-10 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
|
||||||
|
* libs/gst/base/gstbasesrc.c: (gst_base_src_class_init),
|
||||||
|
(gst_base_src_init), (gst_base_src_set_do_timestamp),
|
||||||
|
(gst_base_src_get_do_timestamp), (gst_base_src_set_property),
|
||||||
|
(gst_base_src_get_property), (gst_base_src_do_sync):
|
||||||
|
* libs/gst/base/gstbasesrc.h:
|
||||||
|
Add property to make the basesrc timestamp buffers based on the current
|
||||||
|
running time.
|
||||||
|
API: GstBaseSrc::do-timestamp
|
||||||
|
API: gst_base_src_set_do_timestamp()
|
||||||
|
API: gst_base_src_get_do_timestamp()
|
||||||
|
|
||||||
2007-09-08 Tim-Philipp Müller <tim at centricular dot net>
|
2007-09-08 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
* docs/random/release:
|
* docs/random/release:
|
||||||
|
|
|
@ -219,6 +219,7 @@ enum
|
||||||
#define DEFAULT_BLOCKSIZE 4096
|
#define DEFAULT_BLOCKSIZE 4096
|
||||||
#define DEFAULT_NUM_BUFFERS -1
|
#define DEFAULT_NUM_BUFFERS -1
|
||||||
#define DEFAULT_TYPEFIND FALSE
|
#define DEFAULT_TYPEFIND FALSE
|
||||||
|
#define DEFAULT_DO_TIMESTAMP FALSE
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -226,6 +227,7 @@ enum
|
||||||
PROP_BLOCKSIZE,
|
PROP_BLOCKSIZE,
|
||||||
PROP_NUM_BUFFERS,
|
PROP_NUM_BUFFERS,
|
||||||
PROP_TYPEFIND,
|
PROP_TYPEFIND,
|
||||||
|
PROP_DO_TIMESTAMP
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GST_BASE_SRC_GET_PRIVATE(obj) \
|
#define GST_BASE_SRC_GET_PRIVATE(obj) \
|
||||||
|
@ -245,6 +247,8 @@ struct _GstBaseSrcPrivate
|
||||||
* the first BUFFER with running_time 0. This value is included in the latency
|
* the first BUFFER with running_time 0. This value is included in the latency
|
||||||
* reporting. */
|
* reporting. */
|
||||||
GstClockTime startup_latency;
|
GstClockTime startup_latency;
|
||||||
|
|
||||||
|
gboolean do_timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
static GstElementClass *parent_class = NULL;
|
||||||
|
@ -353,6 +357,10 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
|
||||||
g_param_spec_boolean ("typefind", "Typefind",
|
g_param_spec_boolean ("typefind", "Typefind",
|
||||||
"Run typefind before negotiating", DEFAULT_TYPEFIND,
|
"Run typefind before negotiating", DEFAULT_TYPEFIND,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_DO_TIMESTAMP,
|
||||||
|
g_param_spec_boolean ("do-timestamp", "Do timestamp",
|
||||||
|
"Apply current stream time to buffers", DEFAULT_DO_TIMESTAMP,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_base_src_change_state);
|
GST_DEBUG_FUNCPTR (gst_base_src_change_state);
|
||||||
|
@ -421,6 +429,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
|
||||||
/* we operate in BYTES by default */
|
/* we operate in BYTES by default */
|
||||||
gst_base_src_set_format (basesrc, GST_FORMAT_BYTES);
|
gst_base_src_set_format (basesrc, GST_FORMAT_BYTES);
|
||||||
basesrc->data.ABI.typefind = DEFAULT_TYPEFIND;
|
basesrc->data.ABI.typefind = DEFAULT_TYPEFIND;
|
||||||
|
basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
|
||||||
|
|
||||||
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
|
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
|
||||||
|
|
||||||
|
@ -606,6 +615,47 @@ gst_base_src_query_latency (GstBaseSrc * src, gboolean * live,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_src_set_do_timestamp:
|
||||||
|
* @src: the source
|
||||||
|
* @timestamp: enable or disable timestamping
|
||||||
|
*
|
||||||
|
* Configure @src to automatically timestamp outgoing buffers based on the
|
||||||
|
* current running_time of the pipeline. This property is mostly useful for live
|
||||||
|
* sources.
|
||||||
|
*
|
||||||
|
* Since: 0.10.15
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_base_src_set_do_timestamp (GstBaseSrc * src, gboolean timestamp)
|
||||||
|
{
|
||||||
|
GST_OBJECT_LOCK (src);
|
||||||
|
src->priv->do_timestamp = timestamp;
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_src_get_do_timestamp:
|
||||||
|
* @src: the source
|
||||||
|
*
|
||||||
|
* Query if @src timestamps outgoing buffers based on the current running_time.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the base class will automatically timestamp outgoing buffers.
|
||||||
|
*
|
||||||
|
* Since: 0.10.15
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_base_src_get_do_timestamp (GstBaseSrc * src)
|
||||||
|
{
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (src);
|
||||||
|
res = src->priv->do_timestamp;
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
|
gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -1362,6 +1412,9 @@ gst_base_src_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_TYPEFIND:
|
case PROP_TYPEFIND:
|
||||||
src->data.ABI.typefind = g_value_get_boolean (value);
|
src->data.ABI.typefind = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DO_TIMESTAMP:
|
||||||
|
src->priv->do_timestamp = g_value_get_boolean (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;
|
||||||
|
@ -1386,6 +1439,9 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_TYPEFIND:
|
case PROP_TYPEFIND:
|
||||||
g_value_set_boolean (value, src->data.ABI.typefind);
|
g_value_set_boolean (value, src->data.ABI.typefind);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DO_TIMESTAMP:
|
||||||
|
g_value_set_boolean (value, src->priv->do_timestamp);
|
||||||
|
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;
|
||||||
|
@ -1425,6 +1481,8 @@ gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
|
||||||
GstBaseSrcClass *bclass;
|
GstBaseSrcClass *bclass;
|
||||||
GstClockTime base_time;
|
GstClockTime base_time;
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
|
GstClockTime now = -1, timestamp;
|
||||||
|
gboolean do_timestamp;
|
||||||
|
|
||||||
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
|
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
|
||||||
|
|
||||||
|
@ -1436,14 +1494,18 @@ gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
|
||||||
* latency. */
|
* latency. */
|
||||||
GST_OBJECT_LOCK (basesrc);
|
GST_OBJECT_LOCK (basesrc);
|
||||||
|
|
||||||
base_time = GST_ELEMENT_CAST (basesrc)->base_time;
|
|
||||||
|
|
||||||
/* get clock, if no clock, we can't sync or get the latency */
|
/* get clock, if no clock, we can't sync or get the latency */
|
||||||
if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL)
|
if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL)
|
||||||
goto no_clock;
|
goto no_clock;
|
||||||
|
|
||||||
|
base_time = GST_ELEMENT_CAST (basesrc)->base_time;
|
||||||
|
|
||||||
|
do_timestamp = basesrc->priv->do_timestamp;
|
||||||
|
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
|
||||||
|
/* first buffer, calculate the startup latency */
|
||||||
if (basesrc->priv->startup_latency == -1) {
|
if (basesrc->priv->startup_latency == -1) {
|
||||||
GstClockTime now = gst_clock_get_time (clock);
|
now = gst_clock_get_time (clock);
|
||||||
|
|
||||||
/* startup latency is the diff between when we went to PLAYING (base_time)
|
/* startup latency is the diff between when we went to PLAYING (base_time)
|
||||||
* and the current clock time */
|
* and the current clock time */
|
||||||
|
@ -1454,19 +1516,38 @@ gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
|
||||||
|
|
||||||
GST_LOG_OBJECT (basesrc, "startup latency: %" GST_TIME_FORMAT,
|
GST_LOG_OBJECT (basesrc, "startup latency: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (basesrc->priv->startup_latency));
|
GST_TIME_ARGS (basesrc->priv->startup_latency));
|
||||||
|
|
||||||
|
if (!GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||||
|
if (do_timestamp)
|
||||||
|
timestamp = now - base_time;
|
||||||
|
else
|
||||||
|
timestamp = 0;
|
||||||
|
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer) = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have a timestamp, we can subtract it from the startup_latency when it is
|
||||||
|
* smaller. If the timestamp is bigger, there is no startup latency. */
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||||
|
if (timestamp < basesrc->priv->startup_latency)
|
||||||
|
basesrc->priv->startup_latency -= timestamp;
|
||||||
|
else
|
||||||
|
basesrc->priv->startup_latency = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* not the first buffer, the timestamp is the diff between the clock and
|
||||||
|
* base_time */
|
||||||
|
if (do_timestamp && !GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||||
|
now = gst_clock_get_time (clock);
|
||||||
|
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer) = now - base_time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we don't have a buffer timestamp, we don't sync */
|
/* if we don't have a buffer timestamp, we don't sync */
|
||||||
if (!GST_CLOCK_TIME_IS_VALID (start))
|
if (!GST_CLOCK_TIME_IS_VALID (start))
|
||||||
goto invalid_start;
|
goto invalid_start;
|
||||||
|
|
||||||
/* we have a timestamp, we can subtract it from the startup_latency when it is
|
|
||||||
* smaller. If the timestamp is bigger, there is no startup latency. */
|
|
||||||
if (start < basesrc->priv->startup_latency)
|
|
||||||
basesrc->priv->startup_latency -= start;
|
|
||||||
else
|
|
||||||
basesrc->priv->startup_latency = 0;
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (basesrc,
|
GST_LOG_OBJECT (basesrc,
|
||||||
"waiting for clock, base time %" GST_TIME_FORMAT
|
"waiting for clock, base time %" GST_TIME_FORMAT
|
||||||
", stream_start %" GST_TIME_FORMAT,
|
", stream_start %" GST_TIME_FORMAT,
|
||||||
|
|
|
@ -241,6 +241,9 @@ gboolean gst_base_src_query_latency (GstBaseSrc *src, gboolean * live,
|
||||||
GstClockTime * min_latency,
|
GstClockTime * min_latency,
|
||||||
GstClockTime * max_latency);
|
GstClockTime * max_latency);
|
||||||
|
|
||||||
|
void gst_base_src_set_do_timestamp (GstBaseSrc *src, gboolean live);
|
||||||
|
gboolean gst_base_src_get_do_timestamp (GstBaseSrc *src);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_BASE_SRC_H__ */
|
#endif /* __GST_BASE_SRC_H__ */
|
||||||
|
|
Loading…
Reference in a new issue