<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>