gboolean pending_flush_stop;
gboolean pending_eos;
+ gboolean first_buffer;
+
GQueue buffers;
+ guint num_buffers;
GstClockTime head_position;
GstClockTime tail_position;
GstClockTime head_time;
GstEvent *event;
gboolean result;
gboolean flush;
+ gboolean only_to_active_pads;
gboolean one_actually_seeked;
} EventData;
}
item = next;
}
+ aggpad->priv->num_buffers = 0;
PAD_BROADCAST_EVENT (aggpad);
PAD_UNLOCK (aggpad);
GST_OBJECT_UNLOCK (self);
}
+ aggpad->priv->first_buffer = TRUE;
+
/* We never forward the event */
goto eat;
}
gst_segment_do_seek (&self->segment, rate, fmt, flags, start_type, start,
stop_type, stop, NULL);
self->priv->seqnum = gst_event_get_seqnum (event);
+ self->priv->first_buffer = FALSE;
GST_OBJECT_UNLOCK (self);
GST_DEBUG_OBJECT (element, "Storing segment %" GST_PTR_FORMAT, event);
GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
if (peer) {
- ret = gst_pad_send_event (peer, gst_event_ref (evdata->event));
- GST_DEBUG_OBJECT (pad, "return of event push is %d", ret);
- gst_object_unref (peer);
+ if (evdata->only_to_active_pads && aggpad->priv->first_buffer) {
+ GST_DEBUG_OBJECT (pad, "not sending event to inactive pad");
+ ret = TRUE;
+ } else {
+ ret = gst_pad_send_event (peer, gst_event_ref (evdata->event));
+ GST_DEBUG_OBJECT (pad, "return of event push is %d", ret);
+ gst_object_unref (peer);
+ }
}
if (ret == FALSE) {
static EventData
gst_aggregator_forward_event_to_all_sinkpads (GstAggregator * self,
- GstEvent * event, gboolean flush)
+ GstEvent * event, gboolean flush, gboolean only_to_active_pads)
{
EventData evdata;
evdata.result = TRUE;
evdata.flush = flush;
evdata.one_actually_seeked = FALSE;
+ evdata.only_to_active_pads = only_to_active_pads;
/* We first need to set all pads as flushing in a first pass
* as flush_start flush_stop is sometimes sent synchronously
GST_OBJECT_UNLOCK (self);
/* forward the seek upstream */
- evdata = gst_aggregator_forward_event_to_all_sinkpads (self, event, flush);
+ evdata =
+ gst_aggregator_forward_event_to_all_sinkpads (self, event, flush, FALSE);
event = NULL;
if (!evdata.result || !evdata.one_actually_seeked) {
}
}
- evdata = gst_aggregator_forward_event_to_all_sinkpads (self, event, FALSE);
+ /* Don't forward QOS events to pads that had no active buffer yet. Otherwise
+ * they will receive a QOS event that has earliest_time=0 (because we can't
+ * have negative timestamps), and consider their buffer as too late */
+ evdata =
+ gst_aggregator_forward_event_to_all_sinkpads (self, event, FALSE,
+ GST_EVENT_TYPE (event) == GST_EVENT_QOS);
res = evdata.result;
done:
return type;
}
-/* Must be called with PAD lock held */
+/* Must be called with SRC lock and PAD lock held */
static gboolean
gst_aggregator_pad_has_space (GstAggregator * self, GstAggregatorPad * aggpad)
{
if (g_queue_get_length (&aggpad->priv->buffers) == 0)
return TRUE;
+ /* We also want at least two buffers, one is being processed and one is ready
+ * for the next iteration when we operate in live mode. */
+ if (self->priv->peer_latency_live && aggpad->priv->num_buffers < 2)
+ return TRUE;
+
/* zero latency, if there is a buffer, it's full */
if (self->priv->latency == 0)
return FALSE;
buf_pts = GST_BUFFER_PTS (actual_buf);
+ aggpad->priv->first_buffer = FALSE;
+
for (;;) {
SRC_LOCK (self);
PAD_LOCK (aggpad);
else
g_queue_push_tail (&aggpad->priv->buffers, actual_buf);
apply_buffer (aggpad, actual_buf, head);
+ aggpad->priv->num_buffers++;
actual_buf = buffer = NULL;
SRC_BROADCAST (self);
break;
self->segment.position = start_time;
else
self->segment.position = MIN (start_time, self->segment.position);
- self->segment.start = MIN (start_time, self->segment.start);
- self->segment.time = MIN (start_time, self->segment.time);
GST_DEBUG_OBJECT (self, "Selecting start time %" GST_TIME_FORMAT,
GST_TIME_ARGS (start_time));
g_mutex_init (&pad->priv->flush_lock);
g_mutex_init (&pad->priv->lock);
+
+ pad->priv->first_buffer = TRUE;
}
/**
if (buffer) {
apply_buffer (pad, buffer, FALSE);
+ pad->priv->num_buffers--;
GST_TRACE_OBJECT (pad, "Consuming buffer");
if (gst_aggregator_pad_queue_is_empty (pad) && pad->priv->pending_eos) {
pad->priv->pending_eos = FALSE;