mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 23:18:52 +00:00
collectpads: Add negative DTS support
Make gst_collect_pads_clip_running_time() function also store the signed DTS in the CollectData. This signed DTS value can be used by muxers to properly handle streams where DTS can be negative initially. https://bugzilla.gnome.org/show_bug.cgi?id=740575
This commit is contained in:
parent
5cab2e14c4
commit
b5e4f7bd9d
3 changed files with 115 additions and 5 deletions
|
@ -495,6 +495,10 @@ gst_collect_pads_set_query_function (GstCollectPads * pads,
|
|||
*
|
||||
* Convenience clipping function that converts incoming buffer's timestamp
|
||||
* to running time, or clips the buffer if outside configured segment.
|
||||
*
|
||||
* Since 1.6, this clipping function also sets the DTS parameter of the
|
||||
* GstCollectData structure. This version of the running time DTS can be
|
||||
* negative. G_MININT64 is used to indicate invalid value.
|
||||
*/
|
||||
GstFlowReturn
|
||||
gst_collect_pads_clip_running_time (GstCollectPads * pads,
|
||||
|
@ -515,13 +519,32 @@ gst_collect_pads_clip_running_time (GstCollectPads * pads,
|
|||
gst_buffer_unref (buf);
|
||||
*outbuf = NULL;
|
||||
} else {
|
||||
GST_LOG_OBJECT (cdata->pad, "buffer ts %" GST_TIME_FORMAT " -> %"
|
||||
GstClockTime buf_dts, abs_dts;
|
||||
gint dts_sign;
|
||||
|
||||
GST_LOG_OBJECT (cdata->pad, "buffer pts %" GST_TIME_FORMAT " -> %"
|
||||
GST_TIME_FORMAT " running time",
|
||||
GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time));
|
||||
*outbuf = gst_buffer_make_writable (buf);
|
||||
GST_BUFFER_PTS (*outbuf) = time;
|
||||
GST_BUFFER_DTS (*outbuf) = gst_segment_to_running_time (&cdata->segment,
|
||||
GST_FORMAT_TIME, GST_BUFFER_DTS (*outbuf));
|
||||
|
||||
dts_sign = gst_segment_to_running_time_full (&cdata->segment,
|
||||
GST_FORMAT_TIME, GST_BUFFER_DTS (*outbuf), &abs_dts);
|
||||
buf_dts = GST_BUFFER_DTS (*outbuf);
|
||||
if (dts_sign > 0) {
|
||||
GST_BUFFER_DTS (*outbuf) = abs_dts;
|
||||
GST_COLLECT_PADS_DTS (cdata) = abs_dts;
|
||||
} else if (dts_sign < 0) {
|
||||
GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_COLLECT_PADS_DTS (cdata) = -((gint64) abs_dts);
|
||||
} else {
|
||||
GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_COLLECT_PADS_DTS (cdata) = GST_CLOCK_STIME_NONE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (cdata->pad, "buffer dts %" GST_TIME_FORMAT " -> %"
|
||||
GST_STIME_FORMAT " running time", GST_TIME_ARGS (buf_dts),
|
||||
GST_STIME_ARGS (GST_COLLECT_PADS_DTS (cdata)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -634,6 +657,7 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size,
|
|||
data->state |= lock ? GST_COLLECT_PADS_STATE_LOCKED : 0;
|
||||
data->priv->refcount = 1;
|
||||
data->priv->destroy_notify = destroy_notify;
|
||||
data->ABI.abi.dts = G_MININT64;
|
||||
|
||||
GST_OBJECT_LOCK (pads);
|
||||
GST_OBJECT_LOCK (pad);
|
||||
|
|
|
@ -103,6 +103,31 @@ typedef enum {
|
|||
*/
|
||||
#define GST_COLLECT_PADS_STATE_UNSET(data,flag) (GST_COLLECT_PADS_STATE (data) &= ~(flag))
|
||||
|
||||
/**
|
||||
* GST_COLLECT_PADS_DTS:
|
||||
* @data: A #GstCollectData.
|
||||
*
|
||||
* Returns the DTS that has been converted to running time when using
|
||||
* gst_collect_pads_clip_running_time(). Unlike the value saved into
|
||||
* the buffer, this value is of type gint64 and may be negative. This allow
|
||||
* properly handling streams with frame reordering where the first DTS may
|
||||
* be negative. If the initial DTS was not set, this value will be
|
||||
* set to %G_MININT64.
|
||||
*
|
||||
* Since 1.6
|
||||
*/
|
||||
#define GST_COLLECT_PADS_DTS(data) (((GstCollectData *) data)->ABI.abi.dts)
|
||||
|
||||
/**
|
||||
* GST_COLLECT_PADS_DTS_IS_VALID:
|
||||
* @data: A #GstCollectData.
|
||||
*
|
||||
* Check if running DTS value store is valid.
|
||||
*
|
||||
* Since 1.6
|
||||
*/
|
||||
#define GST_COLLECT_PADS_DTS_IS_VALID(data) (GST_CLOCK_STIME_IS_VALID (GST_COLLECT_PADS_DTS (data)))
|
||||
|
||||
/**
|
||||
* GstCollectData:
|
||||
* @collect: owner #GstCollectPads
|
||||
|
@ -110,6 +135,7 @@ typedef enum {
|
|||
* @buffer: currently queued buffer.
|
||||
* @pos: position in the buffer
|
||||
* @segment: last segment received.
|
||||
* @dts: the signed version of the DTS converted to running time. Since 1.6
|
||||
*
|
||||
* Structure used by the collect_pads.
|
||||
*/
|
||||
|
@ -129,7 +155,14 @@ struct _GstCollectData
|
|||
|
||||
GstCollectDataPrivate *priv;
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
/*< public >*/
|
||||
union {
|
||||
struct {
|
||||
gint64 dts;
|
||||
} abi;
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
} ABI;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -363,7 +396,7 @@ void gst_collect_pads_set_waiting (GstCollectPads *pads, GstCollect
|
|||
|
||||
/* convenience helper */
|
||||
GstFlowReturn gst_collect_pads_clip_running_time (GstCollectPads * pads,
|
||||
GstCollectData * cdata,
|
||||
GstCollectData * cdata,
|
||||
GstBuffer * buf, GstBuffer ** outbuf,
|
||||
gpointer user_data);
|
||||
|
||||
|
|
|
@ -1005,6 +1005,58 @@ GST_START_TEST (test_flushing_seek)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_clip_running_time)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstCollectData data = { 0 };
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
data.pad = gst_pad_new ("clip_test", GST_PAD_SRC);
|
||||
|
||||
GST_BUFFER_PTS (buf) = 0;
|
||||
GST_BUFFER_DTS (buf) = 0;
|
||||
gst_segment_init (&data.segment, GST_FORMAT_TIME);
|
||||
|
||||
gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL);
|
||||
|
||||
fail_unless (buf != NULL);
|
||||
fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), 0);
|
||||
fail_unless_equals_uint64 (GST_BUFFER_DTS (buf), 0);
|
||||
fail_unless_equals_int64 (GST_COLLECT_PADS_DTS (&data), 0);
|
||||
|
||||
GST_BUFFER_PTS (buf) = 1000;
|
||||
GST_BUFFER_DTS (buf) = 0;
|
||||
data.segment.start = 1000;
|
||||
|
||||
gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL);
|
||||
|
||||
fail_unless (buf != NULL);
|
||||
fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), 0);
|
||||
fail_unless_equals_uint64 (GST_BUFFER_DTS (buf), GST_CLOCK_TIME_NONE);
|
||||
fail_unless_equals_int64 (GST_COLLECT_PADS_DTS (&data), -1000);
|
||||
|
||||
GST_BUFFER_PTS (buf) = 1000;
|
||||
GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
|
||||
|
||||
gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL);
|
||||
|
||||
fail_unless (buf != NULL);
|
||||
fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), 0);
|
||||
fail_unless_equals_uint64 (GST_BUFFER_DTS (buf), GST_CLOCK_TIME_NONE);
|
||||
fail_if (GST_COLLECT_PADS_DTS_IS_VALID (&data));
|
||||
|
||||
GST_BUFFER_PTS (buf) = 0;
|
||||
GST_BUFFER_DTS (buf) = 0;
|
||||
|
||||
gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL);
|
||||
|
||||
fail_unless (buf == NULL);
|
||||
gst_object_unref (data.pad);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static Suite *
|
||||
gst_collect_pads_suite (void)
|
||||
{
|
||||
|
@ -1022,6 +1074,7 @@ gst_collect_pads_suite (void)
|
|||
tcase_add_test (general, test_collect);
|
||||
tcase_add_test (general, test_collect_eos);
|
||||
tcase_add_test (general, test_collect_twice);
|
||||
tcase_add_test (general, test_clip_running_time);
|
||||
|
||||
buffers = tcase_create ("buffers");
|
||||
suite_add_tcase (suite, buffers);
|
||||
|
|
Loading…
Reference in a new issue