mssdemux2: Update for adaptivedemux2 refactoring
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / ext / adaptivedemux2 / mss / gstmssdemux.c
1 /* GStreamer
2  * Copyright (C) 2012 Smart TV Alliance
3  *  Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>, Collabora Ltd.
4  *
5  * gstmssdemux.c:
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:element-mssdemux
25  * @title: mssdemux
26  *
27  * Demuxes a Microsoft's Smooth Streaming manifest into its audio and/or video streams.
28  *
29  */
30
31 /*
32  * == Internals
33  *
34  * = Smooth streaming in a few lines
35  * A SS stream is defined by a xml manifest file. This file has a list of
36  * tracks (StreamIndex), each one can have multiple QualityLevels, that define
37  * different encoding/bitrates. When playing a track, only one of those
38  * QualityLevels can be active at a time (per stream).
39  *
40  * The StreamIndex defines a URL with {time} and {bitrate} tags that are
41  * replaced by values indicated by the fragment start times and the selected
42  * QualityLevel, that generates the fragments URLs.
43  *
44  * Another relevant detail is that the Isomedia fragments for smoothstreaming
45  * won't contains a 'moov' atom, nor a 'stsd', so there is no information
46  * about the media type/configuration on the fragments, it must be extracted
47  * from the Manifest and passed downstream. mssdemux does this via GstCaps.
48  *
49  * = How mssdemux works
50  * There is a gstmssmanifest.c utility that holds the manifest and parses
51  * and has functions to extract information from it. mssdemux received the
52  * manifest from its sink pad and starts processing it when it gets EOS.
53  *
54  * The Manifest is parsed and the streams are exposed, 1 pad for each, with
55  * a initially selected QualityLevel. Each stream starts its own GstTaks that
56  * is responsible for downloading fragments and pushing them downstream.
57  *
58  * When a new connection-speed is set, mssdemux evaluates the available
59  * QualityLevels and might decide to switch to another one. In this case it
60  * pushes a new GstCaps event indicating the new caps on the pads.
61  *
62  * All operations that intend to update the GstTasks state should be protected
63  * with the GST_OBJECT_LOCK.
64  */
65
66 #ifdef HAVE_CONFIG_H
67 #include "config.h"
68 #endif
69
70 #include <glib/gi18n-lib.h>
71
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <string.h>
75
76 #include "gstadaptivedemuxelements.h"
77 #include "gstmssdemux.h"
78
79 GST_DEBUG_CATEGORY (mssdemux2_debug);
80 #define GST_CAT_DEFAULT mssdemux2_debug
81
82 static GstStaticPadTemplate gst_mss_demux_sink_template =
83 GST_STATIC_PAD_TEMPLATE ("sink",
84     GST_PAD_SINK,
85     GST_PAD_ALWAYS,
86     GST_STATIC_CAPS ("application/vnd.ms-sstr+xml")
87     );
88
89 static GstStaticPadTemplate gst_mss_demux_videosrc_template =
90 GST_STATIC_PAD_TEMPLATE ("video_%02u",
91     GST_PAD_SRC,
92     GST_PAD_SOMETIMES,
93     GST_STATIC_CAPS_ANY);
94
95 static GstStaticPadTemplate gst_mss_demux_audiosrc_template =
96 GST_STATIC_PAD_TEMPLATE ("audio_%02u",
97     GST_PAD_SRC,
98     GST_PAD_SOMETIMES,
99     GST_STATIC_CAPS_ANY);
100
101 typedef struct _GstMssDemux2 GstMssDemux2;
102 typedef struct _GstMssDemux2Class GstMssDemux2Class;
103
104 #define gst_mss_demux2_parent_class parent_class
105 G_DEFINE_TYPE (GstMssDemux2, gst_mss_demux2, GST_TYPE_ADAPTIVE_DEMUX);
106
107 #define gst_mss_demux_stream_parent_class stream_parent_class
108 G_DEFINE_TYPE (GstMssDemuxStream, gst_mss_demux_stream,
109     GST_TYPE_ADAPTIVE_DEMUX2_STREAM);
110
111 static gboolean mssdemux_element_init (GstPlugin * plugin);
112
113 GST_ELEMENT_REGISTER_DEFINE_CUSTOM (mssdemux2, mssdemux_element_init);
114
115 static void gst_mss_demux_dispose (GObject * object);
116
117 static gboolean gst_mss_demux_is_live (GstAdaptiveDemux * demux);
118 static gboolean gst_mss_demux_process_manifest (GstAdaptiveDemux * demux,
119     GstBuffer * buffer);
120 static GstClockTime gst_mss_demux_get_duration (GstAdaptiveDemux * demux);
121 static void gst_mss_demux_reset (GstAdaptiveDemux * demux);
122 static GstFlowReturn gst_mss_demux_stream_seek (GstAdaptiveDemux2Stream *
123     stream, gboolean forward, GstSeekFlags flags, GstClockTimeDiff ts,
124     GstClockTimeDiff * final_ts);
125 static gboolean gst_mss_demux_stream_has_next_fragment (GstAdaptiveDemux2Stream
126     * stream);
127 static GstFlowReturn
128 gst_mss_demux_stream_advance_fragment (GstAdaptiveDemux2Stream * stream);
129 static gboolean gst_mss_demux_stream_select_bitrate (GstAdaptiveDemux2Stream *
130     stream, guint64 bitrate);
131 static GstFlowReturn
132 gst_mss_demux_stream_update_fragment_info (GstAdaptiveDemux2Stream * stream);
133 static gboolean gst_mss_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);
134 static gint64
135 gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);
136 static GstClockTime
137 gst_mss_demux_stream_get_fragment_waiting_time (GstAdaptiveDemux2Stream *
138     stream);
139 static GstFlowReturn
140 gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
141     GstBuffer * buffer);
142 static gboolean gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux,
143     gint64 * start, gint64 * stop);
144 static GstFlowReturn gst_mss_demux_stream_data_received (GstAdaptiveDemux2Stream
145     * stream, GstBuffer * buffer);
146 static gboolean
147 gst_mss_demux_requires_periodical_playlist_update (GstAdaptiveDemux * demux);
148 GstStreamType gst_stream_type_from_mss_type (GstMssStreamType mtype);
149
150 static void
151 gst_mss_demux_stream_class_init (GstMssDemuxStreamClass * klass)
152 {
153   GstAdaptiveDemux2StreamClass *adaptivedemux2stream_class =
154       GST_ADAPTIVE_DEMUX2_STREAM_CLASS (klass);
155
156   adaptivedemux2stream_class->stream_seek = gst_mss_demux_stream_seek;
157
158   adaptivedemux2stream_class->get_fragment_waiting_time =
159       gst_mss_demux_stream_get_fragment_waiting_time;
160   adaptivedemux2stream_class->advance_fragment =
161       gst_mss_demux_stream_advance_fragment;
162   adaptivedemux2stream_class->has_next_fragment =
163       gst_mss_demux_stream_has_next_fragment;
164   adaptivedemux2stream_class->select_bitrate =
165       gst_mss_demux_stream_select_bitrate;
166   adaptivedemux2stream_class->update_fragment_info =
167       gst_mss_demux_stream_update_fragment_info;
168
169   adaptivedemux2stream_class->data_received =
170       gst_mss_demux_stream_data_received;
171 }
172
173 static void
174 gst_mss_demux_stream_init (GstMssDemuxStream * stream)
175 {
176 }
177
178 static void
179 gst_mss_demux2_class_init (GstMssDemuxClass * klass)
180 {
181   GObjectClass *gobject_class;
182   GstElementClass *gstelement_class;
183   GstAdaptiveDemuxClass *gstadaptivedemux_class;
184
185   gobject_class = (GObjectClass *) klass;
186   gstelement_class = (GstElementClass *) klass;
187   gstadaptivedemux_class = (GstAdaptiveDemuxClass *) klass;
188
189   gst_element_class_add_static_pad_template (gstelement_class,
190       &gst_mss_demux_sink_template);
191   gst_element_class_add_static_pad_template (gstelement_class,
192       &gst_mss_demux_videosrc_template);
193   gst_element_class_add_static_pad_template (gstelement_class,
194       &gst_mss_demux_audiosrc_template);
195   gst_element_class_set_static_metadata (gstelement_class,
196       "Smooth Streaming demuxer (v2)", "Codec/Demuxer/Adaptive",
197       "Parse and demultiplex a Smooth Streaming manifest into audio and video "
198       "streams", "Thiago Santos <thiago.sousa.santos@collabora.com>");
199
200   gobject_class->dispose = gst_mss_demux_dispose;
201
202   gstadaptivedemux_class->process_manifest = gst_mss_demux_process_manifest;
203   gstadaptivedemux_class->is_live = gst_mss_demux_is_live;
204   gstadaptivedemux_class->get_duration = gst_mss_demux_get_duration;
205   gstadaptivedemux_class->get_manifest_update_interval =
206       gst_mss_demux_get_manifest_update_interval;
207   gstadaptivedemux_class->reset = gst_mss_demux_reset;
208   gstadaptivedemux_class->seek = gst_mss_demux_seek;
209
210   gstadaptivedemux_class->update_manifest_data =
211       gst_mss_demux_update_manifest_data;
212
213   gstadaptivedemux_class->get_live_seek_range =
214       gst_mss_demux_get_live_seek_range;
215   gstadaptivedemux_class->requires_periodical_playlist_update =
216       gst_mss_demux_requires_periodical_playlist_update;
217
218 }
219
220 static void
221 gst_mss_demux2_init (GstMssDemux * mssdemux)
222 {
223 }
224
225 static void
226 gst_mss_demux_reset (GstAdaptiveDemux * demux)
227 {
228   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
229
230   if (mssdemux->manifest) {
231     gst_mss_manifest_free (mssdemux->manifest);
232     mssdemux->manifest = NULL;
233   }
234   g_free (mssdemux->base_url);
235   mssdemux->base_url = NULL;
236 }
237
238 static void
239 gst_mss_demux_dispose (GObject * object)
240 {
241   gst_mss_demux_reset (GST_ADAPTIVE_DEMUX_CAST (object));
242
243   G_OBJECT_CLASS (parent_class)->dispose (object);
244 }
245
246 static gboolean
247 gst_mss_demux_is_live (GstAdaptiveDemux * demux)
248 {
249   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
250
251   g_return_val_if_fail (mssdemux->manifest != NULL, FALSE);
252
253   return gst_mss_manifest_is_live (mssdemux->manifest);
254 }
255
256 static GstClockTime
257 gst_mss_demux_get_duration (GstAdaptiveDemux * demux)
258 {
259   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
260
261   g_return_val_if_fail (mssdemux->manifest != NULL, FALSE);
262
263   return gst_mss_manifest_get_gst_duration (mssdemux->manifest);
264 }
265
266 static GstFlowReturn
267 gst_mss_demux_stream_update_fragment_info (GstAdaptiveDemux2Stream * stream)
268 {
269   GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
270   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (stream->demux);
271   GstFlowReturn ret;
272   gchar *path = NULL;
273
274   gst_adaptive_demux2_stream_fragment_clear (&stream->fragment);
275   ret = gst_mss_stream_get_fragment_url (mssstream->manifest_stream, &path);
276
277   if (ret == GST_FLOW_OK) {
278     GstUri *base_url, *frag_url;
279
280     base_url = gst_uri_from_string (mssdemux->base_url);
281     frag_url = gst_uri_from_string_with_base (base_url, path);
282
283     g_free (stream->fragment.uri);
284     stream->fragment.uri = gst_uri_to_string (frag_url);
285     stream->fragment.stream_time =
286         gst_mss_stream_get_fragment_gst_timestamp (mssstream->manifest_stream);
287     stream->fragment.duration =
288         gst_mss_stream_get_fragment_gst_duration (mssstream->manifest_stream);
289
290     gst_uri_unref (base_url);
291     gst_uri_unref (frag_url);
292   }
293   g_free (path);
294
295   return ret;
296 }
297
298 static GstFlowReturn
299 gst_mss_demux_stream_seek (GstAdaptiveDemux2Stream * stream, gboolean forward,
300     GstSeekFlags flags, GstClockTimeDiff ts, GstClockTimeDiff * final_ts)
301 {
302   GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
303
304   gst_mss_stream_seek (mssstream->manifest_stream, forward, flags, ts,
305       final_ts);
306   return GST_FLOW_OK;
307 }
308
309 static GstFlowReturn
310 gst_mss_demux_stream_advance_fragment (GstAdaptiveDemux2Stream * stream)
311 {
312   GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
313
314   if (stream->demux->segment.rate >= 0)
315     return gst_mss_stream_advance_fragment (mssstream->manifest_stream);
316   else
317     return gst_mss_stream_regress_fragment (mssstream->manifest_stream);
318 }
319
320 static GstCaps *
321 create_mss_caps (GstMssDemuxStream * stream, GstCaps * caps)
322 {
323   return gst_caps_new_simple ("video/quicktime", "variant", G_TYPE_STRING,
324       "mss-fragmented", "timescale", G_TYPE_UINT64,
325       gst_mss_stream_get_timescale (stream->manifest_stream), "media-caps",
326       GST_TYPE_CAPS, caps, NULL);
327 }
328
329 static void
330 gst_mss_demux_apply_protection_system (GstCaps * caps,
331     const gchar * selected_system)
332 {
333   GstStructure *s;
334
335   g_return_if_fail (selected_system);
336   s = gst_caps_get_structure (caps, 0);
337   gst_structure_set (s,
338       "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
339       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
340       NULL);
341   gst_structure_set_name (s, "application/x-cenc");
342
343 }
344
345 static gboolean
346 gst_mss_demux_setup_streams (GstAdaptiveDemux * demux)
347 {
348   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
349   GSList *streams = gst_mss_manifest_get_streams (mssdemux->manifest);
350   GSList *active_streams = NULL;
351   GSList *iter;
352   const gchar *protection_system_id =
353       gst_mss_manifest_get_protection_system_id (mssdemux->manifest);
354   const gchar *protection_data =
355       gst_mss_manifest_get_protection_data (mssdemux->manifest);
356   gboolean protected = protection_system_id && protection_data;
357   const gchar *selected_system = NULL;
358   guint64 max_bitrate = G_MAXUINT64;
359
360   if (streams == NULL) {
361     GST_INFO_OBJECT (mssdemux, "No streams found in the manifest");
362     GST_ELEMENT_ERROR (mssdemux, STREAM, DEMUX,
363         (_("This file contains no playable streams.")),
364         ("no streams found at the Manifest"));
365     return FALSE;
366   }
367
368   if (protected) {
369     const gchar *sys_ids[2] = { protection_system_id, NULL };
370
371     selected_system = gst_protection_select_system (sys_ids);
372     if (!selected_system) {
373       GST_ERROR_OBJECT (mssdemux, "stream is protected, but no "
374           "suitable decryptor element has been found");
375       return FALSE;
376     }
377   }
378
379   if (demux->connection_speed != 0)
380     max_bitrate = demux->connection_speed;
381
382   for (iter = streams; iter; iter = g_slist_next (iter)) {
383     GstAdaptiveDemux2Stream *stream = NULL;
384     GstMssDemuxStream *mss_stream;
385     GstMssStream *manifeststream = iter->data;
386     GstAdaptiveDemuxTrack *track;
387     GstStreamType stream_type =
388         gst_stream_type_from_mss_type (gst_mss_stream_get_type
389         (manifeststream));
390     const gchar *lang = gst_mss_stream_get_lang (manifeststream);
391     const gchar *name = gst_mss_stream_get_name (manifeststream);
392     gchar *stream_id;
393     GstCaps *caps;
394     GstTagList *tags = NULL;
395
396     if (stream_type == GST_STREAM_TYPE_UNKNOWN) {
397       GST_WARNING_OBJECT (mssdemux, "Skipping unknown stream %s", name);
398       continue;
399     }
400
401     if (name)
402       stream_id =
403           g_strdup_printf ("mss-stream-%s-%s",
404           gst_stream_type_get_name (stream_type),
405           gst_mss_stream_get_name (manifeststream));
406     else if (lang)
407       stream_id =
408           g_strdup_printf ("mss-stream-%s-%s",
409           gst_stream_type_get_name (stream_type), lang);
410     else
411       stream_id =
412           g_strdup_printf ("mss-stream-%s",
413           gst_stream_type_get_name (stream_type));
414
415     mss_stream =
416         g_object_new (GST_TYPE_MSS_DEMUX_STREAM, "name", stream_id, NULL);
417
418     stream = GST_ADAPTIVE_DEMUX2_STREAM_CAST (mss_stream);
419     stream->stream_type = stream_type;
420
421     mss_stream->manifest_stream = manifeststream;
422     gst_mss_stream_set_active (manifeststream, TRUE);
423
424     /* Set the maximum bitrate now that the underlying stream is active. This
425      * ensures that we get the proper caps and information. */
426     gst_mss_stream_select_bitrate (manifeststream, max_bitrate);
427
428     caps = gst_mss_stream_get_caps (mss_stream->manifest_stream);
429     gst_adaptive_demux2_stream_set_caps (stream, create_mss_caps (mss_stream,
430             caps));
431     if (lang != NULL)
432       tags = gst_tag_list_new (GST_TAG_LANGUAGE_CODE, lang, NULL);
433
434     track = gst_adaptive_demux_track_new (demux, stream_type,
435         GST_STREAM_FLAG_NONE, (gchar *) stream_id, create_mss_caps (mss_stream,
436             caps), tags);
437
438     g_free (stream_id);
439     gst_adaptive_demux2_add_stream (demux, stream);
440     gst_adaptive_demux2_stream_add_track (stream, track);
441     gst_adaptive_demux_track_unref (track);
442
443     GST_DEBUG_OBJECT (stream, "Current quality bitrate %" G_GUINT64_FORMAT,
444         gst_mss_stream_get_current_bitrate (manifeststream));
445
446     if (tags)
447       gst_adaptive_demux2_stream_set_tags (stream, tags);
448
449     active_streams = g_slist_prepend (active_streams, mss_stream);
450   }
451
452   for (iter = active_streams; iter; iter = g_slist_next (iter)) {
453     GstMssDemuxStream *stream = iter->data;
454
455     if (protected) {
456       GstBuffer *protection_buffer =
457           gst_buffer_new_wrapped (g_strdup (protection_data),
458           strlen (protection_data));
459       GstEvent *event =
460           gst_event_new_protection (protection_system_id, protection_buffer,
461           "smooth-streaming");
462
463       GST_LOG_OBJECT (stream, "Queueing Protection event on source pad");
464       gst_adaptive_demux2_stream_queue_event ((GstAdaptiveDemux2Stream *)
465           stream, event);
466       gst_buffer_unref (protection_buffer);
467     }
468   }
469
470   g_slist_free (active_streams);
471   return TRUE;
472 }
473
474 static void
475 gst_mss_demux_update_base_url (GstMssDemux * mssdemux)
476 {
477   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (mssdemux);
478   GstUri *base_url;
479   gchar *path;
480
481   g_free (mssdemux->base_url);
482
483   mssdemux->base_url =
484       g_strdup (demux->manifest_base_uri ? demux->manifest_base_uri : demux->
485       manifest_uri);
486
487   base_url = gst_uri_from_string (mssdemux->base_url);
488   path = gst_uri_get_path (base_url);
489   GST_DEBUG ("%s", path);
490
491   if (!g_str_has_suffix (path, "/Manifest")
492       && !g_str_has_suffix (path, "/manifest"))
493     GST_WARNING_OBJECT (mssdemux, "Stream's URI didn't end with /manifest");
494
495   g_free (path);
496   gst_uri_unref (base_url);
497 }
498
499 static gboolean
500 gst_mss_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
501 {
502   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
503
504   gst_mss_demux_update_base_url (mssdemux);
505
506   mssdemux->manifest = gst_mss_manifest_new (buf);
507   if (!mssdemux->manifest) {
508     GST_ELEMENT_ERROR (mssdemux, STREAM, FORMAT, ("Bad manifest file"),
509         ("Xml manifest file couldn't be parsed"));
510     return FALSE;
511   }
512   return gst_mss_demux_setup_streams (demux);
513 }
514
515 static gboolean
516 gst_mss_demux_stream_select_bitrate (GstAdaptiveDemux2Stream * stream,
517     guint64 bitrate)
518 {
519   GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
520   gboolean ret = FALSE;
521
522   GST_DEBUG_OBJECT (stream,
523       "Using stream download bitrate %" G_GUINT64_FORMAT, bitrate);
524
525   if (gst_mss_stream_select_bitrate (mssstream->manifest_stream,
526           bitrate / MAX (1.0, ABS (stream->demux->segment.rate)))) {
527     GstCaps *caps;
528     GstCaps *msscaps;
529     GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (stream->demux);
530     const gchar *protection_system_id =
531         gst_mss_manifest_get_protection_system_id (mssdemux->manifest);
532     const gchar *protection_data =
533         gst_mss_manifest_get_protection_data (mssdemux->manifest);
534     gboolean protected = protection_system_id && protection_data;
535
536     caps = gst_mss_stream_get_caps (mssstream->manifest_stream);
537
538     GST_DEBUG_OBJECT (stream,
539         "Starting streams reconfiguration due to bitrate changes");
540
541     if (protected) {
542       const gchar *sys_ids[2] = { protection_system_id, NULL };
543       const gchar *selected_system = gst_protection_select_system (sys_ids);
544
545       if (!selected_system) {
546         GST_ERROR_OBJECT (mssdemux, "stream is protected, but no "
547             "suitable decryptor element has been found");
548         gst_caps_unref (caps);
549         return FALSE;
550       }
551
552       gst_mss_demux_apply_protection_system (caps, selected_system);
553     }
554
555     msscaps = create_mss_caps (mssstream, caps);
556
557     GST_DEBUG_OBJECT (stream,
558         "Stream changed bitrate to %" G_GUINT64_FORMAT " caps: %"
559         GST_PTR_FORMAT,
560         gst_mss_stream_get_current_bitrate (mssstream->manifest_stream), caps);
561
562     gst_caps_unref (caps);
563
564     gst_adaptive_demux2_stream_set_caps (stream, msscaps);
565     ret = TRUE;
566     GST_DEBUG_OBJECT (stream, "Finished streams reconfiguration");
567   }
568   return ret;
569 }
570
571 #define SEEK_UPDATES_PLAY_POSITION(r, start_type, stop_type) \
572   ((r >= 0 && start_type != GST_SEEK_TYPE_NONE) || \
573    (r < 0 && stop_type != GST_SEEK_TYPE_NONE))
574
575 static gboolean
576 gst_mss_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
577 {
578   gdouble rate;
579   GstFormat format;
580   GstSeekFlags flags;
581   GstSeekType start_type, stop_type;
582   gint64 start, stop;
583   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
584
585   gst_event_parse_seek (seek, &rate, &format, &flags, &start_type, &start,
586       &stop_type, &stop);
587
588   GST_DEBUG_OBJECT (mssdemux,
589       "seek event, rate: %f start: %" GST_TIME_FORMAT " stop: %"
590       GST_TIME_FORMAT, rate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
591
592   if (SEEK_UPDATES_PLAY_POSITION (rate, start_type, stop_type)) {
593     if (rate >= 0)
594       gst_mss_manifest_seek (mssdemux->manifest, rate >= 0, start);
595     else
596       gst_mss_manifest_seek (mssdemux->manifest, rate >= 0, stop);
597   }
598
599   return TRUE;
600 }
601
602 static gboolean
603 gst_mss_demux_stream_has_next_fragment (GstAdaptiveDemux2Stream * stream)
604 {
605   GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
606
607   return gst_mss_stream_has_next_fragment (mssstream->manifest_stream);
608 }
609
610 static gint64
611 gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
612 {
613   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
614   GstClockTime interval;
615
616   /* Not much information about this in the MSS spec. It seems that
617    * the fragments contain an UUID box that should tell the next
618    * fragments time and duration so one wouldn't need to fetch
619    * the Manifest again, but we need a fallback here. So use 2 times
620    * the current fragment duration */
621
622   interval = gst_mss_manifest_get_min_fragment_duration (mssdemux->manifest);
623   if (!GST_CLOCK_TIME_IS_VALID (interval))
624     interval = 2 * GST_SECOND;  /* default to 2 seconds */
625
626   interval = 2 * (interval / GST_USECOND);
627
628   return interval;
629 }
630
631 static GstClockTime
632 gst_mss_demux_stream_get_fragment_waiting_time (GstAdaptiveDemux2Stream *
633     stream)
634 {
635   /* Wait a second for live streams so we don't try premature fragments downloading */
636   return GST_SECOND;
637 }
638
639 static GstFlowReturn
640 gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
641     GstBuffer * buffer)
642 {
643   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
644
645   gst_mss_demux_update_base_url (mssdemux);
646
647   gst_mss_manifest_reload_fragments (mssdemux->manifest, buffer);
648   return GST_FLOW_OK;
649 }
650
651 static gboolean
652 gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
653     gint64 * stop)
654 {
655   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
656
657   return gst_mss_manifest_get_live_seek_range (mssdemux->manifest, start, stop);
658 }
659
660 static GstFlowReturn
661 gst_mss_demux_stream_data_received (GstAdaptiveDemux2Stream * stream,
662     GstBuffer * buffer)
663 {
664   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (stream->demux);
665   GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
666   gsize available;
667
668   if (!gst_mss_manifest_is_live (mssdemux->manifest)) {
669     return gst_adaptive_demux2_stream_push_buffer (stream, buffer);
670   }
671
672   if (gst_mss_stream_fragment_parsing_needed (mssstream->manifest_stream)) {
673     gst_mss_manifest_live_adapter_push (mssstream->manifest_stream, buffer);
674     available =
675         gst_mss_manifest_live_adapter_available (mssstream->manifest_stream);
676     // FIXME: try to reduce this minimal size.
677     if (available < 4096) {
678       return GST_FLOW_OK;
679     } else {
680       GST_LOG_OBJECT (stream, "enough data, parsing fragment.");
681       buffer =
682           gst_mss_manifest_live_adapter_take_buffer (mssstream->manifest_stream,
683           available);
684       gst_mss_stream_parse_fragment (mssstream->manifest_stream, buffer);
685     }
686   }
687
688   return gst_adaptive_demux2_stream_push_buffer (stream, buffer);
689 }
690
691 static gboolean
692 gst_mss_demux_requires_periodical_playlist_update (GstAdaptiveDemux * demux)
693 {
694   return TRUE;
695 }
696
697 GstStreamType
698 gst_stream_type_from_mss_type (GstMssStreamType mtype)
699 {
700   switch (mtype) {
701     case MSS_STREAM_TYPE_AUDIO:
702       return GST_STREAM_TYPE_AUDIO;
703     case MSS_STREAM_TYPE_VIDEO:
704       return GST_STREAM_TYPE_VIDEO;
705     default:
706       return GST_STREAM_TYPE_UNKNOWN;
707   }
708 }
709
710 static gboolean
711 mssdemux_element_init (GstPlugin * plugin)
712 {
713   gboolean ret = TRUE;
714
715   GST_DEBUG_CATEGORY_INIT (mssdemux2_debug, "mssdemux2", 0,
716       "mssdemux2 element");
717
718   if (!adaptivedemux2_base_element_init (plugin))
719     return TRUE;
720
721   ret =
722       gst_element_register (plugin, "mssdemux2", GST_RANK_PRIMARY + 1,
723       GST_TYPE_MSS_DEMUX2);
724
725   return ret;
726 }