summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <edward@centricular.com>2017-11-09 10:53:24 +0100
committerEdward Hervey <bilboed@bilboed.com>2018-02-10 12:24:09 +0100
commitebf138e29ec848507b654f53070c076f61014385 (patch)
treeb3b2c6ace8d27a0956d5ce750ebbdd56da2d76b0
parent08044ab7e645f72f0233ec8607f63937684d3fdd (diff)
urisourcebin: Add 'about-to-finish' signal
With push-based sources, urisourcebin will emit this signal when the stream has been fully consumed. This signal can be used to know when the source is done providing data.
-rw-r--r--gst/playback/gsturisourcebin.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/gst/playback/gsturisourcebin.c b/gst/playback/gsturisourcebin.c
index deef99aa4..3e0d26db1 100644
--- a/gst/playback/gsturisourcebin.c
+++ b/gst/playback/gsturisourcebin.c
@@ -167,8 +167,12 @@ struct _GstURISourceBinClass
{
GstBinClass parent_class;
- /* emitted when all data is decoded */
+ /* emitted when all data has been drained out
+ * FIXME : What do we need this for ?? */
void (*drained) (GstElement * element);
+ /* emitted when all data has been fed into buffering slots (i.e the
+ * actual sources are done) */
+ void (*about_to_finish) (GstElement * element);
};
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u",
@@ -185,6 +189,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_uri_source_bin_debug);
enum
{
SIGNAL_DRAINED,
+ SIGNAL_ABOUT_TO_FINISH,
SIGNAL_SOURCE_SETUP,
LAST_SIGNAL
};
@@ -336,6 +341,17 @@ gst_uri_source_bin_class_init (GstURISourceBinClass * klass)
G_STRUCT_OFFSET (GstURISourceBinClass, drained), NULL, NULL,
g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
+ /**
+ * GstURISourceBin::about-to-finish:
+ *
+ * This signal is emitted when the data for the current uri is played.
+ */
+ gst_uri_source_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
+ g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstURISourceBinClass, about_to_finish), NULL, NULL,
+ g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
+
/**
* GstURISourceBin::source-setup:
* @bin: the urisourcebin.
@@ -695,6 +711,20 @@ link_pending_pad_to_output (GstURISourceBin * urisrc, OutputSlotInfo * slot)
return res;
}
+/* Called with lock held */
+static gboolean
+all_slots_are_eos (GstURISourceBin * urisrc)
+{
+ GSList *tmp;
+
+ for (tmp = urisrc->out_slots; tmp; tmp = tmp->next) {
+ OutputSlotInfo *slot = (OutputSlotInfo *) tmp->data;
+ if (slot->is_eos == FALSE)
+ return FALSE;
+ }
+ return TRUE;
+}
+
static GstPadProbeReturn
demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
@@ -718,6 +748,7 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
case GST_EVENT_EOS:
{
GstStructure *s;
+ gboolean all_streams_eos;
GST_LOG_OBJECT (urisrc, "EOS on pad %" GST_PTR_FORMAT, pad);
@@ -732,6 +763,7 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
BUFFERING_LOCK (urisrc);
/* Mark that we fed an EOS to this slot */
child_info->output_slot->is_eos = TRUE;
+ all_streams_eos = all_slots_are_eos (urisrc);
BUFFERING_UNLOCK (urisrc);
/* EOS means this element is no longer buffering */
@@ -744,6 +776,11 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
s = gst_event_writable_structure (ev);
gst_structure_set (s, "urisourcebin-custom-eos", G_TYPE_BOOLEAN, TRUE,
NULL);
+ if (all_streams_eos) {
+ GST_DEBUG_OBJECT (urisrc, "POSTING ABOUT TO FINISH");
+ g_signal_emit (urisrc,
+ gst_uri_source_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
+ }
}
break;
case GST_EVENT_CAPS:
@@ -769,6 +806,28 @@ done:
return ret;
}
+static GstPadProbeReturn
+pre_queue_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
+{
+ GstURISourceBin *urisrc = GST_URI_SOURCE_BIN (user_data);
+ GstPadProbeReturn ret = GST_PAD_PROBE_OK;
+ GstEvent *ev = GST_PAD_PROBE_INFO_EVENT (info);
+
+ switch (GST_EVENT_TYPE (ev)) {
+ case GST_EVENT_EOS:
+ {
+ GST_LOG_OBJECT (urisrc, "EOS on pad %" GST_PTR_FORMAT, pad);
+ GST_DEBUG_OBJECT (urisrc, "POSTING ABOUT TO FINISH");
+ g_signal_emit (urisrc,
+ gst_uri_source_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
+ }
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
/* Called with lock held */
static OutputSlotInfo *
get_output_slot (GstURISourceBin * urisrc, gboolean do_download,
@@ -976,6 +1035,9 @@ create_output_pad (GstURISourceBin * urisrc, GstPad * pad)
gst_object_unref (pad_tmpl);
g_free (padname);
+ GST_DEBUG_OBJECT (urisrc, "Created output pad %s:%s for pad %s:%s",
+ GST_DEBUG_PAD_NAME (newpad), GST_DEBUG_PAD_NAME (pad));
+
return newpad;
}
@@ -1595,7 +1657,7 @@ handle_new_pad (GstURISourceBin * urisrc, GstPad * srcpad, GstCaps * caps)
gst_query_unref (query);
}
- GST_DEBUG_OBJECT (urisrc, "check media-type %s, %d", media_type,
+ GST_DEBUG_OBJECT (urisrc, "check media-type %s, do_download:%d", media_type,
do_download);
GST_URI_SOURCE_BIN_LOCK (urisrc);
@@ -1604,6 +1666,9 @@ handle_new_pad (GstURISourceBin * urisrc, GstPad * srcpad, GstCaps * caps)
if (slot == NULL || gst_pad_link (srcpad, slot->sinkpad) != GST_PAD_LINK_OK)
goto could_not_link;
+ gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
+ pre_queue_event_probe, urisrc, NULL);
+
expose_output_pad (urisrc, slot->srcpad);
GST_URI_SOURCE_BIN_UNLOCK (urisrc);
}