GstTagList *tags;
} PrivateStream;
+typedef struct
+{
+ GstPad *pad;
+ gulong id;
+} PadWithId;
+
struct _GstDiscovererPrivate
{
gboolean async;
/* 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;
/* 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;
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");
}
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)
{
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);
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;
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;
return done;
}
-
static void
handle_current_sync (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) {