<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";
        color:black;}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:"Courier New";
        color:black;}
span.stderr
        {mso-style-name:stderr;}
span.stdout
        {mso-style-name:stdout;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang=EN-US link=blue vlink="#954F72"><div class=WordSection1><p class=MsoNormal>Yep my bad, still in the app layer that I was porting down from. Will update and include the patchwork feedback.</p><p class=MsoNormal><o:p>&nbsp;</o:p></p><div style='mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal style='border:none;padding:0in'><b>From: </b><a href="mailto:akuster808@gmail.com">akuster808</a><br><b>Sent: </b>Saturday, April 28, 2018 9:37 AM<br><b>To: </b><a href="mailto:wouter@wouterlucas.com">wouterlucas</a>; <a href="mailto:openembedded-core@lists.openembedded.org">openembedded-core@lists.openembedded.org</a><br><b>Subject: </b>Re: [OE-core] [pyro][PATCH] gstreamer1.0-plugins-bad: Refresh patchesfor live streaming and add mpdparser for Dash playready support</p></div><p class=MsoNormal><o:p>&nbsp;</o:p></p><p><o:p>&nbsp;</o:p></p><p class=MsoNormal><o:p>&nbsp;</o:p></p><div><p class=MsoNormal>On 04/27/2018 08:38 PM, wouterlucas wrote:<o:p></o:p></p></div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><pre>Signed-off-by: wouterlucas <a href="mailto:wouter@wouterlucas.com">&lt;wouter@wouterlucas.com&gt;</a></pre><pre>---</pre><pre> ...demux-improved-live-playback-support.patch | 358 ++++++++----------</pre><pre> ...implement-adaptivedemux-s-get_live_s.patch |  63 +--</pre><pre> ...vedemux-minimal-HTTP-context-support.patch | 142 +++++++</pre><pre> ...-PlayReady-ContentProtection-parsing.patch | 109 ++++++</pre><pre> .../gstreamer1.0-plugins-bad_1.10.4.bb        |   9 +-</pre><pre> 5 files changed, 452 insertions(+), 229 deletions(-)</pre><pre> create mode 100644 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-adaptivedemux-minimal-HTTP-context-support.patch</pre><pre> create mode 100644 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-mpdparser-MS-PlayReady-ContentProtection-parsing.patch</pre></blockquote><p class=MsoNormal style='margin-bottom:12.0pt'><br>This fails with:<o:p></o:p></p><pre><span class=stderr>RROR: gstreamer1.0-plugins-bad-1.10.4-r0 do_fetch: Fetcher failure: Unable to find file <a href="file://0002-mssdemux-Handle-the-adapter-in-the-subclass-after-bu.patch">file://0002-mssdemux-Handle-the-adapter-in-the-subclass-after-bu.patch</a> anywhere. The paths that were searched were:<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad-1.10.4/poky<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/poky<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/files/poky<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad-1.10.4/qemux86<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/qemux86<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/files/qemux86<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad-1.10.4/qemuall<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/qemuall<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/files/qemuall<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad-1.10.4/x86<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/x86<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/files/x86<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad-1.10.4/i586<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/i586<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/files/i586<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad-1.10.4/<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/<o:p></o:p></span></pre><pre><span class=stderr>    /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/files/<o:p></o:p></span></pre><pre><span class=stderr>    /srv/autobuilder/autobuilder.yoctoproject.org/current_sources<o:p></o:p></span></pre><pre><span class=stderr>ERROR: gstreamer1.0-plugins-bad-1.10.4-r0 do_fetch: Fetcher failure for URL: '<a href="file://0002-mssdemux-Handle-the-adapter-in-the-subclass-after-bu.patch">file://0002-mssdemux-Handle-the-adapter-in-the-subclass-after-bu.patch</a>'. Unable to fetch URL from any source.<o:p></o:p></span></pre><pre><span class=stderr>ERROR: gstreamer1.0-plugins-bad-1.10.4-r0 do_fetch: Function failed: base_do_fetch<o:p></o:p></span></pre><pre><span class=stderr>ERROR: Logfile of failure stored in: /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/build/tmp/work/i586-poky-linux/gstreamer1.0-plugins-bad/1.10.4-r0/temp/log.do_fetch.1786<o:p></o:p></span></pre><pre><span class=stdout>NOTE: recipe gstreamer1.0-plugins-bad-1.10.4-r0: task do_fetch: Failed<o:p></o:p></span></pre><pre><span class=stderr>ERROR: Task (/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-deb-non-deb/build/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.4.bb:do_fetch) </span><o:p></o:p></pre><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><pre><o:p>&nbsp;</o:p></pre><pre>diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mssdemux-improved-live-playback-support.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mssdemux-improved-live-playback-support.patch</pre><pre>index 4832c18e78..041a3d6313 100644</pre><pre>--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mssdemux-improved-live-playback-support.patch</pre><pre>+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mssdemux-improved-live-playback-support.patch</pre><pre>@@ -1,7 +1,7 @@</pre><pre>-From 73721ad4e9e2d32e1c8b6a3b4aaa98401530e58a Mon Sep 17 00:00:00 2001</pre><pre>+From 12b9645c4c5b94ff4fd5062bdb02b63db7648db9 Mon Sep 17 00:00:00 2001</pre><pre> From: Philippe Normand <a href="mailto:philn@igalia.com">&lt;philn@igalia.com&gt;</a></pre><pre>-Date: Tue, 29 Nov 2016 14:43:41 +0100</pre><pre>-Subject: [PATCH] mssdemux: improved live playback support</pre><pre>+Date: Thu, 10 Sep 2015 16:13:30 +0200</pre><pre>+Subject: [PATCH 1/6] mssdemux: improved live playback support</pre><pre> </pre><pre> When a MSS server hosts a live stream the fragments listed in the</pre><pre> manifest usually don't have accurate timestamps and duration, except</pre><pre>@@ -12,23 +12,20 @@ be incrementally built by parsing the first/current fragment.</pre><pre> </pre><pre> <a href="https://bugzilla.gnome.org/show_bug.cgi?id=755036">https://bugzilla.gnome.org/show_bug.cgi?id=755036</a></pre><pre> ---</pre><pre>-Upstream-Status: Backport</pre><pre>-Signed-off-by: Khem Raj <a href="mailto:raj.khem@gmail.com">&lt;raj.khem@gmail.com&gt;</a></pre><pre>-</pre><pre>  ext/smoothstreaming/Makefile.am               |   2 +</pre><pre>- ext/smoothstreaming/gstmssdemux.c             |  60 ++++++</pre><pre>- ext/smoothstreaming/gstmssfragmentparser.c    | 266 ++++++++++++++++++++++++++</pre><pre>- ext/smoothstreaming/gstmssfragmentparser.h    |  84 ++++++++</pre><pre>- ext/smoothstreaming/gstmssmanifest.c          | 158 ++++++++++++++-</pre><pre>- ext/smoothstreaming/gstmssmanifest.h          |   7 +</pre><pre>- gst-libs/gst/adaptivedemux/gstadaptivedemux.c |  27 ++-</pre><pre>+ ext/smoothstreaming/gstmssdemux.c             |  61 ++++++</pre><pre>+ ext/smoothstreaming/gstmssfragmentparser.c    | 255 ++++++++++++++++++++++++++</pre><pre>+ ext/smoothstreaming/gstmssfragmentparser.h    |  84 +++++++++</pre><pre>+ ext/smoothstreaming/gstmssmanifest.c          | 155 ++++++++++++++--</pre><pre>+ ext/smoothstreaming/gstmssmanifest.h          |   3 +</pre><pre>+ gst-libs/gst/adaptivedemux/gstadaptivedemux.c |  28 ++-</pre><pre>  gst-libs/gst/adaptivedemux/gstadaptivedemux.h |  14 ++</pre><pre>- 8 files changed, 606 insertions(+), 12 deletions(-)</pre><pre>+ 8 files changed, 586 insertions(+), 16 deletions(-)</pre><pre>  create mode 100644 ext/smoothstreaming/gstmssfragmentparser.c</pre><pre>  create mode 100644 ext/smoothstreaming/gstmssfragmentparser.h</pre><pre> </pre><pre> diff --git a/ext/smoothstreaming/Makefile.am b/ext/smoothstreaming/Makefile.am</pre><pre>-index 4faf9df9f..a5e1ad6ae 100644</pre><pre>+index 4faf9df..a5e1ad6 100644</pre><pre> --- a/ext/smoothstreaming/Makefile.am</pre><pre> +++ b/ext/smoothstreaming/Makefile.am</pre><pre> @@ -13,8 +13,10 @@ libgstsmoothstreaming_la_LIBADD = \</pre><pre>@@ -43,10 +40,10 @@ index 4faf9df9f..a5e1ad6ae 100644</pre><pre> +       gstmssfragmentparser.h \</pre><pre>  Â Â Â Â Â Â  gstmssmanifest.h</pre><pre> diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c</pre><pre>-index 12fb40497..120d9c22b 100644</pre><pre>+index 9d0aece..70b541e 100644</pre><pre> --- a/ext/smoothstreaming/gstmssdemux.c</pre><pre> +++ b/ext/smoothstreaming/gstmssdemux.c</pre><pre>-@@ -135,11 +135,18 @@ gst_mss_demux_stream_update_fragment_info (GstAdaptiveDemuxStream * stream);</pre><pre>+@@ -135,9 +135,16 @@ gst_mss_demux_stream_update_fragment_info (GstAdaptiveDemuxStream * stream);</pre><pre>  static gboolean gst_mss_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);</pre><pre>  static gint64</pre><pre>  gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);</pre><pre>@@ -56,16 +53,14 @@ index 12fb40497..120d9c22b 100644</pre><pre>  static GstFlowReturn</pre><pre>  gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,</pre><pre>      GstBuffer * buffer);</pre><pre>- static gboolean gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux,</pre><pre>-     gint64 * start, gint64 * stop);</pre><pre> +static GstFlowReturn gst_mss_demux_data_received (GstAdaptiveDemux * demux,</pre><pre>-+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer);</pre><pre>++    GstAdaptiveDemuxStream * stream);</pre><pre> +static gboolean</pre><pre> +gst_mss_demux_requires_periodical_playlist_update (GstAdaptiveDemux * demux);</pre><pre>  </pre><pre>  static void</pre><pre>  gst_mss_demux_class_init (GstMssDemuxClass * klass)</pre><pre>-@@ -192,10 +199,15 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)</pre><pre>+@@ -190,8 +197,13 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)</pre><pre>        gst_mss_demux_stream_select_bitrate;</pre><pre>    gstadaptivedemux_class-&gt;stream_update_fragment_info =</pre><pre>        gst_mss_demux_stream_update_fragment_info;</pre><pre>@@ -73,36 +68,39 @@ index 12fb40497..120d9c22b 100644</pre><pre> +      gst_mss_demux_stream_get_fragment_waiting_time;</pre><pre>    gstadaptivedemux_class-&gt;update_manifest_data =</pre><pre>        gst_mss_demux_update_manifest_data;</pre><pre>-   gstadaptivedemux_class-&gt;get_live_seek_range =</pre><pre>-       gst_mss_demux_get_live_seek_range;</pre><pre> +  gstadaptivedemux_class-&gt;data_received = gst_mss_demux_data_received;</pre><pre> +  gstadaptivedemux_class-&gt;requires_periodical_playlist_update =</pre><pre> +      gst_mss_demux_requires_periodical_playlist_update;</pre><pre>  </pre><pre>    GST_DEBUG_CATEGORY_INIT (mssdemux_debug, &quot;mssdemux&quot;, 0, &quot;mssdemux plugin&quot;);</pre><pre>  }</pre><pre>-@@ -650,6 +662,13 @@ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)</pre><pre>+@@ -648,6 +660,17 @@ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)</pre><pre>    return interval;</pre><pre>  }</pre><pre>  </pre><pre> +static gint64</pre><pre> +gst_mss_demux_stream_get_fragment_waiting_time (GstAdaptiveDemuxStream * stream)</pre><pre> +{</pre><pre>-+  /* Wait a second for live streams so we don't try premature fragments downloading */</pre><pre>-+  return GST_SECOND;</pre><pre>++  GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;</pre><pre>++  GstMssStreamType streamtype =</pre><pre>++      gst_mss_stream_get_type (mssstream-&gt;manifest_stream);</pre><pre>++</pre><pre>++  /* Wait a second for live audio streams so we don't try premature fragments downloading */</pre><pre>++  return streamtype == MSS_STREAM_TYPE_AUDIO ? GST_SECOND : 0;</pre><pre> +}</pre><pre> +</pre><pre>  static GstFlowReturn</pre><pre>  gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,</pre><pre>  Â Â Â Â GstBuffer * buffer)</pre><pre>-@@ -670,3 +689,44 @@ gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,</pre><pre>- </pre><pre>-   return gst_mss_manifest_get_live_seek_range (mssdemux-&gt;manifest, start, stop);</pre><pre>+@@ -659,3 +682,41 @@ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,</pre><pre>+   gst_mss_manifest_reload_fragments (mssdemux-&gt;manifest, buffer);</pre><pre>+   return GST_FLOW_OK;</pre><pre>  }</pre><pre> +</pre><pre>++</pre><pre> +static GstFlowReturn</pre><pre> +gst_mss_demux_data_received (GstAdaptiveDemux * demux,</pre><pre>-+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer)</pre><pre>++    GstAdaptiveDemuxStream * stream)</pre><pre> +{</pre><pre> +  GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);</pre><pre> +  GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;</pre><pre>@@ -110,27 +108,23 @@ index 12fb40497..120d9c22b 100644</pre><pre> +</pre><pre> +  if (!gst_mss_manifest_is_live (mssdemux-&gt;manifest)) {</pre><pre> +    return GST_ADAPTIVE_DEMUX_CLASS (parent_class)-&gt;data_received (demux,</pre><pre>-+        stream, buffer);</pre><pre>++        stream);</pre><pre> +  }</pre><pre> +</pre><pre> +  if (gst_mss_stream_fragment_parsing_needed (mssstream-&gt;manifest_stream)) {</pre><pre>-+    gst_mss_manifest_live_adapter_push (mssstream-&gt;manifest_stream, buffer);</pre><pre>-+    available =</pre><pre>-+        gst_mss_manifest_live_adapter_available (mssstream-&gt;manifest_stream);</pre><pre>++    available = gst_adapter_available (stream-&gt;adapter);</pre><pre> +    // FIXME: try to reduce this minimal size.</pre><pre> +    if (available &lt; 4096) {</pre><pre> +      return GST_FLOW_OK;</pre><pre> +    } else {</pre><pre>++      GstBuffer *buffer = gst_adapter_get_buffer (stream-&gt;adapter, available);</pre><pre> +      GST_LOG_OBJECT (stream-&gt;pad, &quot;enough data, parsing fragment.&quot;);</pre><pre>-+      buffer =</pre><pre>-+          gst_mss_manifest_live_adapter_take_buffer (mssstream-&gt;manifest_stream,</pre><pre>-+          available);</pre><pre>-+      gst_mss_stream_parse_fragment (mssstream-&gt;manifest_stream, buffer);</pre><pre>++      gst_mss_stream_fragment_parse (mssstream-&gt;manifest_stream, buffer);</pre><pre>++      gst_buffer_unref (buffer);</pre><pre> +    }</pre><pre> +  }</pre><pre> +</pre><pre>-+  return GST_ADAPTIVE_DEMUX_CLASS (parent_class)-&gt;data_received (demux, stream,</pre><pre>-+      buffer);</pre><pre>++  return GST_ADAPTIVE_DEMUX_CLASS (parent_class)-&gt;data_received (demux, stream);</pre><pre> +}</pre><pre> +</pre><pre> +static gboolean</pre><pre>@@ -142,17 +136,17 @@ index 12fb40497..120d9c22b 100644</pre><pre> +}</pre><pre> diff --git a/ext/smoothstreaming/gstmssfragmentparser.c b/ext/smoothstreaming/gstmssfragmentparser.c</pre><pre> new file mode 100644</pre><pre>-index 000000000..b554d4f31</pre><pre>+index 0000000..01c3b15</pre><pre> --- /dev/null</pre><pre> +++ b/ext/smoothstreaming/gstmssfragmentparser.c</pre><pre>-@@ -0,0 +1,266 @@</pre><pre>+@@ -0,0 +1,255 @@</pre><pre> +/*</pre><pre> + * Microsoft Smooth-Streaming fragment parsing library</pre><pre> + *</pre><pre> + * gstmssfragmentparser.h</pre><pre> + *</pre><pre>-+ * Copyright (C) 2016 Igalia S.L</pre><pre>-+ * Copyright (C) 2016 Metrological</pre><pre>++ * Copyright (C) 2015 Igalia S.L</pre><pre>++ * Copyright (C) 2015 Metrological</pre><pre> + *   Author: Philippe Normand <a href="mailto:philn@igalia.com">&lt;philn@igalia.com&gt;</a></pre><pre> + *</pre><pre> + * This library is free software; you can redistribute it and/or</pre><pre>@@ -333,12 +327,8 @@ index 000000000..b554d4f31</pre><pre> +          size = gst_byte_reader_get_uint32_be_unchecked (&amp;reader);</pre><pre> +          fourcc = gst_byte_reader_get_uint32_le_unchecked (&amp;reader);</pre><pre> +          if (fourcc == GST_MSS_FRAGMENT_FOURCC_TRUN) {</pre><pre>-+            GST_TRACE (&quot;trun box found, size: %&quot; G_GUINT32_FORMAT, size);</pre><pre>-+            if (!gst_byte_reader_skip (&amp;reader, size - 8)) {</pre><pre>-+              GST_WARNING (&quot;Failed to skip trun box, enough data?&quot;);</pre><pre>-+              error = TRUE;</pre><pre>-+              goto beach;</pre><pre>-+            }</pre><pre>++            gst_byte_reader_skip_unchecked (&amp;reader, size - 8);</pre><pre>++            GST_TRACE (&quot;trun box found, size: %u&quot;, size);</pre><pre> +          }</pre><pre> +        }</pre><pre> +      }</pre><pre>@@ -354,11 +344,7 @@ index 000000000..b554d4f31</pre><pre> +  Â Â }</pre><pre> +</pre><pre> +    GST_TRACE (&quot;box size: %&quot; G_GUINT32_FORMAT, size);</pre><pre>-+    if (!gst_byte_reader_get_uint32_le (&amp;reader, &amp;fourcc)) {</pre><pre>-+      GST_WARNING (&quot;Failed to get fourcc, enough data?&quot;);</pre><pre>-+      error = TRUE;</pre><pre>-+      break;</pre><pre>-+    }</pre><pre>++    fourcc = gst_byte_reader_get_uint32_le_unchecked (&amp;reader);</pre><pre> +</pre><pre> +    if (fourcc == GST_MSS_FRAGMENT_FOURCC_MDAT) {</pre><pre> +      GST_LOG (&quot;mdat box found<a href="mailto:);@@-367,8+353,7@@index000000000..b554d4f31+%7d++if(fourcc!=GST_MSS_FRAGMENT_FOURCC_UUID)%7b-+GST_ERROR(">&quot;);<o:p></o:p></a></pre><pre><span class=MsoHyperlink><a href="mailto:);@@-367,8+353,7@@index000000000..b554d4f31+%7d++if(fourcc!=GST_MSS_FRAGMENT_FOURCC_UUID)%7b-+GST_ERROR(">@@ -367,8 +353,7 @@ index 000000000..b554d4f31<o:p></o:p></a></span></pre><pre><span class=MsoHyperlink><a href="mailto:);@@-367,8+353,7@@index000000000..b554d4f31+%7d++if(fourcc!=GST_MSS_FRAGMENT_FOURCC_UUID)%7b-+GST_ERROR("> +    }<o:p></o:p></a></span></pre><pre><span class=MsoHyperlink><a href="mailto:);@@-367,8+353,7@@index000000000..b554d4f31+%7d++if(fourcc!=GST_MSS_FRAGMENT_FOURCC_UUID)%7b-+GST_ERROR("> +<o:p></o:p></a></span></pre><pre><span class=MsoHyperlink><a href="mailto:);@@-367,8+353,7@@index000000000..b554d4f31+%7d++if(fourcc!=GST_MSS_FRAGMENT_FOURCC_UUID)%7b-+GST_ERROR("> +    if (fourcc != GST_MSS_FRAGMENT_FOURCC_UUID) {<o:p></o:p></a></span></pre><pre><span class=MsoHyperlink><a href="mailto:);@@-367,8+353,7@@index000000000..b554d4f31+%7d++if(fourcc!=GST_MSS_FRAGMENT_FOURCC_UUID)%7b-+GST_ERROR(">-+      GST_ERROR (&quot;</a></span>invalid UUID fourcc: %&quot; GST_FOURCC_FORMAT,</pre><pre>-+          GST_FOURCC_ARGS (fourcc));</pre><pre>++      GST_ERROR (&quot;invalid UUID fourcc&quot;);</pre><pre> +      error = TRUE;</pre><pre> +      break;</pre><pre> +    }</pre><pre>@@ -403,8 +388,6 @@ index 000000000..b554d4f31</pre><pre> +    }</pre><pre> +  }</pre><pre> +</pre><pre>-+beach:</pre><pre>-+</pre><pre> +  if (!error)</pre><pre> +    parser-&gt;status = GST_MSS_FRAGMENT_HEADER_PARSER_FINISHED;</pre><pre> +</pre><pre>@@ -414,7 +397,7 @@ index 000000000..b554d4f31</pre><pre> +}</pre><pre> diff --git a/ext/smoothstreaming/gstmssfragmentparser.h b/ext/smoothstreaming/gstmssfragmentparser.h</pre><pre> new file mode 100644</pre><pre>-index 000000000..cf4711865</pre><pre>+index 0000000..6626358</pre><pre> --- /dev/null</pre><pre> +++ b/ext/smoothstreaming/gstmssfragmentparser.h</pre><pre> @@ -0,0 +1,84 @@</pre><pre>@@ -423,8 +406,8 @@ index 000000000..cf4711865</pre><pre> + *</pre><pre> + * gstmssfragmentparser.h</pre><pre> + *</pre><pre>-+ * Copyright (C) 2016 Igalia S.L</pre><pre>-+ * Copyright (C) 2016 Metrological</pre><pre>++ * Copyright (C) 2015 Igalia S.L</pre><pre>++ * Copyright (C) 2015 Metrological</pre><pre> + *   Author: Philippe Normand <a href="mailto:philn@igalia.com">&lt;philn@igalia.com&gt;</a></pre><pre> + *</pre><pre> + * This library is free software; you can redistribute it and/or</pre><pre>@@ -503,14 +486,14 @@ index 000000000..cf4711865</pre><pre> +</pre><pre> +#endif /* __GST_MSS_FRAGMENT_PARSER_H__ */</pre><pre> diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c</pre><pre>-index 144bbb42d..e1031ba55 100644</pre><pre>+index 1b72e8d..d50a51a 100644</pre><pre> --- a/ext/smoothstreaming/gstmssmanifest.c</pre><pre> +++ b/ext/smoothstreaming/gstmssmanifest.c</pre><pre> @@ -1,5 +1,7 @@</pre><pre>  /* GStreamer</pre><pre>   * Copyright (C) 2012 Smart TV Alliance</pre><pre>-+ * Copyright (C) 2016 Igalia S.L</pre><pre>-+ * Copyright (C) 2016 Metrological</pre><pre>++ * Copyright (C) 2015 Igalia S.L</pre><pre>++ * Copyright (C) 2015 Metrological</pre><pre>   *  Author: Thiago Sousa Santos <a href="mailto:thiago.sousa.santos@collabora.com">&lt;thiago.sousa.santos@collabora.com&gt;</a>, Collabora Ltd.</pre><pre>   *</pre><pre>   * gstmssmanifest.c:</pre><pre>@@ -522,12 +505,12 @@ index 144bbb42d..e1031ba55 100644</pre><pre>  </pre><pre>  GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);</pre><pre>  #define GST_CAT_DEFAULT mssdemux_debug</pre><pre>-@@ -74,12 +77,17 @@ struct _GstMssStream</pre><pre>+@@ -73,12 +76,17 @@ struct _GstMssStream</pre><pre>    gboolean active;              /* if the stream is currently being used */</pre><pre>    gint selectedQualityIndex;</pre><pre>  </pre><pre> +  gboolean has_live_fragments;</pre><pre>-+  GstAdapter *live_adapter;</pre><pre>++  GQueue live_fragments;</pre><pre> +</pre><pre>    GList *fragments;</pre><pre>    GList *qualities;</pre><pre>@@ -540,15 +523,15 @@ index 144bbb42d..e1031ba55 100644</pre><pre>    guint fragment_repetition_index;</pre><pre>    GList *current_fragment;</pre><pre>    GList *current_quality;</pre><pre>-@@ -96,6 +104,7 @@ struct _GstMssManifest</pre><pre>+@@ -94,6 +102,7 @@ struct _GstMssManifest</pre><pre>+   xmlNodePtr xmlrootnode;</pre><pre>  </pre><pre>    gboolean is_live;</pre><pre>-   gint64 dvr_window;</pre><pre> +  guint64 look_ahead_fragment_count;</pre><pre>  </pre><pre>    GString *protection_system_id;</pre><pre>    gchar *protection_data;</pre><pre>-@@ -235,7 +244,8 @@ compare_bitrate (GstMssStreamQuality * a, GstMssStreamQuality * b)</pre><pre>+@@ -233,7 +242,8 @@ compare_bitrate (GstMssStreamQuality * a, GstMssStreamQuality * b)</pre><pre>  }</pre><pre>  </pre><pre>  static void</pre><pre>@@ -558,7 +541,7 @@ index 144bbb42d..e1031ba55 100644</pre><pre>  {</pre><pre>    xmlNodePtr iter;</pre><pre>    GstMssFragmentListBuilder builder;</pre><pre>-@@ -248,9 +258,21 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)</pre><pre>+@@ -246,9 +256,18 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)</pre><pre>    stream-&gt;url = (gchar *) xmlGetProp (node, (xmlChar *) MSS_PROP_URL);</pre><pre>    stream-&gt;lang = (gchar *) xmlGetProp (node, (xmlChar *) MSS_PROP_LANGUAGE);</pre><pre>  </pre><pre>@@ -567,9 +550,6 @@ index 144bbb42d..e1031ba55 100644</pre><pre> +   * playlist can be built incrementally from the first fragment</pre><pre> +   * of the manifest.</pre><pre> +   */</pre><pre>-+</pre><pre>-+  GST_DEBUG (&quot;Live stream: %s, look-ahead fragments: %&quot; G_GUINT64_FORMAT,</pre><pre>-+      manifest-&gt;is_live ? &quot;yes&quot; : &quot;no&quot;, manifest-&gt;look_ahead_fragment_count);</pre><pre> +  stream-&gt;has_live_fragments = manifest-&gt;is_live</pre><pre> +    Â Â &amp;&amp; manifest-&gt;look_ahead_fragment_count;</pre><pre> +</pre><pre>@@ -581,13 +561,15 @@ index 144bbb42d..e1031ba55 100644</pre><pre>      } else if (node_has_type (iter, MSS_NODE_STREAM_QUALITY)) {</pre><pre>        GstMssStreamQuality *quality = gst_mss_stream_quality_new (iter);</pre><pre>        stream-&gt;qualities = g_list_prepend (stream-&gt;qualities, quality);</pre><pre>-@@ -259,17 +281,24 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)</pre><pre>+@@ -257,17 +276,26 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)</pre><pre>      }</pre><pre>    }</pre><pre>  </pre><pre> -  stream-&gt;fragments = g_list_reverse (builder.fragments);</pre><pre> +  if (stream-&gt;has_live_fragments) {</pre><pre>-+    stream-&gt;live_adapter = gst_adapter_new ();</pre><pre>++    g_queue_init (&amp;stream-&gt;live_fragments);</pre><pre>++    g_queue_push_tail (&amp;stream-&gt;live_fragments, builder.fragments-&gt;data);</pre><pre>++    stream-&gt;current_fragment = g_queue_peek_head_link (&amp;stream-&gt;live_fragments);</pre><pre> +  }</pre><pre> +</pre><pre> +  if (builder.fragments) {</pre><pre>@@ -609,7 +591,7 @@ index 144bbb42d..e1031ba55 100644</pre><pre>  }</pre><pre>  </pre><pre>  </pre><pre>-@@ -315,6 +344,7 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>+@@ -313,6 +341,7 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>    xmlNodePtr nodeiter;</pre><pre>    gchar *live_str;</pre><pre>    GstMapInfo mapinfo;</pre><pre>@@ -617,33 +599,21 @@ index 144bbb42d..e1031ba55 100644</pre><pre>  </pre><pre>    if (!gst_buffer_map (data, &amp;mapinfo, GST_MAP_READ)) {</pre><pre>      return NULL;</pre><pre>-@@ -335,6 +365,7 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>-   /* the entire file is always available for non-live streams */</pre><pre>-   if (!manifest-&gt;is_live) {</pre><pre>-     manifest-&gt;dvr_window = 0;</pre><pre>-+    manifest-&gt;look_ahead_fragment_count = 0;</pre><pre>-   } else {</pre><pre>-     /* if 0, or non-existent, the length is infinite */</pre><pre>-     gchar *dvr_window_str = (gchar *) xmlGetProp (root,</pre><pre>-@@ -346,6 +377,17 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>-         manifest-&gt;dvr_window = 0;</pre><pre>-       }</pre><pre>-     }</pre><pre>-+</pre><pre>-+    look_ahead_fragment_count_str =</pre><pre>-+        (gchar *) xmlGetProp (root, (xmlChar *) &quot;LookAheadFragmentCount&quot;);</pre><pre>-+    if (look_ahead_fragment_count_str) {</pre><pre>-+      manifest-&gt;look_ahead_fragment_count =</pre><pre>-+          g_ascii_strtoull (look_ahead_fragment_count_str, NULL, 10);</pre><pre>-+      xmlFree (look_ahead_fragment_count_str);</pre><pre>-+      if (manifest-&gt;look_ahead_fragment_count &lt;= 0) {</pre><pre>-+        manifest-&gt;look_ahead_fragment_count = 0;</pre><pre>-+      }</pre><pre>-+    }</pre><pre>+@@ -330,13 +359,21 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>+    Â xmlFree (live_str);</pre><pre>    }</pre><pre>  </pre><pre>++  look_ahead_fragment_count_str =</pre><pre>++      (gchar *) xmlGetProp (root, (xmlChar *) &quot;LookAheadFragmentCount&quot;);</pre><pre>++  if (look_ahead_fragment_count_str) {</pre><pre>++    manifest-&gt;look_ahead_fragment_count =</pre><pre>++        g_ascii_strtoull (look_ahead_fragment_count_str, NULL, 10);</pre><pre>++    xmlFree (look_ahead_fragment_count_str);</pre><pre>++  }</pre><pre>++</pre><pre>    for (nodeiter = root-&gt;children; nodeiter; nodeiter = nodeiter-&gt;next) {</pre><pre>-@@ -354,7 +396,7 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>+     if (nodeiter-&gt;type == XML_ELEMENT_NODE</pre><pre>+         &amp;&amp; (strcmp ((const char *) nodeiter-&gt;name, &quot;StreamIndex&quot;) == 0)) {</pre><pre>        GstMssStream *stream = g_new0 (GstMssStream, 1);</pre><pre>  </pre><pre>        manifest-&gt;streams = g_slist_append (manifest-&gt;streams, stream);</pre><pre>@@ -652,39 +622,56 @@ index 144bbb42d..e1031ba55 100644</pre><pre>      }</pre><pre>  </pre><pre>      if (nodeiter-&gt;type == XML_ELEMENT_NODE</pre><pre>-@@ -371,6 +413,11 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>+@@ -353,13 +390,19 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>  static void</pre><pre>  gst_mss_stream_free (GstMssStream * stream)</pre><pre>  {</pre><pre>-+  if (stream-&gt;live_adapter) {</pre><pre>-+    gst_adapter_clear (stream-&gt;live_adapter);</pre><pre>-+    g_object_unref (stream-&gt;live_adapter);</pre><pre>+-  g_list_free_full (stream-&gt;fragments, g_free);</pre><pre>++  if (stream-&gt;has_live_fragments) {</pre><pre>++    g_queue_foreach (&amp;stream-&gt;live_fragments, (GFunc) g_free, NULL);</pre><pre>++    g_queue_clear (&amp;stream-&gt;live_fragments);</pre><pre>++  } else {</pre><pre>++    g_list_free_full (stream-&gt;fragments, g_free);</pre><pre> +  }</pre><pre>-+</pre><pre>-   g_list_free_full (stream-&gt;fragments, g_free);</pre><pre>    g_list_free_full (stream-&gt;qualities,</pre><pre>        (GDestroyNotify) gst_mss_stream_quality_free);</pre><pre>-@@ -379,6 +426,7 @@ gst_mss_stream_free (GstMssStream * stream)</pre><pre>+   xmlFree (stream-&gt;url);</pre><pre>+   xmlFree (stream-&gt;lang);</pre><pre>    g_regex_unref (stream-&gt;regex_position);</pre><pre>    g_regex_unref (stream-&gt;regex_bitrate);</pre><pre>-   g_free (stream);</pre><pre> +  gst_mss_fragment_parser_clear (&amp;stream-&gt;fragment_parser);</pre><pre>+   g_free (stream);</pre><pre>  }</pre><pre>  </pre><pre>- void</pre><pre>-@@ -1079,6 +1127,9 @@ GstFlowReturn</pre><pre>+@@ -984,7 +1027,12 @@ gst_mss_stream_get_fragment_gst_timestamp (GstMssStream * stream)</pre><pre>+   g_return_val_if_fail (stream-&gt;active, GST_CLOCK_TIME_NONE);</pre><pre>+ </pre><pre>+   if (!stream-&gt;current_fragment) {</pre><pre>+-    GList *last = g_list_last (stream-&gt;fragments);</pre><pre>++    GList *last;</pre><pre>++</pre><pre>++    if (stream-&gt;has_live_fragments)</pre><pre>++      last = g_queue_peek_tail_link (&amp;stream-&gt;live_fragments);</pre><pre>++    else</pre><pre>++      last = g_list_last (stream-&gt;fragments);</pre><pre>+     if (last == NULL)</pre><pre>+       return GST_CLOCK_TIME_NONE;</pre><pre>+ </pre><pre>+@@ -1037,21 +1085,54 @@ GstFlowReturn</pre><pre>  gst_mss_stream_advance_fragment (GstMssStream * stream)</pre><pre>  {</pre><pre>    GstMssStreamFragment *fragment;</pre><pre>++  GstMssStreamFragment *prev_fragment;</pre><pre> +  const gchar *stream_type_name =</pre><pre> +      gst_mss_stream_type_name (gst_mss_stream_get_type (stream));</pre><pre> +</pre><pre>    g_return_val_if_fail (stream-&gt;active, GST_FLOW_ERROR);</pre><pre>  </pre><pre>    if (stream-&gt;current_fragment == NULL)</pre><pre>-@@ -1086,14 +1137,20 @@ gst_mss_stream_advance_fragment (GstMssStream * stream)</pre><pre>+     return GST_FLOW_EOS;</pre><pre>  </pre><pre>-   fragment = stream-&gt;current_fragment-&gt;data;</pre><pre>+-  fragment = stream-&gt;current_fragment-&gt;data;</pre><pre>++  prev_fragment = fragment = stream-&gt;current_fragment-&gt;data;</pre><pre>    stream-&gt;fragment_repetition_index++;</pre><pre> -  if (stream-&gt;fragment_repetition_index &lt; fragment-&gt;repetitions) {</pre><pre> -    return GST_FLOW_OK;</pre><pre>@@ -693,10 +680,34 @@ index 144bbb42d..e1031ba55 100644</pre><pre> +    goto beach;</pre><pre>  </pre><pre>    stream-&gt;fragment_repetition_index = 0;</pre><pre>-   stream-&gt;current_fragment = g_list_next (stream-&gt;current_fragment);</pre><pre>+-  stream-&gt;current_fragment = g_list_next (stream-&gt;current_fragment);</pre><pre>++</pre><pre>++  if (stream-&gt;has_live_fragments)</pre><pre>++    stream-&gt;current_fragment = g_queue_pop_head_link (&amp;stream-&gt;live_fragments);</pre><pre>++  else</pre><pre>++    stream-&gt;current_fragment = g_list_next (stream-&gt;current_fragment);</pre><pre>++</pre><pre>++  if (stream-&gt;current_fragment != NULL) {</pre><pre>++    fragment = stream-&gt;current_fragment-&gt;data;</pre><pre>++    if (fragment-&gt;time &lt;= prev_fragment-&gt;time) {</pre><pre>++      while (fragment-&gt;time &lt;= prev_fragment-&gt;time) {</pre><pre>++        if (stream-&gt;has_live_fragments)</pre><pre>++          stream-&gt;current_fragment =</pre><pre>++   Â Â Â Â Â Â Â Â Â Â Â g_queue_pop_head_link (&amp;stream-&gt;live_fragments);</pre><pre>++        else</pre><pre>++          stream-&gt;current_fragment = g_list_next (stream-&gt;current_fragment);</pre><pre>++        if (stream-&gt;current_fragment == NULL)</pre><pre>++          break;</pre><pre>++        fragment = stream-&gt;current_fragment-&gt;data;</pre><pre>++      }</pre><pre>++    }</pre><pre>++  }</pre><pre> +</pre><pre> +  GST_DEBUG (&quot;Advanced to fragment #%d on %s stream&quot;, fragment-&gt;number,</pre><pre> +      stream_type_name);</pre><pre>++  if (stream-&gt;has_live_fragments)</pre><pre>++    GST_LOG (&quot;%u fragments left in the %s stream queue&quot;,</pre><pre>++        g_queue_get_length (&amp;stream-&gt;live_fragments), stream_type_name);</pre><pre>    if (stream-&gt;current_fragment == NULL)</pre><pre>      return GST_FLOW_EOS;</pre><pre> +</pre><pre>@@ -706,57 +717,22 @@ index 144bbb42d..e1031ba55 100644</pre><pre>    return GST_FLOW_OK;</pre><pre>  }</pre><pre>  </pre><pre>-@@ -1173,6 +1230,11 @@ gst_mss_stream_seek (GstMssStream * stream, gboolean forward,</pre><pre>-   GST_DEBUG (&quot;Stream %s seeking to %&quot; G_GUINT64_FORMAT, stream-&gt;url, time);</pre><pre>-   for (iter = stream-&gt;fragments; iter; iter = g_list_next (iter)) {</pre><pre>-     fragment = iter-&gt;data;</pre><pre>-+    if (stream-&gt;has_live_fragments) {</pre><pre>-+      if (fragment-&gt;time + fragment-&gt;repetitions * fragment-&gt;duration &gt; time)</pre><pre>-+        stream-&gt;current_fragment = iter;</pre><pre>-+      break;</pre><pre>-+    }</pre><pre>-     if (fragment-&gt;time + fragment-&gt;repetitions * fragment-&gt;duration &gt; time) {</pre><pre>-       stream-&gt;current_fragment = iter;</pre><pre>-       stream-&gt;fragment_repetition_index =</pre><pre>-@@ -1256,9 +1318,14 @@ static void</pre><pre>- gst_mss_stream_reload_fragments (GstMssStream * stream, xmlNodePtr streamIndex)</pre><pre>- {</pre><pre>-   xmlNodePtr iter;</pre><pre>--  guint64 current_gst_time = gst_mss_stream_get_fragment_gst_timestamp (stream);</pre><pre>-+  guint64 current_gst_time;</pre><pre>-   GstMssFragmentListBuilder builder;</pre><pre>+@@ -1125,6 +1206,10 @@ gst_mss_stream_seek (GstMssStream * stream, gboolean forward,</pre><pre>+   guint64 timescale;</pre><pre>+   GstMssStreamFragment *fragment = NULL;</pre><pre>  </pre><pre>++  // FIXME: Seek support for live scenario using DVR window.</pre><pre> +  if (stream-&gt;has_live_fragments)</pre><pre> +    return;</pre><pre> +</pre><pre>-+  current_gst_time = gst_mss_stream_get_fragment_gst_timestamp (stream);</pre><pre>-+</pre><pre>-   gst_mss_fragment_list_builder_init (&amp;builder);</pre><pre>+   timescale = gst_mss_stream_get_timescale (stream);</pre><pre>+   time = gst_util_uint64_scale_round (time, timescale, GST_SECOND);</pre><pre>  </pre><pre>-   GST_DEBUG (&quot;Current position: %&quot; GST_TIME_FORMAT,</pre><pre>-@@ -1514,3 +1581,74 @@ gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start,</pre><pre>- </pre><pre>-   return ret;</pre><pre>+@@ -1406,3 +1491,47 @@ gst_mss_stream_get_lang (GstMssStream * stream)</pre><pre>+ {</pre><pre>+   return stream-&gt;lang;</pre><pre>  }</pre><pre> +</pre><pre>-+void</pre><pre>-+gst_mss_manifest_live_adapter_push (GstMssStream * stream, GstBuffer * buffer)</pre><pre>-+{</pre><pre>-+  gst_adapter_push (stream-&gt;live_adapter, buffer);</pre><pre>-+}</pre><pre>-+</pre><pre>-+gsize</pre><pre>-+gst_mss_manifest_live_adapter_available (GstMssStream * stream)</pre><pre>-+{</pre><pre>-+  return gst_adapter_available (stream-&gt;live_adapter);</pre><pre>-+}</pre><pre>-+</pre><pre>-+GstBuffer *</pre><pre>-+gst_mss_manifest_live_adapter_take_buffer (GstMssStream * stream, gsize nbytes)</pre><pre>-+{</pre><pre>-+  return gst_adapter_take_buffer (stream-&gt;live_adapter, nbytes);</pre><pre>-+}</pre><pre>-+</pre><pre> +gboolean</pre><pre> +gst_mss_stream_fragment_parsing_needed (GstMssStream * stream)</pre><pre> +{</pre><pre>@@ -764,11 +740,11 @@ index 144bbb42d..e1031ba55 100644</pre><pre> +}</pre><pre> +</pre><pre> +void</pre><pre>-+gst_mss_stream_parse_fragment (GstMssStream * stream, GstBuffer * buffer)</pre><pre>++gst_mss_stream_fragment_parse (GstMssStream * stream, GstBuffer * buffer)</pre><pre> +{</pre><pre> +  GstMssStreamFragment *current_fragment = NULL;</pre><pre>-+  const gchar *stream_type_name;</pre><pre>-+  guint8 index;</pre><pre>++  const gchar *stream_type_name =</pre><pre>++      gst_mss_stream_type_name (gst_mss_stream_get_type (stream));</pre><pre> +</pre><pre> +  if (!stream-&gt;has_live_fragments)</pre><pre> +    return;</pre><pre>@@ -780,29 +756,20 @@ index 144bbb42d..e1031ba55 100644</pre><pre> +  current_fragment-&gt;time = stream-&gt;fragment_parser.tfxd.time;</pre><pre> +  current_fragment-&gt;duration = stream-&gt;fragment_parser.tfxd.duration;</pre><pre> +</pre><pre>-+  stream_type_name =</pre><pre>-+      gst_mss_stream_type_name (gst_mss_stream_get_type (stream));</pre><pre>-+</pre><pre>-+  for (index = 0; index &lt; stream-&gt;fragment_parser.tfrf.entries_count; index++) {</pre><pre>-+    GList *l = g_list_last (stream-&gt;fragments);</pre><pre>-+    GstMssStreamFragment *last;</pre><pre>++  for (guint8 index = 0; index &lt; stream-&gt;fragment_parser.tfrf.entries_count;</pre><pre>++      index++) {</pre><pre>++    GstMssStreamFragment *last = g_queue_peek_tail (&amp;stream-&gt;live_fragments);</pre><pre> +    GstMssStreamFragment *fragment;</pre><pre> +</pre><pre>-+    if (l == NULL)</pre><pre>-+      break;</pre><pre>-+</pre><pre>-+    last = (GstMssStreamFragment *) l-&gt;data;</pre><pre>-+</pre><pre>-+    if (last-&gt;time == stream-&gt;fragment_parser.tfrf.entries[index].time)</pre><pre>-+      continue;</pre><pre>-+</pre><pre>++    if (last == NULL)</pre><pre>++        break;</pre><pre> +    fragment = g_new (GstMssStreamFragment, 1);</pre><pre> +    fragment-&gt;number = last-&gt;number + 1;</pre><pre> +    fragment-&gt;repetitions = 1;</pre><pre> +    fragment-&gt;time = stream-&gt;fragment_parser.tfrf.entries[index].time;</pre><pre> + Â Â Â fragment-&gt;duration = stream-&gt;fragment_parser.tfrf.entries[index].duration;</pre><pre> +</pre><pre>-+    stream-&gt;fragments = g_list_append (stream-&gt;fragments, fragment);</pre><pre>++    g_queue_push_tail (&amp;stream-&gt;live_fragments, fragment);</pre><pre> +    GST_LOG (&quot;Adding fragment number: %u to %s stream, time: %&quot; G_GUINT64_FORMAT</pre><pre> +        &quot;, duration: %&quot; G_GUINT64_FORMAT &quot;, repetitions: %u&quot;,</pre><pre> +        fragment-&gt;number, stream_type_name,</pre><pre>@@ -810,31 +777,20 @@ index 144bbb42d..e1031ba55 100644</pre><pre> +  }</pre><pre> +}</pre><pre> diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h</pre><pre>-index 6b7b1f971..03b066ae5 100644</pre><pre>+index af7419c..039877f 100644</pre><pre> --- a/ext/smoothstreaming/gstmssmanifest.h</pre><pre> +++ b/ext/smoothstreaming/gstmssmanifest.h</pre><pre>-@@ -26,6 +26,7 @@</pre><pre>- #include &lt;glib.h&gt;</pre><pre>- #include &lt;gio/gio.h&gt;</pre><pre>- #include &lt;gst/gst.h&gt;</pre><pre>-+#include &lt;gst/base/gstadapter.h&gt;</pre><pre>- </pre><pre>- G_BEGIN_DECLS</pre><pre>- </pre><pre>-@@ -73,5 +74,11 @@ const gchar * gst_mss_stream_get_lang (GstMssStream * stream);</pre><pre>+@@ -72,5 +72,8 @@ const gchar * gst_mss_stream_get_lang (GstMssStream * stream);</pre><pre>  </pre><pre>  const gchar * gst_mss_stream_type_name (GstMssStreamType streamtype);</pre><pre>  </pre><pre>-+void gst_mss_manifest_live_adapter_push(GstMssStream * stream, GstBuffer * buffer);</pre><pre>-+gsize gst_mss_manifest_live_adapter_available(GstMssStream * stream);</pre><pre>-+GstBuffer * gst_mss_manifest_live_adapter_take_buffer(GstMssStream * stream, gsize nbytes);</pre><pre> +gboolean gst_mss_stream_fragment_parsing_needed(GstMssStream * stream);</pre><pre>-+void gst_mss_stream_parse_fragment(GstMssStream * stream, GstBuffer * buffer);</pre><pre>++void gst_mss_stream_fragment_parse(GstMssStream * stream, GstBuffer * buffer);</pre><pre> +</pre><pre>  G_END_DECLS</pre><pre>  #endif /* __GST_MSS_MANIFEST_H__ */</pre><pre> diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c</pre><pre>-index 634e4f388..ddca726b6 100644</pre><pre>+index bf311d3..20bd839 100644</pre><pre> --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c</pre><pre> +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c</pre><pre> @@ -291,6 +291,9 @@ gst_adaptive_demux_wait_until (GstClock * clock, GCond * cond, GMutex * mutex,</pre><pre>@@ -868,7 +824,7 @@ index 634e4f388..ddca726b6 100644</pre><pre>            }</pre><pre>          } else {</pre><pre>            /* no streams */</pre><pre>-@@ -2125,6 +2133,13 @@ gst_adaptive_demux_stream_data_received_default (GstAdaptiveDemux * demux,</pre><pre>+@@ -2113,6 +2121,13 @@ gst_adaptive_demux_stream_data_received_default (GstAdaptiveDemux * demux,</pre><pre>    return gst_adaptive_demux_stream_push_buffer (stream, buffer);</pre><pre>  }</pre><pre>  </pre><pre>@@ -882,25 +838,33 @@ index 634e4f388..ddca726b6 100644</pre><pre>  static GstFlowReturn</pre><pre>  _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)</pre><pre>  {</pre><pre>-@@ -3338,7 +3353,15 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)</pre><pre>+@@ -2209,7 +2224,7 @@ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)</pre><pre>+       stream-&gt;download_chunk_start_time;</pre><pre>+   stream-&gt;download_total_bytes += gst_buffer_get_size (buffer);</pre><pre>+ </pre><pre>+-  GST_DEBUG_OBJECT (stream-&gt;pad, &quot;Received buffer of size %&quot; G_GSIZE_FORMAT,</pre><pre>++  GST_LOG_OBJECT (stream-&gt;pad, &quot;Received buffer of size %&quot; G_GSIZE_FORMAT,</pre><pre>+       gst_buffer_get_size (buffer));</pre><pre>+ </pre><pre>+   ret = klass-&gt;data_received (demux, stream, buffer);</pre><pre>+@@ -3326,7 +3341,14 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)</pre><pre>        GST_DEBUG_OBJECT (stream-&gt;pad, &quot;EOS, checking to stop download loop&quot;);</pre><pre>        /* we push the EOS after releasing the object lock */</pre><pre>        if (gst_adaptive_demux_is_live (demux)) {</pre><pre> -        if (gst_adaptive_demux_stream_wait_manifest_update (demux, stream)) {</pre><pre> +        GstAdaptiveDemuxClass *demux_class =</pre><pre>-+            GST_ADAPTIVE_DEMUX_GET_CLASS (demux);</pre><pre>++          GST_ADAPTIVE_DEMUX_GET_CLASS (demux);</pre><pre> +</pre><pre> +        /* this might be a fragment download error, refresh the manifest, just in case */</pre><pre> +        if (!demux_class-&gt;requires_periodical_playlist_update (demux)) {</pre><pre> +          ret = gst_adaptive_demux_update_manifest (demux);</pre><pre> +          break;</pre><pre>-+        } else if (gst_adaptive_demux_stream_wait_manifest_update (demux,</pre><pre>-+                stream)) {</pre><pre>++        } else if (gst_adaptive_demux_stream_wait_manifest_update (demux, stream)) {</pre><pre>            goto end;</pre><pre>          }</pre><pre>          gst_task_stop (stream-&gt;download_task);</pre><pre> diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h</pre><pre>-index 780f4d93f..9a1a1b7d1 100644</pre><pre>+index 780f4d9..9a1a1b7 100644</pre><pre> --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h</pre><pre> +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h</pre><pre> @@ -459,6 +459,20 @@ struct _GstAdaptiveDemuxClass</pre><pre>@@ -925,5 +889,5 @@ index 780f4d93f..9a1a1b7d1 100644</pre><pre>  </pre><pre>  GType    gst_adaptive_demux_get_type (void);</pre><pre> -- </pre><pre>-2.11.0</pre><pre>+2.7.4</pre><pre> </pre><pre>diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch</pre><pre>index 76d29e151b..c4639a2cda 100644</pre><pre>--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch</pre><pre>+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch</pre><pre>@@ -1,7 +1,7 @@</pre><pre>-From e9178fa082116d4bf733b184a8b6951112c17900 Mon Sep 17 00:00:00 2001</pre><pre>+From e8155c77d8dcaf39ec564b85c4a56e64fce6de2b Mon Sep 17 00:00:00 2001</pre><pre> From: Matthew Waters <a href="mailto:matthew@centricular.com">&lt;matthew@centricular.com&gt;</a></pre><pre> Date: Thu, 10 Nov 2016 17:18:36 +1100</pre><pre>-Subject: [PATCH] smoothstreaming: implement adaptivedemux's</pre><pre>+Subject: [PATCH 1/2] smoothstreaming: implement adaptivedemux's</pre><pre>  get_live_seek_range()</pre><pre> </pre><pre> Allows seeking through the available fragments that are still available</pre><pre>@@ -10,40 +10,45 @@ manifest.</pre><pre> </pre><pre> <a href="https://bugzilla.gnome.org/show_bug.cgi?id=774178">https://bugzilla.gnome.org/show_bug.cgi?id=774178</a></pre><pre> ---</pre><pre>-Upstream-Status: Backport</pre><pre>-Signed-off-by: Khem Raj <a href="mailto:raj.khem@gmail.com">&lt;raj.khem@gmail.com&gt;</a></pre><pre>-</pre><pre>- ext/smoothstreaming/gstmssdemux.c    | 13 ++++++</pre><pre>+ ext/smoothstreaming/gstmssdemux.c    | 14 +++++-</pre><pre>  ext/smoothstreaming/gstmssmanifest.c | 84 ++++++++++++++++++++++++++++++++++++</pre><pre>  ext/smoothstreaming/gstmssmanifest.h |  1 +</pre><pre>- 3 files changed, 98 insertions(+)</pre><pre>+ 3 files changed, 98 insertions(+), 1 deletion(-)</pre><pre> </pre><pre> diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c</pre><pre>-index 9d0aece2b..b66e19514 100644</pre><pre>+index 1a122d4..26147fd 100644</pre><pre> --- a/ext/smoothstreaming/gstmssdemux.c</pre><pre> +++ b/ext/smoothstreaming/gstmssdemux.c</pre><pre>-@@ -138,6 +138,8 @@ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);</pre><pre>- static GstFlowReturn</pre><pre>- gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,</pre><pre>-     GstBuffer * buffer);</pre><pre>+@@ -146,6 +146,8 @@ static GstFlowReturn gst_mss_demux_data_received (GstAdaptiveDemux * demux,</pre><pre>+     GstAdaptiveDemuxStream * stream, GstBuffer * buffer);</pre><pre>+ static gboolean</pre><pre>+ gst_mss_demux_requires_periodical_playlist_update (GstAdaptiveDemux * demux);</pre><pre> +static gboolean gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux,</pre><pre> +    gint64 * start, gint64 * stop);</pre><pre>  </pre><pre>  static void</pre><pre>  gst_mss_demux_class_init (GstMssDemuxClass * klass)</pre><pre>-@@ -192,6 +194,8 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)</pre><pre>-       gst_mss_demux_stream_update_fragment_info;</pre><pre>-   gstadaptivedemux_class-&gt;update_manifest_data =</pre><pre>-       gst_mss_demux_update_manifest_data;</pre><pre>+@@ -206,6 +208,8 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)</pre><pre>+   gstadaptivedemux_class-&gt;data_received = gst_mss_demux_data_received;</pre><pre>+   gstadaptivedemux_class-&gt;requires_periodical_playlist_update =</pre><pre>+       gst_mss_demux_requires_periodical_playlist_update;</pre><pre> +  gstadaptivedemux_class-&gt;get_live_seek_range =</pre><pre> +      gst_mss_demux_get_live_seek_range;</pre><pre>  </pre><pre>    GST_DEBUG_CATEGORY_INIT (mssdemux_debug, &quot;mssdemux&quot;, 0, &quot;mssdemux plugin&quot;);</pre><pre>  }</pre><pre>-@@ -659,3 +663,12 @@ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,</pre><pre>-   gst_mss_manifest_reload_fragments (mssdemux-&gt;manifest, buffer);</pre><pre>+@@ -694,7 +698,6 @@ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,</pre><pre>    return GST_FLOW_OK;</pre><pre>  }</pre><pre>+ </pre><pre>+-</pre><pre>+ static GstFlowReturn</pre><pre>+ gst_mss_demux_data_received (GstAdaptiveDemux * demux,</pre><pre>+     GstAdaptiveDemuxStream * stream, GstBuffer *buffer)</pre><pre>+@@ -739,3 +742,12 @@ gst_mss_demux_requires_periodical_playlist_update (GstAdaptiveDemux * demux)</pre><pre>+ </pre><pre>+   return (!gst_mss_manifest_is_live (mssdemux-&gt;manifest));</pre><pre>+ }</pre><pre> +</pre><pre> +static gboolean</pre><pre> +gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,</pre><pre>@@ -54,10 +59,10 @@ index 9d0aece2b..b66e19514 100644</pre><pre> +  return gst_mss_manifest_get_live_seek_range (mssdemux-&gt;manifest, start, stop);</pre><pre> +}</pre><pre> diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c</pre><pre>-index 1b72e8de1..317b3cef9 100644</pre><pre>+index b9dacb3..291080a 100644</pre><pre> --- a/ext/smoothstreaming/gstmssmanifest.c</pre><pre> +++ b/ext/smoothstreaming/gstmssmanifest.c</pre><pre>-@@ -42,6 +42,7 @@ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);</pre><pre>+@@ -45,6 +45,7 @@ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);</pre><pre>  </pre><pre>  #define MSS_PROP_BITRATE              &quot;Bitrate&quot;</pre><pre>  #define MSS_PROP_DURATION             &quot;d<a href="mailto:@@-65,16+70,16@@index1b72e8de1..317b3cef9100644#defineMSS_PROP_LANGUAGE">&quot;<o:p></o:p></a></pre><pre><span class=MsoHyperlink><a href="mailto:@@-65,16+70,16@@index1b72e8de1..317b3cef9100644#defineMSS_PROP_LANGUAGE">@@ -65,16 +70,16 @@ index 1b72e8de1..317b3cef9 100644<o:p></o:p></a></span></pre><pre><span class=MsoHyperlink><a href="mailto:@@-65,16+70,16@@index1b72e8de1..317b3cef9100644#defineMSS_PROP_LANGUAGE">  #define MSS_PROP_LANGUAGE             &quot;</a></span>Language&quot;</pre><pre>  #define MSS_PROP_NUMBER               &quot;n&quot;</pre><pre>  #define MSS_PROP_REPETITIONS          &quot;r&quot;</pre><pre>-@@ -94,6 +95,7 @@ struct _GstMssManifest</pre><pre>-   xmlNodePtr xmlrootnode;</pre><pre>+@@ -103,6 +104,7 @@ struct _GstMssManifest</pre><pre>  </pre><pre>    gboolean is_live;</pre><pre>+   guint64 look_ahead_fragment_count;</pre><pre> +  gint64 dvr_window;</pre><pre>  </pre><pre>    GString *protection_system_id;</pre><pre>    gchar *protection_data;</pre><pre>-@@ -330,6 +332,22 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>-     xmlFree (live_str);</pre><pre>+@@ -367,6 +369,22 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>+     xmlFree (look_ahead_fragment_count_str);</pre><pre>    }</pre><pre>  </pre><pre> +  /* the entire file is always available for non-live streams */</pre><pre>@@ -96,9 +101,9 @@ index 1b72e8de1..317b3cef9 100644</pre><pre>    for (nodeiter = root-&gt;children; nodeiter; nodeiter = nodeiter-&gt;next) {</pre><pre>      if (nodeiter-&gt;type == XML_ELEMENT_NODE</pre><pre>          &amp;&amp; (strcmp ((const char *) nodeiter-&gt;name, &quot;StreamIndex&quot;) == 0)) {</pre><pre>-@@ -1406,3 +1424,69 @@ gst_mss_stream_get_lang (GstMssStream * stream)</pre><pre>- {</pre><pre>-   return stream-&gt;lang;</pre><pre>+@@ -1546,3 +1564,69 @@ gst_mss_stream_fragment_parse (GstMssStream * stream, GstBuffer * buffer)</pre><pre>+         fragment-&gt;time, fragment-&gt;duration, fragment-&gt;repetitions);</pre><pre>+   }</pre><pre>  }</pre><pre> +</pre><pre> +static GstClockTime</pre><pre>@@ -167,7 +172,7 @@ index 1b72e8de1..317b3cef9 100644</pre><pre> +  return ret;</pre><pre> +}</pre><pre> diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h</pre><pre>-index af7419c23..6b7b1f971 100644</pre><pre>+index 039877f..29545af 100644</pre><pre> --- a/ext/smoothstreaming/gstmssmanifest.h</pre><pre> +++ b/ext/smoothstreaming/gstmssmanifest.h</pre><pre> @@ -54,6 +54,7 @@ void gst_mss_manifest_reload_fragments (GstMssManifest * manifest, GstBuffer * d</pre><pre>@@ -179,5 +184,5 @@ index af7419c23..6b7b1f971 100644</pre><pre>  GstMssStreamType gst_mss_stream_get_type (GstMssStream *stream);</pre><pre>  GstCaps * gst_mss_stream_get_caps (GstMssStream * stream);</pre><pre> -- </pre><pre>-2.11.0</pre><pre>+1.8.3.2</pre><pre> </pre><pre>diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-adaptivedemux-minimal-HTTP-context-support.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-adaptivedemux-minimal-HTTP-context-support.patch</pre><pre>new file mode 100644</pre><pre>index 0000000000..8a4ca68d83</pre><pre>--- /dev/null</pre><pre>+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-adaptivedemux-minimal-HTTP-context-support.patch</pre><pre>@@ -0,0 +1,142 @@</pre><pre>+From 992bd23193978742029966e0a2232b1bfcc06122 Mon Sep 17 00:00:00 2001</pre><pre>+From: Philippe Normand <a href="mailto:philn@igalia.com">&lt;philn@igalia.com&gt;</a></pre><pre>+Date: Wed, 28 Oct 2015 11:52:49 +0100</pre><pre>+Subject: [PATCH 3/6] adaptivedemux: minimal HTTP context support</pre><pre>+</pre><pre>+The uridownloader is now querying the source element for an HTTP</pre><pre>+context, which stores session data (cookies only for now), and reusing</pre><pre>+the data when fetching data over HTTP. Additionally the context is set</pre><pre>+on adaptivedemux, which allows it to also properly use session data</pre><pre>+when downloading fragments.</pre><pre>+</pre><pre>+https://bugzilla.gnome.org/show_bug.cgi?id=726314</pre><pre>+---</pre><pre>+ gst-libs/gst/adaptivedemux/gstadaptivedemux.c | 16 ++++++++++++-</pre><pre>+ gst-libs/gst/uridownloader/gsturidownloader.c | 34 +++++++++++++++++++++++++--</pre><pre>+ gst-libs/gst/uridownloader/gsturidownloader.h |  2 +-</pre><pre>+ 3 files changed, 48 insertions(+), 4 deletions(-)</pre><pre>+</pre><pre>+diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c</pre><pre>+index 20bd839..1b5cace 100644</pre><pre>+--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c</pre><pre>++++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c</pre><pre>+@@ -432,7 +432,7 @@ gst_adaptive_demux_init (GstAdaptiveDemux * demux,</pre><pre>+ </pre><pre>+   demux-&gt;priv = GST_ADAPTIVE_DEMUX_GET_PRIVATE (demux);</pre><pre>+   demux-&gt;priv-&gt;input_adapter = gst_adapter_new ();</pre><pre>+-  demux-&gt;downloader = gst_uri_downloader_new ();</pre><pre>++  demux-&gt;downloader = gst_uri_downloader_new (GST_ELEMENT (demux));</pre><pre>+   demux-&gt;stream_struct_size = sizeof (GstAdaptiveDemuxStream);</pre><pre>+   demux-&gt;priv-&gt;segment_seqnum = gst_util_seqnum_next ();</pre><pre>+   demux-&gt;have_group_id = FALSE;</pre><pre>+@@ -2547,6 +2547,7 @@ gst_adaptive_demux_stream_update_source (GstAdaptiveDemuxStream * stream,</pre><pre>+     GstPadLinkReturn pad_link_ret;</pre><pre>+     GObjectClass *gobject_class;</pre><pre>+     gchar *internal_name, *bin_name;</pre><pre>++    GstContext *context = NULL;</pre><pre>+ </pre><pre>+     /* Our src consists of a bin containing uri_handler -&gt; queue2 . The</pre><pre>+      * purpose of the queue2 is to allow the uri_handler to download an</pre><pre>+@@ -2598,6 +2599,19 @@ gst_adaptive_demux_stream_update_source (GstAdaptiveDemuxStream * stream,</pre><pre>+       }</pre><pre>+     }</pre><pre>+ </pre><pre>++    context =</pre><pre>++        gst_element_get_context (GST_ELEMENT_CAST (demux), &quot;http-headers&quot;);</pre><pre>++    if (context) {</pre><pre>++      const GstStructure *s = gst_context_get_structure (context);</pre><pre>++      const gchar **cookies = NULL;</pre><pre>++      gst_structure_get (s, &quot;cookies&quot;, G_TYPE_STRV, &amp;cookies, NULL);</pre><pre>++      if (cookies) {</pre><pre>++        GST_DEBUG_OBJECT (demux, &quot;Passing cookies through&quot;);</pre><pre>++        g_object_set (uri_handler, &quot;cookies&quot;, cookies, NULL);</pre><pre>++      }</pre><pre>++      gst_context_unref (context);</pre><pre>++    }</pre><pre>++</pre><pre>+     /* Source bin creation */</pre><pre>+     bin_name = g_strdup_printf (&quot;srcbin-%s&quot;, GST_PAD_NAME (stream-&gt;pad));</pre><pre>+     stream-&gt;src = gst_bin_new (bin_name);</pre><pre>+diff --git a/gst-libs/gst/uridownloader/gsturidownloader.c b/gst-libs/gst/uridownloader/gsturidownloader.c</pre><pre>+index 47b6f29..1f61250 100644</pre><pre>+--- a/gst-libs/gst/uridownloader/gsturidownloader.c</pre><pre>++++ b/gst-libs/gst/uridownloader/gsturidownloader.c</pre><pre>+@@ -33,6 +33,8 @@ GST_DEBUG_CATEGORY (uridownloader_debug);</pre><pre>+ </pre><pre>+ struct _GstUriDownloaderPrivate</pre><pre>+ {</pre><pre>++  GstElement *parent;</pre><pre>++</pre><pre>+   /* Fragments fetcher */</pre><pre>+   GstElement *urisrc;</pre><pre>+   GstBus *bus;</pre><pre>+@@ -148,9 +150,11 @@ gst_uri_downloader_finalize (GObject * object)</pre><pre>+ }</pre><pre>+ </pre><pre>+ GstUriDownloader *</pre><pre>+-gst_uri_downloader_new (void)</pre><pre>++gst_uri_downloader_new (GstElement * parent)</pre><pre>+ {</pre><pre>+-  return g_object_new (GST_TYPE_URI_DOWNLOADER, NULL);</pre><pre>++  GstUriDownloader *downloader = g_object_new (GST_TYPE_URI_DOWNLOADER, NULL);</pre><pre>++  downloader-&gt;priv-&gt;parent = parent;</pre><pre>++  return downloader;</pre><pre>+ }</pre><pre>+ </pre><pre>+ static gboolean</pre><pre>+@@ -413,6 +417,7 @@ gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri,</pre><pre>+ {</pre><pre>+   GstPad *pad;</pre><pre>+   GObjectClass *gobject_class;</pre><pre>++  GstContext *context = NULL;</pre><pre>+ </pre><pre>+   if (!gst_uri_is_valid (uri))</pre><pre>+     return FALSE;</pre><pre>+@@ -449,6 +454,31 @@ gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri,</pre><pre>+     }</pre><pre>+   }</pre><pre>+ </pre><pre>++  context = gst_element_get_context (downloader-&gt;priv-&gt;parent, &quot;http-headers&quot;);</pre><pre>++  if (!context) {</pre><pre>++    GstQuery *context_query = gst_query_new_context (&quot;http-headers&quot;);</pre><pre>++    GstPad *parent_sink_pad =</pre><pre>++        gst_element_get_static_pad (downloader-&gt;priv-&gt;parent, &quot;sink&quot;);</pre><pre>++    if (gst_pad_peer_query (parent_sink_pad, context_query)) {</pre><pre>++</pre><pre>++      gst_query_parse_context (context_query, &amp;context);</pre><pre>++      gst_element_set_context (downloader-&gt;priv-&gt;parent, context);</pre><pre>++    }</pre><pre>++    gst_object_unref (parent_sink_pad);</pre><pre>++    gst_query_unref (context_query);</pre><pre>++  }</pre><pre>++</pre><pre>++  if (context) {</pre><pre>++    const GstStructure *s = gst_context_get_structure (context);</pre><pre>++    const gchar **cookies = NULL;</pre><pre>++    gst_structure_get (s, &quot;cookies&quot;, G_TYPE_STRV, &amp;cookies, NULL);</pre><pre>++    if (cookies) {</pre><pre>++      GST_DEBUG_OBJECT (downloader, &quot;Passing cookies through&quot;);</pre><pre>++      g_object_set (downloader-&gt;priv-&gt;urisrc, &quot;cookies&quot;, cookies, NULL);</pre><pre>++    }</pre><pre>++    gst_context_unref (context);</pre><pre>++  }</pre><pre>++</pre><pre>+   /* add a sync handler for the bus messages to detect errors in the download */</pre><pre>+   gst_element_set_bus (GST_ELEMENT (downloader-&gt;priv-&gt;urisrc),</pre><pre>+       downloader-&gt;priv-&gt;bus);</pre><pre>+diff --git a/gst-libs/gst/uridownloader/gsturidownloader.h b/gst-libs/gst/uridownloader/gsturidownloader.h</pre><pre>+index 80b8a3e..36cbf65 100644</pre><pre>+--- a/gst-libs/gst/uridownloader/gsturidownloader.h</pre><pre>++++ b/gst-libs/gst/uridownloader/gsturidownloader.h</pre><pre>+@@ -60,7 +60,7 @@ struct _GstUriDownloaderClass</pre><pre>+ </pre><pre>+ GType gst_uri_downloader_get_type (void);</pre><pre>+ </pre><pre>+-GstUriDownloader * gst_uri_downloader_new (void);</pre><pre>++GstUriDownloader * gst_uri_downloader_new (GstElement * parent);</pre><pre>+ GstFragment * gst_uri_downloader_fetch_uri (GstUriDownloader * downloader, const gchar * uri, const gchar * referer, gboolean compress, gboolean refresh, gboolean allow_cache, GError ** err);</pre><pre>+ GstFragment * gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader, const gchar * uri, const gchar * referer, gboolean compress, gboolean refresh, gboolean allow_cache, gint64 range_start, gint64 range_end, GError ** err);</pre><pre>+ void gst_uri_downloader_reset (GstUriDownloader *downloader);</pre><pre>+-- </pre><pre>+2.7.4</pre><pre>+</pre><pre>diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-mpdparser-MS-PlayReady-ContentProtection-parsing.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-mpdparser-MS-PlayReady-ContentProtection-parsing.patch</pre><pre>new file mode 100644</pre><pre>index 0000000000..97d83aa4f7</pre><pre>--- /dev/null</pre><pre>+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-mpdparser-MS-PlayReady-ContentProtection-parsing.patch</pre><pre>@@ -0,0 +1,109 @@</pre><pre>+From cbf3d75b3d693e50722534d30a8f51995a419803 Mon Sep 17 00:00:00 2001</pre><pre>+From: Philippe Normand <a href="mailto:philn@igalia.com">&lt;philn@igalia.com&gt;</a></pre><pre>+Date: Fri, 4 Nov 2016 09:56:33 +0100</pre><pre>+Subject: [PATCH 5/6] mpdparser: MS PlayReady ContentProtection parsing</pre><pre>+</pre><pre>+The &quot;pro&quot; (PlayReady Object) element contents are now base64-decoded</pre><pre>+and properly stored in Protection events.</pre><pre>+</pre><pre>+https://bugzilla.gnome.org/show_bug.cgi?id=773936</pre><pre>+---</pre><pre>+ ext/dash/gstdashdemux.c |  2 +-</pre><pre>+ ext/dash/gstmpdparser.c | 41 ++++++++++++++++++++++++++++++++++++++++-</pre><pre>+ ext/dash/gstmpdparser.h |  1 +</pre><pre>+ 3 files changed, 42 insertions(+), 2 deletions(-)</pre><pre>+</pre><pre>+diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c</pre><pre>+index 271f70f..b10465e 100644</pre><pre>+--- a/ext/dash/gstdashdemux.c</pre><pre>++++ b/ext/dash/gstdashdemux.c</pre><pre>+@@ -745,7 +745,7 @@ gst_dash_demux_send_content_protection_event (gpointer data, gpointer userdata)</pre><pre>+   /* RFC 2141 states: The leading &quot;urn:&quot; sequence is case-insensitive */</pre><pre>+   schemeIdUri = g_ascii_strdown (cp-&gt;schemeIdUri, -1);</pre><pre>+   if (g_str_has_prefix (schemeIdUri, &quot;urn:uuid:&quot;)) {</pre><pre>+-    pssi_len = strlen (cp-&gt;value);</pre><pre>++    pssi_len = cp-&gt;value_len;</pre><pre>+     pssi = gst_buffer_new_wrapped (g_memdup (cp-&gt;value, pssi_len), pssi_len);</pre><pre>+     GST_LOG_OBJECT (stream, &quot;Queuing Protection event on source pad&quot;);</pre><pre>+     /* RFC 4122 states that the hex part of a UUID is in lower case,</pre><pre>+diff --git a/ext/dash/gstmpdparser.c b/ext/dash/gstmpdparser.c</pre><pre>+index 15d6d98..f0b3ceb 100644</pre><pre>+--- a/ext/dash/gstmpdparser.c</pre><pre>++++ b/ext/dash/gstmpdparser.c</pre><pre>+@@ -1313,6 +1313,7 @@ gst_mpdparser_parse_descriptor_type_node (GList ** list, xmlNode * a_node)</pre><pre>+     /* if no value attribute, use XML string representation of the node */</pre><pre>+     gst_mpdparser_get_xml_node_as_string (a_node, &amp;new_descriptor-&gt;value);</pre><pre>+   }</pre><pre>++  new_descriptor-&gt;value_len = strlen(new_descriptor-&gt;value);</pre><pre>+ }</pre><pre>+ </pre><pre>+ static void</pre><pre>+@@ -1734,6 +1735,44 @@ error:</pre><pre>+ }</pre><pre>+ </pre><pre>+ static void</pre><pre>++gst_mpdparser_parse_content_protection_node (GList ** list, xmlNode * a_node)</pre><pre>++{</pre><pre>++  gchar *value = NULL;</pre><pre>++  if (gst_mpdparser_get_xml_prop_string (a_node, &quot;value&quot;, &amp;value)) {</pre><pre>++    if (!g_strcmp0 (value, &quot;MSPR 2.0&quot;)) {</pre><pre>++      xmlNode *cur_node;</pre><pre>++      for (cur_node = a_node-&gt;children; cur_node; cur_node = cur_node-&gt;next) {</pre><pre>++        if (cur_node-&gt;type == XML_ELEMENT_NODE) {</pre><pre>++          if (xmlStrcmp (cur_node-&gt;name, (xmlChar *) &quot;pro&quot;) == 0) {</pre><pre>++            gsize decoded_len;</pre><pre>++            GstDescriptorType *new_descriptor;</pre><pre>++            new_descriptor = g_slice_new0 (GstDescriptorType);</pre><pre>++            *list = g_list_append (*list, new_descriptor);</pre><pre>++</pre><pre>++            gst_mpdparser_get_xml_prop_string (a_node, &quot;schemeIdUri&quot;,</pre><pre>++                &amp;new_descriptor-&gt;schemeIdUri);</pre><pre>++</pre><pre>++            gst_mpdparser_get_xml_node_content (cur_node,</pre><pre>++                &amp;new_descriptor-&gt;value);</pre><pre>++            g_base64_decode_inplace (new_descriptor-&gt;value, &amp;decoded_len);</pre><pre>++            *(new_descriptor-&gt;value + decoded_len) = '\0';</pre><pre>++            new_descriptor-&gt;value_len = decoded_len;</pre><pre>++            goto beach;</pre><pre>++          }</pre><pre>++        }</pre><pre>++      }</pre><pre>++    } else {</pre><pre>++      gst_mpdparser_parse_descriptor_type_node (list, a_node);</pre><pre>++    }</pre><pre>++  } else {</pre><pre>++    gst_mpdparser_parse_descriptor_type_node (list, a_node);</pre><pre>++  }</pre><pre>++beach:</pre><pre>++  if (value)</pre><pre>++    g_free (value);</pre><pre>++}</pre><pre>++</pre><pre>++static void</pre><pre>+ gst_mpdparser_parse_representation_base_type (GstRepresentationBaseType **</pre><pre>+     pointer, xmlNode * a_node)</pre><pre>+ {</pre><pre>+@@ -1788,7 +1827,7 @@ gst_mpdparser_parse_representation_base_type (GstRepresentationBaseType **</pre><pre>+             (&amp;representation_base-&gt;AudioChannelConfiguration, cur_node);</pre><pre>+       } else if (xmlStrcmp (cur_node-&gt;name,</pre><pre>+               (xmlChar *) &quot;ContentProtection&quot;) == 0) {</pre><pre>+-        gst_mpdparser_parse_descriptor_type_node</pre><pre>++        gst_mpdparser_parse_content_protection_node</pre><pre>+             (&amp;representation_base-&gt;ContentProtection, cur_node);</pre><pre>+       }</pre><pre>+     }</pre><pre>+diff --git a/ext/dash/gstmpdparser.h b/ext/dash/gstmpdparser.h</pre><pre>+index 85b97ea..738de68 100644</pre><pre>+--- a/ext/dash/gstmpdparser.h</pre><pre>++++ b/ext/dash/gstmpdparser.h</pre><pre>+@@ -277,6 +277,7 @@ struct _GstDescriptorType</pre><pre>+ {</pre><pre>+   gchar *schemeIdUri;</pre><pre>+   gchar *value;</pre><pre>++  glong value_len;</pre><pre>+ };</pre><pre>+ </pre><pre>+ struct _GstContentComponentNode</pre><pre>+-- </pre><pre>+2.7.4</pre><pre>+</pre><pre>diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.4.bb</pre><pre>index 0bb4053e43..c894945748 100644</pre><pre>--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.4.bb</pre><pre>+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.4.bb</pre><pre>@@ -11,13 +11,16 @@ SRC_URI = &quot; \</pre><pre>     <a href="file://fix-maybe-uninitialized-warnings-when-compiling-with-Os.patch">file://fix-maybe-uninitialized-warnings-when-compiling-with-Os.patch</a> \</pre><pre>     <a href="file://avoid-including-sys-poll.h-directly.patch">file://avoid-including-sys-poll.h-directly.patch</a> \</pre><pre>     <a href="file://ensure-valid-sentinels-for-gst_structure_get-etc.patch">file://ensure-valid-sentinels-for-gst_structure_get-etc.patch</a> \</pre><pre>+    <a href="file://0001-mssdemux-improved-live-playback-support.patch">file://0001-mssdemux-improved-live-playback-support.patch</a> \</pre><pre>     <a href="file://0001-gstreamer-gl.pc.in-don-t-append-GL_CFLAGS-to-CFLAGS.patch">file://0001-gstreamer-gl.pc.in-don-t-append-GL_CFLAGS-to-CFLAGS.patch</a> \</pre><pre>-    <a href="file://0009-glimagesink-Downrank-to-marginal.patch">file://0009-glimagesink-Downrank-to-marginal.patch</a> \</pre><pre>     <a href="file://0001-introspection.m4-prefix-pkgconfig-paths-with-PKG_CON.patch">file://0001-introspection.m4-prefix-pkgconfig-paths-with-PKG_CON.patch</a> \</pre><pre>     <a href="file://0001-Prepend-PKG_CONFIG_SYSROOT_DIR-to-pkg-config-output.patch">file://0001-Prepend-PKG_CONFIG_SYSROOT_DIR-to-pkg-config-output.patch</a> \</pre><pre>-    <a href="file://0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch">file://0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch</a> \</pre><pre>     <a href="file://0001-smoothstreaming-use-the-duration-from-the-list-of-fr.patch">file://0001-smoothstreaming-use-the-duration-from-the-list-of-fr.patch</a> \</pre><pre>-    <a href="file://0001-mssdemux-improved-live-playback-support.patch">file://0001-mssdemux-improved-live-playback-support.patch</a> \</pre><pre>+    <a href="file://0002-mssdemux-Handle-the-adapter-in-the-subclass-after-bu.patch">file://0002-mssdemux-Handle-the-adapter-in-the-subclass-after-bu.patch</a> \</pre><pre>+    <a href="file://0003-adaptivedemux-minimal-HTTP-context-support.patch">file://0003-adaptivedemux-minimal-HTTP-context-support.patch</a> \</pre><pre>+    <a href="file://0005-mpdparser-MS-PlayReady-ContentProtection-parsing.patch">file://0005-mpdparser-MS-PlayReady-ContentProtection-parsing.patch</a> \</pre><pre>+    <a href="file://0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch">file://0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch</a> \</pre><pre>+    <a href="file://0009-glimagesink-Downrank-to-marginal.patch">file://0009-glimagesink-Downrank-to-marginal.patch</a> \</pre><pre> &quot;</pre><pre> SRC_URI[md5sum] = &quot;2757103e57a096a1a05b3ab85b8381af&quot;</pre><pre> SRC_URI[sha256sum] = &quot;23ddae506b3a223b94869a0d3eea3e9a12e847f94d2d0e0b97102ce13ecd6966&quot;</pre></blockquote><p class=MsoNormal><o:p>&nbsp;</o:p></p><p class=MsoNormal><span style='color:black'><o:p>&nbsp;</o:p></span></p></div></body></html>