decodebin3/urisourcebin: Switch to actual EOS events internally
authorEdward Hervey <edward@centricular.com>
Wed, 9 Aug 2017 14:23:03 +0000 (16:23 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 11 Aug 2017 08:23:29 +0000 (11:23 +0300)
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

gst/playback/gstdecodebin3-parse.c
gst/playback/gstdecodebin3.c
gst/playback/gsturisourcebin.c

index 6acef21..eeae721 100644 (file)
@@ -268,8 +268,11 @@ parse_chain_output_probe (GstPad * pad, GstPadProbeInfo * info,
 
             GST_DEBUG_OBJECT (pad,
                 "Got EOS end of input stream, post custom-eos");
-            s = gst_structure_new_empty ("decodebin3-custom-eos");
-            event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
+            event = gst_event_new_eos ();
+            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_object_unref (peer);
           } else {
index e965ed6..0423acd 100644 (file)
@@ -1506,7 +1506,7 @@ check_all_slot_for_eos (GstDecodebin3 * dbin)
       continue;
 
     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;
     }
 
@@ -1538,11 +1538,17 @@ check_all_slot_for_eos (GstDecodebin3 * dbin)
       DecodebinInputStream *input = (DecodebinInputStream *) iter->data;
       GstPad *peer = gst_pad_get_peer (input->srcpad);
 
-      /* Send EOS and then remove elements */
+      /* Send EOS to all slots */
       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_object_unref (peer);
-      }
+      } else
+        GST_DEBUG_OBJECT (dbin, "no output");
     }
   }
 }
@@ -1627,10 +1633,36 @@ multiqueue_src_probe (GstPad * pad, GstPadProbeInfo * info,
       }
         break;
       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",
             slot->input);
-        slot->is_drained = TRUE;
         if (slot->input == NULL) {
           GstPad *peer;
           GST_DEBUG_OBJECT (pad,
@@ -1657,32 +1689,13 @@ multiqueue_src_probe (GstPad * pad, GstPadProbeInfo * info,
 
           free_multiqueue_slot_async (dbin, slot);
           ret = GST_PAD_PROBE_REMOVE;
-        }
-        break;
-      case GST_EVENT_CUSTOM_DOWNSTREAM:
-        if (gst_event_has_name (ev, "decodebin3-custom-eos")) {
-          slot->is_drained = TRUE;
-          ret = GST_PAD_PROBE_DROP;
+        } else {
+          GST_DEBUG_OBJECT (pad, "What happens with event ?");
           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);
-          }
+          check_all_slot_for_eos (dbin);
           SELECTION_UNLOCK (dbin);
         }
+      }
         break;
       default:
         break;
index 5b238a7..faf1d62 100644 (file)
@@ -1109,19 +1109,15 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
   switch (GST_EVENT_TYPE (ev)) {
     case GST_EVENT_EOS:
     {
-      GstEvent *event;
       GstStructure *s;
-      guint32 seqnum = gst_event_get_seqnum (ev);
 
       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 &&
               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 */
         GST_URI_SOURCE_BIN_UNLOCK (urisrc);
+        ret = GST_PAD_PROBE_DROP;
         goto done;
       }
 
@@ -1134,11 +1130,12 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
       remove_buffering_msgs (urisrc,
           GST_OBJECT_CAST (child_info->output_slot->queue));
 
-      /* Actually feed a custom EOS event to avoid marking pads as EOSed */
-      s = gst_structure_new_empty ("urisourcebin-custom-eos");
-      event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
-      gst_event_set_seqnum (event, seqnum);
-      gst_pad_send_event (child_info->output_slot->sinkpad, event);
+      /* Mark this custom EOS */
+      ev = gst_event_make_writable (ev);
+      GST_PAD_PROBE_INFO_DATA (info) = ev;
+      s = gst_event_writable_structure (ev);
+      gst_structure_set (s, "urisourcebin-custom-eos", G_TYPE_BOOLEAN, TRUE,
+          NULL);
     }
       break;
     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);
 
-  if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM &&
-      gst_event_has_name (event, "urisourcebin-custom-eos")) {
+  if (GST_EVENT_TYPE (event) == GST_EVENT_EOS && gst_event_get_structure (event)
+      && gst_structure_has_field (gst_event_get_structure (event),
+          "urisourcebin-custom-eos")) {
     OutputSlotInfo *slot;
     GST_DEBUG_OBJECT (pad, "we received EOS");
 
@@ -1442,8 +1440,10 @@ pad_removed_cb (GstElement * element, GstPad * pad, GstURISourceBin * urisrc)
     GST_LOG_OBJECT (element,
         "Pad %" GST_PTR_FORMAT " was removed without EOS. Sending.", pad);
 
-    s = gst_structure_new_empty ("urisourcebin-custom-eos");
-    event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
+    event = gst_event_new_eos ();
+    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);
   } else {
     GST_LOG_OBJECT (urisrc, "Removed pad has no output slot");