<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> </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> </o:p></p><p><o:p> </o:p></p><p class=MsoNormal><o:p> </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"><wouter@wouterlucas.com></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> </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"><philn@igalia.com></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"><raj.khem@gmail.com></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->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->update_manifest_data =</pre><pre>       gst_mss_demux_update_manifest_data;</pre><pre>-  gstadaptivedemux_class->get_live_seek_range =</pre><pre>-      gst_mss_demux_get_live_seek_range;</pre><pre> + gstadaptivedemux_class->data_received = gst_mss_demux_data_received;</pre><pre> + gstadaptivedemux_class->requires_periodical_playlist_update =</pre><pre> +     gst_mss_demux_requires_periodical_playlist_update;</pre><pre> </pre><pre>    GST_DEBUG_CATEGORY_INIT (mssdemux_debug, "mssdemux", 0, "mssdemux plugin");</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->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->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->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->manifest)) {</pre><pre> +   return GST_ADAPTIVE_DEMUX_CLASS (parent_class)->data_received (demux,</pre><pre>-+       stream, buffer);</pre><pre>++       stream);</pre><pre> + }</pre><pre> +</pre><pre> + if (gst_mss_stream_fragment_parsing_needed (mssstream->manifest_stream)) {</pre><pre>-+   gst_mss_manifest_live_adapter_push (mssstream->manifest_stream, buffer);</pre><pre>-+   available =</pre><pre>-+       gst_mss_manifest_live_adapter_available (mssstream->manifest_stream);</pre><pre>++   available = gst_adapter_available (stream->adapter);</pre><pre> +   // FIXME: try to reduce this minimal size.</pre><pre> +   if (available < 4096) {</pre><pre> +     return GST_FLOW_OK;</pre><pre> +   } else {</pre><pre>++     GstBuffer *buffer = gst_adapter_get_buffer (stream->adapter, available);</pre><pre> +     GST_LOG_OBJECT (stream->pad, "enough data, parsing fragment.");</pre><pre>-+     buffer =</pre><pre>-+         gst_mss_manifest_live_adapter_take_buffer (mssstream->manifest_stream,</pre><pre>-+         available);</pre><pre>-+     gst_mss_stream_parse_fragment (mssstream->manifest_stream, buffer);</pre><pre>++     gst_mss_stream_fragment_parse (mssstream->manifest_stream, buffer);</pre><pre>++     gst_buffer_unref (buffer);</pre><pre> +   }</pre><pre> + }</pre><pre> +</pre><pre>-+ return GST_ADAPTIVE_DEMUX_CLASS (parent_class)->data_received (demux, stream,</pre><pre>-+     buffer);</pre><pre>++ return GST_ADAPTIVE_DEMUX_CLASS (parent_class)->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"><philn@igalia.com></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 (&reader);</pre><pre> +         fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);</pre><pre> +         if (fourcc == GST_MSS_FRAGMENT_FOURCC_TRUN) {</pre><pre>-+           GST_TRACE ("trun box found, size: %" G_GUINT32_FORMAT, size);</pre><pre>-+           if (!gst_byte_reader_skip (&reader, size - 8)) {</pre><pre>-+             GST_WARNING ("Failed to skip trun box, enough data?");</pre><pre>-+             error = TRUE;</pre><pre>-+             goto beach;</pre><pre>-+           }</pre><pre>++           gst_byte_reader_skip_unchecked (&reader, size - 8);</pre><pre>++           GST_TRACE ("trun box found, size: %u", size);</pre><pre> +         }</pre><pre> +       }</pre><pre> +     }</pre><pre>@@ -354,11 +344,7 @@ index 000000000..b554d4f31</pre><pre> +   }</pre><pre> +</pre><pre> +   GST_TRACE ("box size: %" G_GUINT32_FORMAT, size);</pre><pre>-+   if (!gst_byte_reader_get_uint32_le (&reader, &fourcc)) {</pre><pre>-+     GST_WARNING ("Failed to get fourcc, enough data?");</pre><pre>-+     error = TRUE;</pre><pre>-+     break;</pre><pre>-+   }</pre><pre>++   fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);</pre><pre> +</pre><pre> +   if (fourcc == GST_MSS_FRAGMENT_FOURCC_MDAT) {</pre><pre> +     GST_LOG ("mdat box found<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></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 ("</a></span>invalid UUID fourcc: %" GST_FOURCC_FORMAT,</pre><pre>-+         GST_FOURCC_ARGS (fourcc));</pre><pre>++     GST_ERROR ("invalid UUID fourcc");</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->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"><philn@igalia.com></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"><thiago.sousa.santos@collabora.com></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->url = (gchar *) xmlGetProp (node, (xmlChar *) MSS_PROP_URL);</pre><pre>   stream->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 ("Live stream: %s, look-ahead fragments: %" G_GUINT64_FORMAT,</pre><pre>-+     manifest->is_live ? "yes" : "no", manifest->look_ahead_fragment_count);</pre><pre> + stream->has_live_fragments = manifest->is_live</pre><pre> +     && manifest->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->qualities = g_list_prepend (stream->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->fragments = g_list_reverse (builder.fragments);</pre><pre> + if (stream->has_live_fragments) {</pre><pre>-+   stream->live_adapter = gst_adapter_new ();</pre><pre>++   g_queue_init (&stream->live_fragments);</pre><pre>++   g_queue_push_tail (&stream->live_fragments, builder.fragments->data);</pre><pre>++   stream->current_fragment = g_queue_peek_head_link (&stream->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, &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->is_live) {</pre><pre>-    manifest->dvr_window = 0;</pre><pre>-+   manifest->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->dvr_window = 0;</pre><pre>-      }</pre><pre>-    }</pre><pre>-+</pre><pre>-+   look_ahead_fragment_count_str =</pre><pre>-+       (gchar *) xmlGetProp (root, (xmlChar *) "LookAheadFragmentCount");</pre><pre>-+   if (look_ahead_fragment_count_str) {</pre><pre>-+     manifest->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->look_ahead_fragment_count <= 0) {</pre><pre>-+       manifest->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 *) "LookAheadFragmentCount");</pre><pre>++ if (look_ahead_fragment_count_str) {</pre><pre>++   manifest->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->children; nodeiter; nodeiter = nodeiter->next) {</pre><pre>-@@ -354,7 +396,7 @@ gst_mss_manifest_new (GstBuffer * data)</pre><pre>+    if (nodeiter->type == XML_ELEMENT_NODE</pre><pre>+        && (strcmp ((const char *) nodeiter->name, "StreamIndex") == 0)) {</pre><pre>       GstMssStream *stream = g_new0 (GstMssStream, 1);</pre><pre> </pre><pre>        manifest->streams = g_slist_append (manifest->streams, stream);</pre><pre>@@ -652,39 +622,56 @@ index 144bbb42d..e1031ba55 100644</pre><pre>     }</pre><pre> </pre><pre>      if (nodeiter->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->live_adapter) {</pre><pre>-+   gst_adapter_clear (stream->live_adapter);</pre><pre>-+   g_object_unref (stream->live_adapter);</pre><pre>+- g_list_free_full (stream->fragments, g_free);</pre><pre>++ if (stream->has_live_fragments) {</pre><pre>++   g_queue_foreach (&stream->live_fragments, (GFunc) g_free, NULL);</pre><pre>++   g_queue_clear (&stream->live_fragments);</pre><pre>++ } else {</pre><pre>++   g_list_free_full (stream->fragments, g_free);</pre><pre> + }</pre><pre>-+</pre><pre>-  g_list_free_full (stream->fragments, g_free);</pre><pre>   g_list_free_full (stream->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->url);</pre><pre>+  xmlFree (stream->lang);</pre><pre>   g_regex_unref (stream->regex_position);</pre><pre>   g_regex_unref (stream->regex_bitrate);</pre><pre>-  g_free (stream);</pre><pre> + gst_mss_fragment_parser_clear (&stream->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->active, GST_CLOCK_TIME_NONE);</pre><pre>+ </pre><pre>+  if (!stream->current_fragment) {</pre><pre>+-   GList *last = g_list_last (stream->fragments);</pre><pre>++   GList *last;</pre><pre>++</pre><pre>++   if (stream->has_live_fragments)</pre><pre>++     last = g_queue_peek_tail_link (&stream->live_fragments);</pre><pre>++   else</pre><pre>++     last = g_list_last (stream->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->active, GST_FLOW_ERROR);</pre><pre> </pre><pre>    if (stream->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->current_fragment->data;</pre><pre>+- fragment = stream->current_fragment->data;</pre><pre>++ prev_fragment = fragment = stream->current_fragment->data;</pre><pre>   stream->fragment_repetition_index++;</pre><pre> - if (stream->fragment_repetition_index < fragment->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->fragment_repetition_index = 0;</pre><pre>-  stream->current_fragment = g_list_next (stream->current_fragment);</pre><pre>+- stream->current_fragment = g_list_next (stream->current_fragment);</pre><pre>++</pre><pre>++ if (stream->has_live_fragments)</pre><pre>++   stream->current_fragment = g_queue_pop_head_link (&stream->live_fragments);</pre><pre>++ else</pre><pre>++   stream->current_fragment = g_list_next (stream->current_fragment);</pre><pre>++</pre><pre>++ if (stream->current_fragment != NULL) {</pre><pre>++   fragment = stream->current_fragment->data;</pre><pre>++   if (fragment->time <= prev_fragment->time) {</pre><pre>++     while (fragment->time <= prev_fragment->time) {</pre><pre>++       if (stream->has_live_fragments)</pre><pre>++         stream->current_fragment =</pre><pre>++             g_queue_pop_head_link (&stream->live_fragments);</pre><pre>++       else</pre><pre>++         stream->current_fragment = g_list_next (stream->current_fragment);</pre><pre>++       if (stream->current_fragment == NULL)</pre><pre>++         break;</pre><pre>++       fragment = stream->current_fragment->data;</pre><pre>++     }</pre><pre>++   }</pre><pre>++ }</pre><pre> +</pre><pre> + GST_DEBUG ("Advanced to fragment #%d on %s stream", fragment->number,</pre><pre> +     stream_type_name);</pre><pre>++ if (stream->has_live_fragments)</pre><pre>++   GST_LOG ("%u fragments left in the %s stream queue",</pre><pre>++       g_queue_get_length (&stream->live_fragments), stream_type_name);</pre><pre>   if (stream->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 ("Stream %s seeking to %" G_GUINT64_FORMAT, stream->url, time);</pre><pre>-  for (iter = stream->fragments; iter; iter = g_list_next (iter)) {</pre><pre>-    fragment = iter->data;</pre><pre>-+   if (stream->has_live_fragments) {</pre><pre>-+     if (fragment->time + fragment->repetitions * fragment->duration > time)</pre><pre>-+       stream->current_fragment = iter;</pre><pre>-+     break;</pre><pre>-+   }</pre><pre>-    if (fragment->time + fragment->repetitions * fragment->duration > time) {</pre><pre>-      stream->current_fragment = iter;</pre><pre>-      stream->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->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 (&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 ("Current position: %" 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->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->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->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->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->has_live_fragments)</pre><pre> +   return;</pre><pre>@@ -780,29 +756,20 @@ index 144bbb42d..e1031ba55 100644</pre><pre> + current_fragment->time = stream->fragment_parser.tfxd.time;</pre><pre> + current_fragment->duration = stream->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 < stream->fragment_parser.tfrf.entries_count; index++) {</pre><pre>-+   GList *l = g_list_last (stream->fragments);</pre><pre>-+   GstMssStreamFragment *last;</pre><pre>++ for (guint8 index = 0; index < stream->fragment_parser.tfrf.entries_count;</pre><pre>++     index++) {</pre><pre>++   GstMssStreamFragment *last = g_queue_peek_tail (&stream->live_fragments);</pre><pre> +   GstMssStreamFragment *fragment;</pre><pre> +</pre><pre>-+   if (l == NULL)</pre><pre>-+     break;</pre><pre>-+</pre><pre>-+   last = (GstMssStreamFragment *) l->data;</pre><pre>-+</pre><pre>-+   if (last->time == stream->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->number = last->number + 1;</pre><pre> +   fragment->repetitions = 1;</pre><pre> +   fragment->time = stream->fragment_parser.tfrf.entries[index].time;</pre><pre> +    fragment->duration = stream->fragment_parser.tfrf.entries[index].duration;</pre><pre> +</pre><pre>-+   stream->fragments = g_list_append (stream->fragments, fragment);</pre><pre>++   g_queue_push_tail (&stream->live_fragments, fragment);</pre><pre> +   GST_LOG ("Adding fragment number: %u to %s stream, time: %" G_GUINT64_FORMAT</pre><pre> +       ", duration: %" G_GUINT64_FORMAT ", repetitions: %u",</pre><pre> +       fragment->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 <glib.h></pre><pre>- #include <gio/gio.h></pre><pre>- #include <gst/gst.h></pre><pre>-+#include <gst/base/gstadapter.h></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->download_chunk_start_time;</pre><pre>+  stream->download_total_bytes += gst_buffer_get_size (buffer);</pre><pre>+ </pre><pre>+- GST_DEBUG_OBJECT (stream->pad, "Received buffer of size %" G_GSIZE_FORMAT,</pre><pre>++ GST_LOG_OBJECT (stream->pad, "Received buffer of size %" G_GSIZE_FORMAT,</pre><pre>+      gst_buffer_get_size (buffer));</pre><pre>+ </pre><pre>+  ret = klass->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->pad, "EOS, checking to stop download loop");</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->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->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"><matthew@centricular.com></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"><raj.khem@gmail.com></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->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->data_received = gst_mss_demux_data_received;</pre><pre>+  gstadaptivedemux_class->requires_periodical_playlist_update =</pre><pre>+      gst_mss_demux_requires_periodical_playlist_update;</pre><pre> + gstadaptivedemux_class->get_live_seek_range =</pre><pre> +     gst_mss_demux_get_live_seek_range;</pre><pre> </pre><pre>    GST_DEBUG_CATEGORY_INIT (mssdemux_debug, "mssdemux", 0, "mssdemux plugin");</pre><pre> }</pre><pre>-@@ -659,3 +663,12 @@ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,</pre><pre>-  gst_mss_manifest_reload_fragments (mssdemux->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->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->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             "Bitrate"</pre><pre> #define MSS_PROP_DURATION            "d<a href="mailto:@@-65,16+70,16@@index1b72e8de1..317b3cef9100644#defineMSS_PROP_LANGUAGE">"<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            "</a></span>Language"</pre><pre> #define MSS_PROP_NUMBER              "n"</pre><pre> #define MSS_PROP_REPETITIONS         "r"</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->children; nodeiter; nodeiter = nodeiter->next) {</pre><pre>     if (nodeiter->type == XML_ELEMENT_NODE</pre><pre>         && (strcmp ((const char *) nodeiter->name, "StreamIndex") == 0)) {</pre><pre>-@@ -1406,3 +1424,69 @@ gst_mss_stream_get_lang (GstMssStream * stream)</pre><pre>- {</pre><pre>-  return stream->lang;</pre><pre>+@@ -1546,3 +1564,69 @@ gst_mss_stream_fragment_parse (GstMssStream * stream, GstBuffer * buffer)</pre><pre>+        fragment->time, fragment->duration, fragment->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"><philn@igalia.com></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->priv = GST_ADAPTIVE_DEMUX_GET_PRIVATE (demux);</pre><pre>+  demux->priv->input_adapter = gst_adapter_new ();</pre><pre>+- demux->downloader = gst_uri_downloader_new ();</pre><pre>++ demux->downloader = gst_uri_downloader_new (GST_ELEMENT (demux));</pre><pre>+  demux->stream_struct_size = sizeof (GstAdaptiveDemuxStream);</pre><pre>+  demux->priv->segment_seqnum = gst_util_seqnum_next ();</pre><pre>+  demux->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 -> 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), "http-headers");</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, "cookies", G_TYPE_STRV, &cookies, NULL);</pre><pre>++     if (cookies) {</pre><pre>++       GST_DEBUG_OBJECT (demux, "Passing cookies through");</pre><pre>++       g_object_set (uri_handler, "cookies", 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 ("srcbin-%s", GST_PAD_NAME (stream->pad));</pre><pre>+    stream->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->priv->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->priv->parent, "http-headers");</pre><pre>++ if (!context) {</pre><pre>++   GstQuery *context_query = gst_query_new_context ("http-headers");</pre><pre>++   GstPad *parent_sink_pad =</pre><pre>++       gst_element_get_static_pad (downloader->priv->parent, "sink");</pre><pre>++   if (gst_pad_peer_query (parent_sink_pad, context_query)) {</pre><pre>++</pre><pre>++     gst_query_parse_context (context_query, &context);</pre><pre>++     gst_element_set_context (downloader->priv->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, "cookies", G_TYPE_STRV, &cookies, NULL);</pre><pre>++   if (cookies) {</pre><pre>++     GST_DEBUG_OBJECT (downloader, "Passing cookies through");</pre><pre>++     g_object_set (downloader->priv->urisrc, "cookies", 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->priv->urisrc),</pre><pre>+      downloader->priv->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"><philn@igalia.com></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 "pro" (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 "urn:" sequence is case-insensitive */</pre><pre>+  schemeIdUri = g_ascii_strdown (cp->schemeIdUri, -1);</pre><pre>+  if (g_str_has_prefix (schemeIdUri, "urn:uuid:")) {</pre><pre>+-   pssi_len = strlen (cp->value);</pre><pre>++   pssi_len = cp->value_len;</pre><pre>+    pssi = gst_buffer_new_wrapped (g_memdup (cp->value, pssi_len), pssi_len);</pre><pre>+    GST_LOG_OBJECT (stream, "Queuing Protection event on source pad");</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, &new_descriptor->value);</pre><pre>+  }</pre><pre>++ new_descriptor->value_len = strlen(new_descriptor->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, "value", &value)) {</pre><pre>++   if (!g_strcmp0 (value, "MSPR 2.0")) {</pre><pre>++     xmlNode *cur_node;</pre><pre>++     for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {</pre><pre>++       if (cur_node->type == XML_ELEMENT_NODE) {</pre><pre>++         if (xmlStrcmp (cur_node->name, (xmlChar *) "pro") == 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, "schemeIdUri",</pre><pre>++               &new_descriptor->schemeIdUri);</pre><pre>++</pre><pre>++           gst_mpdparser_get_xml_node_content (cur_node,</pre><pre>++               &new_descriptor->value);</pre><pre>++           g_base64_decode_inplace (new_descriptor->value, &decoded_len);</pre><pre>++           *(new_descriptor->value + decoded_len) = '\0';</pre><pre>++           new_descriptor->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>+            (&representation_base->AudioChannelConfiguration, cur_node);</pre><pre>+      } else if (xmlStrcmp (cur_node->name,</pre><pre>+              (xmlChar *) "ContentProtection") == 0) {</pre><pre>+-       gst_mpdparser_parse_descriptor_type_node</pre><pre>++       gst_mpdparser_parse_content_protection_node</pre><pre>+            (&representation_base->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 = " \</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> "</pre><pre> SRC_URI[md5sum] = "2757103e57a096a1a05b3ab85b8381af"</pre><pre> SRC_URI[sha256sum] = "23ddae506b3a223b94869a0d3eea3e9a12e847f94d2d0e0b97102ce13ecd6966"</pre></blockquote><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><span style='color:black'><o:p> </o:p></span></p></div></body></html>