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.
This commit is contained in:
Vivia Nikolaidou 2012-05-10 23:08:21 +03:00 committed by Sebastian Dröge
parent 6bd0272512
commit 4d9d707e32

View file

@ -71,6 +71,12 @@ typedef struct
GstTagList *tags; GstTagList *tags;
} PrivateStream; } PrivateStream;
typedef struct
{
GstPad *pad;
gulong id;
} PadWithId;
struct _GstDiscovererPrivate struct _GstDiscovererPrivate
{ {
gboolean async; gboolean async;
@ -89,6 +95,9 @@ struct _GstDiscovererPrivate
/* TRUE if discoverer has been started */ /* TRUE if discoverer has been started */
gboolean running; gboolean running;
/* TRUE if ASYNC_DONE has been received (need to check for subtitle tags) */
gboolean async_done;
/* current items */ /* current items */
GstDiscovererInfo *current_info; GstDiscovererInfo *current_info;
GError *current_error; GError *current_error;
@ -97,6 +106,9 @@ struct _GstDiscovererPrivate
/* List of private streams */ /* List of private streams */
GList *streams; GList *streams;
/* List of these sinks and their handler IDs (to remove the probe) */
GList *pending_subtitle_pads;
/* Global elements */ /* Global elements */
GstBin *pipeline; GstBin *pipeline;
GstElement *uridecodebin; GstElement *uridecodebin;
@ -262,9 +274,12 @@ gst_discoverer_init (GstDiscoverer * dc)
dc->priv->timeout = DEFAULT_PROP_TIMEOUT; dc->priv->timeout = DEFAULT_PROP_TIMEOUT;
dc->priv->async = FALSE; dc->priv->async = FALSE;
dc->priv->async_done = FALSE;
dc->priv->lock = g_mutex_new (); dc->priv->lock = g_mutex_new ();
dc->priv->pending_subtitle_pads = NULL;
GST_LOG ("Creating pipeline"); GST_LOG ("Creating pipeline");
dc->priv->pipeline = (GstBin *) gst_pipeline_new ("Discoverer"); dc->priv->pipeline = (GstBin *) gst_pipeline_new ("Discoverer");
GST_LOG_OBJECT (dc, "Creating uridecodebin"); GST_LOG_OBJECT (dc, "Creating uridecodebin");
@ -461,6 +476,57 @@ is_subtitle_caps (const GstCaps * caps)
return ret; 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 static void
uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad, uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
GstDiscoverer * dc) GstDiscoverer * dc)
@ -486,10 +552,23 @@ uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
caps = gst_pad_query_caps (pad, NULL); 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)) { if (is_subtitle_caps (caps)) {
/* Subtitle streams are sparse and may not provide any information - don't /* Subtitle streams are sparse and may not provide any information - don't
* wait for data to preroll */ * 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); 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); 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)) if (!gst_element_sync_state_with_parent (ps->queue))
goto error; goto error;
sinkpad = gst_element_get_static_pad (ps->queue, "sink");
if (sinkpad == NULL)
goto error;
if (gst_pad_link_full (pad, sinkpad, if (gst_pad_link_full (pad, sinkpad,
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK) GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)
goto error; goto error;
@ -1175,10 +1251,30 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
done = TRUE; done = TRUE;
break; 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: case GST_MESSAGE_ASYNC_DONE:
if (GST_MESSAGE_SRC (msg) == (GstObject *) dc->priv->pipeline) { if (GST_MESSAGE_SRC (msg) == (GstObject *) dc->priv->pipeline) {
GST_DEBUG ("Finished changing state asynchronously"); 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; break;
@ -1233,7 +1329,6 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
return done; return done;
} }
static void static void
handle_current_sync (GstDiscoverer * dc) handle_current_sync (GstDiscoverer * dc)
{ {
@ -1320,6 +1415,11 @@ discoverer_cleanup (GstDiscoverer * dc)
dc->priv->current_info = NULL; 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 */ /* Try popping the next uri */
if (dc->priv->async) { if (dc->priv->async) {
if (dc->priv->pending_uris != NULL) { if (dc->priv->pending_uris != NULL) {