adaptivedemux: Get rid of internal stream adapter and let subclasses handle this...
[platform/upstream/gstreamer.git] / ext / dash / 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  * Copyright (C) 2013 Smart TV Alliance
13  *  Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>, Collabora Ltd.
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Library General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Library General Public License for more details.
24  *
25  * You should have received a copy of the GNU Library General Public
26  * License along with this library (COPYING); if not, write to the
27  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28  * Boston, MA 02111-1307, USA.
29  */
30 /**
31  * SECTION:element-dashdemux
32  *
33  * DASH demuxer element.
34  * <title>Example launch line</title>
35  * |[
36  * gst-launch-1.0 playbin 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"
37  * ]|
38  */
39
40 /* Implementation notes:
41  *
42  * The following section describes how dashdemux works internally.
43  *
44  * Introduction:
45  *
46  * dashdemux is a "fake" demux, as unlike traditional demux elements, it
47  * doesn't split data streams contained in an enveloppe to expose them
48  * to downstream decoding elements.
49  *
50  * Instead, it parses an XML file called a manifest to identify a set of
51  * individual stream fragments it needs to fetch and expose to the actual
52  * demux elements that will handle them (this behavior is sometimes
53  * referred as the "demux after a demux" scenario).
54  *
55  * For a given section of content, several representations corresponding
56  * to different bitrates may be available: dashdemux will select the most
57  * appropriate representation based on local conditions (typically the
58  * available bandwidth and the amount of buffering available, capped by
59  * a maximum allowed bitrate).
60  *
61  * The representation selection algorithm can be configured using
62  * specific properties: max bitrate, min/max buffering, bandwidth ratio.
63  *
64  *
65  * General Design:
66  *
67  * dashdemux has a single sink pad that accepts the data corresponding
68  * to the manifest, typically fetched from an HTTP or file source.
69  *
70  * dashdemux exposes the streams it recreates based on the fragments it
71  * fetches through dedicated src pads corresponding to the caps of the
72  * fragments container (ISOBMFF/MP4 or MPEG2TS).
73  *
74  * During playback, new representations will typically be exposed as a
75  * new set of pads (see 'Switching between representations' below).
76  *
77  * Fragments downloading is performed using a dedicated task that fills
78  * an internal queue. Another task is in charge of popping fragments
79  * from the queue and pushing them downstream.
80  *
81  * Switching between representations:
82  *
83  * Decodebin supports scenarios allowing to seamlessly switch from one
84  * stream to another inside the same "decoding chain".
85  *
86  * To achieve that, it combines the elements it autoplugged in chains
87  *  and groups, allowing only one decoding group to be active at a given
88  * time for a given chain.
89  *
90  * A chain can signal decodebin that it is complete by sending a
91  * no-more-pads event, but even after that new pads can be added to
92  * create new subgroups, providing that a new no-more-pads event is sent.
93  *
94  * We take advantage of that to dynamically create a new decoding group
95  * in order to select a different representation during playback.
96  *
97  * Typically, assuming that each fragment contains both audio and video,
98  * the following tree would be created:
99  *
100  * chain "DASH Demux"
101  * |_ group "Representation set 1"
102  * |   |_ chain "Qt Demux 0"
103  * |       |_ group "Stream 0"
104  * |           |_ chain "H264"
105  * |           |_ chain "AAC"
106  * |_ group "Representation set 2"
107  *     |_ chain "Qt Demux 1"
108  *         |_ group "Stream 1"
109  *             |_ chain "H264"
110  *             |_ chain "AAC"
111  *
112  * Or, if audio and video are contained in separate fragments:
113  *
114  * chain "DASH Demux"
115  * |_ group "Representation set 1"
116  * |   |_ chain "Qt Demux 0"
117  * |   |   |_ group "Stream 0"
118  * |   |       |_ chain "H264"
119  * |   |_ chain "Qt Demux 1"
120  * |       |_ group "Stream 1"
121  * |           |_ chain "AAC"
122  * |_ group "Representation set 2"
123  *     |_ chain "Qt Demux 3"
124  *     |   |_ group "Stream 2"
125  *     |       |_ chain "H264"
126  *     |_ chain "Qt Demux 4"
127  *         |_ group "Stream 3"
128  *             |_ chain "AAC"
129  *
130  * In both cases, when switching from Set 1 to Set 2 an EOS is sent on
131  * each end pad corresponding to Rep 0, triggering the "drain" state to
132  * propagate upstream.
133  * Once both EOS have been processed, the "Set 1" group is completely
134  * drained, and decodebin2 will switch to the "Set 2" group.
135  *
136  * Note: nothing can be pushed to the new decoding group before the
137  * old one has been drained, which means that in order to be able to
138  * adapt quickly to bandwidth changes, we will not be able to rely
139  * on downstream buffering, and will instead manage an internal queue.
140  *
141  */
142
143 #ifdef HAVE_CONFIG_H
144 #  include "config.h"
145 #endif
146
147 #include <string.h>
148 #include <stdio.h>
149 #include <stdlib.h>
150 #include <inttypes.h>
151 #include <gio/gio.h>
152 #include <gst/base/gsttypefindhelper.h>
153 #include <gst/tag/tag.h>
154 #include <gst/net/gstnet.h>
155 #include "gst/gst-i18n-plugin.h"
156 #include "gstdashdemux.h"
157 #include "gstdash_debug.h"
158
159 static GstStaticPadTemplate gst_dash_demux_videosrc_template =
160 GST_STATIC_PAD_TEMPLATE ("video_%02u",
161     GST_PAD_SRC,
162     GST_PAD_SOMETIMES,
163     GST_STATIC_CAPS_ANY);
164
165 static GstStaticPadTemplate gst_dash_demux_audiosrc_template =
166 GST_STATIC_PAD_TEMPLATE ("audio_%02u",
167     GST_PAD_SRC,
168     GST_PAD_SOMETIMES,
169     GST_STATIC_CAPS_ANY);
170
171 static GstStaticPadTemplate gst_dash_demux_subtitlesrc_template =
172 GST_STATIC_PAD_TEMPLATE ("subtitle_%02u",
173     GST_PAD_SRC,
174     GST_PAD_SOMETIMES,
175     GST_STATIC_CAPS_ANY);
176
177 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
178     GST_PAD_SINK,
179     GST_PAD_ALWAYS,
180     GST_STATIC_CAPS ("application/dash+xml"));
181
182 GST_DEBUG_CATEGORY (gst_dash_demux_debug);
183 #define GST_CAT_DEFAULT gst_dash_demux_debug
184
185 enum
186 {
187   PROP_0,
188
189   PROP_MAX_BUFFERING_TIME,
190   PROP_BANDWIDTH_USAGE,
191   PROP_MAX_BITRATE,
192   PROP_PRESENTATION_DELAY,
193   PROP_LAST
194 };
195
196 /* Default values for properties */
197 #define DEFAULT_MAX_BUFFERING_TIME       30     /* in seconds */
198 #define DEFAULT_BANDWIDTH_USAGE         0.8     /* 0 to 1     */
199 #define DEFAULT_MAX_BITRATE        24000000     /* in bit/s  */
200 #define DEFAULT_PRESENTATION_DELAY     NULL     /* zero */
201
202 /* Clock drift compensation for live streams */
203 #define SLOW_CLOCK_UPDATE_INTERVAL  (1000000 * 30 * 60) /* 30 minutes */
204 #define FAST_CLOCK_UPDATE_INTERVAL  (1000000 * 30)      /* 30 seconds */
205 #define SUPPORTED_CLOCK_FORMATS (GST_MPD_UTCTIMING_TYPE_NTP | GST_MPD_UTCTIMING_TYPE_HTTP_HEAD | GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE | GST_MPD_UTCTIMING_TYPE_HTTP_ISO | GST_MPD_UTCTIMING_TYPE_HTTP_NTP)
206 #define NTP_TO_UNIX_EPOCH G_GUINT64_CONSTANT(2208988800)        /* difference (in seconds) between NTP epoch and Unix epoch */
207
208 struct _GstDashDemuxClockDrift
209 {
210   GMutex clock_lock;            /* used to protect access to struct */
211   guint selected_url;
212   gint64 next_update;
213   /* @clock_compensation: amount (in usecs) to add to client's idea of
214      now to map it to the server's idea of now */
215   GTimeSpan clock_compensation;
216   GstClock *ntp_clock;
217 };
218
219 /* GObject */
220 static void gst_dash_demux_set_property (GObject * object, guint prop_id,
221     const GValue * value, GParamSpec * pspec);
222 static void gst_dash_demux_get_property (GObject * object, guint prop_id,
223     GValue * value, GParamSpec * pspec);
224 static void gst_dash_demux_dispose (GObject * obj);
225
226 /* GstAdaptiveDemux */
227 static GstClockTime gst_dash_demux_get_duration (GstAdaptiveDemux * ademux);
228 static gboolean gst_dash_demux_is_live (GstAdaptiveDemux * ademux);
229 static void gst_dash_demux_reset (GstAdaptiveDemux * ademux);
230 static gboolean gst_dash_demux_process_manifest (GstAdaptiveDemux * ademux,
231     GstBuffer * buf);
232 static gboolean gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);
233 static GstFlowReturn
234 gst_dash_demux_stream_update_fragment_info (GstAdaptiveDemuxStream * stream);
235 static GstFlowReturn gst_dash_demux_stream_seek (GstAdaptiveDemuxStream *
236     stream, gboolean forward, GstSeekFlags flags, GstClockTime ts,
237     GstClockTime * final_ts);
238 static gboolean gst_dash_demux_stream_has_next_fragment (GstAdaptiveDemuxStream
239     * stream);
240 static GstFlowReturn
241 gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream);
242 static gboolean
243 gst_dash_demux_stream_advance_subfragment (GstAdaptiveDemuxStream * stream);
244 static gboolean gst_dash_demux_stream_select_bitrate (GstAdaptiveDemuxStream *
245     stream, guint64 bitrate);
246 static gint64 gst_dash_demux_get_manifest_update_interval (GstAdaptiveDemux *
247     demux);
248 static GstFlowReturn gst_dash_demux_update_manifest_data (GstAdaptiveDemux *
249     demux, GstBuffer * buf);
250 static gint64
251 gst_dash_demux_stream_get_fragment_waiting_time (GstAdaptiveDemuxStream *
252     stream);
253 static void gst_dash_demux_advance_period (GstAdaptiveDemux * demux);
254 static gboolean gst_dash_demux_has_next_period (GstAdaptiveDemux * demux);
255 static GstFlowReturn gst_dash_demux_data_received (GstAdaptiveDemux * demux,
256     GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
257 static GstFlowReturn
258 gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
259     GstAdaptiveDemuxStream * stream);
260
261 /* GstDashDemux */
262 static gboolean gst_dash_demux_setup_all_streams (GstDashDemux * demux);
263 static void gst_dash_demux_stream_free (GstAdaptiveDemuxStream * stream);
264
265 static GstCaps *gst_dash_demux_get_input_caps (GstDashDemux * demux,
266     GstActiveStream * stream);
267 static GstPad *gst_dash_demux_create_pad (GstDashDemux * demux,
268     GstActiveStream * stream);
269 static GstDashDemuxClockDrift *gst_dash_demux_clock_drift_new (GstDashDemux *
270     demux);
271 static void gst_dash_demux_clock_drift_free (GstDashDemuxClockDrift *);
272 static gboolean gst_dash_demux_poll_clock_drift (GstDashDemux * demux);
273 static GTimeSpan gst_dash_demux_get_clock_compensation (GstDashDemux * demux);
274 static GDateTime *gst_dash_demux_get_server_now_utc (GstDashDemux * demux);
275
276 #define SIDX(s) (&(s)->sidx_parser.sidx)
277 #define SIDX_ENTRY(s,i) (&(SIDX(s)->entries[(i)]))
278 #define SIDX_CURRENT_ENTRY(s) SIDX_ENTRY(s, SIDX(s)->entry_index)
279
280 static void gst_dash_demux_send_content_protection_event (gpointer cp_data,
281     gpointer stream);
282
283 #define gst_dash_demux_parent_class parent_class
284 G_DEFINE_TYPE_WITH_CODE (GstDashDemux, gst_dash_demux, GST_TYPE_ADAPTIVE_DEMUX,
285     GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "dashdemux", 0,
286         "dashdemux element")
287     );
288
289 static void
290 gst_dash_demux_dispose (GObject * obj)
291 {
292   GstDashDemux *demux = GST_DASH_DEMUX (obj);
293
294   gst_dash_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
295
296   if (demux->client) {
297     gst_mpd_client_free (demux->client);
298     demux->client = NULL;
299   }
300
301   g_mutex_clear (&demux->client_lock);
302
303   gst_dash_demux_clock_drift_free (demux->clock_drift);
304   demux->clock_drift = NULL;
305   g_free (demux->default_presentation_delay);
306   G_OBJECT_CLASS (parent_class)->dispose (obj);
307 }
308
309 static gboolean
310 gst_dash_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
311     gint64 * stop)
312 {
313   GstDashDemux *self = GST_DASH_DEMUX (demux);
314   GDateTime *now;
315   GDateTime *mstart;
316   GTimeSpan stream_now;
317
318   if (self->client->mpd_node->availabilityStartTime == NULL)
319     return FALSE;
320
321   now = gst_dash_demux_get_server_now_utc (self);
322   mstart =
323       gst_date_time_to_g_date_time (self->client->
324       mpd_node->availabilityStartTime);
325   stream_now = g_date_time_difference (now, mstart);
326   g_date_time_unref (now);
327   g_date_time_unref (mstart);
328
329   if (stream_now <= 0)
330     return FALSE;
331
332   *stop = stream_now * GST_USECOND;
333   if (self->client->mpd_node->timeShiftBufferDepth == GST_MPD_DURATION_NONE) {
334     *start = 0;
335   } else {
336     *start =
337         *stop - (self->client->mpd_node->timeShiftBufferDepth * GST_MSECOND);
338     if (*start < 0)
339       *start = 0;
340   }
341   return TRUE;
342 }
343
344 static GstClockTime
345 gst_dash_demux_get_presentation_offset (GstAdaptiveDemux * demux,
346     GstAdaptiveDemuxStream * stream)
347 {
348   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
349   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
350
351   return gst_mpd_parser_get_stream_presentation_offset (dashdemux->client,
352       dashstream->index);
353 }
354
355 static GstClockTime
356 gst_dash_demux_get_period_start_time (GstAdaptiveDemux * demux)
357 {
358   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
359
360   return gst_mpd_parser_get_period_start_time (dashdemux->client);
361 }
362
363 static void
364 gst_dash_demux_class_init (GstDashDemuxClass * klass)
365 {
366   GObjectClass *gobject_class;
367   GstElementClass *gstelement_class;
368   GstAdaptiveDemuxClass *gstadaptivedemux_class;
369
370   gobject_class = (GObjectClass *) klass;
371   gstelement_class = (GstElementClass *) klass;
372   gstadaptivedemux_class = (GstAdaptiveDemuxClass *) klass;
373
374   gobject_class->set_property = gst_dash_demux_set_property;
375   gobject_class->get_property = gst_dash_demux_get_property;
376   gobject_class->dispose = gst_dash_demux_dispose;
377
378 #ifndef GST_REMOVE_DEPRECATED
379   g_object_class_install_property (gobject_class, PROP_MAX_BUFFERING_TIME,
380       g_param_spec_uint ("max-buffering-time", "Maximum buffering time",
381           "Maximum number of seconds of buffer accumulated during playback"
382           "(deprecated)",
383           2, G_MAXUINT, DEFAULT_MAX_BUFFERING_TIME,
384           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
385
386   g_object_class_install_property (gobject_class, PROP_BANDWIDTH_USAGE,
387       g_param_spec_float ("bandwidth-usage",
388           "Bandwidth usage [0..1]",
389           "Percentage of the available bandwidth to use when "
390           "selecting representations (deprecated)",
391           0, 1, DEFAULT_BANDWIDTH_USAGE,
392           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
393 #endif
394
395   g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
396       g_param_spec_uint ("max-bitrate", "Max bitrate",
397           "Max of bitrate supported by target decoder",
398           1000, G_MAXUINT, DEFAULT_MAX_BITRATE,
399           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
400
401   g_object_class_install_property (gobject_class, PROP_PRESENTATION_DELAY,
402       g_param_spec_string ("presentation-delay", "Presentation delay",
403           "Default presentation delay (in seconds, milliseconds or fragments) (e.g. 12s, 2500ms, 3f)",
404           DEFAULT_PRESENTATION_DELAY,
405           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
406
407   gst_element_class_add_static_pad_template (gstelement_class,
408       &gst_dash_demux_audiosrc_template);
409   gst_element_class_add_static_pad_template (gstelement_class,
410       &gst_dash_demux_videosrc_template);
411   gst_element_class_add_static_pad_template (gstelement_class,
412       &gst_dash_demux_subtitlesrc_template);
413
414   gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
415
416   gst_element_class_set_static_metadata (gstelement_class,
417       "DASH Demuxer",
418       "Codec/Demuxer/Adaptive",
419       "Dynamic Adaptive Streaming over HTTP demuxer",
420       "David Corvoysier <david.corvoysier@orange.com>\n\
421                 Hamid Zakari <hamid.zakari@gmail.com>\n\
422                 Gianluca Gennari <gennarone@gmail.com>");
423
424
425   gstadaptivedemux_class->get_duration = gst_dash_demux_get_duration;
426   gstadaptivedemux_class->is_live = gst_dash_demux_is_live;
427   gstadaptivedemux_class->reset = gst_dash_demux_reset;
428   gstadaptivedemux_class->seek = gst_dash_demux_seek;
429
430   gstadaptivedemux_class->process_manifest = gst_dash_demux_process_manifest;
431   gstadaptivedemux_class->update_manifest_data =
432       gst_dash_demux_update_manifest_data;
433   gstadaptivedemux_class->get_manifest_update_interval =
434       gst_dash_demux_get_manifest_update_interval;
435
436   gstadaptivedemux_class->has_next_period = gst_dash_demux_has_next_period;
437   gstadaptivedemux_class->advance_period = gst_dash_demux_advance_period;
438   gstadaptivedemux_class->stream_has_next_fragment =
439       gst_dash_demux_stream_has_next_fragment;
440   gstadaptivedemux_class->stream_advance_fragment =
441       gst_dash_demux_stream_advance_fragment;
442   gstadaptivedemux_class->stream_get_fragment_waiting_time =
443       gst_dash_demux_stream_get_fragment_waiting_time;
444   gstadaptivedemux_class->stream_seek = gst_dash_demux_stream_seek;
445   gstadaptivedemux_class->stream_select_bitrate =
446       gst_dash_demux_stream_select_bitrate;
447   gstadaptivedemux_class->stream_update_fragment_info =
448       gst_dash_demux_stream_update_fragment_info;
449   gstadaptivedemux_class->stream_free = gst_dash_demux_stream_free;
450   gstadaptivedemux_class->get_live_seek_range =
451       gst_dash_demux_get_live_seek_range;
452   gstadaptivedemux_class->get_presentation_offset =
453       gst_dash_demux_get_presentation_offset;
454   gstadaptivedemux_class->get_period_start_time =
455       gst_dash_demux_get_period_start_time;
456
457   gstadaptivedemux_class->finish_fragment =
458       gst_dash_demux_stream_fragment_finished;
459   gstadaptivedemux_class->data_received = gst_dash_demux_data_received;
460 }
461
462 static void
463 gst_dash_demux_init (GstDashDemux * demux)
464 {
465   /* Properties */
466   demux->max_buffering_time = DEFAULT_MAX_BUFFERING_TIME * GST_SECOND;
467   demux->max_bitrate = DEFAULT_MAX_BITRATE;
468   demux->default_presentation_delay = DEFAULT_PRESENTATION_DELAY;
469
470   g_mutex_init (&demux->client_lock);
471
472   gst_adaptive_demux_set_stream_struct_size (GST_ADAPTIVE_DEMUX_CAST (demux),
473       sizeof (GstDashDemuxStream));
474 }
475
476 static void
477 gst_dash_demux_set_property (GObject * object, guint prop_id,
478     const GValue * value, GParamSpec * pspec)
479 {
480   GstAdaptiveDemux *adaptivedemux = GST_ADAPTIVE_DEMUX_CAST (object);
481   GstDashDemux *demux = GST_DASH_DEMUX (object);
482
483   switch (prop_id) {
484     case PROP_MAX_BUFFERING_TIME:
485       demux->max_buffering_time = g_value_get_uint (value) * GST_SECOND;
486       break;
487     case PROP_BANDWIDTH_USAGE:
488       adaptivedemux->bitrate_limit = g_value_get_float (value);
489       break;
490     case PROP_MAX_BITRATE:
491       demux->max_bitrate = g_value_get_uint (value);
492       break;
493     case PROP_PRESENTATION_DELAY:
494       g_free (demux->default_presentation_delay);
495       demux->default_presentation_delay = g_value_dup_string (value);
496       break;
497     default:
498       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
499       break;
500   }
501 }
502
503 static void
504 gst_dash_demux_get_property (GObject * object, guint prop_id, GValue * value,
505     GParamSpec * pspec)
506 {
507   GstAdaptiveDemux *adaptivedemux = GST_ADAPTIVE_DEMUX_CAST (object);
508   GstDashDemux *demux = GST_DASH_DEMUX (object);
509
510   switch (prop_id) {
511     case PROP_MAX_BUFFERING_TIME:
512       g_value_set_uint (value, demux->max_buffering_time / GST_SECOND);
513       break;
514     case PROP_BANDWIDTH_USAGE:
515       g_value_set_float (value, adaptivedemux->bitrate_limit);
516       break;
517     case PROP_MAX_BITRATE:
518       g_value_set_uint (value, demux->max_bitrate);
519       break;
520     case PROP_PRESENTATION_DELAY:
521       if (demux->default_presentation_delay == NULL)
522         g_value_set_static_string (value, "");
523       else
524         g_value_set_string (value, demux->default_presentation_delay);
525       break;
526     default:
527       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
528       break;
529   }
530 }
531
532 static gboolean
533 gst_dash_demux_setup_mpdparser_streams (GstDashDemux * demux,
534     GstMpdClient * client)
535 {
536   gboolean has_streams = FALSE;
537   GList *adapt_sets, *iter;
538
539   adapt_sets = gst_mpd_client_get_adaptation_sets (client);
540   for (iter = adapt_sets; iter; iter = g_list_next (iter)) {
541     GstAdaptationSetNode *adapt_set_node = iter->data;
542
543     gst_mpd_client_setup_streaming (client, adapt_set_node);
544     has_streams = TRUE;
545   }
546
547   if (!has_streams) {
548     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, ("Manifest has no playable "
549             "streams"), ("No streams could be activated from the manifest"));
550   }
551   return has_streams;
552 }
553
554 static gboolean
555 gst_dash_demux_setup_all_streams (GstDashDemux * demux)
556 {
557   guint i;
558
559   GST_DEBUG_OBJECT (demux, "Setting up streams for period %d",
560       gst_mpd_client_get_period_index (demux->client));
561
562   /* clean old active stream list, if any */
563   gst_active_streams_free (demux->client);
564
565   if (!gst_dash_demux_setup_mpdparser_streams (demux, demux->client)) {
566     return FALSE;
567   }
568
569   GST_DEBUG_OBJECT (demux, "Creating stream objects");
570   for (i = 0; i < gst_mpdparser_get_nb_active_stream (demux->client); i++) {
571     GstDashDemuxStream *stream;
572     GstActiveStream *active_stream;
573     GstCaps *caps;
574     GstPad *srcpad;
575     gchar *lang = NULL;
576     GstTagList *tags = NULL;
577
578     active_stream = gst_mpdparser_get_active_stream_by_index (demux->client, i);
579     if (active_stream == NULL)
580       continue;
581
582     srcpad = gst_dash_demux_create_pad (demux, active_stream);
583     if (srcpad == NULL)
584       continue;
585
586     caps = gst_dash_demux_get_input_caps (demux, active_stream);
587     GST_LOG_OBJECT (demux, "Creating stream %d %" GST_PTR_FORMAT, i, caps);
588
589     if (active_stream->cur_adapt_set) {
590       GstAdaptationSetNode *adp_set = active_stream->cur_adapt_set;
591       lang = adp_set->lang;
592
593       /* Fallback to the language in ContentComponent node */
594       if (lang == NULL) {
595         GList *it;
596
597         for (it = adp_set->ContentComponents; it; it = it->next) {
598           GstContentComponentNode *cc_node = it->data;
599           if (cc_node->lang) {
600             lang = cc_node->lang;
601             break;
602           }
603         }
604       }
605     }
606
607     if (lang) {
608       if (gst_tag_check_language_code (lang))
609         tags = gst_tag_list_new (GST_TAG_LANGUAGE_CODE, lang, NULL);
610       else
611         tags = gst_tag_list_new (GST_TAG_LANGUAGE_NAME, lang, NULL);
612     }
613
614     stream = (GstDashDemuxStream *)
615         gst_adaptive_demux_stream_new (GST_ADAPTIVE_DEMUX_CAST (demux), srcpad);
616     stream->active_stream = active_stream;
617     gst_adaptive_demux_stream_set_caps (GST_ADAPTIVE_DEMUX_STREAM_CAST (stream),
618         caps);
619     if (tags)
620       gst_adaptive_demux_stream_set_tags (GST_ADAPTIVE_DEMUX_STREAM_CAST
621           (stream), tags);
622     stream->index = i;
623     stream->pending_seek_ts = GST_CLOCK_TIME_NONE;
624     if (active_stream->cur_adapt_set &&
625         active_stream->cur_adapt_set->RepresentationBase &&
626         active_stream->cur_adapt_set->RepresentationBase->ContentProtection) {
627       GST_DEBUG_OBJECT (demux, "Adding ContentProtection events to source pad");
628       g_list_foreach (active_stream->cur_adapt_set->RepresentationBase->
629           ContentProtection, gst_dash_demux_send_content_protection_event,
630           stream);
631     }
632
633     gst_isoff_sidx_parser_init (&stream->sidx_parser);
634     if (gst_mpd_client_has_isoff_ondemand_profile (demux->client))
635       stream->sidx_adapter = gst_adapter_new ();
636   }
637
638   return TRUE;
639 }
640
641 static void
642 gst_dash_demux_send_content_protection_event (gpointer data, gpointer userdata)
643 {
644   GstDescriptorType *cp = (GstDescriptorType *) data;
645   GstDashDemuxStream *stream = (GstDashDemuxStream *) userdata;
646   GstEvent *event;
647   GstBuffer *pssi;
648   glong pssi_len;
649   gchar *schemeIdUri;
650
651   if (cp->schemeIdUri == NULL)
652     return;
653
654   GST_TRACE_OBJECT (stream, "check schemeIdUri %s", cp->schemeIdUri);
655   /* RFC 2141 states: The leading "urn:" sequence is case-insensitive */
656   schemeIdUri = g_ascii_strdown (cp->schemeIdUri, -1);
657   if (g_str_has_prefix (schemeIdUri, "urn:uuid:")) {
658     pssi_len = strlen (cp->value);
659     pssi = gst_buffer_new_wrapped (g_memdup (cp->value, pssi_len), pssi_len);
660     GST_LOG_OBJECT (stream, "Queuing Protection event on source pad");
661     /* RFC 4122 states that the hex part of a UUID is in lower case,
662      * but some streams seem to ignore this and use upper case for the
663      * protection system ID */
664     event = gst_event_new_protection (cp->schemeIdUri + 9, pssi, "dash/mpd");
665     gst_adaptive_demux_stream_queue_event ((GstAdaptiveDemuxStream *) stream,
666         event);
667     gst_buffer_unref (pssi);
668   }
669   g_free (schemeIdUri);
670 }
671
672 static GstClockTime
673 gst_dash_demux_get_duration (GstAdaptiveDemux * ademux)
674 {
675   GstDashDemux *demux = GST_DASH_DEMUX_CAST (ademux);
676
677   g_return_val_if_fail (demux->client != NULL, GST_CLOCK_TIME_NONE);
678
679   return gst_mpd_client_get_media_presentation_duration (demux->client);
680 }
681
682 static gboolean
683 gst_dash_demux_is_live (GstAdaptiveDemux * ademux)
684 {
685   GstDashDemux *demux = GST_DASH_DEMUX_CAST (ademux);
686
687   g_return_val_if_fail (demux->client != NULL, FALSE);
688
689   return gst_mpd_client_is_live (demux->client);
690 }
691
692 static gboolean
693 gst_dash_demux_setup_streams (GstAdaptiveDemux * demux)
694 {
695   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
696   gboolean ret = TRUE;
697   GstDateTime *now = NULL;
698   guint period_idx;
699
700   /* setup video, audio and subtitle streams, starting from first Period if
701    * non-live */
702   period_idx = 0;
703   if (gst_mpd_client_is_live (dashdemux->client)) {
704     GDateTime *g_now;
705     if (dashdemux->client->mpd_node->availabilityStartTime == NULL) {
706       ret = FALSE;
707       GST_ERROR_OBJECT (demux, "MPD does not have availabilityStartTime");
708       goto done;
709     }
710     if (dashdemux->clock_drift == NULL) {
711       gchar **urls;
712       urls =
713           gst_mpd_client_get_utc_timing_sources (dashdemux->client,
714           SUPPORTED_CLOCK_FORMATS, NULL);
715       if (urls) {
716         GST_DEBUG_OBJECT (dashdemux, "Found a supported UTCTiming element");
717         dashdemux->clock_drift = gst_dash_demux_clock_drift_new (dashdemux);
718         gst_dash_demux_poll_clock_drift (dashdemux);
719       }
720     }
721     /* get period index for period encompassing the current time */
722     g_now = gst_dash_demux_get_server_now_utc (dashdemux);
723     now = gst_date_time_new_from_g_date_time (g_now);
724     if (dashdemux->client->mpd_node->suggestedPresentationDelay != -1) {
725       GstDateTime *target = gst_mpd_client_add_time_difference (now,
726           dashdemux->client->mpd_node->suggestedPresentationDelay * -1000);
727       gst_date_time_unref (now);
728       now = target;
729     } else if (dashdemux->default_presentation_delay) {
730       gint64 dfp =
731           gst_mpd_client_parse_default_presentation_delay (dashdemux->client,
732           dashdemux->default_presentation_delay);
733       GstDateTime *target = gst_mpd_client_add_time_difference (now, dfp);
734       gst_date_time_unref (now);
735       now = target;
736     }
737     period_idx =
738         gst_mpd_client_get_period_index_at_time (dashdemux->client, now);
739     if (period_idx == G_MAXUINT) {
740 #ifndef GST_DISABLE_GST_DEBUG
741       gchar *date_str = gst_date_time_to_iso8601_string (now);
742       GST_DEBUG_OBJECT (demux, "Unable to find live period active at %s",
743           date_str);
744       g_free (date_str);
745 #endif
746       ret = FALSE;
747       goto done;
748     }
749   }
750
751   if (!gst_mpd_client_set_period_index (dashdemux->client, period_idx) ||
752       !gst_dash_demux_setup_all_streams (dashdemux)) {
753     ret = FALSE;
754     goto done;
755   }
756
757   /* If stream is live, try to find the segment that
758    * is closest to current time */
759   if (gst_mpd_client_is_live (dashdemux->client)) {
760     GDateTime *gnow;
761
762     GST_DEBUG_OBJECT (demux, "Seeking to current time of day for live stream ");
763
764     gnow = gst_date_time_to_g_date_time (now);
765     gst_mpd_client_seek_to_time (dashdemux->client, gnow);
766     g_date_time_unref (gnow);
767   } else {
768     GST_DEBUG_OBJECT (demux, "Seeking to first segment for on-demand stream ");
769
770     /* start playing from the first segment */
771     gst_mpd_client_seek_to_first_segment (dashdemux->client);
772   }
773
774 done:
775   if (now != NULL)
776     gst_date_time_unref (now);
777   return ret;
778 }
779
780 static gboolean
781 gst_dash_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
782 {
783   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
784   gboolean ret = FALSE;
785   gchar *manifest;
786   GstMapInfo mapinfo;
787
788   if (dashdemux->client)
789     gst_mpd_client_free (dashdemux->client);
790   dashdemux->client = gst_mpd_client_new ();
791   gst_mpd_client_set_uri_downloader (dashdemux->client, demux->downloader);
792
793   dashdemux->client->mpd_uri = g_strdup (demux->manifest_uri);
794   dashdemux->client->mpd_base_uri = g_strdup (demux->manifest_base_uri);
795
796   GST_DEBUG_OBJECT (demux, "Fetched MPD file at URI: %s (base: %s)",
797       dashdemux->client->mpd_uri,
798       GST_STR_NULL (dashdemux->client->mpd_base_uri));
799
800   if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
801     manifest = (gchar *) mapinfo.data;
802     if (gst_mpd_parse (dashdemux->client, manifest, mapinfo.size)) {
803       if (gst_mpd_client_setup_media_presentation (dashdemux->client, 0, 0,
804               NULL)) {
805         ret = TRUE;
806       } else {
807         GST_ELEMENT_ERROR (demux, STREAM, DECODE,
808             ("Incompatible manifest file."), (NULL));
809       }
810     }
811     gst_buffer_unmap (buf, &mapinfo);
812   } else {
813     GST_WARNING_OBJECT (demux, "Failed to map manifest buffer");
814   }
815
816   if (ret)
817     ret = gst_dash_demux_setup_streams (demux);
818
819   return ret;
820 }
821
822 static GstPad *
823 gst_dash_demux_create_pad (GstDashDemux * demux, GstActiveStream * stream)
824 {
825   GstPad *pad;
826   GstPadTemplate *tmpl;
827   gchar *name;
828
829   switch (stream->mimeType) {
830     case GST_STREAM_AUDIO:
831       name = g_strdup_printf ("audio_%02u", demux->n_audio_streams++);
832       tmpl = gst_static_pad_template_get (&gst_dash_demux_audiosrc_template);
833       break;
834     case GST_STREAM_VIDEO:
835       name = g_strdup_printf ("video_%02u", demux->n_video_streams++);
836       tmpl = gst_static_pad_template_get (&gst_dash_demux_videosrc_template);
837       break;
838     case GST_STREAM_APPLICATION:
839       if (gst_mpd_client_active_stream_contains_subtitles (stream)) {
840         name = g_strdup_printf ("subtitle_%02u", demux->n_subtitle_streams++);
841         tmpl =
842             gst_static_pad_template_get (&gst_dash_demux_subtitlesrc_template);
843       } else {
844         return NULL;
845       }
846       break;
847     default:
848       g_assert_not_reached ();
849       return NULL;
850   }
851
852   /* Create and activate new pads */
853   pad = gst_pad_new_from_template (tmpl, name);
854   g_free (name);
855   gst_object_unref (tmpl);
856
857   gst_pad_set_active (pad, TRUE);
858   GST_INFO_OBJECT (demux, "Creating srcpad %s:%s", GST_DEBUG_PAD_NAME (pad));
859   return pad;
860 }
861
862 static void
863 gst_dash_demux_reset (GstAdaptiveDemux * ademux)
864 {
865   GstDashDemux *demux = GST_DASH_DEMUX_CAST (ademux);
866
867   GST_DEBUG_OBJECT (demux, "Resetting demux");
868
869   demux->end_of_period = FALSE;
870   demux->end_of_manifest = FALSE;
871
872   if (demux->client) {
873     gst_mpd_client_free (demux->client);
874     demux->client = NULL;
875   }
876   gst_dash_demux_clock_drift_free (demux->clock_drift);
877   demux->clock_drift = NULL;
878   demux->client = gst_mpd_client_new ();
879   gst_mpd_client_set_uri_downloader (demux->client, ademux->downloader);
880
881   demux->n_audio_streams = 0;
882   demux->n_video_streams = 0;
883 }
884
885 static GstCaps *
886 gst_dash_demux_get_video_input_caps (GstDashDemux * demux,
887     GstActiveStream * stream)
888 {
889   guint width = 0, height = 0;
890   gint fps_num = 0, fps_den = 1;
891   gboolean have_fps = FALSE;
892   GstCaps *caps = NULL;
893
894   if (stream == NULL)
895     return NULL;
896
897   /* if bitstreamSwitching is true we dont need to swich pads on resolution change */
898   if (!gst_mpd_client_get_bitstream_switching_flag (stream)) {
899     width = gst_mpd_client_get_video_stream_width (stream);
900     height = gst_mpd_client_get_video_stream_height (stream);
901     have_fps =
902         gst_mpd_client_get_video_stream_framerate (stream, &fps_num, &fps_den);
903   }
904   caps = gst_mpd_client_get_stream_caps (stream);
905   if (caps == NULL)
906     return NULL;
907
908   if (width > 0 && height > 0) {
909     gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
910         G_TYPE_INT, height, NULL);
911   }
912
913   if (have_fps) {
914     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, fps_num,
915         fps_den, NULL);
916   }
917
918   return caps;
919 }
920
921 static GstCaps *
922 gst_dash_demux_get_audio_input_caps (GstDashDemux * demux,
923     GstActiveStream * stream)
924 {
925   guint rate = 0, channels = 0;
926   GstCaps *caps = NULL;
927
928   if (stream == NULL)
929     return NULL;
930
931   /* if bitstreamSwitching is true we dont need to swich pads on rate/channels change */
932   if (!gst_mpd_client_get_bitstream_switching_flag (stream)) {
933     channels = gst_mpd_client_get_audio_stream_num_channels (stream);
934     rate = gst_mpd_client_get_audio_stream_rate (stream);
935   }
936   caps = gst_mpd_client_get_stream_caps (stream);
937   if (caps == NULL)
938     return NULL;
939
940   if (rate > 0) {
941     gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL);
942   }
943   if (channels > 0) {
944     gst_caps_set_simple (caps, "channels", G_TYPE_INT, channels, NULL);
945   }
946
947   return caps;
948 }
949
950 static GstCaps *
951 gst_dash_demux_get_application_input_caps (GstDashDemux * demux,
952     GstActiveStream * stream)
953 {
954   GstCaps *caps = NULL;
955
956   if (stream == NULL)
957     return NULL;
958
959   caps = gst_mpd_client_get_stream_caps (stream);
960   if (caps == NULL)
961     return NULL;
962
963   return caps;
964 }
965
966 static GstCaps *
967 gst_dash_demux_get_input_caps (GstDashDemux * demux, GstActiveStream * stream)
968 {
969   switch (stream->mimeType) {
970     case GST_STREAM_VIDEO:
971       return gst_dash_demux_get_video_input_caps (demux, stream);
972     case GST_STREAM_AUDIO:
973       return gst_dash_demux_get_audio_input_caps (demux, stream);
974     case GST_STREAM_APPLICATION:
975       return gst_dash_demux_get_application_input_caps (demux, stream);
976     default:
977       return GST_CAPS_NONE;
978   }
979 }
980
981 static void
982 gst_dash_demux_stream_update_headers_info (GstAdaptiveDemuxStream * stream)
983 {
984   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
985   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
986   gchar *path = NULL;
987
988   gst_mpd_client_get_next_header (dashdemux->client,
989       &path, dashstream->index,
990       &stream->fragment.header_range_start, &stream->fragment.header_range_end);
991
992   if (path != NULL) {
993     stream->fragment.header_uri =
994         gst_uri_join_strings (gst_mpdparser_get_baseURL (dashdemux->client,
995             dashstream->index), path);
996     g_free (path);
997     path = NULL;
998   }
999
1000   gst_mpd_client_get_next_header_index (dashdemux->client,
1001       &path, dashstream->index,
1002       &stream->fragment.index_range_start, &stream->fragment.index_range_end);
1003
1004   if (path != NULL) {
1005     stream->fragment.index_uri =
1006         gst_uri_join_strings (gst_mpdparser_get_baseURL (dashdemux->client,
1007             dashstream->index), path);
1008     g_free (path);
1009   }
1010 }
1011
1012 static GstFlowReturn
1013 gst_dash_demux_stream_update_fragment_info (GstAdaptiveDemuxStream * stream)
1014 {
1015   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1016   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
1017   GstClockTime ts;
1018   GstMediaFragmentInfo fragment;
1019   gboolean isombff;
1020
1021   gst_adaptive_demux_stream_fragment_clear (&stream->fragment);
1022
1023   isombff = gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client);
1024
1025   if (GST_ADAPTIVE_DEMUX_STREAM_NEED_HEADER (stream) && isombff) {
1026     gst_dash_demux_stream_update_headers_info (stream);
1027     dashstream->sidx_base_offset = stream->fragment.index_range_end + 1;
1028     if (dashstream->sidx_index != 0) {
1029       /* request only the index to be downloaded as we need to reposition the
1030        * stream to a subsegment */
1031       return GST_FLOW_OK;
1032     }
1033   }
1034
1035   if (gst_mpd_client_get_next_fragment_timestamp (dashdemux->client,
1036           dashstream->index, &ts)) {
1037     if (GST_ADAPTIVE_DEMUX_STREAM_NEED_HEADER (stream)) {
1038       gst_adaptive_demux_stream_fragment_clear (&stream->fragment);
1039       gst_dash_demux_stream_update_headers_info (stream);
1040     }
1041
1042     gst_mpd_client_get_next_fragment (dashdemux->client, dashstream->index,
1043         &fragment);
1044
1045     stream->fragment.uri = fragment.uri;
1046     if (isombff && dashstream->sidx_index != 0) {
1047       GstSidxBoxEntry *entry = SIDX_CURRENT_ENTRY (dashstream);
1048       stream->fragment.range_start =
1049           dashstream->sidx_base_offset + entry->offset;
1050       stream->fragment.timestamp = entry->pts;
1051       stream->fragment.duration = entry->duration;
1052       if (stream->demux->segment.rate < 0.0) {
1053         stream->fragment.range_end =
1054             stream->fragment.range_start + entry->size - 1;
1055       } else {
1056         stream->fragment.range_end = fragment.range_end;
1057       }
1058     } else {
1059       stream->fragment.timestamp = fragment.timestamp;
1060       stream->fragment.duration = fragment.duration;
1061       stream->fragment.range_start =
1062           MAX (fragment.range_start, dashstream->sidx_base_offset);
1063       stream->fragment.range_end = fragment.range_end;
1064     }
1065
1066     return GST_FLOW_OK;
1067   }
1068
1069   return GST_FLOW_EOS;
1070 }
1071
1072 static gint
1073 gst_dash_demux_index_entry_search (GstSidxBoxEntry * entry, GstClockTime * ts,
1074     gpointer user_data)
1075 {
1076   GstClockTime entry_ts = entry->pts + entry->duration;
1077   if (entry_ts < *ts)
1078     return -1;
1079   else if (entry->pts > *ts)
1080     return 1;
1081   else
1082     return 0;
1083 }
1084
1085 static void
1086 gst_dash_demux_stream_sidx_seek (GstDashDemuxStream * dashstream,
1087     gboolean forward, GstSeekFlags flags, GstClockTime ts,
1088     GstClockTime * final_ts)
1089 {
1090   GstSidxBox *sidx = SIDX (dashstream);
1091   GstSidxBoxEntry *entry;
1092   gint idx = sidx->entries_count;
1093
1094   /* check whether ts is already past the last element or not */
1095   if (sidx->entries[idx - 1].pts + sidx->entries[idx - 1].duration < ts) {
1096     dashstream->sidx_current_remaining = 0;
1097   } else {
1098     GstSearchMode mode = GST_SEARCH_MODE_BEFORE;
1099
1100     if ((flags & GST_SEEK_FLAG_SNAP_NEAREST) == GST_SEEK_FLAG_SNAP_NEAREST) {
1101       mode = GST_SEARCH_MODE_BEFORE;
1102     } else if ((forward && (flags & GST_SEEK_FLAG_SNAP_AFTER)) ||
1103         (!forward && (flags & GST_SEEK_FLAG_SNAP_BEFORE))) {
1104       mode = GST_SEARCH_MODE_AFTER;
1105     } else {
1106       mode = GST_SEARCH_MODE_BEFORE;
1107     }
1108
1109     entry =
1110         gst_util_array_binary_search (sidx->entries, sidx->entries_count,
1111         sizeof (GstSidxBoxEntry),
1112         (GCompareDataFunc) gst_dash_demux_index_entry_search, mode, &ts, NULL);
1113
1114     idx = entry - sidx->entries;
1115
1116     /* FIXME in reverse mode, if we are exactly at a fragment start it makes more
1117      * sense to start from the end of the previous fragment */
1118     /* FIXME we should have a GST_SEARCH_MODE_NEAREST */
1119     if ((flags & GST_SEEK_FLAG_SNAP_NEAREST) == GST_SEEK_FLAG_SNAP_NEAREST &&
1120         idx + 1 < sidx->entries_count) {
1121       if (ABS (sidx->entries[idx + 1].pts - ts) <
1122           ABS (sidx->entries[idx].pts - ts))
1123         idx += 1;
1124     }
1125
1126     dashstream->sidx_current_remaining = sidx->entries[idx].size;
1127   }
1128
1129   sidx->entry_index = idx;
1130   dashstream->sidx_index = idx;
1131
1132   if (final_ts) {
1133     if (idx == sidx->entries_count)
1134       *final_ts = sidx->entries[idx].pts + sidx->entries[idx].duration;
1135     else
1136       *final_ts = sidx->entries[idx].pts;
1137   }
1138 }
1139
1140 static GstFlowReturn
1141 gst_dash_demux_stream_seek (GstAdaptiveDemuxStream * stream, gboolean forward,
1142     GstSeekFlags flags, GstClockTime ts, GstClockTime * final_ts)
1143 {
1144   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1145   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
1146
1147   if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client)) {
1148     if (dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
1149       gst_dash_demux_stream_sidx_seek (dashstream, forward, flags, ts,
1150           final_ts);
1151     } else {
1152       /* no index yet, seek when we have it */
1153       /* FIXME - the final_ts won't be correct here */
1154       dashstream->pending_seek_ts = ts;
1155     }
1156   }
1157
1158   gst_mpd_client_stream_seek (dashdemux->client, dashstream->active_stream,
1159       forward, flags, ts, final_ts);
1160   return GST_FLOW_OK;
1161 }
1162
1163 static gboolean
1164 gst_dash_demux_stream_has_next_subfragment (GstAdaptiveDemuxStream * stream)
1165 {
1166   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1167   GstSidxBox *sidx = SIDX (dashstream);
1168
1169   if (dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
1170     if (stream->demux->segment.rate > 0.0) {
1171       if (sidx->entry_index + 1 < sidx->entries_count)
1172         return TRUE;
1173     } else {
1174       if (sidx->entry_index >= 1)
1175         return TRUE;
1176     }
1177   }
1178   return FALSE;
1179 }
1180
1181 static gboolean
1182 gst_dash_demux_stream_advance_subfragment (GstAdaptiveDemuxStream * stream)
1183 {
1184   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1185
1186   GstSidxBox *sidx = SIDX (dashstream);
1187   gboolean fragment_finished = TRUE;
1188
1189   if (dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
1190     if (stream->demux->segment.rate > 0.0) {
1191       sidx->entry_index++;
1192       if (sidx->entry_index < sidx->entries_count) {
1193         fragment_finished = FALSE;
1194       }
1195     } else {
1196       sidx->entry_index--;
1197       if (sidx->entry_index >= 0) {
1198         fragment_finished = FALSE;
1199       }
1200     }
1201   }
1202
1203   GST_DEBUG_OBJECT (stream->pad, "New sidx index: %d / %d. "
1204       "Finished fragment: %d", sidx->entry_index, sidx->entries_count,
1205       fragment_finished);
1206
1207   if (!fragment_finished) {
1208     dashstream->sidx_current_remaining = sidx->entries[sidx->entry_index].size;
1209   }
1210   return !fragment_finished;
1211 }
1212
1213 static gboolean
1214 gst_dash_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
1215 {
1216   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
1217   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1218
1219   if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client)) {
1220     if (gst_dash_demux_stream_has_next_subfragment (stream))
1221       return TRUE;
1222   }
1223
1224   return gst_mpd_client_has_next_segment (dashdemux->client,
1225       dashstream->active_stream, stream->demux->segment.rate > 0.0);
1226 }
1227
1228 static GstFlowReturn
1229 gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream)
1230 {
1231   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1232   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
1233
1234   GST_DEBUG_OBJECT (stream->pad, "Advance fragment");
1235
1236   if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client)) {
1237     if (gst_dash_demux_stream_advance_subfragment (stream))
1238       return GST_FLOW_OK;
1239   }
1240
1241   return gst_mpd_client_advance_segment (dashdemux->client,
1242       dashstream->active_stream, stream->demux->segment.rate > 0.0);
1243 }
1244
1245 static gboolean
1246 gst_dash_demux_stream_select_bitrate (GstAdaptiveDemuxStream * stream,
1247     guint64 bitrate)
1248 {
1249   GstActiveStream *active_stream = NULL;
1250   GList *rep_list = NULL;
1251   gint new_index;
1252   GstDashDemux *demux = GST_DASH_DEMUX_CAST (stream->demux);
1253   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1254   gboolean ret = FALSE;
1255
1256   active_stream = dashstream->active_stream;
1257   if (active_stream == NULL) {
1258     goto end;
1259   }
1260
1261   /* retrieve representation list */
1262   if (active_stream->cur_adapt_set)
1263     rep_list = active_stream->cur_adapt_set->Representations;
1264   if (!rep_list) {
1265     goto end;
1266   }
1267
1268   GST_DEBUG_OBJECT (stream->pad,
1269       "Trying to change to bitrate: %" G_GUINT64_FORMAT, bitrate);
1270
1271   /* get representation index with current max_bandwidth */
1272   new_index = gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list, bitrate);
1273
1274   /* if no representation has the required bandwidth, take the lowest one */
1275   if (new_index == -1)
1276     new_index = gst_mpdparser_get_rep_idx_with_min_bandwidth (rep_list);
1277
1278   if (new_index != active_stream->representation_idx) {
1279     GstRepresentationNode *rep = g_list_nth_data (rep_list, new_index);
1280     GST_INFO_OBJECT (demux, "Changing representation idx: %d %d %u",
1281         dashstream->index, new_index, rep->bandwidth);
1282     if (gst_mpd_client_setup_representation (demux->client, active_stream, rep)) {
1283       GstCaps *caps;
1284
1285       GST_INFO_OBJECT (demux, "Switching bitrate to %d",
1286           active_stream->cur_representation->bandwidth);
1287       caps = gst_dash_demux_get_input_caps (demux, active_stream);
1288       gst_adaptive_demux_stream_set_caps (stream, caps);
1289       ret = TRUE;
1290
1291     } else {
1292       GST_WARNING_OBJECT (demux, "Can not switch representation, aborting...");
1293     }
1294   }
1295
1296   if (gst_mpd_client_has_isoff_ondemand_profile (demux->client)) {
1297
1298     /* store our current position to change to the same one in a different
1299      * representation if needed */
1300     dashstream->sidx_index = SIDX (dashstream)->entry_index;
1301     if (ret) {
1302       /* TODO cache indexes to avoid re-downloading and parsing */
1303       /* if we switched, we need a new index */
1304       gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
1305       gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
1306       gst_adapter_clear (dashstream->sidx_adapter);
1307     }
1308   }
1309
1310 end:
1311   return ret;
1312 }
1313
1314 #define SEEK_UPDATES_PLAY_POSITION(r, start_type, stop_type) \
1315   ((r >= 0 && start_type != GST_SEEK_TYPE_NONE) || \
1316    (r < 0 && stop_type != GST_SEEK_TYPE_NONE))
1317
1318 static gboolean
1319 gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
1320 {
1321   gdouble rate;
1322   GstFormat format;
1323   GstSeekFlags flags;
1324   GstSeekType start_type, stop_type;
1325   gint64 start, stop;
1326   GList *list;
1327   GstClockTime current_pos, target_pos;
1328   guint current_period;
1329   GstStreamPeriod *period;
1330   GList *iter;
1331   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
1332   gboolean switched_period = FALSE;
1333
1334   gst_event_parse_seek (seek, &rate, &format, &flags, &start_type, &start,
1335       &stop_type, &stop);
1336
1337   if (!SEEK_UPDATES_PLAY_POSITION (rate, start_type, stop_type)) {
1338     /* nothing to do if we don't have to update the current position */
1339     return TRUE;
1340   }
1341
1342   if (demux->segment.rate > 0.0) {
1343     target_pos = (GstClockTime) start;
1344   } else {
1345     target_pos = (GstClockTime) stop;
1346   }
1347
1348   /* select the requested Period in the Media Presentation */
1349   if (!gst_mpd_client_setup_media_presentation (dashdemux->client, target_pos,
1350           -1, NULL))
1351     return FALSE;
1352
1353   current_period = 0;
1354   for (list = g_list_first (dashdemux->client->periods); list;
1355       list = g_list_next (list)) {
1356     period = list->data;
1357     current_pos = period->start;
1358     current_period = period->number;
1359     GST_DEBUG_OBJECT (demux, "Looking at period %u) start:%"
1360         GST_TIME_FORMAT " - duration:%"
1361         GST_TIME_FORMAT ") for position %" GST_TIME_FORMAT,
1362         current_period, GST_TIME_ARGS (current_pos),
1363         GST_TIME_ARGS (period->duration), GST_TIME_ARGS (target_pos));
1364     if (current_pos <= target_pos
1365         && target_pos <= current_pos + period->duration) {
1366       break;
1367     }
1368   }
1369   if (list == NULL) {
1370     GST_WARNING_OBJECT (demux, "Could not find seeked Period");
1371     return FALSE;
1372   }
1373   if (current_period != gst_mpd_client_get_period_index (dashdemux->client)) {
1374     GST_DEBUG_OBJECT (demux, "Seeking to Period %d", current_period);
1375
1376     /* clean old active stream list, if any */
1377     gst_active_streams_free (dashdemux->client);
1378
1379     /* setup video, audio and subtitle streams, starting from the new Period */
1380     if (!gst_mpd_client_set_period_index (dashdemux->client, current_period)
1381         || !gst_dash_demux_setup_all_streams (dashdemux))
1382       return FALSE;
1383     switched_period = TRUE;
1384   }
1385
1386   /* Update the current sequence on all streams */
1387   for (iter = (switched_period ? demux->next_streams : demux->streams); iter;
1388       iter = g_list_next (iter)) {
1389     GstDashDemuxStream *dashstream = iter->data;
1390
1391     if (flags & GST_SEEK_FLAG_FLUSH) {
1392       gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
1393       gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
1394       if (dashstream->sidx_adapter)
1395         gst_adapter_clear (dashstream->sidx_adapter);
1396     }
1397     gst_dash_demux_stream_seek (iter->data, rate >= 0, 0, target_pos, NULL);
1398   }
1399   return TRUE;
1400 }
1401
1402 static gint64
1403 gst_dash_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
1404 {
1405   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
1406   return MIN (dashdemux->client->mpd_node->minimumUpdatePeriod * 1000,
1407       SLOW_CLOCK_UPDATE_INTERVAL);
1408 }
1409
1410 static GstFlowReturn
1411 gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux,
1412     GstBuffer * buffer)
1413 {
1414   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
1415   GstMpdClient *new_client = NULL;
1416   GstMapInfo mapinfo;
1417
1418   GST_DEBUG_OBJECT (demux, "Updating manifest file from URL");
1419
1420   /* parse the manifest file */
1421   new_client = gst_mpd_client_new ();
1422   gst_mpd_client_set_uri_downloader (new_client, demux->downloader);
1423   new_client->mpd_uri = g_strdup (demux->manifest_uri);
1424   new_client->mpd_base_uri = g_strdup (demux->manifest_base_uri);
1425   gst_buffer_map (buffer, &mapinfo, GST_MAP_READ);
1426
1427   if (gst_mpd_parse (new_client, (gchar *) mapinfo.data, mapinfo.size)) {
1428     const gchar *period_id;
1429     guint period_idx;
1430     GList *iter;
1431     GList *streams_iter;
1432
1433     /* prepare the new manifest and try to transfer the stream position
1434      * status from the old manifest client  */
1435
1436     GST_DEBUG_OBJECT (demux, "Updating manifest");
1437
1438     period_id = gst_mpd_client_get_period_id (dashdemux->client);
1439     period_idx = gst_mpd_client_get_period_index (dashdemux->client);
1440
1441     /* setup video, audio and subtitle streams, starting from current Period */
1442     if (!gst_mpd_client_setup_media_presentation (new_client, -1,
1443             (period_id ? -1 : period_idx), period_id)) {
1444       /* TODO */
1445     }
1446
1447     if (period_id) {
1448       if (!gst_mpd_client_set_period_id (new_client, period_id)) {
1449         GST_DEBUG_OBJECT (demux, "Error setting up the updated manifest file");
1450         gst_mpd_client_free (new_client);
1451         gst_buffer_unmap (buffer, &mapinfo);
1452         return GST_FLOW_EOS;
1453       }
1454     } else {
1455       if (!gst_mpd_client_set_period_index (new_client, period_idx)) {
1456         GST_DEBUG_OBJECT (demux, "Error setting up the updated manifest file");
1457         gst_mpd_client_free (new_client);
1458         gst_buffer_unmap (buffer, &mapinfo);
1459         return GST_FLOW_EOS;
1460       }
1461     }
1462
1463     if (!gst_dash_demux_setup_mpdparser_streams (dashdemux, new_client)) {
1464       GST_ERROR_OBJECT (demux, "Failed to setup streams on manifest " "update");
1465       gst_mpd_client_free (new_client);
1466       gst_buffer_unmap (buffer, &mapinfo);
1467       return GST_FLOW_ERROR;
1468     }
1469
1470     /* update the streams to play from the next segment */
1471     for (iter = demux->streams, streams_iter = new_client->active_streams;
1472         iter && streams_iter;
1473         iter = g_list_next (iter), streams_iter = g_list_next (streams_iter)) {
1474       GstDashDemuxStream *demux_stream = iter->data;
1475       GstActiveStream *new_stream = streams_iter->data;
1476       GstClockTime ts;
1477
1478       if (!new_stream) {
1479         GST_DEBUG_OBJECT (demux,
1480             "Stream of index %d is missing from manifest update",
1481             demux_stream->index);
1482         gst_mpd_client_free (new_client);
1483         gst_buffer_unmap (buffer, &mapinfo);
1484         return GST_FLOW_EOS;
1485       }
1486
1487       if (gst_mpd_client_get_next_fragment_timestamp (dashdemux->client,
1488               demux_stream->index, &ts)
1489           || gst_mpd_client_get_last_fragment_timestamp_end (dashdemux->client,
1490               demux_stream->index, &ts)) {
1491
1492         /* Due to rounding when doing the timescale conversions it might happen
1493          * that the ts falls back to a previous segment, leading the same data
1494          * to be downloaded twice. We try to work around this by always adding
1495          * 10 microseconds to get back to the correct segment. The errors are
1496          * usually on the order of nanoseconds so it should be enough.
1497          */
1498         GST_DEBUG_OBJECT (GST_ADAPTIVE_DEMUX_STREAM_PAD (demux_stream),
1499             "Current position: %" GST_TIME_FORMAT ", updating to %"
1500             GST_TIME_FORMAT, GST_TIME_ARGS (ts),
1501             GST_TIME_ARGS (ts + (10 * GST_USECOND)));
1502         ts += 10 * GST_USECOND;
1503         gst_mpd_client_stream_seek (new_client, new_stream,
1504             demux->segment.rate >= 0, 0, ts, NULL);
1505       }
1506
1507       demux_stream->active_stream = new_stream;
1508     }
1509
1510     gst_mpd_client_free (dashdemux->client);
1511     dashdemux->client = new_client;
1512
1513     GST_DEBUG_OBJECT (demux, "Manifest file successfully updated");
1514     if (dashdemux->clock_drift) {
1515       gst_dash_demux_poll_clock_drift (dashdemux);
1516     }
1517   } else {
1518     /* In most cases, this will happen if we set a wrong url in the
1519      * source element and we have received the 404 HTML response instead of
1520      * the manifest */
1521     GST_WARNING_OBJECT (demux, "Error parsing the manifest.");
1522     gst_mpd_client_free (new_client);
1523     gst_buffer_unmap (buffer, &mapinfo);
1524     return GST_FLOW_ERROR;
1525   }
1526
1527   gst_buffer_unmap (buffer, &mapinfo);
1528
1529   return GST_FLOW_OK;
1530 }
1531
1532 static gint64
1533 gst_dash_demux_stream_get_fragment_waiting_time (GstAdaptiveDemuxStream *
1534     stream)
1535 {
1536   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
1537   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1538   GstDateTime *segmentAvailability;
1539   GstActiveStream *active_stream = dashstream->active_stream;
1540
1541   segmentAvailability =
1542       gst_mpd_client_get_next_segment_availability_start_time
1543       (dashdemux->client, active_stream);
1544
1545   if (segmentAvailability) {
1546     gint64 diff;
1547     GstDateTime *cur_time;
1548
1549     cur_time =
1550         gst_date_time_new_from_g_date_time
1551         (gst_adaptive_demux_get_client_now_utc (GST_ADAPTIVE_DEMUX_CAST
1552             (dashdemux)));
1553     diff =
1554         gst_mpd_client_calculate_time_difference (cur_time,
1555         segmentAvailability);
1556     gst_date_time_unref (segmentAvailability);
1557     gst_date_time_unref (cur_time);
1558     /* subtract the server's clock drift, so that if the server's
1559        time is behind our idea of UTC, we need to sleep for longer
1560        before requesting a fragment */
1561     return diff -
1562         gst_dash_demux_get_clock_compensation (dashdemux) * GST_USECOND;
1563   }
1564   return 0;
1565 }
1566
1567 static gboolean
1568 gst_dash_demux_has_next_period (GstAdaptiveDemux * demux)
1569 {
1570   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
1571
1572   if (demux->segment.rate >= 0)
1573     return gst_mpd_client_has_next_period (dashdemux->client);
1574   else
1575     return gst_mpd_client_has_previous_period (dashdemux->client);
1576 }
1577
1578 static void
1579 gst_dash_demux_advance_period (GstAdaptiveDemux * demux)
1580 {
1581   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
1582
1583   g_return_if_fail (gst_mpd_client_has_next_period (dashdemux->client));
1584
1585   if (demux->segment.rate >= 0) {
1586     if (!gst_mpd_client_set_period_index (dashdemux->client,
1587             gst_mpd_client_get_period_index (dashdemux->client) + 1)) {
1588       /* TODO error */
1589       return;
1590     }
1591   } else {
1592     if (!gst_mpd_client_set_period_index (dashdemux->client,
1593             gst_mpd_client_get_period_index (dashdemux->client) - 1)) {
1594       /* TODO error */
1595       return;
1596     }
1597   }
1598
1599   gst_dash_demux_setup_all_streams (dashdemux);
1600   gst_mpd_client_seek_to_first_segment (dashdemux->client);
1601 }
1602
1603 static GstBuffer *
1604 _gst_buffer_split (GstBuffer * buffer, gint offset, gsize size)
1605 {
1606   GstBuffer *newbuf = gst_buffer_copy_region (buffer,
1607       GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_META
1608       | GST_BUFFER_COPY_MEMORY, offset, size == -1 ? size : size - offset);
1609
1610   gst_buffer_resize (buffer, 0, offset);
1611
1612   return newbuf;
1613 }
1614
1615 static GstFlowReturn
1616 gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
1617     GstAdaptiveDemuxStream * stream)
1618 {
1619   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
1620   GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
1621
1622   if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client) &&
1623       dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
1624     /* fragment is advanced on data_received when byte limits are reached */
1625     if (gst_dash_demux_stream_has_next_fragment (stream))
1626       return GST_FLOW_OK;
1627     return GST_FLOW_EOS;
1628   }
1629
1630   if (G_UNLIKELY (stream->downloading_header || stream->downloading_index))
1631     return GST_FLOW_OK;
1632
1633   return gst_adaptive_demux_stream_advance_fragment (demux, stream,
1634       stream->fragment.duration);
1635 }
1636
1637 static GstFlowReturn
1638 gst_dash_demux_data_received (GstAdaptiveDemux * demux,
1639     GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
1640 {
1641   GstDashDemuxStream *dash_stream = (GstDashDemuxStream *) stream;
1642   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
1643   GstFlowReturn ret = GST_FLOW_OK;
1644
1645   if (!gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client))
1646     return gst_adaptive_demux_stream_push_buffer (stream, buffer);
1647
1648   gst_adapter_push (dash_stream->sidx_adapter, buffer);
1649   buffer = NULL;
1650
1651   if (stream->downloading_index) {
1652     GstIsoffParserResult res;
1653     guint consumed;
1654     gsize available;
1655
1656     available = gst_adapter_available (dash_stream->sidx_adapter);
1657     buffer = gst_adapter_take_buffer (dash_stream->sidx_adapter, available);
1658
1659     if (dash_stream->sidx_parser.status != GST_ISOFF_SIDX_PARSER_FINISHED) {
1660       res =
1661           gst_isoff_sidx_parser_add_buffer (&dash_stream->sidx_parser, buffer,
1662           &consumed);
1663
1664       if (res == GST_ISOFF_PARSER_ERROR) {
1665       } else if (res == GST_ISOFF_PARSER_UNEXPECTED) {
1666         /* this is not a 'sidx' index, just skip it and continue playback */
1667       } else {
1668         /* when finished, prepare for real data streaming */
1669         if (dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
1670           if (GST_CLOCK_TIME_IS_VALID (dash_stream->pending_seek_ts)) {
1671             /* FIXME, preserve seek flags */
1672             gst_dash_demux_stream_sidx_seek (dash_stream,
1673                 demux->segment.rate >= 0, 0, dash_stream->pending_seek_ts,
1674                 NULL);
1675             dash_stream->pending_seek_ts = GST_CLOCK_TIME_NONE;
1676           } else {
1677             SIDX (dash_stream)->entry_index = dash_stream->sidx_index;
1678           }
1679           dash_stream->sidx_current_remaining =
1680               SIDX_CURRENT_ENTRY (dash_stream)->size;
1681         } else if (consumed < available) {
1682           GstBuffer *pending;
1683           /* we still need to keep some data around for the next parsing round
1684            * so just push what was already processed by the parser */
1685           pending = _gst_buffer_split (buffer, consumed, -1);
1686           gst_adapter_push (dash_stream->sidx_adapter, pending);
1687         }
1688       }
1689     }
1690     ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
1691   } else if (dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
1692     gsize available;
1693
1694     while (ret == GST_FLOW_OK
1695         && ((available = gst_adapter_available (dash_stream->sidx_adapter)) > 0)) {
1696       gboolean advance = FALSE;
1697
1698       if (available < dash_stream->sidx_current_remaining) {
1699         buffer = gst_adapter_take_buffer (dash_stream->sidx_adapter, available);
1700         dash_stream->sidx_current_remaining -= available;
1701       } else {
1702         buffer =
1703             gst_adapter_take_buffer (dash_stream->sidx_adapter,
1704             dash_stream->sidx_current_remaining);
1705         dash_stream->sidx_current_remaining = 0;
1706         advance = TRUE;
1707       }
1708       ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
1709       if (advance) {
1710         GstFlowReturn new_ret;
1711         new_ret =
1712             gst_adaptive_demux_stream_advance_fragment (demux, stream,
1713             SIDX_CURRENT_ENTRY (dash_stream)->duration);
1714
1715         /* only overwrite if it was OK before */
1716         if (ret == GST_FLOW_OK)
1717           ret = new_ret;
1718       }
1719     }
1720   } else {
1721     /* this should be the main header, just push it all */
1722     ret =
1723         gst_adaptive_demux_stream_push_buffer (stream,
1724         gst_adapter_take_buffer (dash_stream->sidx_adapter,
1725             gst_adapter_available (dash_stream->sidx_adapter)));
1726   }
1727
1728   return ret;
1729 }
1730
1731 static void
1732 gst_dash_demux_stream_free (GstAdaptiveDemuxStream * stream)
1733 {
1734   GstDashDemuxStream *dash_stream = (GstDashDemuxStream *) stream;
1735
1736   gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
1737   if (dash_stream->sidx_adapter)
1738     g_object_unref (dash_stream->sidx_adapter);
1739 }
1740
1741 static GstDashDemuxClockDrift *
1742 gst_dash_demux_clock_drift_new (GstDashDemux * demux)
1743 {
1744   GstDashDemuxClockDrift *clock_drift;
1745
1746   clock_drift = g_slice_new0 (GstDashDemuxClockDrift);
1747   g_mutex_init (&clock_drift->clock_lock);
1748   clock_drift->next_update =
1749       GST_TIME_AS_USECONDS (gst_adaptive_demux_get_monotonic_time
1750       (GST_ADAPTIVE_DEMUX_CAST (demux)));
1751   return clock_drift;
1752 }
1753
1754 static void
1755 gst_dash_demux_clock_drift_free (GstDashDemuxClockDrift * clock_drift)
1756 {
1757   if (clock_drift) {
1758     g_mutex_lock (&clock_drift->clock_lock);
1759     if (clock_drift->ntp_clock)
1760       g_object_unref (clock_drift->ntp_clock);
1761     g_mutex_unlock (&clock_drift->clock_lock);
1762     g_mutex_clear (&clock_drift->clock_lock);
1763     g_slice_free (GstDashDemuxClockDrift, clock_drift);
1764   }
1765 }
1766
1767 /*
1768  * The value attribute of the UTCTiming element contains a white-space
1769  * separated list of servers that are recommended to be used in
1770  * combination with the NTP protocol as defined in IETF RFC 5905 for
1771  * getting the appropriate time.
1772  *
1773  * The DASH standard does not specify which version of NTP. This
1774  * function only works with NTPv4 servers.
1775 */
1776 static GstDateTime *
1777 gst_dash_demux_poll_ntp_server (GstDashDemuxClockDrift * clock_drift,
1778     gchar ** urls)
1779 {
1780   GstClockTime ntp_clock_time;
1781   GDateTime *dt, *dt2;
1782
1783   if (!clock_drift->ntp_clock) {
1784     GResolver *resolver;
1785     GList *inet_addrs;
1786     GError *err;
1787     gchar *ip_addr;
1788
1789     resolver = g_resolver_get_default ();
1790     /* We don't round-robin NTP servers. If the manifest specifies multiple
1791        NTP time servers, select one at random */
1792     clock_drift->selected_url = g_random_int_range (0, g_strv_length (urls));
1793     GST_DEBUG ("Connecting to NTP time server %s",
1794         urls[clock_drift->selected_url]);
1795     inet_addrs = g_resolver_lookup_by_name (resolver,
1796         urls[clock_drift->selected_url], NULL, &err);
1797     g_object_unref (resolver);
1798     if (!inet_addrs || g_list_length (inet_addrs) == 0) {
1799       GST_ERROR ("Failed to resolve hostname of NTP server: %s",
1800           err ? (err->message) : "unknown error");
1801       if (inet_addrs)
1802         g_resolver_free_addresses (inet_addrs);
1803       if (err)
1804         g_error_free (err);
1805       return NULL;
1806     }
1807     ip_addr =
1808         g_inet_address_to_string ((GInetAddress
1809             *) (g_list_first (inet_addrs)->data));
1810     clock_drift->ntp_clock = gst_ntp_clock_new ("dashntp", ip_addr, 123, 0);
1811     g_free (ip_addr);
1812     g_resolver_free_addresses (inet_addrs);
1813     if (!clock_drift->ntp_clock) {
1814       GST_ERROR ("Failed to create NTP clock");
1815       return NULL;
1816     }
1817     if (!gst_clock_wait_for_sync (clock_drift->ntp_clock, 5 * GST_SECOND)) {
1818       g_object_unref (clock_drift->ntp_clock);
1819       clock_drift->ntp_clock = NULL;
1820       GST_ERROR ("Failed to lock to NTP clock");
1821       return NULL;
1822     }
1823   }
1824   ntp_clock_time = gst_clock_get_time (clock_drift->ntp_clock);
1825   if (ntp_clock_time == GST_CLOCK_TIME_NONE) {
1826     GST_ERROR ("Failed to get time from NTP clock");
1827     return NULL;
1828   }
1829   ntp_clock_time -= NTP_TO_UNIX_EPOCH * GST_SECOND;
1830   dt = g_date_time_new_from_unix_utc (ntp_clock_time / GST_SECOND);
1831   if (!dt) {
1832     GST_ERROR ("Failed to create GstDateTime");
1833     return NULL;
1834   }
1835   ntp_clock_time =
1836       gst_util_uint64_scale (ntp_clock_time % GST_SECOND, 1000000, GST_SECOND);
1837   dt2 = g_date_time_add (dt, ntp_clock_time);
1838   g_date_time_unref (dt);
1839   return gst_date_time_new_from_g_date_time (dt2);
1840 }
1841
1842 struct Rfc5322TimeZone
1843 {
1844   const gchar *name;
1845   gfloat tzoffset;
1846 };
1847
1848 /*
1849  Parse an RFC5322 (section 3.3) date-time from the Date: field in the
1850  HTTP response. 
1851  See https://tools.ietf.org/html/rfc5322#section-3.3
1852 */
1853 static GstDateTime *
1854 gst_dash_demux_parse_http_head (GstDashDemuxClockDrift * clock_drift,
1855     GstFragment * download)
1856 {
1857   static const gchar *months[] = { NULL, "Jan", "Feb", "Mar", "Apr",
1858     "May", "Jun", "Jul", "Aug",
1859     "Sep", "Oct", "Nov", "Dec", NULL
1860   };
1861   static const struct Rfc5322TimeZone timezones[] = {
1862     {"Z", 0},
1863     {"UT", 0},
1864     {"GMT", 0},
1865     {"BST", 1},
1866     {"EST", -5},
1867     {"EDT", -4},
1868     {"CST", -6},
1869     {"CDT", -5},
1870     {"MST", -7},
1871     {"MDT", -6},
1872     {"PST", -8},
1873     {"PDT", -7},
1874     {NULL, 0}
1875   };
1876   GstDateTime *value = NULL;
1877   const GstStructure *response_headers;
1878   const gchar *http_date;
1879   const GValue *val;
1880   gint ret;
1881   const gchar *pos;
1882   gint year = -1, month = -1, day = -1, hour = -1, minute = -1, second = -1;
1883   gchar zone[6];
1884   gchar monthstr[4];
1885   gfloat tzoffset = 0;
1886   gboolean parsed_tz = FALSE;
1887
1888   g_return_val_if_fail (download != NULL, NULL);
1889   g_return_val_if_fail (download->headers != NULL, NULL);
1890
1891   val = gst_structure_get_value (download->headers, "response-headers");
1892   if (!val) {
1893     return NULL;
1894   }
1895   response_headers = gst_value_get_structure (val);
1896   http_date = gst_structure_get_string (response_headers, "Date");
1897   if (!http_date) {
1898     return NULL;
1899   }
1900
1901   /* skip optional text version of day of the week */
1902   pos = strchr (http_date, ',');
1903   if (pos)
1904     pos++;
1905   else
1906     pos = http_date;
1907   ret =
1908       sscanf (pos, "%02d %3s %04d %02d:%02d:%02d %5s", &day, monthstr, &year,
1909       &hour, &minute, &second, zone);
1910   if (ret == 7) {
1911     gchar *z = zone;
1912     for (int i = 1; months[i]; ++i) {
1913       if (g_ascii_strncasecmp (months[i], monthstr, strlen (months[i])) == 0) {
1914         month = i;
1915         break;
1916       }
1917     }
1918     for (int i = 0; timezones[i].name && !parsed_tz; ++i) {
1919       if (g_ascii_strncasecmp (timezones[i].name, z,
1920               strlen (timezones[i].name)) == 0) {
1921         tzoffset = timezones[i].tzoffset;
1922         parsed_tz = TRUE;
1923       }
1924     }
1925     if (!parsed_tz) {
1926       gint hh, mm;
1927       gboolean neg = FALSE;
1928       /* check if it is in the form +-HHMM */
1929       if (*z == '+' || *z == '-') {
1930         if (*z == '+')
1931           ++z;
1932         else if (*z == '-') {
1933           ++z;
1934           neg = TRUE;
1935         }
1936         ret = sscanf (z, "%02d%02d", &hh, &mm);
1937         if (ret == 2) {
1938           tzoffset = hh;
1939           tzoffset += mm / 60.0;
1940           if (neg)
1941             tzoffset = -tzoffset;
1942           parsed_tz = TRUE;
1943         }
1944       }
1945     }
1946     /* Accept year in both 2 digit or 4 digit format */
1947     if (year < 100)
1948       year += 2000;
1949   }
1950   if (month > 0 && parsed_tz) {
1951     value = gst_date_time_new (tzoffset,
1952         year, month, day, hour, minute, second);
1953   }
1954   return value;
1955 }
1956
1957 /*
1958    The timing information is contained in the message body of the HTTP
1959    response and contains a time value formatted according to NTP timestamp
1960    format in IETF RFC 5905.
1961
1962        0                   1                   2                   3
1963        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1964       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1965       |                            Seconds                            |
1966       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1967       |                            Fraction                           |
1968       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1969
1970                              NTP Timestamp Format
1971 */
1972 static GstDateTime *
1973 gst_dash_demux_parse_http_ntp (GstDashDemuxClockDrift * clock_drift,
1974     GstBuffer * buffer)
1975 {
1976   gint64 seconds;
1977   guint64 fraction;
1978   GDateTime *dt, *dt2;
1979   GstMapInfo mapinfo;
1980
1981   /* See https://tools.ietf.org/html/rfc5905#page-12 for details of
1982      the NTP Timestamp Format */
1983   gst_buffer_map (buffer, &mapinfo, GST_MAP_READ);
1984   if (mapinfo.size != 8) {
1985     gst_buffer_unmap (buffer, &mapinfo);
1986     return NULL;
1987   }
1988   seconds = GST_READ_UINT32_BE (mapinfo.data);
1989   fraction = GST_READ_UINT32_BE (mapinfo.data + 4);
1990   gst_buffer_unmap (buffer, &mapinfo);
1991   fraction = gst_util_uint64_scale (fraction, 1000000,
1992       G_GUINT64_CONSTANT (1) << 32);
1993   /* subtract constant to convert from 1900 based time to 1970 based time */
1994   seconds -= NTP_TO_UNIX_EPOCH;
1995   dt = g_date_time_new_from_unix_utc (seconds);
1996   dt2 = g_date_time_add (dt, fraction);
1997   g_date_time_unref (dt);
1998   return gst_date_time_new_from_g_date_time (dt2);
1999 }
2000
2001 /*
2002   The timing information is contained in the message body of the
2003   HTTP response and contains a time value formatted according to
2004   xs:dateTime as defined in W3C XML Schema Part 2: Datatypes specification.
2005 */
2006 static GstDateTime *
2007 gst_dash_demux_parse_http_xsdate (GstDashDemuxClockDrift * clock_drift,
2008     GstBuffer * buffer)
2009 {
2010   GstDateTime *value = NULL;
2011   GstMapInfo mapinfo;
2012
2013   /* the string from the server might not be zero terminated */
2014   if (gst_buffer_map (buffer, &mapinfo, GST_MAP_READ)) {
2015     gchar *str;
2016     str = g_strndup ((const gchar *) mapinfo.data, mapinfo.size);
2017     gst_buffer_unmap (buffer, &mapinfo);
2018     value = gst_date_time_new_from_iso8601_string (str);
2019     g_free (str);
2020   }
2021   return value;
2022 }
2023
2024 static gboolean
2025 gst_dash_demux_poll_clock_drift (GstDashDemux * demux)
2026 {
2027   GstDashDemuxClockDrift *clock_drift;
2028   GDateTime *start = NULL, *end;
2029   GstBuffer *buffer = NULL;
2030   GstDateTime *value = NULL;
2031   gboolean ret = FALSE;
2032   gint64 now;
2033   GstMPDUTCTimingType method;
2034   gchar **urls;
2035
2036   g_return_val_if_fail (demux != NULL, FALSE);
2037   g_return_val_if_fail (demux->clock_drift != NULL, FALSE);
2038   clock_drift = demux->clock_drift;
2039   now =
2040       GST_TIME_AS_USECONDS (gst_adaptive_demux_get_monotonic_time
2041       (GST_ADAPTIVE_DEMUX_CAST (demux)));
2042   if (now < clock_drift->next_update) {
2043     /*TODO: If a fragment fails to download in adaptivedemux, it waits
2044        for a manifest reload before another attempt to fetch a fragment.
2045        Section 10.8.6 of the DVB-DASH standard states that the DASH client
2046        shall refresh the manifest and resynchronise to one of the time sources.
2047
2048        Currently the fact that the manifest refresh follows a download failure
2049        does not make it into dashdemux. */
2050     return TRUE;
2051   }
2052   urls = gst_mpd_client_get_utc_timing_sources (demux->client,
2053       SUPPORTED_CLOCK_FORMATS, &method);
2054   if (!urls) {
2055     return FALSE;
2056   }
2057   /* Update selected_url just in case the number of URLs in the UTCTiming
2058      element has shrunk since the last poll */
2059   clock_drift->selected_url = clock_drift->selected_url % g_strv_length (urls);
2060   g_mutex_lock (&clock_drift->clock_lock);
2061
2062   if (method == GST_MPD_UTCTIMING_TYPE_NTP) {
2063     value = gst_dash_demux_poll_ntp_server (clock_drift, urls);
2064     if (!value) {
2065       GST_ERROR_OBJECT (demux, "Failed to fetch time from NTP server %s",
2066           urls[clock_drift->selected_url]);
2067       g_mutex_unlock (&clock_drift->clock_lock);
2068       goto quit;
2069     }
2070   }
2071   start =
2072       gst_adaptive_demux_get_client_now_utc (GST_ADAPTIVE_DEMUX_CAST (demux));
2073   if (!value) {
2074     GstFragment *download;
2075     gint64 range_start = 0, range_end = -1;
2076     GST_DEBUG_OBJECT (demux, "Fetching current time from %s",
2077         urls[clock_drift->selected_url]);
2078     if (method == GST_MPD_UTCTIMING_TYPE_HTTP_HEAD) {
2079       range_start = -1;
2080     }
2081     download =
2082         gst_uri_downloader_fetch_uri_with_range (GST_ADAPTIVE_DEMUX_CAST
2083         (demux)->downloader, urls[clock_drift->selected_url], NULL, TRUE, TRUE,
2084         TRUE, range_start, range_end, NULL);
2085     if (download) {
2086       if (method == GST_MPD_UTCTIMING_TYPE_HTTP_HEAD && download->headers) {
2087         value = gst_dash_demux_parse_http_head (clock_drift, download);
2088       } else {
2089         buffer = gst_fragment_get_buffer (download);
2090       }
2091       g_object_unref (download);
2092     }
2093   }
2094   g_mutex_unlock (&clock_drift->clock_lock);
2095   if (!value && !buffer) {
2096     GST_ERROR_OBJECT (demux, "Failed to fetch time from %s",
2097         urls[clock_drift->selected_url]);
2098     goto quit;
2099   }
2100   end = gst_adaptive_demux_get_client_now_utc (GST_ADAPTIVE_DEMUX_CAST (demux));
2101   if (!value && method == GST_MPD_UTCTIMING_TYPE_HTTP_NTP) {
2102     value = gst_dash_demux_parse_http_ntp (clock_drift, buffer);
2103   } else if (!value) {
2104     /* GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE or GST_MPD_UTCTIMING_TYPE_HTTP_ISO */
2105     value = gst_dash_demux_parse_http_xsdate (clock_drift, buffer);
2106   }
2107   if (buffer)
2108     gst_buffer_unref (buffer);
2109   if (value) {
2110     GTimeSpan download_duration = g_date_time_difference (end, start);
2111     GDateTime *client_now, *server_now;
2112     /* We don't know when the server sampled its clock, but we know
2113        it must have been before "end" and probably after "start".
2114        A reasonable estimate is to use (start+end)/2
2115      */
2116     client_now = g_date_time_add (start, download_duration / 2);
2117     server_now = gst_date_time_to_g_date_time (value);
2118     /* If gst_date_time_new_from_iso8601_string is given an unsupported
2119        ISO 8601 format, it can return a GstDateTime that is not valid,
2120        which causes gst_date_time_to_g_date_time to return NULL */
2121     if (server_now) {
2122       g_mutex_lock (&clock_drift->clock_lock);
2123       clock_drift->clock_compensation =
2124           g_date_time_difference (server_now, client_now);
2125       g_mutex_unlock (&clock_drift->clock_lock);
2126       GST_DEBUG_OBJECT (demux,
2127           "Difference between client and server clocks is %lfs",
2128           ((double) clock_drift->clock_compensation) / 1000000.0);
2129       g_date_time_unref (server_now);
2130       ret = TRUE;
2131     } else {
2132       GST_ERROR_OBJECT (demux, "Failed to parse DateTime from server");
2133     }
2134     g_date_time_unref (client_now);
2135     gst_date_time_unref (value);
2136   } else {
2137     GST_ERROR_OBJECT (demux, "Failed to parse DateTime from server");
2138   }
2139   g_date_time_unref (end);
2140 quit:
2141   if (start)
2142     g_date_time_unref (start);
2143   /* if multiple URLs were specified, use a simple round-robin to
2144      poll each server */
2145   g_mutex_lock (&clock_drift->clock_lock);
2146   if (method == GST_MPD_UTCTIMING_TYPE_NTP) {
2147     clock_drift->next_update = now + FAST_CLOCK_UPDATE_INTERVAL;
2148   } else {
2149     clock_drift->selected_url =
2150         (1 + clock_drift->selected_url) % g_strv_length (urls);
2151     if (ret) {
2152       clock_drift->next_update = now + SLOW_CLOCK_UPDATE_INTERVAL;
2153     } else {
2154       clock_drift->next_update = now + FAST_CLOCK_UPDATE_INTERVAL;
2155     }
2156   }
2157   g_mutex_unlock (&clock_drift->clock_lock);
2158   return ret;
2159 }
2160
2161 static GTimeSpan
2162 gst_dash_demux_get_clock_compensation (GstDashDemux * demux)
2163 {
2164   GTimeSpan rv = 0;
2165   if (demux->clock_drift) {
2166     g_mutex_lock (&demux->clock_drift->clock_lock);
2167     rv = demux->clock_drift->clock_compensation;
2168     g_mutex_unlock (&demux->clock_drift->clock_lock);
2169   }
2170   GST_LOG_OBJECT (demux, "Clock drift %" GST_STIME_FORMAT, GST_STIME_ARGS (rv));
2171   return rv;
2172 }
2173
2174 static GDateTime *
2175 gst_dash_demux_get_server_now_utc (GstDashDemux * demux)
2176 {
2177   GDateTime *client_now;
2178   GDateTime *server_now;
2179
2180   client_now =
2181       gst_adaptive_demux_get_client_now_utc (GST_ADAPTIVE_DEMUX_CAST (demux));
2182   server_now =
2183       g_date_time_add (client_now,
2184       gst_dash_demux_get_clock_compensation (demux));
2185   g_date_time_unref (client_now);
2186   return server_now;
2187 }