Initialize Tizen 2.3
[framework/multimedia/gst-plugins-ext0.10.git] / wearable / dashdemux / src / gstdashdemux.c
1 /*
2  * DASH demux plugin for GStreamer
3  *
4  * gstdashdemux.c
5  *
6  * Copyright (C) 2012 Orange
7  *
8  * Authors:
9  *   David Corvoysier <david.corvoysier@orange.com>
10  *   Hamid Zakari <hamid.zakari@gmail.com>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with this library (COPYING); if not, write to the
24  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25  * Boston, MA 02111-1307, USA.
26  */
27 /**
28  * SECTION:element-dashdemux
29  *
30  * DASH demuxer element.
31  * <title>Example launch line</title>
32  * |[
33  * gst-launch playbin2 uri="http://www-itec.uni-klu.ac.at/ftp/datasets/mmsys12/RedBullPlayStreets/redbull_4s/RedBullPlayStreets_4s_isoffmain_DIS_23009_1_v_2_1c2_2011_08_30.mpd"
34  * ]|
35  */
36
37 /* Implementation notes:
38  *
39  * The following section describes how dashdemux works internally.
40  *
41  * Introduction:
42  *
43  * dashdemux is a "fake" demux, as unlike traditional demux elements, it
44  * doesn't split data streams contained in an enveloppe to expose them
45  * to downstream decoding elements.
46  *
47  * Instead, it parses an XML file called a manifest to identify a set of
48  * individual stream fragments it needs to fetch and expose to the actual
49  * demux elements that will handle them (this behavior is sometimes
50  * referred as the "demux after a demux" scenario).
51  *
52  * For a given section of content, several representations corresponding
53  * to different bitrates may be available: dashdemux will select the most
54  * appropriate representation based on local conditions (typically the
55  * available bandwidth and the amount of buffering available, capped by
56  * a maximum allowed bitrate).
57  *
58  * The representation selection algorithm can be configured using
59  * specific properties: max bitrate, min/max buffering, bandwidth ratio.
60  *
61  *
62  * General Design:
63  *
64  * dashdemux has a single sink pad that accepts the data corresponding
65  * to the manifest, typically fetched from an HTTP or file source.
66  *
67  * dashdemux exposes the streams it recreates based on the fragments it
68  * fetches through dedicated src pads corresponding to the caps of the
69  * fragments container (ISOBMFF/MP4 or MPEG2TS).
70  *
71  * During playback, new representations will typically be exposed as a
72  * new set of pads (see 'Switching between representations' below).
73  *
74  * Fragments downloading is performed using a dedicated task that fills
75  * an internal queue. Another task is in charge of popping fragments
76  * from the queue and pushing them downstream.
77  *
78  * Switching between representations:
79  *
80  * Decodebin supports scenarios allowing to seamlessly switch from one
81  * stream to another inside the same "decoding chain".
82  *
83  * To achieve that, it combines the elements it autoplugged in chains
84  *  and groups, allowing only one decoding group to be active at a given
85  * time for a given chain.
86  *
87  * A chain can signal decodebin that it is complete by sending a
88  * no-more-pads event, but even after that new pads can be added to
89  * create new subgroups, providing that a new no-more-pads event is sent.
90  *
91  * We take advantage of that to dynamically create a new decoding group
92  * in order to select a different representation during playback.
93  *
94  * Typically, assuming that each fragment contains both audio and video,
95  * the following tree would be created:
96  *
97  * chain "DASH Demux"
98  * |_ group "Representation set 1"
99  * |   |_ chain "Qt Demux 0"
100  * |       |_ group "Stream 0"
101  * |           |_ chain "H264"
102  * |           |_ chain "AAC"
103  * |_ group "Representation set 2"
104  *     |_ chain "Qt Demux 1"
105  *         |_ group "Stream 1"
106  *             |_ chain "H264"
107  *             |_ chain "AAC"
108  *
109  * Or, if audio and video are contained in separate fragments:
110  *
111  * chain "DASH Demux"
112  * |_ group "Representation set 1"
113  * |   |_ chain "Qt Demux 0"
114  * |   |   |_ group "Stream 0"
115  * |   |       |_ chain "H264"
116  * |   |_ chain "Qt Demux 1"
117  * |       |_ group "Stream 1"
118  * |           |_ chain "AAC"
119  * |_ group "Representation set 2"
120  *     |_ chain "Qt Demux 3"
121  *     |   |_ group "Stream 2"
122  *     |       |_ chain "H264"
123  *     |_ chain "Qt Demux 4"
124  *         |_ group "Stream 3"
125  *             |_ chain "AAC"
126  *
127  * In both cases, when switching from Set 1 to Set 2 an EOS is sent on
128  * each end pad corresponding to Rep 0, triggering the "drain" state to
129  * propagate upstream.
130  * Once both EOS have been processed, the "Set 1" group is completely
131  * drained, and decodebin2 will switch to the "Set 2" group.
132  *
133  * Note: nothing can be pushed to the new decoding group before the
134  * old one has been drained, which means that in order to be able to
135  * adapt quickly to bandwidth changes, we will not be able to rely
136  * on downstream buffering, and will instead manage an internal queue.
137  *
138  */
139
140 #ifdef HAVE_CONFIG_H
141 #  include "config.h"
142 #endif
143
144 /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
145  * with newer GLib versions (>= 2.31.0) */
146 #define GLIB_DISABLE_DEPRECATION_WARNINGS
147
148 #include <string.h>
149 #include <inttypes.h>
150 #include <gst/base/gsttypefindhelper.h>
151 #include "gstdashdemux.h"
152
153 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
154     GST_PAD_SRC,
155     GST_PAD_SOMETIMES,
156     GST_STATIC_CAPS_ANY);
157
158 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
159     GST_PAD_SINK,
160     GST_PAD_ALWAYS,
161     GST_STATIC_CAPS ("application/dash+xml"));
162
163 GST_DEBUG_CATEGORY_STATIC (gst_dash_demux_debug);
164 #define GST_CAT_DEFAULT gst_dash_demux_debug
165
166 enum
167 {
168   PROP_0,
169
170   PROP_MIN_BUFFERING_TIME,
171   PROP_MAX_BUFFERING_TIME,
172   PROP_BANDWIDTH_USAGE,
173   PROP_MAX_BITRATE,
174   PROP_LAST
175 };
176
177 /* Default values for properties */
178 #define DEFAULT_MIN_BUFFERING_TIME        5     /* in seconds */
179 #define DEFAULT_MAX_BUFFERING_TIME       30     /* in seconds */
180 #define DEFAULT_BANDWIDTH_USAGE         0.8     /* 0 to 1     */
181 #define DEFAULT_MAX_BITRATE        24000000     /* in bit/s  */
182
183 #define DEFAULT_FAILED_COUNT 3
184
185
186 /* GObject */
187 static void gst_dash_demux_set_property (GObject * object, guint prop_id,
188     const GValue * value, GParamSpec * pspec);
189 static void gst_dash_demux_get_property (GObject * object, guint prop_id,
190     GValue * value, GParamSpec * pspec);
191 static void gst_dash_demux_dispose (GObject * obj);
192
193 /* GstElement */
194 static GstStateChangeReturn
195 gst_dash_demux_change_state (GstElement * element, GstStateChange transition);
196
197 /* GstDashDemux */
198 static GstFlowReturn gst_dash_demux_pad (GstPad * pad, GstBuffer * buf);
199 static gboolean gst_dash_demux_sink_event (GstPad * pad, GstEvent * event);
200 static gboolean gst_dash_demux_src_event (GstPad * pad, GstEvent * event);
201 static gboolean gst_dash_demux_src_query (GstPad * pad, GstQuery * query);
202 static void gst_dash_demux_stream_loop (GstDashDemux * demux);
203 static void gst_dash_demux_download_loop (GstDashDemux * demux);
204 static void gst_dash_demux_stop (GstDashDemux * demux);
205 static void gst_dash_demux_pause_stream_task (GstDashDemux * demux);
206 static void gst_dash_demux_resume_stream_task (GstDashDemux * demux);
207 static void gst_dash_demux_resume_download_task (GstDashDemux * demux);
208 static gboolean gst_dash_demux_setup_all_streams (GstDashDemux * demux);
209 static gboolean gst_dash_demux_select_representations (GstDashDemux * demux,
210     guint64 current_bitrate);
211 static gboolean gst_dash_demux_get_next_fragment_set (GstDashDemux * demux);
212
213 static void gst_dash_demux_reset (GstDashDemux * demux, gboolean dispose);
214 static GstClockTime gst_dash_demux_get_buffering_time (GstDashDemux * demux);
215 static float gst_dash_demux_get_buffering_ratio (GstDashDemux * demux);
216 static GstBuffer *gst_dash_demux_merge_buffer_list (GstFragment * fragment);
217
218 static void
219 _do_init (GType type)
220 {
221   GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "dashdemux", 0,
222       "dashdemux element");
223 }
224
225 GST_BOILERPLATE_FULL (GstDashDemux, gst_dash_demux, GstElement,
226     GST_TYPE_ELEMENT, _do_init);
227
228 static void
229 gst_dash_demux_base_init (gpointer g_class)
230 {
231   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
232
233   gst_element_class_add_static_pad_template (element_class, &srctemplate);
234
235   gst_element_class_add_static_pad_template (element_class, &sinktemplate);
236
237   gst_element_class_set_details_simple (element_class,
238       "DASH Demuxer",
239       "Codec/Demuxer",
240       "Dynamic Adaptive Streaming over HTTP demuxer",
241       "David Corvoysier <david.corvoysier@orange.com>\n\
242                 Hamid Zakari <hamid.zakari@gmail.com>\n\
243                 Gianluca Gennari <gennarone@gmail.com>");
244 }
245
246 static void
247 gst_dash_demux_dispose (GObject * obj)
248 {
249   GstDashDemux *demux = GST_DASH_DEMUX (obj);
250
251   if (demux->stream_task) {
252     if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
253       GST_DEBUG_OBJECT (demux, "Leaving streaming task");
254       gst_task_stop (demux->stream_task);
255       gst_task_join (demux->stream_task);
256     }
257     gst_object_unref (demux->stream_task);
258     g_static_rec_mutex_free (&demux->stream_lock);
259     g_mutex_free(demux->stream_timed_lock);
260     demux->stream_task = NULL;
261   }
262
263   if (demux->download_task) {
264     if (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED) {
265       GST_DEBUG_OBJECT (demux, "Leaving download task");
266       gst_task_stop (demux->download_task);
267       gst_task_join (demux->download_task);
268     }
269     gst_object_unref (demux->download_task);
270     g_static_rec_mutex_free (&demux->download_lock);
271     g_mutex_free(demux->download_timed_lock);
272     demux->download_task = NULL;
273   }
274
275   if (demux->downloader != NULL) {
276     g_object_unref (demux->downloader);
277     demux->downloader = NULL;
278   }
279
280   gst_dash_demux_reset (demux, TRUE);
281
282   g_queue_free (demux->queue);
283
284   G_OBJECT_CLASS (parent_class)->dispose (obj);
285 }
286
287 static void
288 gst_dash_demux_class_init (GstDashDemuxClass * klass)
289 {
290   GObjectClass *gobject_class;
291   GstElementClass *gstelement_class;
292
293   gobject_class = (GObjectClass *) klass;
294   gstelement_class = (GstElementClass *) klass;
295
296   gobject_class->set_property = gst_dash_demux_set_property;
297   gobject_class->get_property = gst_dash_demux_get_property;
298   gobject_class->dispose = gst_dash_demux_dispose;
299
300   g_object_class_install_property (gobject_class, PROP_MIN_BUFFERING_TIME,
301       g_param_spec_uint ("min-buffering-time", "Minimum buffering time",
302           "Minimum number of seconds of buffer accumulated before playback",
303           1, G_MAXUINT, DEFAULT_MIN_BUFFERING_TIME,
304           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
305
306   g_object_class_install_property (gobject_class, PROP_MAX_BUFFERING_TIME,
307       g_param_spec_uint ("max-buffering-time", "Maximum buffering time",
308           "Maximum number of seconds of buffer accumulated during playback",
309           2, G_MAXUINT, DEFAULT_MAX_BUFFERING_TIME,
310           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
311
312   g_object_class_install_property (gobject_class, PROP_BANDWIDTH_USAGE,
313       g_param_spec_float ("bandwidth-usage",
314           "Bandwidth usage [0..1]",
315           "Percentage of the available bandwidth to use when selecting representations",
316           0, 1, DEFAULT_BANDWIDTH_USAGE,
317           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
318
319   g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
320       g_param_spec_uint ("max-bitrate", "Max bitrate",
321           "Max of bitrate supported by target decoder",
322           1000, G_MAXUINT, DEFAULT_MAX_BITRATE,
323           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
324
325   gstelement_class->change_state =
326       GST_DEBUG_FUNCPTR (gst_dash_demux_change_state);
327 }
328
329 static void
330 gst_dash_demux_init (GstDashDemux * demux, GstDashDemuxClass * klass)
331 {
332   /* sink pad */
333   demux->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
334   gst_pad_set_chain_function (demux->sinkpad,
335       GST_DEBUG_FUNCPTR (gst_dash_demux_pad));
336   gst_pad_set_event_function (demux->sinkpad,
337       GST_DEBUG_FUNCPTR (gst_dash_demux_sink_event));
338   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
339
340   /* Downloader */
341   demux->downloader = gst_uri_downloader_new ();
342
343   /* Properties */
344   demux->min_buffering_time = DEFAULT_MIN_BUFFERING_TIME * GST_SECOND;
345   demux->max_buffering_time = DEFAULT_MAX_BUFFERING_TIME * GST_SECOND;
346   demux->bandwidth_usage = DEFAULT_BANDWIDTH_USAGE;
347   demux->max_bitrate = DEFAULT_MAX_BITRATE;
348
349   demux->queue = g_queue_new ();
350   /* Updates task */
351   g_static_rec_mutex_init (&demux->download_lock);
352   demux->download_task =
353       gst_task_create ((GstTaskFunction) gst_dash_demux_download_loop, demux);
354   gst_task_set_lock (demux->download_task, &demux->download_lock);
355   demux->download_timed_lock = g_mutex_new ();
356
357   /* Streaming task */
358   g_static_rec_mutex_init (&demux->stream_lock);
359   demux->stream_task =
360       gst_task_create ((GstTaskFunction) gst_dash_demux_stream_loop, demux);
361   gst_task_set_lock (demux->stream_task, &demux->stream_lock);
362   demux->stream_timed_lock = g_mutex_new ();
363 }
364
365 static void
366 gst_dash_demux_set_property (GObject * object, guint prop_id,
367     const GValue * value, GParamSpec * pspec)
368 {
369   GstDashDemux *demux = GST_DASH_DEMUX (object);
370
371   switch (prop_id) {
372     case PROP_MIN_BUFFERING_TIME:
373       demux->min_buffering_time = g_value_get_uint (value) * GST_SECOND;
374       break;
375     case PROP_MAX_BUFFERING_TIME:
376       demux->max_buffering_time = g_value_get_uint (value) * GST_SECOND;
377       break;
378     case PROP_BANDWIDTH_USAGE:
379       demux->bandwidth_usage = g_value_get_float (value);
380       break;
381     case PROP_MAX_BITRATE:
382       demux->max_bitrate = g_value_get_uint (value);
383       break;
384     default:
385       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386       break;
387   }
388 }
389
390 static void
391 gst_dash_demux_get_property (GObject * object, guint prop_id, GValue * value,
392     GParamSpec * pspec)
393 {
394   GstDashDemux *demux = GST_DASH_DEMUX (object);
395
396   switch (prop_id) {
397     case PROP_MIN_BUFFERING_TIME:
398       g_value_set_uint (value, demux->min_buffering_time);
399       demux->min_buffering_time *= GST_SECOND;
400       break;
401     case PROP_MAX_BUFFERING_TIME:
402       g_value_set_uint (value, demux->max_buffering_time);
403       demux->max_buffering_time *= GST_SECOND;
404       break;
405     case PROP_BANDWIDTH_USAGE:
406       g_value_set_float (value, demux->bandwidth_usage);
407       break;
408     case PROP_MAX_BITRATE:
409       g_value_set_uint (value, demux->max_bitrate);
410       break;
411     default:
412       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
413       break;
414   }
415 }
416
417 static GstStateChangeReturn
418 gst_dash_demux_change_state (GstElement * element, GstStateChange transition)
419 {
420   GstStateChangeReturn ret;
421   GstDashDemux *demux = GST_DASH_DEMUX (element);
422
423   switch (transition) {
424     case GST_STATE_CHANGE_READY_TO_PAUSED:
425       gst_dash_demux_reset (demux, FALSE);
426       break;
427     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
428       /* Start the streaming loop in paused only if we already received
429          the manifest. It might have been stopped if we were in PAUSED
430          state and we filled our queue with enough cached fragments
431        */
432       if (demux->client->mpd_node != NULL)
433         gst_dash_demux_resume_stream_task (demux);
434       break;
435     default:
436       break;
437   }
438
439   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
440
441   switch (transition) {
442     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
443       gst_dash_demux_pause_stream_task (demux);
444       break;
445     case GST_STATE_CHANGE_PAUSED_TO_READY:
446       demux->cancelled = TRUE;
447       gst_dash_demux_stop (demux);
448       gst_task_join (demux->stream_task);
449       gst_task_join (demux->download_task);
450       break;
451     default:
452       break;
453   }
454   return ret;
455 }
456
457 void
458 gst_dash_demux_clear_queue (GstDashDemux * demux)
459 {
460   while (!g_queue_is_empty (demux->queue)) {
461     GList *listfragment = g_queue_pop_head (demux->queue);
462     guint j = 0;
463     while (j < g_list_length (listfragment)) {
464       GstFragment *fragment = g_list_nth_data (listfragment, j);
465       g_object_unref (fragment);
466       j++;
467     }
468     g_list_free (listfragment);
469   }
470   g_queue_clear (demux->queue);
471 }
472
473 static gboolean
474 gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
475 {
476   GstDashDemux *demux;
477
478   demux = GST_DASH_DEMUX (gst_pad_get_element_private (pad));
479
480   switch (event->type) {
481     case GST_EVENT_SEEK:
482     {
483       gdouble rate;
484       GstFormat format;
485       GstSeekFlags flags;
486       GstSeekType start_type, stop_type;
487       gint64 start, stop;
488       GList *list;
489       GstClockTime current_pos, target_pos;
490       guint current_sequence, current_period;
491       GstActiveStream *stream;
492       GstMediaSegment *chunk;
493       GstStreamPeriod *period;
494       guint nb_active_stream;
495       guint stream_idx;
496
497       if (gst_mpd_client_is_live (demux->client)) {
498         GST_WARNING_OBJECT (demux, "Received seek event for live stream");
499         return FALSE;
500       }
501
502       gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
503           &stop_type, &stop);
504
505       if (format != GST_FORMAT_TIME)
506         return FALSE;
507
508       GST_DEBUG_OBJECT (demux,
509           "seek event, rate: %f type: %d start: %" GST_TIME_FORMAT " stop: %"
510           GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
511           GST_TIME_ARGS (stop));
512
513       //GST_MPD_CLIENT_LOCK (demux->client);
514
515       /* select the requested Period in the Media Presentation */
516       target_pos = (GstClockTime) start;
517       current_period = 0;
518       for (list = g_list_first (demux->client->periods); list;
519           list = g_list_next (list)) {
520         period = list->data;
521         current_pos = period->start;
522         current_period = period->number;
523         if (current_pos <= target_pos
524             && target_pos < current_pos + period->duration) {
525           break;
526         }
527       }
528       if (list == NULL) {
529         GST_WARNING_OBJECT (demux, "Could not find seeked Period");
530         return FALSE;
531       }
532       if (current_period != gst_mpd_client_get_period_index (demux->client)) {
533         GST_DEBUG_OBJECT (demux, "Seeking to Period %d", current_period);
534         /* setup video, audio and subtitle streams, starting from the new Period */
535         if (!gst_mpd_client_set_period_index (demux->client, current_period) ||
536             !gst_dash_demux_setup_all_streams (demux))
537           return FALSE;
538       }
539
540       stream = gst_mpdparser_get_active_stream_by_index (demux->client, 0);
541       current_pos = 0;
542       for (list = g_list_first (stream->segments); list;
543           list = g_list_next (list)) {
544         chunk = list->data;
545         current_pos = chunk->start_time;
546         current_sequence = chunk->number;
547         if (current_pos <= target_pos
548             && target_pos < current_pos + chunk->duration) {
549           break;
550         }
551       }
552       //GST_MPD_CLIENT_UNLOCK (demux->client);
553
554       if (list == NULL) {
555         GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
556         return FALSE;
557       }
558
559       /* We can actually perform the seek */
560       nb_active_stream = gst_mpdparser_get_nb_active_stream (demux->client);
561
562       if (flags & GST_SEEK_FLAG_FLUSH) {
563         GST_DEBUG_OBJECT (demux, "sending flush start");
564         stream_idx = 0;
565         while (stream_idx < nb_active_stream) {
566           gst_pad_push_event (demux->srcpad[stream_idx],
567               gst_event_new_flush_start ());
568           stream_idx++;
569         }
570       }
571
572       /* Stop the demux */
573       demux->cancelled = TRUE;
574       gst_dash_demux_stop (demux);
575
576       /* Wait for streaming to finish */
577       g_static_rec_mutex_lock (&demux->stream_lock);
578
579       /* Clear the buffering queue */
580       /* FIXME: allow seeking in the buffering queue */
581       gst_dash_demux_clear_queue (demux);
582
583       //GST_MPD_CLIENT_LOCK (demux->client);
584       GST_DEBUG_OBJECT (demux, "Seeking to sequence %d", current_sequence);
585       /* Update the current sequence on all streams */
586       gst_mpd_client_set_segment_index_for_all_streams (demux->client,
587           current_sequence);
588       /* Calculate offset in the next fragment */
589       demux->position = gst_mpd_client_get_current_position (demux->client);
590       demux->position_shift = start - demux->position;
591       demux->need_segment = TRUE;
592       //GST_MPD_CLIENT_UNLOCK (demux->client);
593
594       if (flags & GST_SEEK_FLAG_FLUSH) {
595         GST_DEBUG_OBJECT (demux, "Sending flush stop on all pad");
596         stream_idx = 0;
597         while (stream_idx < nb_active_stream) {
598           gst_pad_push_event (demux->srcpad[stream_idx],
599               gst_event_new_flush_stop ());
600           stream_idx++;
601         }
602       }
603
604       /* Restart the demux */
605       demux->cancelled = FALSE;
606       gst_dash_demux_resume_download_task (demux);
607       gst_dash_demux_resume_stream_task (demux);
608       g_static_rec_mutex_unlock (&demux->stream_lock);
609
610       return TRUE;
611     }
612     default:
613       break;
614   }
615
616   return gst_pad_event_default (pad, event);
617 }
618
619 static gboolean
620 gst_dash_demux_setup_all_streams (GstDashDemux * demux)
621 {
622   GList *listLang = NULL;
623   guint i, nb_audio;
624   gchar *lang;
625
626   GST_MPD_CLIENT_LOCK (demux->client);
627   /* clean old active stream list, if any */
628   gst_active_streams_free (demux->client);
629
630   if (!gst_mpd_client_setup_streaming (demux->client, GST_STREAM_VIDEO, ""))
631     GST_INFO_OBJECT (demux, "No video adaptation set found");
632
633   nb_audio =
634       gst_mpdparser_get_list_and_nb_of_audio_language (demux->client,
635       &listLang);
636   if (nb_audio == 0)
637     nb_audio = 1;
638   GST_INFO_OBJECT (demux, "Number of language is=%d", nb_audio);
639
640   for (i = 0; i < nb_audio; i++) {
641     lang = (gchar *) g_list_nth_data (listLang, i);
642     if (gst_mpdparser_get_nb_adaptationSet (demux->client) > 1)
643       if (!gst_mpd_client_setup_streaming (demux->client, GST_STREAM_AUDIO,
644               lang))
645         GST_INFO_OBJECT (demux, "No audio adaptation set found");
646
647     if (gst_mpdparser_get_nb_adaptationSet (demux->client) > nb_audio)
648       if (!gst_mpd_client_setup_streaming (demux->client,
649               GST_STREAM_APPLICATION, lang))
650         GST_INFO_OBJECT (demux, "No application adaptation set found");
651   }
652   GST_MPD_CLIENT_UNLOCK (demux->client);
653
654   return TRUE;
655 }
656
657 static gboolean
658 gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
659 {
660   GstDashDemux *demux = GST_DASH_DEMUX (gst_pad_get_parent (pad));
661
662   switch (event->type) {
663     case GST_EVENT_EOS:{
664       gchar *manifest;
665       GstQuery *query;
666       gboolean res;
667
668       if (demux->manifest == NULL) {
669         GST_WARNING_OBJECT (demux, "Received EOS without a manifest.");
670         break;
671       }
672
673       GST_DEBUG_OBJECT (demux, "Got EOS on the sink pad: manifest fetched");
674
675       if (demux->client)
676         gst_mpd_client_free (demux->client);
677       demux->client = gst_mpd_client_new ();
678
679       query = gst_query_new_uri ();
680       res = gst_pad_peer_query (pad, query);
681       if (res) {
682         gst_query_parse_uri (query, &demux->client->mpd_uri);
683         GST_DEBUG_OBJECT (demux, "Fetched MPD file at URI: %s",
684             demux->client->mpd_uri);
685       } else {
686         GST_WARNING_OBJECT (demux, "MPD URI query failed.");
687       }
688       gst_query_unref (query);
689
690       manifest = (gchar *) GST_BUFFER_DATA (demux->manifest);
691       if (manifest == NULL) {
692         GST_WARNING_OBJECT (demux, "Error validating the manifest.");
693       } else if (!gst_mpd_parse (demux->client, manifest,
694               GST_BUFFER_SIZE (demux->manifest))) {
695         /* In most cases, this will happen if we set a wrong url in the
696          * source element and we have received the 404 HTML response instead of
697          * the manifest */
698         GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid manifest."),
699             (NULL));
700         return FALSE;
701       }
702       gst_buffer_unref (demux->manifest);
703       demux->manifest = NULL;
704
705       if (!gst_mpd_client_setup_media_presentation (demux->client)) {
706         GST_ELEMENT_ERROR (demux, STREAM, DECODE,
707             ("Incompatible manifest file."), (NULL));
708         return FALSE;
709       }
710
711       /* setup video, audio and subtitle streams, starting from first Period */
712       if (!gst_mpd_client_set_period_index (demux->client, 0) ||
713           !gst_dash_demux_setup_all_streams (demux))
714         return FALSE;
715
716       /* start playing from the first segment */
717       gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
718
719       /* Send duration message */
720       if (!gst_mpd_client_is_live (demux->client)) {
721         GstClockTime duration =
722             gst_mpd_client_get_media_presentation_duration (demux->client);
723
724         if (duration != GST_CLOCK_TIME_NONE) {
725           GST_DEBUG_OBJECT (demux,
726               "Sending duration message : %" GST_TIME_FORMAT,
727               GST_TIME_ARGS (duration));
728           gst_element_post_message (GST_ELEMENT (demux),
729               gst_message_new_duration (GST_OBJECT (demux), GST_FORMAT_TIME,
730                   duration));
731         } else {
732           GST_DEBUG_OBJECT (demux,
733               "mediaPresentationDuration unknown, can not send the duration message");
734         }
735       }
736       gst_dash_demux_resume_download_task (demux);
737       gst_dash_demux_resume_stream_task (demux);
738       gst_event_unref (event);
739       return TRUE;
740     }
741     case GST_EVENT_NEWSEGMENT:
742       /* Swallow newsegments, we'll push our own */
743       gst_event_unref (event);
744       return TRUE;
745     default:
746       break;
747   }
748
749   return gst_pad_event_default (pad, event);
750 }
751
752 static gboolean
753 gst_dash_demux_src_query (GstPad * pad, GstQuery * query)
754 {
755   GstDashDemux *dashdemux;
756   gboolean ret = FALSE;
757
758   if (query == NULL)
759     return FALSE;
760
761   dashdemux = GST_DASH_DEMUX (gst_pad_get_element_private (pad));
762
763   switch (query->type) {
764     case GST_QUERY_DURATION:{
765       GstClockTime duration = -1;
766       GstFormat fmt;
767
768       gst_query_parse_duration (query, &fmt, NULL);
769       if (fmt == GST_FORMAT_TIME) {
770         duration =
771             gst_mpd_client_get_media_presentation_duration (dashdemux->client);
772         if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) {
773           gst_query_set_duration (query, GST_FORMAT_TIME, duration);
774           ret = TRUE;
775         }
776       }
777       GST_DEBUG_OBJECT (dashdemux,
778           "GST_QUERY_DURATION returns %s with duration %" GST_TIME_FORMAT,
779           ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration));
780       break;
781     }
782     case GST_QUERY_SEEKING:{
783       GstFormat fmt;
784       gint64 stop = -1;
785
786       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
787       GST_DEBUG_OBJECT (dashdemux, "Received GST_QUERY_SEEKING with format %d",
788           fmt);
789       if (fmt == GST_FORMAT_TIME) {
790         GstClockTime duration;
791
792         duration =
793             gst_mpd_client_get_media_presentation_duration (dashdemux->client);
794         if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0)
795           stop = duration;
796
797         gst_query_set_seeking (query, fmt,
798             !gst_mpd_client_is_live (dashdemux->client), 0, stop);
799         ret = TRUE;
800         GST_DEBUG_OBJECT (dashdemux, "GST_QUERY_SEEKING returning with stop : %"
801             GST_TIME_FORMAT, GST_TIME_ARGS (stop));
802       }
803       break;
804     }
805     case GST_QUERY_URI: {
806       /* forwarding uri */
807       GST_DEBUG("URI query recevied in DASH demux.....");
808         gboolean res;
809         res = gst_pad_query_default (pad,query);
810         if(res)
811           GST_DEBUG("forwarding URI is done successfully!!...");
812       ret = TRUE;
813       break;
814     }
815     default:{
816       // By default, do not forward queries upstream
817       break;
818     }
819   }
820
821   return ret;
822 }
823
824 static GstFlowReturn
825 gst_dash_demux_pad (GstPad * pad, GstBuffer * buf)
826 {
827   GstDashDemux *demux = GST_DASH_DEMUX (gst_pad_get_parent (pad));
828
829   if (demux->manifest == NULL)
830     demux->manifest = buf;
831   else
832     demux->manifest = gst_buffer_join (demux->manifest, buf);
833
834   gst_object_unref (demux);
835
836   return GST_FLOW_OK;
837 }
838
839 static void
840 gst_dash_demux_stop (GstDashDemux * demux)
841 {
842   gst_uri_downloader_cancel (demux->downloader);
843
844   if (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED) {
845     GST_TASK_SIGNAL (demux->download_task);
846     gst_task_stop (demux->download_task);
847   }
848   if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
849     GST_TASK_SIGNAL (demux->stream_task);
850     gst_task_stop (demux->stream_task);
851   }
852 }
853 #ifdef DASHDEMUX_MODIFICATION
854 static void
855 _update_caps(GstDashDemux * demux, guint nb_adaptation_set)
856 {
857   guint i = 0;
858   GstCaps *caps;
859
860   /* Create and activate new pads */
861   i = 0;
862   while (i < nb_adaptation_set) {
863     caps = gst_pad_get_caps(demux->srcpad[i]);
864     if(caps){
865       caps = gst_caps_make_writable(caps);
866       gst_caps_replace(&caps,demux->output_caps[i]);
867     }
868     else{
869       caps = demux->output_caps[i];
870     }
871     gst_pad_use_fixed_caps (demux->srcpad[i]);
872     gst_pad_set_caps (demux->srcpad[i], caps);
873     gst_caps_unref(caps);
874     i++;
875   }
876 }
877
878 static void
879 _add_pads(GstDashDemux * demux, guint nb_adaptation_set)
880 {
881   guint i = 0;
882
883   /* Create and activate new pads */
884   i = 0;
885   while (i < nb_adaptation_set) {
886     demux->srcpad[i] = gst_pad_new_from_static_template (&srctemplate, NULL);
887     gst_pad_set_event_function (demux->srcpad[i],
888         GST_DEBUG_FUNCPTR (gst_dash_demux_src_event));
889     gst_pad_set_query_function (demux->srcpad[i],
890         GST_DEBUG_FUNCPTR (gst_dash_demux_src_query));
891     gst_pad_set_element_private (demux->srcpad[i], demux);
892     gst_pad_set_active (demux->srcpad[i], TRUE);
893     gst_pad_set_caps (demux->srcpad[i], demux->output_caps[i]);
894     gst_caps_unref(demux->output_caps[i]);
895     gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad[i]);
896     i++;
897   }
898   /* Send 'no-more-pads' to have decodebin create the new group */
899   gst_element_no_more_pads (GST_ELEMENT (demux));
900 }
901
902 static gboolean
903 _needs_caps_update (GstDashDemux * demux, GList * fragment)
904 {
905
906   gboolean update_caps = FALSE;
907   guint i = 0;
908   while (i < g_list_length (fragment)) {
909     GstFragment *newFragment = g_list_nth_data (fragment, i);
910     if (newFragment == NULL) {
911       continue;
912     }
913     GstCaps *srccaps = NULL;
914     demux->output_caps[i] = gst_fragment_get_caps (newFragment);
915     if (G_LIKELY (demux->srcpad[i]))
916       srccaps = gst_pad_get_negotiated_caps (demux->srcpad[i]);
917     if (G_UNLIKELY (!srccaps
918             || (!gst_caps_is_equal_fixed (demux->output_caps[i], srccaps))
919             || demux->need_segment)) {
920       update_caps = TRUE;
921     }
922     if (G_LIKELY (srccaps))
923       gst_caps_unref (srccaps);
924     i++;
925   }
926   return update_caps;
927 }
928
929 #else
930 /* switch_pads:
931  *
932  * Called when switching from one set of representations to another, but
933  * only if one of the new representations requires different downstream
934  * elements (see the next function).
935  *
936  * This function first creates the new pads, then sends a no-more-pads
937  * event (that will tell decodebin to create a new group), then sends
938  * EOS on the old pads to trigger the group switch.
939  *
940  */
941 static void
942 switch_pads (GstDashDemux * demux, guint nb_adaptation_set)
943 {
944   GstPad *oldpad[MAX_LANGUAGES];
945   guint i = 0;
946   /* Remember old pads */
947   while (i < nb_adaptation_set) {
948     oldpad[i] = demux->srcpad[i];
949     if (oldpad[i]) {
950       GST_DEBUG_OBJECT (demux,
951           "Switching pads (oldpad:%p)" GST_PTR_FORMAT, oldpad[i]);
952     }
953     i++;
954   }
955   /* Create and activate new pads */
956   i = 0;
957   while (i < nb_adaptation_set) {
958     demux->srcpad[i] = gst_pad_new_from_static_template (&srctemplate, NULL);
959     gst_pad_set_event_function (demux->srcpad[i],
960         GST_DEBUG_FUNCPTR (gst_dash_demux_src_event));
961     gst_pad_set_query_function (demux->srcpad[i],
962         GST_DEBUG_FUNCPTR (gst_dash_demux_src_query));
963     gst_pad_set_element_private (demux->srcpad[i], demux);
964     gst_pad_set_active (demux->srcpad[i], TRUE);
965     gst_pad_set_caps (demux->srcpad[i], demux->output_caps[i]);
966     gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad[i]);
967     i++;
968   }
969   /* Send 'no-more-pads' to have decodebin create the new group */
970   gst_element_no_more_pads (GST_ELEMENT (demux));
971   /* Push out EOS on all old pads to switch to the new group */
972   i = 0;
973   while (i < nb_adaptation_set) {
974     if (oldpad[i]) {
975       gst_pad_push_event (oldpad[i], gst_event_new_eos ());
976       gst_pad_set_active (oldpad[i], FALSE);
977       gst_element_remove_pad (GST_ELEMENT (demux), oldpad[i]);
978     }
979     i++;
980   }
981 }
982
983 /* needs_pad_switch:
984  *
985  * Figure out if the newly selected representations require a new set
986  * of demuxers and decoders or if we can carry on with the existing ones.
987  *
988  * Basically, we look at the list of fragments we need to push downstream,
989  * and compare their caps with those of the corresponding src pads.
990  *
991  * As soon as one fragment requires a new set of caps, we need to switch
992  * all decoding pads to recreate a whole decoding group as we cannot
993  * move pads between groups (FIXME: or can we ?).
994  *
995  * FIXME: redundant with need_add_header
996  *
997  */
998 static gboolean
999 needs_pad_switch (GstDashDemux * demux, GList * fragment)
1000 {
1001
1002   gboolean switch_pad = FALSE;
1003   guint i = 0;
1004   while (i < g_list_length (fragment)) {
1005     GstFragment *newFragment = g_list_nth_data (fragment, i);
1006     if (newFragment == NULL) {
1007       continue;
1008     }
1009     GstCaps *srccaps = NULL;
1010     demux->output_caps[i] = gst_fragment_get_caps (newFragment);
1011     if (G_LIKELY (demux->srcpad[i]))
1012       srccaps = gst_pad_get_negotiated_caps (demux->srcpad[i]);
1013     if (G_UNLIKELY (!srccaps
1014             || (!gst_caps_is_equal_fixed (demux->output_caps[i], srccaps))
1015             || demux->need_segment)) {
1016       switch_pad = TRUE;
1017     }
1018     if (G_LIKELY (srccaps))
1019       gst_caps_unref (srccaps);
1020     i++;
1021   }
1022   return switch_pad;
1023 }
1024 #endif
1025
1026 /* gst_dash_demux_stream_loop:
1027  *
1028  * Loop for the "stream' task that pushes fragments to the src pads.
1029  *
1030  * Startup:
1031  * The task is started as soon as we have received the manifest and
1032  * waits for the first fragment to be downloaded and pushed in the
1033  * queue. Once this fragment has been pushed, the task pauses itself
1034  * until actual playback begins.
1035  *
1036  * During playback:
1037  * The task pushes fragments downstream at regular intervals based on
1038  * the fragment duration. If it detects a queue underrun, it sends
1039  * a buffering event to tell the main application to pause.
1040  *
1041  * Teardown:
1042  * The task is stopped when we have reached the end of the manifest
1043  * and emptied our queue.
1044  *
1045  */
1046 static void
1047 gst_dash_demux_stream_loop (GstDashDemux * demux)
1048 {
1049   GList *listfragment;
1050   GstFlowReturn ret;
1051   GstBufferList *buffer_list;
1052   guint nb_adaptation_set = 0;
1053   GstActiveStream *stream;
1054
1055   /* Wait until the next scheduled push downstream */
1056   if (g_cond_timed_wait (GST_TASK_GET_COND (demux->stream_task),
1057           demux->stream_timed_lock, &demux->next_push)) {
1058     goto quit;
1059   }
1060
1061   if (g_queue_is_empty (demux->queue)) {
1062     if (demux->end_of_manifest)
1063       goto end_of_manifest;
1064
1065     return;
1066   }
1067
1068   if (GST_STATE (demux) == GST_STATE_PLAYING) {
1069     if (!demux->end_of_manifest
1070         && gst_dash_demux_get_buffering_time (demux) <
1071         demux->min_buffering_time) {
1072       /* Warn we are below our threshold: this will eventually pause
1073        * the pipeline */
1074       gst_element_post_message (GST_ELEMENT (demux),
1075           gst_message_new_buffering (GST_OBJECT (demux),
1076               100 * gst_dash_demux_get_buffering_ratio (demux)));
1077     }
1078   }
1079   listfragment = g_queue_pop_head (demux->queue);
1080   nb_adaptation_set = g_list_length (listfragment);
1081 #ifdef DASHDEMUX_MODIFICATION
1082   /* Figure out if we need to create pads or update caps */
1083   gboolean caps_changed = _needs_caps_update (demux, listfragment);
1084   if (caps_changed) {
1085     if(demux->srcpad[0] == NULL)
1086     {
1087       _add_pads(demux,nb_adaptation_set);
1088       demux->need_segment = TRUE;
1089     }else{
1090       _update_caps(demux,nb_adaptation_set);
1091     }
1092   }
1093 #else
1094   /* Figure out if we need to create/switch pads */
1095   gboolean switch_pad = needs_pad_switch (demux, listfragment);
1096   if (switch_pad) {
1097     switch_pads (demux, nb_adaptation_set);
1098     demux->need_segment = TRUE;
1099   }
1100 #endif
1101   guint i = 0;
1102   for (i = 0; i < nb_adaptation_set; i++) {
1103     GstFragment *fragment = g_list_nth_data (listfragment, i);
1104     stream = gst_mpdparser_get_active_stream_by_index (demux->client, i);
1105     if (demux->need_segment) {
1106       GstClockTime start = fragment->start_time + demux->position_shift;
1107       /* And send a newsegment */
1108       GST_DEBUG_OBJECT (demux, "Sending new-segment. segment start:%"
1109           GST_TIME_FORMAT, GST_TIME_ARGS (start));
1110       gst_pad_push_event (demux->srcpad[i],
1111           gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
1112               start, GST_CLOCK_TIME_NONE, start));
1113       demux->position_shift = 0;
1114     }
1115
1116     GST_DEBUG_OBJECT (demux, "Pushing fragment #%d", fragment->index);
1117     buffer_list = gst_fragment_get_buffer_list (fragment);
1118     g_object_unref (fragment);
1119     ret = gst_pad_push_list (demux->srcpad[i], buffer_list);
1120     if ((ret != GST_FLOW_OK) && (stream->mimeType == GST_STREAM_VIDEO))
1121       goto error_pushing;
1122   }
1123   demux->need_segment = FALSE;
1124   g_list_free (listfragment);
1125   GST_STATE_LOCK(demux);
1126   if (GST_STATE (demux) == GST_STATE_PLAYING) {
1127     /* Wait for the duration of a fragment before resuming this task */
1128     g_get_current_time (&demux->next_push);
1129     g_time_val_add (&demux->next_push,
1130         gst_mpd_client_get_next_fragment_duration (demux->client)
1131         / GST_SECOND * G_USEC_PER_SEC);
1132     GST_DEBUG_OBJECT (demux, "Next push scheduled at %s",
1133         g_time_val_to_iso8601 (&demux->next_push));
1134   } else {
1135     /* The pipeline is now set up, wait until playback begins */
1136     GST_INFO_OBJECT (demux, "Pausing streaming task");
1137     gst_task_pause (demux->stream_task);
1138   }
1139   GST_STATE_UNLOCK(demux);
1140
1141 quit:
1142   {
1143     return;
1144   }
1145
1146 end_of_manifest:
1147   {
1148     GST_INFO_OBJECT (demux, "Reached end of manifest, sending EOS");
1149     guint i = 0;
1150     for (i = 0; i < gst_mpdparser_get_nb_active_stream (demux->client); i++) {
1151       gst_pad_push_event (demux->srcpad[i], gst_event_new_eos ());
1152     }
1153     GST_INFO_OBJECT (demux, "Stopped streaming task");
1154     gst_task_stop (demux->stream_task);
1155     return;
1156   }
1157
1158 error_pushing:
1159   {
1160     /* FIXME: handle error */
1161     GST_ERROR_OBJECT (demux,
1162         "Error pushing buffer: %s... terminating the demux",
1163         gst_flow_get_name (ret));
1164     gst_dash_demux_stop (demux);
1165     return;
1166   }
1167 }
1168
1169 static void
1170 gst_dash_demux_reset (GstDashDemux * demux, gboolean dispose)
1171 {
1172   demux->end_of_period = FALSE;
1173   demux->end_of_manifest = FALSE;
1174   demux->cancelled = FALSE;
1175
1176   guint i = 0;
1177   for (i = 0; i < MAX_LANGUAGES; i++)
1178     if (demux->input_caps[i]) {
1179       gst_caps_unref (demux->input_caps[i]);
1180       demux->input_caps[i] = NULL;
1181     }
1182
1183   if (demux->manifest) {
1184     gst_buffer_unref (demux->manifest);
1185     demux->manifest = NULL;
1186   }
1187   if (demux->client) {
1188     gst_mpd_client_free (demux->client);
1189     demux->client = NULL;
1190   }
1191   if (!dispose) {
1192     demux->client = gst_mpd_client_new ();
1193   }
1194
1195   gst_dash_demux_clear_queue (demux);
1196
1197   demux->last_manifest_update = GST_CLOCK_TIME_NONE;
1198   demux->position = 0;
1199   demux->position_shift = 0;
1200   demux->need_segment = TRUE;
1201 }
1202
1203 static GstClockTime
1204 gst_dash_demux_get_buffering_time (GstDashDemux * demux)
1205 {
1206   GstClockTime buffer_time = 0;
1207   GList *listfragment;
1208   GstFragment *first_fragment, *last_fragment;
1209
1210   if (g_queue_is_empty (demux->queue))
1211     return 0;
1212
1213   /* get first fragment */
1214   listfragment = g_queue_peek_head (demux->queue);
1215   first_fragment = listfragment->data;
1216   /* get last fragment */
1217   listfragment = g_queue_peek_tail (demux->queue);
1218   last_fragment = listfragment->data;
1219
1220   if (first_fragment && last_fragment) {
1221     buffer_time = last_fragment->stop_time - first_fragment->start_time;
1222   }
1223
1224   return buffer_time;
1225 }
1226
1227 static float
1228 gst_dash_demux_get_buffering_ratio (GstDashDemux * demux)
1229 {
1230   float buffering_time = gst_dash_demux_get_buffering_time (demux);
1231   if (buffering_time >= demux->min_buffering_time) {
1232     return 1.0;
1233   } else
1234     return buffering_time / demux->min_buffering_time;
1235 }
1236
1237 static GstBuffer *
1238 gst_dash_demux_merge_buffer_list (GstFragment * fragment)
1239 {
1240   GstBufferList *list;
1241   GstBufferListIterator *it;
1242   GstBuffer *buffer, *ret = NULL;
1243   GstAdapter *adapter;
1244   gsize size;
1245
1246   adapter = gst_adapter_new ();
1247   list = gst_fragment_get_buffer_list (fragment);
1248   it = gst_buffer_list_iterate (list);
1249   while (gst_buffer_list_iterator_next_group (it)) {
1250     while ((buffer = gst_buffer_list_iterator_next (it)) != NULL) {
1251       gst_adapter_push (adapter, gst_buffer_ref (buffer));
1252     }
1253   }
1254   gst_buffer_list_iterator_free (it);
1255   gst_buffer_list_unref (list);
1256   size = gst_adapter_available (adapter);
1257   if (size > 0)
1258     ret = gst_adapter_take_buffer (adapter, size);
1259   GST_DEBUG ("Extracted a buffer of size %d from the fragment", size);
1260   g_object_unref (adapter);
1261
1262   return ret;
1263 }
1264
1265 /* gst_dash_demux_download_loop:
1266  *
1267  * Loop for the "download' task that fetches fragments based on the
1268  * selected representations.
1269  *
1270  * Startup:
1271  *
1272  * The task is started from the stream loop.
1273  *
1274  * During playback:
1275  *
1276  * It sequentially fetches fragments corresponding to the current
1277  * representations and pushes them into a queue.
1278  *
1279  * It tries to maintain the number of queued items within a predefined
1280  * range: if the queue is full, it will pause, checking every 100 ms if
1281  * it needs to restart downloading fragments.
1282  *
1283  * When a new set of fragments has been downloaded, it evaluates the
1284  * download time to check if we can or should switch to a different
1285  * set of representations.
1286  *
1287  * Teardown:
1288  *
1289  * The task will exit when it encounters an error or when the end of the
1290  * manifest has been reached.
1291  *
1292  */
1293 void
1294 gst_dash_demux_download_loop (GstDashDemux * demux)
1295 {
1296   GstClock *clock = gst_element_get_clock (GST_ELEMENT (demux));
1297   gint64 update_period = demux->client->mpd_node->minimumUpdatePeriod;
1298
1299   /* Wait until the next scheduled download */
1300   if (g_cond_timed_wait (GST_TASK_GET_COND (demux->download_task),
1301           demux->download_timed_lock, &demux->next_download)) {
1302     goto quit;
1303   }
1304
1305   if (clock && gst_mpd_client_is_live (demux->client)
1306       && demux->client->mpd_uri != NULL && update_period != -1) {
1307     GstFragment *download;
1308     GstBuffer *buffer;
1309     GstClockTime duration, now = gst_clock_get_time (clock);
1310
1311     /* init reference time for manifest file updates */
1312     if (!GST_CLOCK_TIME_IS_VALID (demux->last_manifest_update))
1313       demux->last_manifest_update = now;
1314
1315     /* update the manifest file */
1316     if (now >= demux->last_manifest_update + update_period * GST_MSECOND) {
1317       GST_DEBUG_OBJECT (demux, "Updating manifest file from URL %s",
1318           demux->client->mpd_uri);
1319       download =
1320           gst_uri_downloader_fetch_uri (demux->downloader,
1321           demux->client->mpd_uri);
1322       if (download == NULL) {
1323         GST_WARNING_OBJECT (demux,
1324             "Failed to update the manifest file from URL %s",
1325             demux->client->mpd_uri);
1326       } else {
1327         buffer = gst_dash_demux_merge_buffer_list (download);
1328         g_object_unref (download);
1329         /* parse the manifest file */
1330         if (buffer == NULL) {
1331           GST_WARNING_OBJECT (demux, "Error validating the manifest.");
1332         } else if (!gst_mpd_parse (demux->client,
1333                 (gchar *) GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
1334           /* In most cases, this will happen if we set a wrong url in the
1335            * source element and we have received the 404 HTML response instead of
1336            * the manifest */
1337           GST_WARNING_OBJECT (demux, "Error parsing the manifest.");
1338           gst_buffer_unref (buffer);
1339         } else {
1340           GstActiveStream *stream;
1341           guint segment_index;
1342
1343           gst_buffer_unref (buffer);
1344           stream = gst_mpdparser_get_active_stream_by_index (demux->client, 0);
1345           segment_index = gst_mpd_client_get_segment_index (stream);
1346           /* setup video, audio and subtitle streams, starting from first Period */
1347           if (!gst_mpd_client_setup_media_presentation (demux->client) ||
1348               !gst_mpd_client_set_period_index (demux->client,
1349                   gst_mpd_client_get_period_index (demux->client))
1350               || !gst_dash_demux_setup_all_streams (demux)) {
1351             GST_DEBUG_OBJECT (demux,
1352                 "Error setting up the updated manifest file");
1353             goto end_of_manifest;
1354           }
1355           /* continue playing from the the next segment */
1356           /* FIXME: support multiple streams with different segment duration */
1357           gst_mpd_client_set_segment_index_for_all_streams (demux->client,
1358               segment_index);
1359
1360           /* Send an updated duration message */
1361           duration =
1362               gst_mpd_client_get_media_presentation_duration (demux->client);
1363
1364           if (duration != GST_CLOCK_TIME_NONE) {
1365             GST_DEBUG_OBJECT (demux,
1366                 "Sending duration message : %" GST_TIME_FORMAT,
1367                 GST_TIME_ARGS (duration));
1368             gst_element_post_message (GST_ELEMENT (demux),
1369                 gst_message_new_duration (GST_OBJECT (demux), GST_FORMAT_TIME,
1370                     duration));
1371           } else {
1372             GST_DEBUG_OBJECT (demux,
1373                 "mediaPresentationDuration unknown, can not send the duration message");
1374           }
1375           demux->last_manifest_update += update_period * GST_MSECOND;
1376           GST_DEBUG_OBJECT (demux, "Manifest file successfully updated");
1377         }
1378       }
1379     }
1380   }
1381
1382
1383   /* Target buffering time MUST at least exceeds mimimum buffering time
1384    * by the duration of a fragment, but SHOULD NOT exceed maximum
1385    * buffering time */
1386   GstClockTime target_buffering_time =
1387       demux->min_buffering_time +
1388       gst_mpd_client_get_next_fragment_duration (demux->client);
1389   if (demux->max_buffering_time > target_buffering_time)
1390     target_buffering_time = demux->max_buffering_time;
1391   if (!demux->end_of_manifest
1392       && gst_dash_demux_get_buffering_time (demux) < target_buffering_time) {
1393     if (GST_STATE (demux) != GST_STATE_PLAYING) {
1394       /* Signal our buffering status (this will eventually restart the
1395        * pipeline when we have reached 100 %) */
1396       gst_element_post_message (GST_ELEMENT (demux),
1397           gst_message_new_buffering (GST_OBJECT (demux),
1398               100 * gst_dash_demux_get_buffering_ratio (demux)));
1399     }
1400
1401     /* try to switch to another set of representations if needed */
1402     gst_dash_demux_select_representations (demux,
1403         demux->bandwidth_usage * demux->dnl_rate *
1404         gst_dash_demux_get_buffering_ratio (demux));
1405
1406     /* fetch the next fragment */
1407     while (!gst_dash_demux_get_next_fragment_set (demux)) {
1408       if (demux->end_of_period) {
1409         GST_INFO_OBJECT (demux, "Reached the end of the Period");
1410         /* setup video, audio and subtitle streams, starting from the next Period */
1411         if (!gst_mpd_client_set_period_index (demux->client,
1412                 gst_mpd_client_get_period_index (demux->client) + 1)
1413             || !gst_dash_demux_setup_all_streams (demux)) {
1414           GST_INFO_OBJECT (demux, "Reached the end of the manifest file");
1415           demux->end_of_manifest = TRUE;
1416           if (GST_STATE (demux) != GST_STATE_PLAYING) {
1417             /* Restart the pipeline regardless of the current buffering level */
1418             gst_element_post_message (GST_ELEMENT (demux),
1419                 gst_message_new_buffering (GST_OBJECT (demux), 100));
1420           }
1421           gst_task_start (demux->stream_task);
1422           goto end_of_manifest;
1423         }
1424         /* start playing from the first segment of the new period */
1425         gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
1426         demux->end_of_period = FALSE;
1427       } else if (!demux->cancelled) {
1428         demux->client->update_failed_count++;
1429         if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
1430           GST_WARNING_OBJECT (demux, "Could not fetch the next fragment");
1431           goto quit;
1432         } else {
1433           goto error_downloading;
1434         }
1435       } else {
1436         goto quit;
1437       }
1438     }
1439     GST_INFO_OBJECT (demux, "Internal buffering : %" PRIu64 " s",
1440         gst_dash_demux_get_buffering_time (demux) / GST_SECOND);
1441     demux->client->update_failed_count = 0;
1442   } else {
1443     /* schedule the next download in 100 ms */
1444     g_get_current_time (&demux->next_download);
1445     g_time_val_add (&demux->next_download, 100000);
1446   }
1447
1448 quit:
1449   {
1450     return;
1451   }
1452
1453 end_of_manifest:
1454   {
1455     GST_INFO_OBJECT (demux, "Stopped download task");
1456     gst_task_stop (demux->download_task);
1457     return;
1458   }
1459
1460 error_downloading:
1461   {
1462     GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
1463         ("Could not fetch the next fragment"), (NULL));
1464     gst_dash_demux_stop (demux);
1465     return;
1466   }
1467 }
1468
1469 static void
1470 gst_dash_demux_pause_stream_task (GstDashDemux * demux)
1471 {
1472   /* Send a signal to the stream task so that it pauses itself */
1473   GST_TASK_SIGNAL (demux->stream_task);
1474   /* Pause it explicitly (if it was not in the COND) */
1475   gst_task_pause (demux->stream_task);
1476 }
1477
1478 static void
1479 gst_dash_demux_resume_stream_task (GstDashDemux * demux)
1480 {
1481   g_get_current_time (&demux->next_push);
1482   gst_task_start (demux->stream_task);
1483 }
1484
1485 static void
1486 gst_dash_demux_resume_download_task (GstDashDemux * demux)
1487 {
1488   g_get_current_time (&demux->next_download);
1489   gst_task_start (demux->download_task);
1490 }
1491
1492 /* gst_dash_demux_select_representations:
1493  *
1494  * Select the most appropriate media representations based on a target
1495  * bitrate.
1496  *
1497  * FIXME: all representations are selected against the same bitrate, but
1498  * they will share the same bandwidth. This only works today because the
1499  * audio representations bitrate usage is negligible as compared to the
1500  * video representation one.
1501  *
1502  * Returns TRUE if a new set of representations has been selected
1503  */
1504 static gboolean
1505 gst_dash_demux_select_representations (GstDashDemux * demux, guint64 bitrate)
1506 {
1507   GstActiveStream *stream = NULL;
1508   GList *rep_list = NULL;
1509   gint new_index;
1510   gboolean ret = FALSE;
1511
1512   guint i = 0;
1513   while (i < gst_mpdparser_get_nb_active_stream (demux->client)) {
1514     stream = gst_mpdparser_get_active_stream_by_index (demux->client, i);
1515     if (!stream)
1516       return FALSE;
1517
1518     /* retrieve representation list */
1519     if (stream->cur_adapt_set)
1520       rep_list = stream->cur_adapt_set->Representations;
1521     if (!rep_list)
1522       return FALSE;
1523
1524     /* get representation index with current max_bandwidth */
1525     new_index =
1526         gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list, bitrate);
1527
1528     /* if no representation has the required bandwidth, take the lowest one */
1529     if (new_index == -1)
1530       new_index = 0;
1531
1532     if (new_index != stream->representation_idx) {
1533       GST_MPD_CLIENT_LOCK (demux->client);
1534       ret =
1535           gst_mpd_client_setup_representation (demux->client, stream,
1536           g_list_nth_data (rep_list, new_index));
1537       GST_MPD_CLIENT_UNLOCK (demux->client);
1538       if (ret) {
1539         GST_INFO_OBJECT (demux, "Switching bitrate to %d",
1540             stream->cur_representation->bandwidth);
1541       } else {
1542         GST_WARNING_OBJECT (demux,
1543             "Can not switch representation, aborting...");
1544       }
1545     }
1546     i++;
1547   }
1548   return ret;
1549 }
1550
1551 static GstFragment *
1552 gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
1553 {
1554   const gchar *initializationURL;
1555   gchar *next_header_uri;
1556   GstFragment *fragment;
1557
1558   if (!gst_mpd_client_get_next_header (demux->client, &initializationURL,
1559           stream_idx))
1560     return NULL;
1561
1562   if (strncmp (initializationURL, "http://", 7) != 0) {
1563     next_header_uri =
1564         g_strconcat (gst_mpdparser_get_baseURL (demux->client),
1565         initializationURL, NULL);
1566   } else {
1567     next_header_uri = g_strdup (initializationURL);
1568   }
1569
1570   GST_INFO_OBJECT (demux, "Fetching header %s", next_header_uri);
1571
1572   fragment = gst_uri_downloader_fetch_uri (demux->downloader, next_header_uri);
1573   g_free (next_header_uri);
1574
1575   return fragment;
1576 }
1577
1578 static GstBufferListItem
1579 gst_dash_demux_add_buffer_cb (GstBuffer ** buffer,
1580     guint group, guint idx, gpointer user_data)
1581 {
1582   GstFragment *frag = GST_FRAGMENT (user_data);
1583   /* This buffer still belongs to the original fragment */
1584   /* so we need to increase refcount */
1585   gst_fragment_add_buffer (frag, gst_buffer_ref (*buffer));
1586   return GST_BUFFER_LIST_CONTINUE;
1587 }
1588
1589 /* Since we cannot add headers after the chunk has been downloaded, we have to recreate a new fragment */
1590 static GstFragment *
1591 gst_dash_demux_prepend_header (GstDashDemux * demux,
1592     GstFragment * frag, GstFragment * header)
1593 {
1594   GstFragment *res = gst_fragment_new ();
1595   res->name = g_strdup (frag->name);
1596   res->download_start_time = frag->download_start_time;
1597   res->download_stop_time = frag->download_stop_time;
1598   res->start_time = frag->start_time;
1599   res->stop_time = frag->stop_time;
1600   res->index = frag->index;
1601   res->discontinuous = frag->discontinuous;
1602
1603   GstBufferList *list;
1604   list = gst_fragment_get_buffer_list (header);
1605   gst_buffer_list_foreach (list, gst_dash_demux_add_buffer_cb, res);
1606   gst_buffer_list_unref (list);
1607   list = gst_fragment_get_buffer_list (frag);
1608   gst_buffer_list_foreach (list, gst_dash_demux_add_buffer_cb, res);
1609   gst_buffer_list_unref (list);
1610
1611   res->completed = TRUE;
1612
1613   return res;
1614 }
1615
1616 static GstCaps *
1617 gst_dash_demux_get_video_input_caps (GstDashDemux * demux,
1618     GstActiveStream * stream)
1619 {
1620   guint width = 0, height = 0;
1621   const gchar *mimeType = NULL;
1622   GstCaps *caps = NULL;
1623
1624   if (stream == NULL)
1625     return NULL;
1626 #ifdef DASHDEMUX_MODIFICATION
1627   /* caps need to inlcude resolution  */
1628     width = gst_mpd_client_get_video_stream_width (stream);
1629     height = gst_mpd_client_get_video_stream_height (stream);
1630 #else
1631   /* if bitstreamSwitching is true we dont need to swich pads on resolution change */  
1632   if (!gst_mpd_client_get_bitstream_switching_flag (stream)) {
1633     width = gst_mpd_client_get_video_stream_width (stream);
1634     height = gst_mpd_client_get_video_stream_height (stream);
1635   }
1636 #endif
1637   mimeType = gst_mpd_client_get_stream_mimeType (stream);
1638   if (mimeType == NULL)
1639     return NULL;
1640
1641   caps = gst_caps_new_simple (mimeType, NULL);
1642   if (width > 0 && height > 0) {
1643     gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
1644         G_TYPE_INT, height, NULL);
1645   }
1646
1647 /*  add ContentProtection to caps  */
1648   if ( stream->cur_adapt_set->RepresentationBase->ContentProtection != NULL){
1649     GList *list;
1650     GstDescriptorType *ContentProtectionDesc;
1651
1652     list = g_list_first (stream->cur_adapt_set->RepresentationBase->ContentProtection);
1653     ContentProtectionDesc = (GstDescriptorType *) list->data;
1654     gchar *schemeIdUri = ContentProtectionDesc->schemeIdUri;
1655     gchar *msprPro = ContentProtectionDesc->msprPro;
1656
1657   if ( (schemeIdUri != NULL) && (msprPro != NULL) ){
1658     gst_caps_set_simple (caps, "contentprotection_scheme_iduri", G_TYPE_STRING, schemeIdUri, "mspr:pro", G_TYPE_STRING, msprPro, NULL);
1659   }
1660  }
1661   return caps;
1662 }
1663
1664 static GstCaps *
1665 gst_dash_demux_get_audio_input_caps (GstDashDemux * demux,
1666     GstActiveStream * stream)
1667 {
1668   guint rate = 0, channels = 0;
1669   const gchar *mimeType;
1670   GstCaps *caps = NULL;
1671
1672   if (stream == NULL)
1673     return NULL;
1674
1675   /* if bitstreamSwitching is true we dont need to swich pads on rate/channels change */
1676   if (!gst_mpd_client_get_bitstream_switching_flag (stream)) {
1677     channels = gst_mpd_client_get_audio_stream_num_channels (stream);
1678     rate = gst_mpd_client_get_audio_stream_rate (stream);
1679   }
1680   mimeType = gst_mpd_client_get_stream_mimeType (stream);
1681   if (mimeType == NULL)
1682     return NULL;
1683
1684   caps = gst_caps_new_simple (mimeType, NULL);
1685   if (rate > 0) {
1686     gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL);
1687   }
1688   if (channels > 0) {
1689     gst_caps_set_simple (caps, "channels", G_TYPE_INT, channels, NULL);
1690   }
1691
1692 /*  add ContentProtection to caps  */
1693   if ( stream->cur_adapt_set->RepresentationBase->ContentProtection != NULL){
1694     GList *list;
1695     GstDescriptorType *ContentProtectionDesc;
1696
1697     list = g_list_first (stream->cur_adapt_set->RepresentationBase->ContentProtection);
1698     ContentProtectionDesc = (GstDescriptorType *) list->data;
1699     gchar *schemeIdUri = ContentProtectionDesc->schemeIdUri;
1700     gchar *msprPro = ContentProtectionDesc->msprPro;
1701
1702   if ( (schemeIdUri != NULL) && (msprPro != NULL) ){
1703     gst_caps_set_simple (caps, "contentprotection_scheme_iduri", G_TYPE_STRING, schemeIdUri, "mspr:pro", G_TYPE_STRING, msprPro, NULL);
1704   }
1705  }
1706   return caps;
1707 }
1708
1709 static GstCaps *
1710 gst_dash_demux_get_application_input_caps (GstDashDemux * demux,
1711     GstActiveStream * stream)
1712 {
1713   const gchar *mimeType;
1714   GstCaps *caps = NULL;
1715
1716   if (stream == NULL)
1717     return NULL;
1718
1719   mimeType = gst_mpd_client_get_stream_mimeType (stream);
1720   if (mimeType == NULL)
1721     return NULL;
1722
1723   caps = gst_caps_new_simple (mimeType, NULL);
1724
1725   return caps;
1726 }
1727
1728 static GstCaps *
1729 gst_dash_demux_get_input_caps (GstDashDemux * demux, GstActiveStream * stream)
1730 {
1731   switch (stream->mimeType) {
1732     case GST_STREAM_VIDEO:
1733       return gst_dash_demux_get_video_input_caps (demux, stream);
1734     case GST_STREAM_AUDIO:
1735       return gst_dash_demux_get_audio_input_caps (demux, stream);
1736     case GST_STREAM_APPLICATION:
1737       return gst_dash_demux_get_application_input_caps (demux, stream);
1738     default:
1739       return GST_CAPS_NONE;
1740   }
1741 }
1742
1743 static gboolean
1744 need_add_header (GstDashDemux * demux)
1745 {
1746   GstActiveStream *stream;
1747   GstCaps *caps;
1748   guint stream_idx = 0;
1749   gboolean switch_caps = FALSE;
1750   while (stream_idx < gst_mpdparser_get_nb_active_stream (demux->client)) {
1751     stream =
1752         gst_mpdparser_get_active_stream_by_index (demux->client, stream_idx);
1753     if (stream == NULL)
1754       return FALSE;
1755     caps = gst_dash_demux_get_input_caps (demux, stream);
1756     if (!demux->input_caps[stream_idx]
1757         || !gst_caps_is_equal (caps, demux->input_caps[stream_idx])) {
1758       switch_caps = TRUE;
1759       gst_caps_unref (caps);
1760       break;
1761     }
1762     gst_caps_unref (caps);
1763     stream_idx++;
1764   }
1765   return switch_caps;
1766 }
1767
1768 /* gst_dash_demux_get_next_fragment_set:
1769  *
1770  * Get the next set of fragments for the current representations.
1771  *
1772  * This function uses the generic URI downloader API.
1773  *
1774  * Returns FALSE if an error occured while downloading fragments
1775  *
1776  */
1777 static gboolean
1778 gst_dash_demux_get_next_fragment_set (GstDashDemux * demux)
1779 {
1780   GstActiveStream *stream;
1781   GstFragment *download, *header;
1782   GList *fragment_set;
1783   gchar *next_fragment_uri;
1784   GstClockTime duration;
1785   GstClockTime timestamp;
1786   gboolean discont;
1787   GTimeVal now;
1788   GTimeVal start;
1789   GstClockTime diff;
1790   guint64 size_buffer = 0;
1791
1792   g_get_current_time (&start);
1793   /* Figure out if we will need to switch pads, thus requiring a new
1794    * header to initialize the new decoding chain
1795    * FIXME: redundant with needs_pad_switch */
1796   gboolean need_header = need_add_header (demux);
1797   guint stream_idx = 0;
1798   fragment_set = NULL;
1799   /* Get the fragment corresponding to each stream index */
1800   while (stream_idx < gst_mpdparser_get_nb_active_stream (demux->client)) {
1801     if (!gst_mpd_client_get_next_fragment (demux->client,
1802             stream_idx, &discont, &next_fragment_uri, &duration, &timestamp)) {
1803       GST_INFO_OBJECT (demux, "This Period doesn't contain more fragments");
1804       demux->end_of_period = TRUE;
1805       return FALSE;
1806     }
1807
1808     GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);
1809
1810     download = gst_uri_downloader_fetch_uri (demux->downloader,
1811         next_fragment_uri);
1812     g_free (next_fragment_uri);
1813
1814     if (download == NULL)
1815       return FALSE;
1816
1817     download->start_time = timestamp;
1818     download->stop_time = timestamp + duration;
1819
1820     stream =
1821         gst_mpdparser_get_active_stream_by_index (demux->client, stream_idx);
1822     if (stream == NULL)
1823       return FALSE;
1824
1825     download->index = gst_mpd_client_get_segment_index (stream) - 1;
1826
1827     GstCaps *caps = gst_dash_demux_get_input_caps (demux, stream);
1828
1829     if (need_header) {
1830       /* Store the new input caps for that stream */
1831       gst_caps_replace (&demux->input_caps[stream_idx], caps);
1832       GST_INFO_OBJECT (demux, "Input source caps: %" GST_PTR_FORMAT,
1833           demux->input_caps[stream_idx]);
1834       /* We need to fetch a new header */
1835       if ((header = gst_dash_demux_get_next_header (demux, stream_idx)) == NULL) {
1836         GST_INFO_OBJECT (demux, "Unable to fetch header");
1837       } else {
1838         /* Replace fragment with a new one including the header */
1839         GstFragment *new_fragment =
1840             gst_dash_demux_prepend_header (demux, download, header);
1841         g_object_unref (header);
1842         g_object_unref (download);
1843         download = new_fragment;
1844       }
1845     } else
1846       gst_caps_unref (caps);
1847
1848     gst_fragment_set_caps (download, demux->input_caps[stream_idx]);
1849     fragment_set = g_list_append (fragment_set, download);
1850     size_buffer += gst_fragment_get_buffer_size (download);
1851     stream_idx++;
1852   }
1853   /* Push fragment set into the queue */
1854   g_queue_push_tail (demux->queue, fragment_set);
1855   /* Wake the download task up */
1856   GST_TASK_SIGNAL (demux->download_task);
1857   g_get_current_time (&now);
1858   diff = (GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (start));
1859   demux->dnl_rate = (size_buffer * 8) / ((double) diff / GST_SECOND);
1860   GST_INFO_OBJECT (demux,
1861       "Download rate = %" PRIu64 " Kbits/s (%" PRIu64 " Ko in %.2f s)",
1862       demux->dnl_rate / 1000, size_buffer / 1024, ((double) diff / GST_SECOND));
1863   return TRUE;
1864 }