Commit 4d9d707e authored by Vivia Nikolaidou's avatar Vivia Nikolaidou Committed by Sebastian Dröge
Browse files

discoverer: Wait until an update/filler newsegment event or buffer for subtitle streams

This makes sure that we wait until we received all tags for the
subtitle streams and have all information that is collected by
the discoverer.

Fixes bug #673504.
parent 6bd02725
......@@ -71,6 +71,12 @@ typedef struct
GstTagList *tags;
} PrivateStream;
typedef struct
{
GstPad *pad;
gulong id;
} PadWithId;
struct _GstDiscovererPrivate
{
gboolean async;
......@@ -89,6 +95,9 @@ struct _GstDiscovererPrivate
/* TRUE if discoverer has been started */
gboolean running;
/* TRUE if ASYNC_DONE has been received (need to check for subtitle tags) */
gboolean async_done;
/* current items */
GstDiscovererInfo *current_info;
GError *current_error;
......@@ -97,6 +106,9 @@ struct _GstDiscovererPrivate
/* List of private streams */
GList *streams;
/* List of these sinks and their handler IDs (to remove the probe) */
GList *pending_subtitle_pads;
/* Global elements */
GstBin *pipeline;
GstElement *uridecodebin;
......@@ -262,9 +274,12 @@ gst_discoverer_init (GstDiscoverer * dc)
dc->priv->timeout = DEFAULT_PROP_TIMEOUT;
dc->priv->async = FALSE;
dc->priv->async_done = FALSE;
dc->priv->lock = g_mutex_new ();
dc->priv->pending_subtitle_pads = NULL;
GST_LOG ("Creating pipeline");
dc->priv->pipeline = (GstBin *) gst_pipeline_new ("Discoverer");
GST_LOG_OBJECT (dc, "Creating uridecodebin");
......@@ -461,6 +476,57 @@ is_subtitle_caps (const GstCaps * caps)
return ret;
}
static void
free_pad_id (PadWithId * d)
{
gst_pad_remove_data_probe (d->pad, d->id);
gst_object_unref (d->pad);
g_slice_free (PadWithId, d);
}
static void
got_subtitle_data (GstPad * pad, GstMiniObject * obj, GstDiscoverer * dc)
{
GList *item = NULL;
gboolean update;
gboolean is_event;
is_event = GST_IS_EVENT (obj);
if (!(GST_IS_BUFFER (obj) || (is_event
&& GST_EVENT_TYPE ((GstEvent *) obj) == GST_EVENT_NEWSEGMENT)))
return;
if (is_event) {
gst_event_parse_new_segment ((GstEvent *) obj, &update, NULL, NULL, NULL,
NULL, NULL);
if (!update)
return;
}
DISCO_LOCK (dc);
for (item = dc->priv->pending_subtitle_pads; item; item = item->next) {
PadWithId *pad_id = (PadWithId *) item->data;
if (pad_id->pad == pad) {
dc->priv->pending_subtitle_pads =
g_list_remove_link (dc->priv->pending_subtitle_pads, item);
free_pad_id (pad_id);
break;
}
}
if (dc->priv->pending_subtitle_pads == NULL) {
GstMessage *msg = gst_message_new_application (NULL,
gst_structure_empty_new ("DiscovererDone"));
gst_element_post_message ((GstElement *) dc->priv->pipeline, msg);
}
DISCO_UNLOCK (dc);
}
static void
uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
GstDiscoverer * dc)
......@@ -486,10 +552,23 @@ uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
caps = gst_pad_query_caps (pad, NULL);
sinkpad = gst_element_get_static_pad (ps->queue, "sink");
if (sinkpad == NULL)
goto error;
if (is_subtitle_caps (caps)) {
/* Subtitle streams are sparse and may not provide any information - don't
* wait for data to preroll */
PadWithId *pad_id;
pad_id = g_slice_new0 (PadWithId);
pad_id->pad = GST_PAD_CAST (gst_object_ref (sinkpad));
pad_id->id =
gst_pad_add_data_probe (sinkpad, (GCallback) got_subtitle_data, dc);
g_object_set (ps->sink, "async", FALSE, NULL);
DISCO_LOCK (dc);
dc->priv->pending_subtitle_pads =
g_list_prepend (dc->priv->pending_subtitle_pads, pad_id);
DISCO_UNLOCK (dc);
}
gst_caps_unref (caps);
......@@ -504,9 +583,6 @@ uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
if (!gst_element_sync_state_with_parent (ps->queue))
goto error;
sinkpad = gst_element_get_static_pad (ps->queue, "sink");
if (sinkpad == NULL)
goto error;
if (gst_pad_link_full (pad, sinkpad,
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)
goto error;
......@@ -1175,10 +1251,30 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
done = TRUE;
break;
case GST_MESSAGE_APPLICATION:{
const gchar *name;
gboolean async_done;
name = gst_structure_get_name (gst_message_get_structure (msg));
/* Maybe ASYNC_DONE is received & we're just waiting for subtitle tags */
DISCO_LOCK (dc);
async_done = dc->priv->async_done;
DISCO_UNLOCK (dc);
if (g_str_equal (name, "DiscovererDone") && async_done)
return TRUE;
break;
}
case GST_MESSAGE_ASYNC_DONE:
if (GST_MESSAGE_SRC (msg) == (GstObject *) dc->priv->pipeline) {
GST_DEBUG ("Finished changing state asynchronously");
done = TRUE;
DISCO_LOCK (dc);
if (dc->priv->pending_subtitle_pads == NULL) {
done = TRUE;
} else {
/* Remember that ASYNC_DONE has been received, wait for subtitles */
dc->priv->async_done = TRUE;
}
DISCO_UNLOCK (dc);
}
break;
......@@ -1233,7 +1329,6 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
return done;
}
static void
handle_current_sync (GstDiscoverer * dc)
{
......@@ -1320,6 +1415,11 @@ discoverer_cleanup (GstDiscoverer * dc)
dc->priv->current_info = NULL;
g_list_foreach (dc->priv->pending_subtitle_pads, (GFunc) free_pad_id, NULL);
g_list_free (dc->priv->pending_subtitle_pads);
dc->priv->pending_subtitle_pads = NULL;
dc->priv->async_done = FALSE;
/* Try popping the next uri */
if (dc->priv->async) {
if (dc->priv->pending_uris != NULL) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment