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
1 From 7186918c4d8ecb95f7b669205f7b06c1f462b6b2 Mon Sep 17 00:00:00 2001
2 From: Maemo Multimedia <multimedia@maemo.org>
3 Date: Thu, 22 Jan 2009 09:02:18 +0200
4 Subject: [PATCH] playbasebin: add network queue support, adding nw-queue
5  property
6
7 ---
8  gst/playback/gstplaybasebin.c |  256 ++++++++++++++++++++++++++++++++---------
9  gst/playback/gstplaybasebin.h |    1 +
10  2 files changed, 205 insertions(+), 52 deletions(-)
11
12 diff --git a/gst/playback/gstplaybasebin.c b/gst/playback/gstplaybasebin.c
13 index 847e12f..7f81da6 100644
14 --- a/gst/playback/gstplaybasebin.c
15 +++ b/gst/playback/gstplaybasebin.c
16 @@ -29,6 +29,11 @@
17  
18  #include <gst/pbutils/pbutils.h>
19  
20 +#define SCAN_SINKS_FROM_REGISTRY
21 +#define PREROLL_QUEUE_MAX_BUFFERS 5
22 +#define PREROLL_QUEUE_MAX_BYTES (1 * 1024 * 1024)
23 +#define NETWORK_QUEUE_MAX_BUFFERS 100
24 +
25  GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug);
26  #define GST_CAT_DEFAULT gst_play_base_bin_debug
27  
28 @@ -59,7 +64,8 @@ enum
29    ARG_AUDIO,
30    ARG_TEXT,
31    ARG_SUBTITLE_ENCODING,
32 -  ARG_CONNECTION_SPEED
33 +  ARG_CONNECTION_SPEED,
34 +  ARG_NW_QUEUE
35  };
36  
37  static void gst_play_base_bin_class_init (GstPlayBaseBinClass * klass);
38 @@ -94,6 +100,8 @@ static void set_active_source (GstPlayBaseBin * play_base_bin,
39  static gboolean probe_triggered (GstPad * pad, GstEvent * event,
40      gpointer user_data);
41  static void setup_substreams (GstPlayBaseBin * play_base_bin);
42 +static void queue_threshold_reached (GstElement * queue, GstPlayBaseBin
43 +    * play_base_bin);
44  
45  static GstPipelineClass *parent_class;
46  
47 @@ -215,6 +223,10 @@ gst_play_base_bin_class_init (GstPlayBaseBinClass * klass)
48            "Network connection speed in kbps (0 = unknown)",
49            0, G_MAXUINT, DEFAULT_CONNECTION_SPEED,
50            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
51 +  g_object_class_install_property (gobject_klass, ARG_NW_QUEUE,
52 +      g_param_spec_boolean ("nw-queue", "Use network queue",
53 +          "Use separate queue for network buffering instead of using "
54 +          "internal audio/video queues.", FALSE, G_PARAM_READWRITE));
55  
56    GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0,
57        "playbasebin");
58 @@ -236,6 +248,7 @@ gst_play_base_bin_init (GstPlayBaseBin * play_base_bin)
59    play_base_bin->suburi = NULL;
60    play_base_bin->need_rebuild = TRUE;
61    play_base_bin->is_stream = FALSE;
62 +  play_base_bin->use_nw_queue = FALSE;
63    play_base_bin->source = NULL;
64    play_base_bin->decoders = NULL;
65    play_base_bin->subtitle = NULL;
66 @@ -518,7 +531,6 @@ group_is_muted (GstPlayBaseGroup * group)
67  /*
68   * Buffer/cache checking.
69   */
70 -
71  static inline void
72  fill_buffer (GstPlayBaseBin * play_base_bin, gint percent)
73  {
74 @@ -716,12 +728,18 @@ queue_overrun (GstElement * queue, GstPlayBaseBin * play_base_bin)
75  
76    preroll_remove_overrun (queue, play_base_bin);
77  
78 -  group_commit (play_base_bin, FALSE,
79 -      GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) ==
80 -      GST_OBJECT_CAST (play_base_bin->subtitle));
81 +  // Commit the group only when we are using "stupid" buffering, because when
82 +  // using separate network queue element this preroll queue size is much
83 +  // smaller, causing premature overrun (decodebin2 is still in the
84 +  // pad expose-unlocking loop when that happens)
85 +  if (play_base_bin->use_nw_queue == FALSE) {
86 +    group_commit (play_base_bin, FALSE,
87 +        GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) ==
88 +        GST_OBJECT_CAST (play_base_bin->subtitle));
89  
90 -  /* notify end of buffering */
91 -  queue_threshold_reached (queue, play_base_bin);
92 +    /* notify end of buffering */
93 +    queue_threshold_reached (queue, play_base_bin);
94 +  }
95  }
96  
97  /* this signal is only added when in streaming mode to catch underruns
98 @@ -832,6 +850,11 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin,
99            "max-size-buffers", 0, "max-size-bytes",
100            2 * 1024 * 1024, "max-size-time", play_base_bin->queue_size, NULL);
101      }
102 +  } else if (play_base_bin->use_nw_queue) {
103 +    g_object_set (G_OBJECT (preroll),
104 +        "max-size-buffers", PREROLL_QUEUE_MAX_BUFFERS,
105 +        "max-size-bytes", PREROLL_QUEUE_MAX_BYTES,
106 +        "max-size-time", play_base_bin->queue_size, NULL);
107    } else {
108      g_object_set (G_OBJECT (preroll),
109          "max-size-buffers", 0, "max-size-bytes",
110 @@ -860,42 +883,45 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin,
111    g_object_set_data (G_OBJECT (preroll), "overrun_signal_id",
112        GINT_TO_POINTER (overrun_sig));
113  
114 -  if (play_base_bin->is_stream &&
115 -      ((type == GST_STREAM_TYPE_VIDEO &&
116 -              group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) ||
117 -          (type == GST_STREAM_TYPE_AUDIO &&
118 -              group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) {
119 -    GstPad *sinkpad;
120 -    guint id;
121 -
122 -    /* catch deadlocks when we are network buffering in time but the max-limit
123 -     * in bytes is hit. */
124 -    g_signal_connect (G_OBJECT (preroll), "overrun",
125 -        G_CALLBACK (queue_deadlock_check), play_base_bin);
126 -
127 -    /* attach pointer to playbasebin */
128 -    g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin);
129 -
130 -    /* give updates on queue size */
131 -    sinkpad = gst_element_get_static_pad (preroll, "sink");
132 -    id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), preroll);
133 -    GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)",
134 -        GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
135 -    g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id));
136 -
137 -    /* catch eos and flush events so that we can ignore underruns */
138 -    id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event),
139 -        preroll);
140 -    g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id));
141 -
142 -    gst_object_unref (sinkpad);
143 +  if (play_base_bin->use_nw_queue == FALSE) {
144 +    if (play_base_bin->is_stream &&
145 +        ((type == GST_STREAM_TYPE_VIDEO &&
146 +                group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) ||
147 +            (type == GST_STREAM_TYPE_AUDIO &&
148 +                group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) {
149 +      GstPad *sinkpad;
150 +      guint id;
151  
152 -    /* When we connect this queue, it will start running and immediatly
153 -     * fire an underrun. */
154 -    g_signal_connect (G_OBJECT (preroll), "underrun",
155 -        G_CALLBACK (queue_out_of_data), play_base_bin);
156 -    /* configure threshold and callbacks */
157 -    queue_out_of_data (preroll, play_base_bin);
158 +      /* catch deadlocks when we are network buffering in time but the max-limit
159 +       * in bytes is hit. */
160 +      g_signal_connect (G_OBJECT (preroll), "overrun",
161 +          G_CALLBACK (queue_deadlock_check), play_base_bin);
162 +
163 +      /* attach pointer to playbasebin */
164 +      g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin);
165 +
166 +      /* give updates on queue size */
167 +      sinkpad = gst_element_get_static_pad (preroll, "sink");
168 +      id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue),
169 +          preroll);
170 +      GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)",
171 +          GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
172 +      g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id));
173 +
174 +      /* catch eos and flush events so that we can ignore underruns */
175 +      id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event),
176 +          preroll);
177 +      g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id));
178 +
179 +      gst_object_unref (sinkpad);
180 +
181 +      /* When we connect this queue, it will start running and immediatly
182 +       * fire an underrun. */
183 +      g_signal_connect (G_OBJECT (preroll), "underrun",
184 +          G_CALLBACK (queue_out_of_data), play_base_bin);
185 +      /* configure threshold and callbacks */
186 +      queue_out_of_data (preroll, play_base_bin);
187 +    }
188    }
189  
190    /* listen for EOS so we can switch groups when one ended. */
191 @@ -1508,10 +1534,7 @@ setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri)
192    if (!source)
193      goto unknown_uri;
194  
195 -  if (g_getenv ("USE_DECODEBIN2"))
196 -    subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder");
197 -  else
198 -    subdecodebin = gst_element_factory_make ("decodebin", "subtitle-decoder");
199 +  subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder");
200    g_signal_connect (subdecodebin, "element-added",
201        G_CALLBACK (decodebin_element_added_cb), play_base_bin);
202    g_signal_connect (subdecodebin, "element-removed",
203 @@ -1572,7 +1595,7 @@ array_has_value (const gchar * values[], const gchar * value)
204  /* list of URIs that we consider to be streams and that need buffering.
205   * We have no mechanism yet to figure this out with a query. */
206  static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
207 -  "mmsu://", "mmst://", "myth://", NULL
208 +  "mmsu://", "mmst://", "myth://", "upnpav://", "obex://", "smb://", NULL
209  };
210  
211  /* blacklisted URIs, we know they will always fail. */
212 @@ -1974,16 +1997,80 @@ remove_decoders (GstPlayBaseBin * bin)
213    bin->decoders = NULL;
214  }
215  
216 +#ifdef SCAN_SINKS_FROM_REGISTRY
217 +
218 +/* filter function for sink elements */
219 +static gboolean
220 +gst_play_base_bin_sink_factory_filter (GstPluginFeature * feature,
221 +    GstPlayBaseBin * bin)
222 +{
223 +  guint rank;
224 +  const gchar *klass;
225 +
226 +  /* we only care about element factories */
227 +  if (!GST_IS_ELEMENT_FACTORY (feature))
228 +    return FALSE;
229 +
230 +  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
231 +  /* only sinks */
232 +  if (strstr (klass, "Sink") == NULL) {
233 +    return FALSE;
234 +  }
235 +
236 +  /* only select elements with autoplugging rank */
237 +  rank = gst_plugin_feature_get_rank (feature);
238 +  if (rank < GST_RANK_MARGINAL)
239 +    return FALSE;
240 +
241 +  return TRUE;
242 +}
243 +
244 +static GstCaps *
245 +get_supported_sink_caps (GstPlayBaseBin * bin)
246 +{
247 +  GList *sink_factories;
248 +  GstCaps *sink_caps = gst_caps_new_empty ();
249 +  GstCaps *caps = NULL;
250 +  const GList *item, *pad_templates;
251 +  GstStaticPadTemplate *templ;
252 +
253 +  /* filter out the sink factories;
254 +     stop decodebin construction when compatible sink is found */
255 +  sink_factories = gst_default_registry_feature_filter (
256 +      (GstPluginFeatureFilter) gst_play_base_bin_sink_factory_filter,
257 +      FALSE, bin);
258 +
259 +  /* scan sink caps from registry, assumes only 1 pad template per sink */
260 +  for (item = sink_factories; item != NULL; item = item->next) {
261 +    pad_templates =
262 +        gst_element_factory_get_static_pad_templates (GST_ELEMENT_FACTORY
263 +        (item->data));
264 +    templ = pad_templates->data;
265 +    /* Get caps from template */
266 +    caps = gst_caps_make_writable (gst_static_pad_template_get_caps (templ));
267 +    if (!gst_caps_is_any (caps)) {
268 +      gst_caps_append (sink_caps, caps);
269 +    } else {
270 +      gst_caps_unref (caps);
271 +    }
272 +  }
273 +
274 +  gst_plugin_feature_list_free (sink_factories);
275 +  GST_DEBUG_OBJECT (bin, "Sink caps from registry: %" GST_PTR_FORMAT,
276 +      sink_caps);
277 +
278 +  return sink_caps;
279 +
280 +}
281 +#endif
282 +
283  static GstElement *
284  make_decoder (GstPlayBaseBin * play_base_bin)
285  {
286    GstElement *decoder;
287  
288    /* now create the decoder element */
289 -  if (g_getenv ("USE_DECODEBIN2"))
290 -    decoder = gst_element_factory_make ("decodebin2", NULL);
291 -  else
292 -    decoder = gst_element_factory_make ("decodebin", NULL);
293 +  decoder = gst_element_factory_make ("decodebin2", NULL);
294    if (!decoder)
295      goto no_decodebin;
296  
297 @@ -2010,6 +2097,14 @@ make_decoder (GstPlayBaseBin * play_base_bin)
298  
299    play_base_bin->decoders = g_slist_prepend (play_base_bin->decoders, decoder);
300  
301 +#ifdef SCAN_SINKS_FROM_REGISTRY
302 +  {
303 +    GstCaps *sink_caps = get_supported_sink_caps (play_base_bin);
304 +    g_object_set (decoder, "caps", sink_caps, NULL);
305 +    gst_caps_unref (sink_caps);
306 +  }
307 +#endif
308 +
309    return decoder;
310  
311    /* ERRORS */
312 @@ -2021,6 +2116,32 @@ no_decodebin:
313    }
314  }
315  
316 +/* SOURCE ! NETWORK QUEUE ! DECODEBIN ! SINKS */
317 +static gboolean
318 +add_network_queue (GstPlayBaseBin * play_base_bin, GstElement * decoder)
319 +{
320 +  gboolean ret = FALSE;
321 +  GstElement *nw_queue = gst_element_factory_make ("queue2", "nw_queue");
322 +
323 +  /* Add network queue to bin */
324 +  if (nw_queue && gst_bin_add (GST_BIN_CAST (play_base_bin), nw_queue)) {
325 +    /* Link network queue */
326 +    if (gst_element_link (play_base_bin->source, nw_queue) &&
327 +        gst_element_link (nw_queue, decoder)) {
328 +      /* Set queue2 properties */
329 +      g_object_set (G_OBJECT (nw_queue),
330 +          "max-size-buffers", NETWORK_QUEUE_MAX_BUFFERS,
331 +          "max-size-bytes", 0,
332 +          "max-size-time", (guint64) 0,
333 +          "use-buffering", TRUE, "use-rate-estimate", FALSE, NULL);
334 +      ret = TRUE;
335 +    } else {
336 +      gst_bin_remove (GST_BIN_CAST (play_base_bin), nw_queue);
337 +    }
338 +  }
339 +  return ret;
340 +}
341 +
342  static void
343  remove_source (GstPlayBaseBin * bin)
344  {
345 @@ -2040,6 +2161,17 @@ remove_source (GstPlayBaseBin * bin)
346      }
347      gst_bin_remove (GST_BIN_CAST (bin), source);
348      bin->source = NULL;
349 +
350 +    if (bin->use_nw_queue) {
351 +      if (bin->is_stream) {
352 +        GstElement *nw_queue =
353 +            gst_bin_get_by_name (GST_BIN_CAST (bin), "nw_queue");
354 +        GST_DEBUG_OBJECT (bin, "removing network queue element");
355 +        gst_element_set_state (nw_queue, GST_STATE_NULL);
356 +        gst_bin_remove (GST_BIN_CAST (bin), nw_queue);
357 +        gst_object_unref (nw_queue);
358 +      }
359 +    }
360    }
361  }
362  
363 @@ -2210,13 +2342,27 @@ setup_source (GstPlayBaseBin * play_base_bin)
364          "Source has dynamic output pads, %d pending", play_base_bin->pending);
365    } else {
366      GstElement *decoder;
367 +    gboolean link_ok = FALSE;
368  
369      /* no dynamic source, we can link now */
370      decoder = make_decoder (play_base_bin);
371      if (!decoder)
372        goto no_decodebin;
373  
374 -    if (!gst_element_link (play_base_bin->source, decoder))
375 +    if (play_base_bin->use_nw_queue) {
376 +      /* FIXME: network queue isn't added with source having dynamic pads */
377 +      if (play_base_bin->is_stream) {
378 +        GST_DEBUG_OBJECT (play_base_bin,
379 +            "linking source to decoder using network queue");
380 +        link_ok = add_network_queue (play_base_bin, decoder);
381 +      } else {
382 +        GST_DEBUG_OBJECT (play_base_bin, "linking source to decoder");
383 +        link_ok = gst_element_link (play_base_bin->source, decoder);
384 +      }
385 +    } else {
386 +      link_ok = gst_element_link (play_base_bin->source, decoder);
387 +    }
388 +    if (!link_ok)
389        goto could_not_link;
390    }
391  
392 @@ -2631,6 +2777,9 @@ gst_play_base_bin_set_property (GObject * object, guint prop_id,
393        g_slist_free (list);
394        break;
395      }
396 +    case ARG_NW_QUEUE:
397 +      play_base_bin->use_nw_queue = g_value_get_boolean (value);
398 +      break;
399      default:
400        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
401        break;
402 @@ -2718,6 +2867,9 @@ gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value,
403        g_value_set_string (value, play_base_bin->subencoding);
404        GST_OBJECT_UNLOCK (play_base_bin);
405        break;
406 +    case ARG_NW_QUEUE:
407 +      g_value_set_boolean (value, play_base_bin->use_nw_queue);
408 +      break;
409      default:
410        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
411        break;
412 diff --git a/gst/playback/gstplaybasebin.h b/gst/playback/gstplaybasebin.h
413 index c8c8649..26c9fcd 100644
414 --- a/gst/playback/gstplaybasebin.h
415 +++ b/gst/playback/gstplaybasebin.h
416 @@ -88,6 +88,7 @@ struct _GstPlayBaseBin {
417    gboolean       subtitle_done;
418    gboolean       need_rebuild;
419    gboolean       raw_decoding_mode;     /* Use smaller queues when source outputs raw data */
420 +  gboolean       use_nw_queue;
421  
422    GSList        *subtitle_elements;     /* subtitle elements that have 'subtitle-encoding' property */
423    gchar         *subencoding;           /* encoding to propagate to the above subtitle elements     */