decodebin3/urisourcebin: Switch to actual EOS events internally

Use the intended sequence for re-using elements:
* EOS
* STREAM_START if element is to be re-used

This avoids having elements (such as queue/multiqueue/queue2) not
properly resetting themselves.

When delaying EOS propagation (because we want to wait until all
streams of a group are done for example), we re-trigger them by
first sending the cached STREAM_START and then EOS (which will
cause elements to re-set themselves if needed and accept new
buffers/events).

https://bugzilla.gnome.org/show_bug.cgi?id=785951
This commit is contained in:
Edward Hervey 2017-08-09 16:23:03 +02:00 committed by Sebastian Dröge
parent 94d2e4c223
commit ce65017d03
3 changed files with 60 additions and 44 deletions

View file

@ -268,8 +268,11 @@ parse_chain_output_probe (GstPad * pad, GstPadProbeInfo * info,
GST_DEBUG_OBJECT (pad, GST_DEBUG_OBJECT (pad,
"Got EOS end of input stream, post custom-eos"); "Got EOS end of input stream, post custom-eos");
s = gst_structure_new_empty ("decodebin3-custom-eos"); event = gst_event_new_eos ();
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); gst_event_set_seqnum (event, gst_event_get_seqnum (ev));
s = gst_event_writable_structure (event);
gst_structure_set (s, "decodebin3-custom-eos", G_TYPE_BOOLEAN, TRUE,
NULL);
gst_pad_send_event (peer, event); gst_pad_send_event (peer, event);
gst_object_unref (peer); gst_object_unref (peer);
} else { } else {

View file

@ -1506,7 +1506,7 @@ check_all_slot_for_eos (GstDecodebin3 * dbin)
continue; continue;
if (slot->is_drained) { if (slot->is_drained) {
GST_DEBUG_OBJECT (slot->sink_pad, "slot %p is draned", slot); GST_LOG_OBJECT (slot->sink_pad, "slot %p is drained", slot);
continue; continue;
} }
@ -1538,11 +1538,17 @@ check_all_slot_for_eos (GstDecodebin3 * dbin)
DecodebinInputStream *input = (DecodebinInputStream *) iter->data; DecodebinInputStream *input = (DecodebinInputStream *) iter->data;
GstPad *peer = gst_pad_get_peer (input->srcpad); GstPad *peer = gst_pad_get_peer (input->srcpad);
/* Send EOS and then remove elements */ /* Send EOS to all slots */
if (peer) { if (peer) {
GstEvent *stream_start =
gst_pad_get_sticky_event (input->srcpad, GST_EVENT_STREAM_START, 0);
/* First forward the STREAM_START event to reset the EOS status (if any) */
if (stream_start)
gst_pad_send_event (peer, stream_start);
gst_pad_send_event (peer, gst_event_new_eos ()); gst_pad_send_event (peer, gst_event_new_eos ());
gst_object_unref (peer); gst_object_unref (peer);
} } else
GST_DEBUG_OBJECT (dbin, "no output");
} }
} }
} }
@ -1627,10 +1633,36 @@ multiqueue_src_probe (GstPad * pad, GstPadProbeInfo * info,
} }
break; break;
case GST_EVENT_EOS: case GST_EVENT_EOS:
/* FIXME : Figure out */ {
const GstStructure *s = gst_event_get_structure (ev);
slot->is_drained = TRUE;
/* Custom EOS handling first */
if (s && gst_structure_has_field (s, "decodebin3-custom-eos")) {
ret = GST_PAD_PROBE_DROP;
SELECTION_LOCK (dbin);
if (slot->input == NULL) {
GST_DEBUG_OBJECT (pad,
"Got custom-eos from null input stream, remove output stream");
/* Remove the output */
if (slot->output) {
DecodebinOutputStream *output = slot->output;
dbin->output_streams =
g_list_remove (dbin->output_streams, output);
free_output_stream (dbin, output);
}
slot->probe_id = 0;
dbin->slots = g_list_remove (dbin->slots, slot);
free_multiqueue_slot_async (dbin, slot);
ret = GST_PAD_PROBE_REMOVE;
} else {
check_all_slot_for_eos (dbin);
}
SELECTION_UNLOCK (dbin);
break;
}
GST_FIXME_OBJECT (pad, "EOS on multiqueue source pad. input:%p", GST_FIXME_OBJECT (pad, "EOS on multiqueue source pad. input:%p",
slot->input); slot->input);
slot->is_drained = TRUE;
if (slot->input == NULL) { if (slot->input == NULL) {
GstPad *peer; GstPad *peer;
GST_DEBUG_OBJECT (pad, GST_DEBUG_OBJECT (pad,
@ -1657,32 +1689,13 @@ multiqueue_src_probe (GstPad * pad, GstPadProbeInfo * info,
free_multiqueue_slot_async (dbin, slot); free_multiqueue_slot_async (dbin, slot);
ret = GST_PAD_PROBE_REMOVE; ret = GST_PAD_PROBE_REMOVE;
} } else {
break; GST_DEBUG_OBJECT (pad, "What happens with event ?");
case GST_EVENT_CUSTOM_DOWNSTREAM:
if (gst_event_has_name (ev, "decodebin3-custom-eos")) {
slot->is_drained = TRUE;
ret = GST_PAD_PROBE_DROP;
SELECTION_LOCK (dbin); SELECTION_LOCK (dbin);
if (slot->input == NULL) { check_all_slot_for_eos (dbin);
GST_DEBUG_OBJECT (pad,
"Got custom-eos from null input stream, remove output stream");
/* Remove the output */
if (slot->output) {
DecodebinOutputStream *output = slot->output;
dbin->output_streams =
g_list_remove (dbin->output_streams, output);
free_output_stream (dbin, output);
}
slot->probe_id = 0;
dbin->slots = g_list_remove (dbin->slots, slot);
free_multiqueue_slot_async (dbin, slot);
ret = GST_PAD_PROBE_REMOVE;
} else {
check_all_slot_for_eos (dbin);
}
SELECTION_UNLOCK (dbin); SELECTION_UNLOCK (dbin);
} }
}
break; break;
default: default:
break; break;

View file

@ -1109,19 +1109,15 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
switch (GST_EVENT_TYPE (ev)) { switch (GST_EVENT_TYPE (ev)) {
case GST_EVENT_EOS: case GST_EVENT_EOS:
{ {
GstEvent *event;
GstStructure *s; GstStructure *s;
guint32 seqnum = gst_event_get_seqnum (ev);
GST_LOG_OBJECT (urisrc, "EOS on pad %" GST_PTR_FORMAT, pad); GST_LOG_OBJECT (urisrc, "EOS on pad %" GST_PTR_FORMAT, pad);
/* never forward actual EOS to slot */
ret = GST_PAD_PROBE_DROP;
if ((urisrc->pending_pads && if ((urisrc->pending_pads &&
link_pending_pad_to_output (urisrc, child_info->output_slot))) { link_pending_pad_to_output (urisrc, child_info->output_slot))) {
/* Found a new source pad to give this slot data - no need to send EOS */ /* Found a new source pad to give this slot data - no need to send EOS */
GST_URI_SOURCE_BIN_UNLOCK (urisrc); GST_URI_SOURCE_BIN_UNLOCK (urisrc);
ret = GST_PAD_PROBE_DROP;
goto done; goto done;
} }
@ -1134,11 +1130,12 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
remove_buffering_msgs (urisrc, remove_buffering_msgs (urisrc,
GST_OBJECT_CAST (child_info->output_slot->queue)); GST_OBJECT_CAST (child_info->output_slot->queue));
/* Actually feed a custom EOS event to avoid marking pads as EOSed */ /* Mark this custom EOS */
s = gst_structure_new_empty ("urisourcebin-custom-eos"); ev = gst_event_make_writable (ev);
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); GST_PAD_PROBE_INFO_DATA (info) = ev;
gst_event_set_seqnum (event, seqnum); s = gst_event_writable_structure (ev);
gst_pad_send_event (child_info->output_slot->sinkpad, event); gst_structure_set (s, "urisourcebin-custom-eos", G_TYPE_BOOLEAN, TRUE,
NULL);
} }
break; break;
case GST_EVENT_CAPS: case GST_EVENT_CAPS:
@ -1301,8 +1298,9 @@ source_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
GST_LOG_OBJECT (pad, "%s, urisrc %p", GST_EVENT_TYPE_NAME (event), event); GST_LOG_OBJECT (pad, "%s, urisrc %p", GST_EVENT_TYPE_NAME (event), event);
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM && if (GST_EVENT_TYPE (event) == GST_EVENT_EOS && gst_event_get_structure (event)
gst_event_has_name (event, "urisourcebin-custom-eos")) { && gst_structure_has_field (gst_event_get_structure (event),
"urisourcebin-custom-eos")) {
OutputSlotInfo *slot; OutputSlotInfo *slot;
GST_DEBUG_OBJECT (pad, "we received EOS"); GST_DEBUG_OBJECT (pad, "we received EOS");
@ -1442,8 +1440,10 @@ pad_removed_cb (GstElement * element, GstPad * pad, GstURISourceBin * urisrc)
GST_LOG_OBJECT (element, GST_LOG_OBJECT (element,
"Pad %" GST_PTR_FORMAT " was removed without EOS. Sending.", pad); "Pad %" GST_PTR_FORMAT " was removed without EOS. Sending.", pad);
s = gst_structure_new_empty ("urisourcebin-custom-eos"); event = gst_event_new_eos ();
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); s = gst_event_writable_structure (event);
gst_structure_set (s, "urisourcebin-custom-eos", G_TYPE_BOOLEAN, TRUE,
NULL);
gst_pad_send_event (slot->sinkpad, event); gst_pad_send_event (slot->sinkpad, event);
} else { } else {
GST_LOG_OBJECT (urisrc, "Removed pad has no output slot"); GST_LOG_OBJECT (urisrc, "Removed pad has no output slot");