GMutex stream_changed_pending_lock;
GList *stream_changed_pending;
+ /* to prevent that suburidecodebin seek flushes disrupt playback */
+ GMutex suburi_flushes_to_drop_lock;
+ GSList *suburi_flushes_to_drop;
+
/* selectors for different streams */
GstSourceSelect selector[PLAYBIN_STREAM_LAST];
};
static void gst_play_bin_suburidecodebin_block (GstSourceGroup * group,
GstElement * suburidecodebin, gboolean block);
-static void gst_play_bin_suburidecodebin_seek_to_start (GstElement *
- suburidecodebin);
+static void gst_play_bin_suburidecodebin_seek_to_start (GstSourceGroup * group);
static GstElementClass *parent_class;
if (group->stream_changed_pending_lock.p)
g_mutex_clear (&group->stream_changed_pending_lock);
group->stream_changed_pending_lock.p = NULL;
+
+ g_slist_free (group->suburi_flushes_to_drop);
+ group->suburi_flushes_to_drop = NULL;
+
+ if (group->suburi_flushes_to_drop_lock.p)
+ g_mutex_clear (&group->suburi_flushes_to_drop_lock);
+ group->suburi_flushes_to_drop_lock.p = NULL;
}
static void
}
static void
-gst_play_bin_suburidecodebin_seek_to_start (GstElement * suburidecodebin)
+gst_play_bin_suburidecodebin_seek_to_start (GstSourceGroup * group)
{
+ GstElement *suburidecodebin = group->suburidecodebin;
GstIterator *it = gst_element_iterate_src_pads (suburidecodebin);
GstPad *sinkpad;
GValue item = { 0, };
if (it && gst_iterator_next (it, &item) == GST_ITERATOR_OK
&& ((sinkpad = g_value_get_object (&item)) != NULL)) {
GstEvent *event;
+ guint32 seqnum;
event =
- gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
+ gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1);
+ seqnum = gst_event_get_seqnum (event);
+
+ /* store the seqnum to drop flushes from this seek later */
+ g_mutex_lock (&group->suburi_flushes_to_drop_lock);
+ group->suburi_flushes_to_drop =
+ g_slist_append (group->suburi_flushes_to_drop,
+ GUINT_TO_POINTER (seqnum));
+ g_mutex_unlock (&group->suburi_flushes_to_drop_lock);
+
if (!gst_pad_send_event (sinkpad, event)) {
event =
- gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+ gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1);
- if (!gst_pad_send_event (sinkpad, event))
+ gst_event_set_seqnum (event, seqnum);
+ if (!gst_pad_send_event (sinkpad, event)) {
GST_DEBUG_OBJECT (suburidecodebin, "Seeking to the beginning failed!");
+
+ g_mutex_lock (&group->suburi_flushes_to_drop_lock);
+ group->suburi_flushes_to_drop =
+ g_slist_remove (group->suburi_flushes_to_drop,
+ GUINT_TO_POINTER (seqnum));
+ g_mutex_unlock (&group->suburi_flushes_to_drop_lock);
+ }
}
g_value_unset (&item);
/* seek to the beginning */
if (need_seek)
- gst_play_bin_suburidecodebin_seek_to_start (group->suburidecodebin);
+ gst_play_bin_suburidecodebin_seek_to_start (group);
}
gst_object_unref (selector);
}
}
+static GstPadProbeReturn
+_suburidecodebin_event_probe (GstPad * pad, GstPadProbeInfo * info,
+ gpointer udata)
+{
+ GstPadProbeReturn ret = GST_PAD_PROBE_OK;
+ GstSourceGroup *group = udata;
+ GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_START:
+ case GST_EVENT_FLUSH_STOP:
+ {
+ guint32 seqnum = gst_event_get_seqnum (event);
+ GSList *item = g_slist_find (group->suburi_flushes_to_drop,
+ GUINT_TO_POINTER (seqnum));
+ if (item) {
+ ret = GST_PAD_PROBE_DROP; /* this is from subtitle seek only, drop it */
+ if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
+ group->suburi_flushes_to_drop =
+ g_slist_delete_link (group->suburi_flushes_to_drop, item);
+ }
+ }
+ }
+ default:
+ break;
+ }
+ return ret;
+}
+
/* helper function to lookup stuff in lists */
static gboolean
array_has_value (const gchar * values[], const gchar * value, gboolean exact)
}
GST_SOURCE_GROUP_UNLOCK (group);
+ if (decodebin == group->suburidecodebin) {
+ /* TODO store the probe id */
+ /* to avoid propagating flushes from suburi specific seeks */
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
+ _suburidecodebin_event_probe, group, NULL);
+ }
+
if (changed) {
int signal;
gboolean always_ok = (decodebin == group->suburidecodebin);
if (!group->stream_changed_pending_lock.p)
g_mutex_init (&group->stream_changed_pending_lock);
+ g_slist_free (group->suburi_flushes_to_drop);
+ group->suburi_flushes_to_drop = NULL;
+ if (!group->suburi_flushes_to_drop_lock.p)
+ g_mutex_init (&group->suburi_flushes_to_drop_lock);
+
if (group->uridecodebin) {
GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin");
uridecodebin = group->uridecodebin;