concat: Handle single-pad use-cases

When EOS reaches concat, it will switch to the next candidate as its
activate pad.

The problem arises when there is only one sinkpad, the "active" pad
becomes NULL. This results in concat becoming unusable after it receives
a *single* EOS on its single sinkpad.

If we detect there is a single sinkpad and there is no current active pad:
* If we are waiting (from selected sink event/buffer), become the current
  active pad.
* If there is a seek request, send it upstream. We don't switch the
  active_sinkpad property at that point in time, since the seek could
  fail. If the seek succeeds, the following SEGMENT (or STREAM_START)
  will cause the pad_wait() to elect that pad as the new active one.
* Flush events get forwarded

https://bugzilla.gnome.org/show_bug.cgi?id=790167
This commit is contained in:
Edward Hervey 2017-11-10 14:10:31 +01:00
parent 08ad748ced
commit f03443f90c

View file

@ -395,6 +395,12 @@ gst_concat_pad_wait (GstConcatPad * spad, GstConcat * self)
while (spad != GST_CONCAT_PAD_CAST (self->current_sinkpad)) {
GST_TRACE_OBJECT (spad, "Not the current sinkpad - waiting");
if (self->current_sinkpad == NULL && g_list_length (self->sinkpads) == 1) {
GST_LOG_OBJECT (spad, "Sole pad waiting, switching");
/* If we are the only sinkpad, take active pad ownership */
self->current_sinkpad = gst_object_ref (self->sinkpads->data);
break;
}
g_cond_wait (&self->cond, &self->lock);
if (spad->flushing) {
g_mutex_unlock (&self->lock);
@ -614,6 +620,8 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
spad->flushing = TRUE;
g_cond_broadcast (&self->cond);
forward = (self->current_sinkpad == GST_PAD_CAST (spad));
if (!forward && g_list_length (self->sinkpads) == 1)
forward = TRUE;
g_mutex_unlock (&self->lock);
if (forward)
@ -630,6 +638,8 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
g_mutex_lock (&self->lock);
forward = (self->current_sinkpad == GST_PAD_CAST (spad));
if (!forward && g_list_length (self->sinkpads) == 1)
forward = TRUE;
g_mutex_unlock (&self->lock);
if (forward) {
@ -700,6 +710,10 @@ gst_concat_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
g_mutex_lock (&self->lock);
if ((sinkpad = self->current_sinkpad))
gst_object_ref (sinkpad);
/* If no current active sinkpad but only one sinkpad, try reactivating that pad */
if (sinkpad == NULL && g_list_length (self->sinkpads) == 1) {
sinkpad = gst_object_ref (self->sinkpads->data);
}
g_mutex_unlock (&self->lock);
if (sinkpad) {
ret = gst_pad_push_event (sinkpad, event);