PROP_ACTIVE_PAD,
PROP_SYNC_STREAMS,
PROP_SYNC_MODE,
- PROP_CACHE_BUFFERS
+ PROP_CACHE_BUFFERS,
+ PROP_DROP_BACKWARDS
};
#define DEFAULT_SYNC_STREAMS TRUE
#define DEFAULT_SYNC_MODE GST_INPUT_SELECTOR_SYNC_MODE_ACTIVE_SEGMENT
#define DEFAULT_CACHE_BUFFERS FALSE
#define DEFAULT_PAD_ALWAYS_OK TRUE
+#define DEFAULT_DROP_BACKWARDS FALSE
enum
{
break;
case GST_EVENT_FLUSH_STOP:
gst_selector_pad_reset (selpad);
+ sel->last_output_ts = GST_CLOCK_TIME_NONE;
break;
case GST_EVENT_SEGMENT:
{
GstPad *active_sinkpad;
GstPad *prev_active_sinkpad = NULL;
GstSelectorPad *selpad;
+ GstSegment seg;
+ GstClockTime running_time = GST_CLOCK_TIME_NONE;
sel = GST_INPUT_SELECTOR (parent);
selpad = GST_SELECTOR_PAD_CAST (pad);
prev_active_sinkpad = NULL;
}
+ seg = selpad->segment;
+ if (seg.format == GST_FORMAT_TIME)
+ running_time =
+ gst_segment_to_running_time (&seg, GST_FORMAT_TIME,
+ GST_BUFFER_DTS_OR_PTS (buf));
+
if (selpad->discont) {
+ GST_INPUT_SELECTOR_LOCK (sel);
+ if (sel->sync_streams && sel->drop_backwards
+ && GST_CLOCK_TIME_IS_VALID (running_time)) {
+ /* Just switched. Make sure timestamps don't go backwards */
+ if (running_time < sel->last_output_ts
+ && GST_CLOCK_TIME_IS_VALID (sel->last_output_ts)) {
+ GST_DEBUG_OBJECT (pad, "Discarding buffer %p with backwards timestamp",
+ buf);
+ goto ignore;
+ }
+ }
+ GST_INPUT_SELECTOR_UNLOCK (sel);
buf = gst_buffer_make_writable (buf);
GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf);
/* forward */
GST_LOG_OBJECT (pad, "Forwarding buffer %p with timestamp %" GST_TIME_FORMAT,
buf, GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
+ sel->last_output_ts = running_time;
/* Only make the buffer read-only when necessary */
if (sel->sync_streams && sel->cache_buffers)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY));
+ /**
+ * GstInputSelector:drop-backwards
+ *
+ * If set to %TRUE and GstInputSelector:sync-streams is also set to %TRUE,
+ * every time the input is switched, buffers that would go backwards related
+ * to the last output buffer pre-switch will be dropped.
+ *
+ * Since: 1.22
+ */
+ g_object_class_install_property (gobject_class, PROP_DROP_BACKWARDS,
+ g_param_spec_boolean ("drop-backwards", "Drop Backwards Buffers",
+ "Drop backwards buffers on pad switch",
+ DEFAULT_DROP_BACKWARDS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
gst_element_class_set_static_metadata (gstelement_class, "Input selector",
"Generic", "N-to-1 input stream selector",
"Julien Moutte <julien@moutte.net>, "
sel->eos = FALSE;
sel->upstream_latency = 0;
+ sel->last_output_ts = GST_CLOCK_TIME_NONE;
/* lets give a change for downstream to do something on
* active-pad change before we start pushing new buffers */
sel->cache_buffers = g_value_get_boolean (value);
GST_INPUT_SELECTOR_UNLOCK (object);
break;
+ case PROP_DROP_BACKWARDS:
+ GST_INPUT_SELECTOR_LOCK (object);
+ sel->drop_backwards = g_value_get_boolean (value);
+ GST_INPUT_SELECTOR_UNLOCK (object);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_value_set_boolean (value, sel->cache_buffers);
GST_INPUT_SELECTOR_UNLOCK (object);
break;
+ case PROP_DROP_BACKWARDS:
+ GST_INPUT_SELECTOR_LOCK (object);
+ g_value_set_boolean (value, sel->drop_backwards);
+ GST_INPUT_SELECTOR_UNLOCK (object);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
sel->have_group_id = TRUE;
sel->upstream_latency = 0;
+ sel->last_output_ts = GST_CLOCK_TIME_NONE;
GST_INPUT_SELECTOR_UNLOCK (sel);
}