Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / debian / patches / 0010-playbasebin-add-network-queue-support-adding-nw-queu.patch
diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0010-playbasebin-add-network-queue-support-adding-nw-queu.patch b/gst-plugins-base-subtitles0.10/debian/patches/0010-playbasebin-add-network-queue-support-adding-nw-queu.patch
new file mode 100644 (file)
index 0000000..59f67db
--- /dev/null
@@ -0,0 +1,423 @@
+From 7186918c4d8ecb95f7b669205f7b06c1f462b6b2 Mon Sep 17 00:00:00 2001
+From: Maemo Multimedia <multimedia@maemo.org>
+Date: Thu, 22 Jan 2009 09:02:18 +0200
+Subject: [PATCH] playbasebin: add network queue support, adding nw-queue
+ property
+
+---
+ gst/playback/gstplaybasebin.c |  256 ++++++++++++++++++++++++++++++++---------
+ gst/playback/gstplaybasebin.h |    1 +
+ 2 files changed, 205 insertions(+), 52 deletions(-)
+
+diff --git a/gst/playback/gstplaybasebin.c b/gst/playback/gstplaybasebin.c
+index 847e12f..7f81da6 100644
+--- a/gst/playback/gstplaybasebin.c
++++ b/gst/playback/gstplaybasebin.c
+@@ -29,6 +29,11 @@
+ #include <gst/pbutils/pbutils.h>
++#define SCAN_SINKS_FROM_REGISTRY
++#define PREROLL_QUEUE_MAX_BUFFERS 5
++#define PREROLL_QUEUE_MAX_BYTES (1 * 1024 * 1024)
++#define NETWORK_QUEUE_MAX_BUFFERS 100
++
+ GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug);
+ #define GST_CAT_DEFAULT gst_play_base_bin_debug
+@@ -59,7 +64,8 @@ enum
+   ARG_AUDIO,
+   ARG_TEXT,
+   ARG_SUBTITLE_ENCODING,
+-  ARG_CONNECTION_SPEED
++  ARG_CONNECTION_SPEED,
++  ARG_NW_QUEUE
+ };
+ static void gst_play_base_bin_class_init (GstPlayBaseBinClass * klass);
+@@ -94,6 +100,8 @@ static void set_active_source (GstPlayBaseBin * play_base_bin,
+ static gboolean probe_triggered (GstPad * pad, GstEvent * event,
+     gpointer user_data);
+ static void setup_substreams (GstPlayBaseBin * play_base_bin);
++static void queue_threshold_reached (GstElement * queue, GstPlayBaseBin
++    * play_base_bin);
+ static GstPipelineClass *parent_class;
+@@ -215,6 +223,10 @@ gst_play_base_bin_class_init (GstPlayBaseBinClass * klass)
+           "Network connection speed in kbps (0 = unknown)",
+           0, G_MAXUINT, DEFAULT_CONNECTION_SPEED,
+           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++  g_object_class_install_property (gobject_klass, ARG_NW_QUEUE,
++      g_param_spec_boolean ("nw-queue", "Use network queue",
++          "Use separate queue for network buffering instead of using "
++          "internal audio/video queues.", FALSE, G_PARAM_READWRITE));
+   GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0,
+       "playbasebin");
+@@ -236,6 +248,7 @@ gst_play_base_bin_init (GstPlayBaseBin * play_base_bin)
+   play_base_bin->suburi = NULL;
+   play_base_bin->need_rebuild = TRUE;
+   play_base_bin->is_stream = FALSE;
++  play_base_bin->use_nw_queue = FALSE;
+   play_base_bin->source = NULL;
+   play_base_bin->decoders = NULL;
+   play_base_bin->subtitle = NULL;
+@@ -518,7 +531,6 @@ group_is_muted (GstPlayBaseGroup * group)
+ /*
+  * Buffer/cache checking.
+  */
+-
+ static inline void
+ fill_buffer (GstPlayBaseBin * play_base_bin, gint percent)
+ {
+@@ -716,12 +728,18 @@ queue_overrun (GstElement * queue, GstPlayBaseBin * play_base_bin)
+   preroll_remove_overrun (queue, play_base_bin);
+-  group_commit (play_base_bin, FALSE,
+-      GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) ==
+-      GST_OBJECT_CAST (play_base_bin->subtitle));
++  // Commit the group only when we are using "stupid" buffering, because when
++  // using separate network queue element this preroll queue size is much
++  // smaller, causing premature overrun (decodebin2 is still in the
++  // pad expose-unlocking loop when that happens)
++  if (play_base_bin->use_nw_queue == FALSE) {
++    group_commit (play_base_bin, FALSE,
++        GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) ==
++        GST_OBJECT_CAST (play_base_bin->subtitle));
+-  /* notify end of buffering */
+-  queue_threshold_reached (queue, play_base_bin);
++    /* notify end of buffering */
++    queue_threshold_reached (queue, play_base_bin);
++  }
+ }
+ /* this signal is only added when in streaming mode to catch underruns
+@@ -832,6 +850,11 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin,
+           "max-size-buffers", 0, "max-size-bytes",
+           2 * 1024 * 1024, "max-size-time", play_base_bin->queue_size, NULL);
+     }
++  } else if (play_base_bin->use_nw_queue) {
++    g_object_set (G_OBJECT (preroll),
++        "max-size-buffers", PREROLL_QUEUE_MAX_BUFFERS,
++        "max-size-bytes", PREROLL_QUEUE_MAX_BYTES,
++        "max-size-time", play_base_bin->queue_size, NULL);
+   } else {
+     g_object_set (G_OBJECT (preroll),
+         "max-size-buffers", 0, "max-size-bytes",
+@@ -860,42 +883,45 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin,
+   g_object_set_data (G_OBJECT (preroll), "overrun_signal_id",
+       GINT_TO_POINTER (overrun_sig));
+-  if (play_base_bin->is_stream &&
+-      ((type == GST_STREAM_TYPE_VIDEO &&
+-              group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) ||
+-          (type == GST_STREAM_TYPE_AUDIO &&
+-              group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) {
+-    GstPad *sinkpad;
+-    guint id;
+-
+-    /* catch deadlocks when we are network buffering in time but the max-limit
+-     * in bytes is hit. */
+-    g_signal_connect (G_OBJECT (preroll), "overrun",
+-        G_CALLBACK (queue_deadlock_check), play_base_bin);
+-
+-    /* attach pointer to playbasebin */
+-    g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin);
+-
+-    /* give updates on queue size */
+-    sinkpad = gst_element_get_static_pad (preroll, "sink");
+-    id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), preroll);
+-    GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)",
+-        GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
+-    g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id));
+-
+-    /* catch eos and flush events so that we can ignore underruns */
+-    id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event),
+-        preroll);
+-    g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id));
+-
+-    gst_object_unref (sinkpad);
++  if (play_base_bin->use_nw_queue == FALSE) {
++    if (play_base_bin->is_stream &&
++        ((type == GST_STREAM_TYPE_VIDEO &&
++                group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) ||
++            (type == GST_STREAM_TYPE_AUDIO &&
++                group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) {
++      GstPad *sinkpad;
++      guint id;
+-    /* When we connect this queue, it will start running and immediatly
+-     * fire an underrun. */
+-    g_signal_connect (G_OBJECT (preroll), "underrun",
+-        G_CALLBACK (queue_out_of_data), play_base_bin);
+-    /* configure threshold and callbacks */
+-    queue_out_of_data (preroll, play_base_bin);
++      /* catch deadlocks when we are network buffering in time but the max-limit
++       * in bytes is hit. */
++      g_signal_connect (G_OBJECT (preroll), "overrun",
++          G_CALLBACK (queue_deadlock_check), play_base_bin);
++
++      /* attach pointer to playbasebin */
++      g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin);
++
++      /* give updates on queue size */
++      sinkpad = gst_element_get_static_pad (preroll, "sink");
++      id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue),
++          preroll);
++      GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)",
++          GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
++      g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id));
++
++      /* catch eos and flush events so that we can ignore underruns */
++      id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event),
++          preroll);
++      g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id));
++
++      gst_object_unref (sinkpad);
++
++      /* When we connect this queue, it will start running and immediatly
++       * fire an underrun. */
++      g_signal_connect (G_OBJECT (preroll), "underrun",
++          G_CALLBACK (queue_out_of_data), play_base_bin);
++      /* configure threshold and callbacks */
++      queue_out_of_data (preroll, play_base_bin);
++    }
+   }
+   /* listen for EOS so we can switch groups when one ended. */
+@@ -1508,10 +1534,7 @@ setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri)
+   if (!source)
+     goto unknown_uri;
+-  if (g_getenv ("USE_DECODEBIN2"))
+-    subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder");
+-  else
+-    subdecodebin = gst_element_factory_make ("decodebin", "subtitle-decoder");
++  subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder");
+   g_signal_connect (subdecodebin, "element-added",
+       G_CALLBACK (decodebin_element_added_cb), play_base_bin);
+   g_signal_connect (subdecodebin, "element-removed",
+@@ -1572,7 +1595,7 @@ array_has_value (const gchar * values[], const gchar * value)
+ /* list of URIs that we consider to be streams and that need buffering.
+  * We have no mechanism yet to figure this out with a query. */
+ static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
+-  "mmsu://", "mmst://", "myth://", NULL
++  "mmsu://", "mmst://", "myth://", "upnpav://", "obex://", "smb://", NULL
+ };
+ /* blacklisted URIs, we know they will always fail. */
+@@ -1974,16 +1997,80 @@ remove_decoders (GstPlayBaseBin * bin)
+   bin->decoders = NULL;
+ }
++#ifdef SCAN_SINKS_FROM_REGISTRY
++
++/* filter function for sink elements */
++static gboolean
++gst_play_base_bin_sink_factory_filter (GstPluginFeature * feature,
++    GstPlayBaseBin * bin)
++{
++  guint rank;
++  const gchar *klass;
++
++  /* we only care about element factories */
++  if (!GST_IS_ELEMENT_FACTORY (feature))
++    return FALSE;
++
++  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
++  /* only sinks */
++  if (strstr (klass, "Sink") == NULL) {
++    return FALSE;
++  }
++
++  /* only select elements with autoplugging rank */
++  rank = gst_plugin_feature_get_rank (feature);
++  if (rank < GST_RANK_MARGINAL)
++    return FALSE;
++
++  return TRUE;
++}
++
++static GstCaps *
++get_supported_sink_caps (GstPlayBaseBin * bin)
++{
++  GList *sink_factories;
++  GstCaps *sink_caps = gst_caps_new_empty ();
++  GstCaps *caps = NULL;
++  const GList *item, *pad_templates;
++  GstStaticPadTemplate *templ;
++
++  /* filter out the sink factories;
++     stop decodebin construction when compatible sink is found */
++  sink_factories = gst_default_registry_feature_filter (
++      (GstPluginFeatureFilter) gst_play_base_bin_sink_factory_filter,
++      FALSE, bin);
++
++  /* scan sink caps from registry, assumes only 1 pad template per sink */
++  for (item = sink_factories; item != NULL; item = item->next) {
++    pad_templates =
++        gst_element_factory_get_static_pad_templates (GST_ELEMENT_FACTORY
++        (item->data));
++    templ = pad_templates->data;
++    /* Get caps from template */
++    caps = gst_caps_make_writable (gst_static_pad_template_get_caps (templ));
++    if (!gst_caps_is_any (caps)) {
++      gst_caps_append (sink_caps, caps);
++    } else {
++      gst_caps_unref (caps);
++    }
++  }
++
++  gst_plugin_feature_list_free (sink_factories);
++  GST_DEBUG_OBJECT (bin, "Sink caps from registry: %" GST_PTR_FORMAT,
++      sink_caps);
++
++  return sink_caps;
++
++}
++#endif
++
+ static GstElement *
+ make_decoder (GstPlayBaseBin * play_base_bin)
+ {
+   GstElement *decoder;
+   /* now create the decoder element */
+-  if (g_getenv ("USE_DECODEBIN2"))
+-    decoder = gst_element_factory_make ("decodebin2", NULL);
+-  else
+-    decoder = gst_element_factory_make ("decodebin", NULL);
++  decoder = gst_element_factory_make ("decodebin2", NULL);
+   if (!decoder)
+     goto no_decodebin;
+@@ -2010,6 +2097,14 @@ make_decoder (GstPlayBaseBin * play_base_bin)
+   play_base_bin->decoders = g_slist_prepend (play_base_bin->decoders, decoder);
++#ifdef SCAN_SINKS_FROM_REGISTRY
++  {
++    GstCaps *sink_caps = get_supported_sink_caps (play_base_bin);
++    g_object_set (decoder, "caps", sink_caps, NULL);
++    gst_caps_unref (sink_caps);
++  }
++#endif
++
+   return decoder;
+   /* ERRORS */
+@@ -2021,6 +2116,32 @@ no_decodebin:
+   }
+ }
++/* SOURCE ! NETWORK QUEUE ! DECODEBIN ! SINKS */
++static gboolean
++add_network_queue (GstPlayBaseBin * play_base_bin, GstElement * decoder)
++{
++  gboolean ret = FALSE;
++  GstElement *nw_queue = gst_element_factory_make ("queue2", "nw_queue");
++
++  /* Add network queue to bin */
++  if (nw_queue && gst_bin_add (GST_BIN_CAST (play_base_bin), nw_queue)) {
++    /* Link network queue */
++    if (gst_element_link (play_base_bin->source, nw_queue) &&
++        gst_element_link (nw_queue, decoder)) {
++      /* Set queue2 properties */
++      g_object_set (G_OBJECT (nw_queue),
++          "max-size-buffers", NETWORK_QUEUE_MAX_BUFFERS,
++          "max-size-bytes", 0,
++          "max-size-time", (guint64) 0,
++          "use-buffering", TRUE, "use-rate-estimate", FALSE, NULL);
++      ret = TRUE;
++    } else {
++      gst_bin_remove (GST_BIN_CAST (play_base_bin), nw_queue);
++    }
++  }
++  return ret;
++}
++
+ static void
+ remove_source (GstPlayBaseBin * bin)
+ {
+@@ -2040,6 +2161,17 @@ remove_source (GstPlayBaseBin * bin)
+     }
+     gst_bin_remove (GST_BIN_CAST (bin), source);
+     bin->source = NULL;
++
++    if (bin->use_nw_queue) {
++      if (bin->is_stream) {
++        GstElement *nw_queue =
++            gst_bin_get_by_name (GST_BIN_CAST (bin), "nw_queue");
++        GST_DEBUG_OBJECT (bin, "removing network queue element");
++        gst_element_set_state (nw_queue, GST_STATE_NULL);
++        gst_bin_remove (GST_BIN_CAST (bin), nw_queue);
++        gst_object_unref (nw_queue);
++      }
++    }
+   }
+ }
+@@ -2210,13 +2342,27 @@ setup_source (GstPlayBaseBin * play_base_bin)
+         "Source has dynamic output pads, %d pending", play_base_bin->pending);
+   } else {
+     GstElement *decoder;
++    gboolean link_ok = FALSE;
+     /* no dynamic source, we can link now */
+     decoder = make_decoder (play_base_bin);
+     if (!decoder)
+       goto no_decodebin;
+-    if (!gst_element_link (play_base_bin->source, decoder))
++    if (play_base_bin->use_nw_queue) {
++      /* FIXME: network queue isn't added with source having dynamic pads */
++      if (play_base_bin->is_stream) {
++        GST_DEBUG_OBJECT (play_base_bin,
++            "linking source to decoder using network queue");
++        link_ok = add_network_queue (play_base_bin, decoder);
++      } else {
++        GST_DEBUG_OBJECT (play_base_bin, "linking source to decoder");
++        link_ok = gst_element_link (play_base_bin->source, decoder);
++      }
++    } else {
++      link_ok = gst_element_link (play_base_bin->source, decoder);
++    }
++    if (!link_ok)
+       goto could_not_link;
+   }
+@@ -2631,6 +2777,9 @@ gst_play_base_bin_set_property (GObject * object, guint prop_id,
+       g_slist_free (list);
+       break;
+     }
++    case ARG_NW_QUEUE:
++      play_base_bin->use_nw_queue = g_value_get_boolean (value);
++      break;
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+@@ -2718,6 +2867,9 @@ gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value,
+       g_value_set_string (value, play_base_bin->subencoding);
+       GST_OBJECT_UNLOCK (play_base_bin);
+       break;
++    case ARG_NW_QUEUE:
++      g_value_set_boolean (value, play_base_bin->use_nw_queue);
++      break;
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+diff --git a/gst/playback/gstplaybasebin.h b/gst/playback/gstplaybasebin.h
+index c8c8649..26c9fcd 100644
+--- a/gst/playback/gstplaybasebin.h
++++ b/gst/playback/gstplaybasebin.h
+@@ -88,6 +88,7 @@ struct _GstPlayBaseBin {
+   gboolean       subtitle_done;
+   gboolean       need_rebuild;
+   gboolean       raw_decoding_mode;     /* Use smaller queues when source outputs raw data */
++  gboolean       use_nw_queue;
+   GSList        *subtitle_elements;     /* subtitle elements that have 'subtitle-encoding' property */
+   gchar         *subencoding;           /* encoding to propagate to the above subtitle elements     */