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
new file mode 100644
index 0000000000..4832c18e78
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mssdemux-improved-live-playback-support.patch
@@ -0,0 +1,929 @@
+From 73721ad4e9e2d32e1c8b6a3b4aaa98401530e58a Mon Sep 17 00:00:00 2001
+From: Philippe Normand <philn@igalia.com>
+Date: Tue, 29 Nov 2016 14:43:41 +0100
+Subject: [PATCH] mssdemux: improved live playback support
+
+When a MSS server hosts a live stream the fragments listed in the
+manifest usually don't have accurate timestamps and duration, except
+for the first fragment, which additionally stores timing information
+for the few upcoming fragments. In this scenario it is useless to
+periodically fetch and update the manifest and the fragments list can
+be incrementally built by parsing the first/current fragment.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=755036
+---
+Upstream-Status: Backport
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+
+ ext/smoothstreaming/Makefile.am               |   2 +
+ ext/smoothstreaming/gstmssdemux.c             |  60 ++++++
+ ext/smoothstreaming/gstmssfragmentparser.c    | 266 ++++++++++++++++++++++++++
+ ext/smoothstreaming/gstmssfragmentparser.h    |  84 ++++++++
+ ext/smoothstreaming/gstmssmanifest.c          | 158 ++++++++++++++-
+ ext/smoothstreaming/gstmssmanifest.h          |   7 +
+ gst-libs/gst/adaptivedemux/gstadaptivedemux.c |  27 ++-
+ gst-libs/gst/adaptivedemux/gstadaptivedemux.h |  14 ++
+ 8 files changed, 606 insertions(+), 12 deletions(-)
+ create mode 100644 ext/smoothstreaming/gstmssfragmentparser.c
+ create mode 100644 ext/smoothstreaming/gstmssfragmentparser.h
+
+diff --git a/ext/smoothstreaming/Makefile.am b/ext/smoothstreaming/Makefile.am
+index 4faf9df9f..a5e1ad6ae 100644
+--- a/ext/smoothstreaming/Makefile.am
++++ b/ext/smoothstreaming/Makefile.am
+@@ -13,8 +13,10 @@ libgstsmoothstreaming_la_LIBADD = \
+ libgstsmoothstreaming_la_LDFLAGS = ${GST_PLUGIN_LDFLAGS}
+ libgstsmoothstreaming_la_SOURCES = gstsmoothstreaming-plugin.c \
+ 	gstmssdemux.c \
++	gstmssfragmentparser.c \
+ 	gstmssmanifest.c
+ libgstsmoothstreaming_la_LIBTOOLFLAGS = --tag=disable-static
+ 
+ noinst_HEADERS = gstmssdemux.h \
++	gstmssfragmentparser.h \
+ 	gstmssmanifest.h
+diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c
+index 12fb40497..120d9c22b 100644
+--- a/ext/smoothstreaming/gstmssdemux.c
++++ b/ext/smoothstreaming/gstmssdemux.c
+@@ -135,11 +135,18 @@ gst_mss_demux_stream_update_fragment_info (GstAdaptiveDemuxStream * stream);
+ static gboolean gst_mss_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);
+ static gint64
+ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);
++static gint64
++gst_mss_demux_stream_get_fragment_waiting_time (GstAdaptiveDemuxStream *
++    stream);
+ static GstFlowReturn
+ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
+     GstBuffer * buffer);
+ static gboolean gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux,
+     gint64 * start, gint64 * stop);
++static GstFlowReturn gst_mss_demux_data_received (GstAdaptiveDemux * demux,
++    GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
++static gboolean
++gst_mss_demux_requires_periodical_playlist_update (GstAdaptiveDemux * demux);
+ 
+ static void
+ gst_mss_demux_class_init (GstMssDemuxClass * klass)
+@@ -192,10 +199,15 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)
+       gst_mss_demux_stream_select_bitrate;
+   gstadaptivedemux_class->stream_update_fragment_info =
+       gst_mss_demux_stream_update_fragment_info;
++  gstadaptivedemux_class->stream_get_fragment_waiting_time =
++      gst_mss_demux_stream_get_fragment_waiting_time;
+   gstadaptivedemux_class->update_manifest_data =
+       gst_mss_demux_update_manifest_data;
+   gstadaptivedemux_class->get_live_seek_range =
+       gst_mss_demux_get_live_seek_range;
++  gstadaptivedemux_class->data_received = gst_mss_demux_data_received;
++  gstadaptivedemux_class->requires_periodical_playlist_update =
++      gst_mss_demux_requires_periodical_playlist_update;
+ 
+   GST_DEBUG_CATEGORY_INIT (mssdemux_debug, "mssdemux", 0, "mssdemux plugin");
+ }
+@@ -650,6 +662,13 @@ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
+   return interval;
+ }
+ 
++static gint64
++gst_mss_demux_stream_get_fragment_waiting_time (GstAdaptiveDemuxStream * stream)
++{
++  /* Wait a second for live streams so we don't try premature fragments downloading */
++  return GST_SECOND;
++}
++
+ static GstFlowReturn
+ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
+     GstBuffer * buffer)
+@@ -670,3 +689,44 @@ gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
+ 
+   return gst_mss_manifest_get_live_seek_range (mssdemux->manifest, start, stop);
+ }
++
++static GstFlowReturn
++gst_mss_demux_data_received (GstAdaptiveDemux * demux,
++    GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
++{
++  GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
++  GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
++  gsize available;
++
++  if (!gst_mss_manifest_is_live (mssdemux->manifest)) {
++    return GST_ADAPTIVE_DEMUX_CLASS (parent_class)->data_received (demux,
++        stream, buffer);
++  }
++
++  if (gst_mss_stream_fragment_parsing_needed (mssstream->manifest_stream)) {
++    gst_mss_manifest_live_adapter_push (mssstream->manifest_stream, buffer);
++    available =
++        gst_mss_manifest_live_adapter_available (mssstream->manifest_stream);
++    // FIXME: try to reduce this minimal size.
++    if (available < 4096) {
++      return GST_FLOW_OK;
++    } else {
++      GST_LOG_OBJECT (stream->pad, "enough data, parsing fragment.");
++      buffer =
++          gst_mss_manifest_live_adapter_take_buffer (mssstream->manifest_stream,
++          available);
++      gst_mss_stream_parse_fragment (mssstream->manifest_stream, buffer);
++    }
++  }
++
++  return GST_ADAPTIVE_DEMUX_CLASS (parent_class)->data_received (demux, stream,
++      buffer);
++}
++
++static gboolean
++gst_mss_demux_requires_periodical_playlist_update (GstAdaptiveDemux * demux)
++{
++  GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
++
++  return (!gst_mss_manifest_is_live (mssdemux->manifest));
++}
+diff --git a/ext/smoothstreaming/gstmssfragmentparser.c b/ext/smoothstreaming/gstmssfragmentparser.c
+new file mode 100644
+index 000000000..b554d4f31
+--- /dev/null
++++ b/ext/smoothstreaming/gstmssfragmentparser.c
+@@ -0,0 +1,266 @@
++/*
++ * Microsoft Smooth-Streaming fragment parsing library
++ *
++ * gstmssfragmentparser.h
++ *
++ * Copyright (C) 2016 Igalia S.L
++ * Copyright (C) 2016 Metrological
++ *   Author: Philippe Normand <philn@igalia.com>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library (COPYING); if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#include "gstmssfragmentparser.h"
++#include <gst/base/gstbytereader.h>
++#include <string.h>
++
++GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
++#define GST_CAT_DEFAULT mssdemux_debug
++
++void
++gst_mss_fragment_parser_init (GstMssFragmentParser * parser)
++{
++  parser->status = GST_MSS_FRAGMENT_HEADER_PARSER_INIT;
++  parser->tfrf.entries_count = 0;
++}
++
++void
++gst_mss_fragment_parser_clear (GstMssFragmentParser * parser)
++{
++  parser->tfrf.entries_count = 0;
++  if (parser->tfrf.entries) {
++    g_free (parser->tfrf.entries);
++    parser->tfrf.entries = 0;
++  }
++}
++
++static gboolean
++_parse_tfrf_box (GstMssFragmentParser * parser, GstByteReader * reader)
++{
++  guint8 version;
++  guint32 flags = 0;
++  guint8 fragment_count = 0;
++  guint8 index = 0;
++
++  if (!gst_byte_reader_get_uint8 (reader, &version)) {
++    GST_ERROR ("Error getting box's version field");
++    return FALSE;
++  }
++
++  if (!gst_byte_reader_get_uint24_be (reader, &flags)) {
++    GST_ERROR ("Error getting box's flags field");
++    return FALSE;
++  }
++
++  gst_byte_reader_get_uint8 (reader, &fragment_count);
++  parser->tfrf.entries_count = fragment_count;
++  parser->tfrf.entries =
++      g_malloc (sizeof (GstTfrfBoxEntry) * parser->tfrf.entries_count);
++  for (index = 0; index < fragment_count; index++) {
++    guint64 absolute_time = 0;
++    guint64 absolute_duration = 0;
++    if (version & 0x01) {
++      gst_byte_reader_get_uint64_be (reader, &absolute_time);
++      gst_byte_reader_get_uint64_be (reader, &absolute_duration);
++    } else {
++      guint32 time = 0;
++      guint32 duration = 0;
++      gst_byte_reader_get_uint32_be (reader, &time);
++      gst_byte_reader_get_uint32_be (reader, &duration);
++      time = ~time;
++      duration = ~duration;
++      absolute_time = ~time;
++      absolute_duration = ~duration;
++    }
++    parser->tfrf.entries[index].time = absolute_time;
++    parser->tfrf.entries[index].duration = absolute_duration;
++  }
++
++  GST_LOG ("tfrf box parsed");
++  return TRUE;
++}
++
++static gboolean
++_parse_tfxd_box (GstMssFragmentParser * parser, GstByteReader * reader)
++{
++  guint8 version;
++  guint32 flags = 0;
++  guint64 absolute_time = 0;
++  guint64 absolute_duration = 0;
++
++  if (!gst_byte_reader_get_uint8 (reader, &version)) {
++    GST_ERROR ("Error getting box's version field");
++    return FALSE;
++  }
++
++  if (!gst_byte_reader_get_uint24_be (reader, &flags)) {
++    GST_ERROR ("Error getting box's flags field");
++    return FALSE;
++  }
++
++  if (version & 0x01) {
++    gst_byte_reader_get_uint64_be (reader, &absolute_time);
++    gst_byte_reader_get_uint64_be (reader, &absolute_duration);
++  } else {
++    guint32 time = 0;
++    guint32 duration = 0;
++    gst_byte_reader_get_uint32_be (reader, &time);
++    gst_byte_reader_get_uint32_be (reader, &duration);
++    time = ~time;
++    duration = ~duration;
++    absolute_time = ~time;
++    absolute_duration = ~duration;
++  }
++
++  parser->tfxd.time = absolute_time;
++  parser->tfxd.duration = absolute_duration;
++  GST_LOG ("tfxd box parsed");
++  return TRUE;
++}
++
++gboolean
++gst_mss_fragment_parser_add_buffer (GstMssFragmentParser * parser,
++    GstBuffer * buffer)
++{
++  GstByteReader reader;
++  GstMapInfo info;
++  guint32 size;
++  guint32 fourcc;
++  const guint8 *uuid;
++  gboolean error = FALSE;
++  gboolean mdat_box_found = FALSE;
++
++  static const guint8 tfrf_uuid[] = {
++    0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
++    0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
++  };
++
++  static const guint8 tfxd_uuid[] = {
++    0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
++    0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
++  };
++
++  static const guint8 piff_uuid[] = {
++    0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
++    0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
++  };
++
++  if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
++    return FALSE;
++  }
++
++  gst_byte_reader_init (&reader, info.data, info.size);
++  GST_TRACE ("Total buffer size: %u", gst_byte_reader_get_size (&reader));
++
++  size = gst_byte_reader_get_uint32_be_unchecked (&reader);
++  fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
++  if (fourcc == GST_MSS_FRAGMENT_FOURCC_MOOF) {
++    GST_TRACE ("moof box found");
++    size = gst_byte_reader_get_uint32_be_unchecked (&reader);
++    fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
++    if (fourcc == GST_MSS_FRAGMENT_FOURCC_MFHD) {
++      gst_byte_reader_skip_unchecked (&reader, size - 8);
++
++      size = gst_byte_reader_get_uint32_be_unchecked (&reader);
++      fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
++      if (fourcc == GST_MSS_FRAGMENT_FOURCC_TRAF) {
++        size = gst_byte_reader_get_uint32_be_unchecked (&reader);
++        fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
++        if (fourcc == GST_MSS_FRAGMENT_FOURCC_TFHD) {
++          gst_byte_reader_skip_unchecked (&reader, size - 8);
++
++          size = gst_byte_reader_get_uint32_be_unchecked (&reader);
++          fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
++          if (fourcc == GST_MSS_FRAGMENT_FOURCC_TRUN) {
++            GST_TRACE ("trun box found, size: %" G_GUINT32_FORMAT, size);
++            if (!gst_byte_reader_skip (&reader, size - 8)) {
++              GST_WARNING ("Failed to skip trun box, enough data?");
++              error = TRUE;
++              goto beach;
++            }
++          }
++        }
++      }
++    }
++  }
++
++  while (!mdat_box_found) {
++    GST_TRACE ("remaining data: %u", gst_byte_reader_get_remaining (&reader));
++    if (!gst_byte_reader_get_uint32_be (&reader, &size)) {
++      GST_WARNING ("Failed to get box size, enough data?");
++      error = TRUE;
++      break;
++    }
++
++    GST_TRACE ("box size: %" G_GUINT32_FORMAT, size);
++    if (!gst_byte_reader_get_uint32_le (&reader, &fourcc)) {
++      GST_WARNING ("Failed to get fourcc, enough data?");
++      error = TRUE;
++      break;
++    }
++
++    if (fourcc == GST_MSS_FRAGMENT_FOURCC_MDAT) {
++      GST_LOG ("mdat box found");
++      mdat_box_found = TRUE;
++      break;
++    }
++
++    if (fourcc != GST_MSS_FRAGMENT_FOURCC_UUID) {
++      GST_ERROR ("invalid UUID fourcc: %" GST_FOURCC_FORMAT,
++          GST_FOURCC_ARGS (fourcc));
++      error = TRUE;
++      break;
++    }
++
++    if (!gst_byte_reader_peek_data (&reader, 16, &uuid)) {
++      GST_ERROR ("not enough data in UUID box");
++      error = TRUE;
++      break;
++    }
++
++    if (memcmp (uuid, piff_uuid, 16) == 0) {
++      gst_byte_reader_skip_unchecked (&reader, size - 8);
++      GST_LOG ("piff box detected");
++    }
++
++    if (memcmp (uuid, tfrf_uuid, 16) == 0) {
++      gst_byte_reader_get_data (&reader, 16, &uuid);
++      if (!_parse_tfrf_box (parser, &reader)) {
++        GST_ERROR ("txrf box parsing error");
++        error = TRUE;
++        break;
++      }
++    }
++
++    if (memcmp (uuid, tfxd_uuid, 16) == 0) {
++      gst_byte_reader_get_data (&reader, 16, &uuid);
++      if (!_parse_tfxd_box (parser, &reader)) {
++        GST_ERROR ("tfrf box parsing error");
++        error = TRUE;
++        break;
++      }
++    }
++  }
++
++beach:
++
++  if (!error)
++    parser->status = GST_MSS_FRAGMENT_HEADER_PARSER_FINISHED;
++
++  GST_LOG ("Fragment parsing successful: %s", error ? "no" : "yes");
++  gst_buffer_unmap (buffer, &info);
++  return !error;
++}
+diff --git a/ext/smoothstreaming/gstmssfragmentparser.h b/ext/smoothstreaming/gstmssfragmentparser.h
+new file mode 100644
+index 000000000..cf4711865
+--- /dev/null
++++ b/ext/smoothstreaming/gstmssfragmentparser.h
+@@ -0,0 +1,84 @@
++/*
++ * Microsoft Smooth-Streaming fragment parsing library
++ *
++ * gstmssfragmentparser.h
++ *
++ * Copyright (C) 2016 Igalia S.L
++ * Copyright (C) 2016 Metrological
++ *   Author: Philippe Normand <philn@igalia.com>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library (COPYING); if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __GST_MSS_FRAGMENT_PARSER_H__
++#define __GST_MSS_FRAGMENT_PARSER_H__
++
++#include <gst/gst.h>
++
++G_BEGIN_DECLS
++
++#define GST_MSS_FRAGMENT_FOURCC_MOOF GST_MAKE_FOURCC('m','o','o','f')
++#define GST_MSS_FRAGMENT_FOURCC_MFHD GST_MAKE_FOURCC('m','f','h','d')
++#define GST_MSS_FRAGMENT_FOURCC_TRAF GST_MAKE_FOURCC('t','r','a','f')
++#define GST_MSS_FRAGMENT_FOURCC_TFHD GST_MAKE_FOURCC('t','f','h','d')
++#define GST_MSS_FRAGMENT_FOURCC_TRUN GST_MAKE_FOURCC('t','r','u','n')
++#define GST_MSS_FRAGMENT_FOURCC_UUID GST_MAKE_FOURCC('u','u','i','d')
++#define GST_MSS_FRAGMENT_FOURCC_MDAT GST_MAKE_FOURCC('m','d','a','t')
++
++typedef struct _GstTfxdBox
++{
++  guint8 version;
++  guint32 flags;
++
++  guint64 time;
++  guint64 duration;
++} GstTfxdBox;
++
++typedef struct _GstTfrfBoxEntry
++{
++  guint64 time;
++  guint64 duration;
++} GstTfrfBoxEntry;
++
++typedef struct _GstTfrfBox
++{
++  guint8 version;
++  guint32 flags;
++
++  gint entries_count;
++  GstTfrfBoxEntry *entries;
++} GstTfrfBox;
++
++typedef enum _GstFragmentHeaderParserStatus
++{
++  GST_MSS_FRAGMENT_HEADER_PARSER_INIT,
++  GST_MSS_FRAGMENT_HEADER_PARSER_FINISHED
++} GstFragmentHeaderParserStatus;
++
++typedef struct _GstMssFragmentParser
++{
++  GstFragmentHeaderParserStatus status;
++  GstTfxdBox tfxd;
++  GstTfrfBox tfrf;
++} GstMssFragmentParser;
++
++void gst_mss_fragment_parser_init (GstMssFragmentParser * parser);
++void gst_mss_fragment_parser_clear (GstMssFragmentParser * parser);
++gboolean gst_mss_fragment_parser_add_buffer (GstMssFragmentParser * parser, GstBuffer * buf);
++
++G_END_DECLS
++
++#endif /* __GST_MSS_FRAGMENT_PARSER_H__ */
+diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c
+index 144bbb42d..e1031ba55 100644
+--- a/ext/smoothstreaming/gstmssmanifest.c
++++ b/ext/smoothstreaming/gstmssmanifest.c
+@@ -1,5 +1,7 @@
+ /* GStreamer
+  * Copyright (C) 2012 Smart TV Alliance
++ * Copyright (C) 2016 Igalia S.L
++ * Copyright (C) 2016 Metrological
+  *  Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>, Collabora Ltd.
+  *
+  * gstmssmanifest.c:
+@@ -31,6 +33,7 @@
+ #include <gst/codecparsers/gsth264parser.h>
+ 
+ #include "gstmssmanifest.h"
++#include "gstmssfragmentparser.h"
+ 
+ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
+ #define GST_CAT_DEFAULT mssdemux_debug
+@@ -74,12 +77,17 @@ struct _GstMssStream
+   gboolean active;              /* if the stream is currently being used */
+   gint selectedQualityIndex;
+ 
++  gboolean has_live_fragments;
++  GstAdapter *live_adapter;
++
+   GList *fragments;
+   GList *qualities;
+ 
+   gchar *url;
+   gchar *lang;
+ 
++  GstMssFragmentParser fragment_parser;
++
+   guint fragment_repetition_index;
+   GList *current_fragment;
+   GList *current_quality;
+@@ -96,6 +104,7 @@ struct _GstMssManifest
+ 
+   gboolean is_live;
+   gint64 dvr_window;
++  guint64 look_ahead_fragment_count;
+ 
+   GString *protection_system_id;
+   gchar *protection_data;
+@@ -235,7 +244,8 @@ compare_bitrate (GstMssStreamQuality * a, GstMssStreamQuality * b)
+ }
+ 
+ static void
+-_gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)
++_gst_mss_stream_init (GstMssManifest * manifest, GstMssStream * stream,
++    xmlNodePtr node)
+ {
+   xmlNodePtr iter;
+   GstMssFragmentListBuilder builder;
+@@ -248,9 +258,21 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)
+   stream->url = (gchar *) xmlGetProp (node, (xmlChar *) MSS_PROP_URL);
+   stream->lang = (gchar *) xmlGetProp (node, (xmlChar *) MSS_PROP_LANGUAGE);
+ 
++  /* for live playback each fragment usually has timing
++   * information for the few next look-ahead fragments so the
++   * playlist can be built incrementally from the first fragment
++   * of the manifest.
++   */
++
++  GST_DEBUG ("Live stream: %s, look-ahead fragments: %" G_GUINT64_FORMAT,
++      manifest->is_live ? "yes" : "no", manifest->look_ahead_fragment_count);
++  stream->has_live_fragments = manifest->is_live
++      && manifest->look_ahead_fragment_count;
++
+   for (iter = node->children; iter; iter = iter->next) {
+     if (node_has_type (iter, MSS_NODE_STREAM_FRAGMENT)) {
+-      gst_mss_fragment_list_builder_add (&builder, iter);
++      if (!stream->has_live_fragments || !builder.fragments)
++        gst_mss_fragment_list_builder_add (&builder, iter);
+     } else if (node_has_type (iter, MSS_NODE_STREAM_QUALITY)) {
+       GstMssStreamQuality *quality = gst_mss_stream_quality_new (iter);
+       stream->qualities = g_list_prepend (stream->qualities, quality);
+@@ -259,17 +281,24 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)
+     }
+   }
+ 
+-  stream->fragments = g_list_reverse (builder.fragments);
++  if (stream->has_live_fragments) {
++    stream->live_adapter = gst_adapter_new ();
++  }
++
++  if (builder.fragments) {
++    stream->fragments = g_list_reverse (builder.fragments);
++    stream->current_fragment = stream->fragments;
++  }
+ 
+   /* order them from smaller to bigger based on bitrates */
+   stream->qualities =
+       g_list_sort (stream->qualities, (GCompareFunc) compare_bitrate);
+-
+-  stream->current_fragment = stream->fragments;
+   stream->current_quality = stream->qualities;
+ 
+   stream->regex_bitrate = g_regex_new ("\\{[Bb]itrate\\}", 0, 0, NULL);
+   stream->regex_position = g_regex_new ("\\{start[ _]time\\}", 0, 0, NULL);
++
++  gst_mss_fragment_parser_init (&stream->fragment_parser);
+ }
+ 
+ 
+@@ -315,6 +344,7 @@ gst_mss_manifest_new (GstBuffer * data)
+   xmlNodePtr nodeiter;
+   gchar *live_str;
+   GstMapInfo mapinfo;
++  gchar *look_ahead_fragment_count_str;
+ 
+   if (!gst_buffer_map (data, &mapinfo, GST_MAP_READ)) {
+     return NULL;
+@@ -335,6 +365,7 @@ gst_mss_manifest_new (GstBuffer * data)
+   /* the entire file is always available for non-live streams */
+   if (!manifest->is_live) {
+     manifest->dvr_window = 0;
++    manifest->look_ahead_fragment_count = 0;
+   } else {
+     /* if 0, or non-existent, the length is infinite */
+     gchar *dvr_window_str = (gchar *) xmlGetProp (root,
+@@ -346,6 +377,17 @@ gst_mss_manifest_new (GstBuffer * data)
+         manifest->dvr_window = 0;
+       }
+     }
++
++    look_ahead_fragment_count_str =
++        (gchar *) xmlGetProp (root, (xmlChar *) "LookAheadFragmentCount");
++    if (look_ahead_fragment_count_str) {
++      manifest->look_ahead_fragment_count =
++          g_ascii_strtoull (look_ahead_fragment_count_str, NULL, 10);
++      xmlFree (look_ahead_fragment_count_str);
++      if (manifest->look_ahead_fragment_count <= 0) {
++        manifest->look_ahead_fragment_count = 0;
++      }
++    }
+   }
+ 
+   for (nodeiter = root->children; nodeiter; nodeiter = nodeiter->next) {
+@@ -354,7 +396,7 @@ gst_mss_manifest_new (GstBuffer * data)
+       GstMssStream *stream = g_new0 (GstMssStream, 1);
+ 
+       manifest->streams = g_slist_append (manifest->streams, stream);
+-      _gst_mss_stream_init (stream, nodeiter);
++      _gst_mss_stream_init (manifest, stream, nodeiter);
+     }
+ 
+     if (nodeiter->type == XML_ELEMENT_NODE
+@@ -371,6 +413,11 @@ gst_mss_manifest_new (GstBuffer * data)
+ static void
+ gst_mss_stream_free (GstMssStream * stream)
+ {
++  if (stream->live_adapter) {
++    gst_adapter_clear (stream->live_adapter);
++    g_object_unref (stream->live_adapter);
++  }
++
+   g_list_free_full (stream->fragments, g_free);
+   g_list_free_full (stream->qualities,
+       (GDestroyNotify) gst_mss_stream_quality_free);
+@@ -379,6 +426,7 @@ gst_mss_stream_free (GstMssStream * stream)
+   g_regex_unref (stream->regex_position);
+   g_regex_unref (stream->regex_bitrate);
+   g_free (stream);
++  gst_mss_fragment_parser_clear (&stream->fragment_parser);
+ }
+ 
+ void
+@@ -1079,6 +1127,9 @@ GstFlowReturn
+ gst_mss_stream_advance_fragment (GstMssStream * stream)
+ {
+   GstMssStreamFragment *fragment;
++  const gchar *stream_type_name =
++      gst_mss_stream_type_name (gst_mss_stream_get_type (stream));
++
+   g_return_val_if_fail (stream->active, GST_FLOW_ERROR);
+ 
+   if (stream->current_fragment == NULL)
+@@ -1086,14 +1137,20 @@ gst_mss_stream_advance_fragment (GstMssStream * stream)
+ 
+   fragment = stream->current_fragment->data;
+   stream->fragment_repetition_index++;
+-  if (stream->fragment_repetition_index < fragment->repetitions) {
+-    return GST_FLOW_OK;
+-  }
++  if (stream->fragment_repetition_index < fragment->repetitions)
++    goto beach;
+ 
+   stream->fragment_repetition_index = 0;
+   stream->current_fragment = g_list_next (stream->current_fragment);
++
++  GST_DEBUG ("Advanced to fragment #%d on %s stream", fragment->number,
++      stream_type_name);
+   if (stream->current_fragment == NULL)
+     return GST_FLOW_EOS;
++
++beach:
++  gst_mss_fragment_parser_clear (&stream->fragment_parser);
++  gst_mss_fragment_parser_init (&stream->fragment_parser);
+   return GST_FLOW_OK;
+ }
+ 
+@@ -1173,6 +1230,11 @@ gst_mss_stream_seek (GstMssStream * stream, gboolean forward,
+   GST_DEBUG ("Stream %s seeking to %" G_GUINT64_FORMAT, stream->url, time);
+   for (iter = stream->fragments; iter; iter = g_list_next (iter)) {
+     fragment = iter->data;
++    if (stream->has_live_fragments) {
++      if (fragment->time + fragment->repetitions * fragment->duration > time)
++        stream->current_fragment = iter;
++      break;
++    }
+     if (fragment->time + fragment->repetitions * fragment->duration > time) {
+       stream->current_fragment = iter;
+       stream->fragment_repetition_index =
+@@ -1256,9 +1318,14 @@ static void
+ gst_mss_stream_reload_fragments (GstMssStream * stream, xmlNodePtr streamIndex)
+ {
+   xmlNodePtr iter;
+-  guint64 current_gst_time = gst_mss_stream_get_fragment_gst_timestamp (stream);
++  guint64 current_gst_time;
+   GstMssFragmentListBuilder builder;
+ 
++  if (stream->has_live_fragments)
++    return;
++
++  current_gst_time = gst_mss_stream_get_fragment_gst_timestamp (stream);
++
+   gst_mss_fragment_list_builder_init (&builder);
+ 
+   GST_DEBUG ("Current position: %" GST_TIME_FORMAT,
+@@ -1514,3 +1581,74 @@ gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start,
+ 
+   return ret;
+ }
++
++void
++gst_mss_manifest_live_adapter_push (GstMssStream * stream, GstBuffer * buffer)
++{
++  gst_adapter_push (stream->live_adapter, buffer);
++}
++
++gsize
++gst_mss_manifest_live_adapter_available (GstMssStream * stream)
++{
++  return gst_adapter_available (stream->live_adapter);
++}
++
++GstBuffer *
++gst_mss_manifest_live_adapter_take_buffer (GstMssStream * stream, gsize nbytes)
++{
++  return gst_adapter_take_buffer (stream->live_adapter, nbytes);
++}
++
++gboolean
++gst_mss_stream_fragment_parsing_needed (GstMssStream * stream)
++{
++  return stream->fragment_parser.status == GST_MSS_FRAGMENT_HEADER_PARSER_INIT;
++}
++
++void
++gst_mss_stream_parse_fragment (GstMssStream * stream, GstBuffer * buffer)
++{
++  GstMssStreamFragment *current_fragment = NULL;
++  const gchar *stream_type_name;
++  guint8 index;
++
++  if (!stream->has_live_fragments)
++    return;
++
++  if (!gst_mss_fragment_parser_add_buffer (&stream->fragment_parser, buffer))
++    return;
++
++  current_fragment = stream->current_fragment->data;
++  current_fragment->time = stream->fragment_parser.tfxd.time;
++  current_fragment->duration = stream->fragment_parser.tfxd.duration;
++
++  stream_type_name =
++      gst_mss_stream_type_name (gst_mss_stream_get_type (stream));
++
++  for (index = 0; index < stream->fragment_parser.tfrf.entries_count; index++) {
++    GList *l = g_list_last (stream->fragments);
++    GstMssStreamFragment *last;
++    GstMssStreamFragment *fragment;
++
++    if (l == NULL)
++      break;
++
++    last = (GstMssStreamFragment *) l->data;
++
++    if (last->time == stream->fragment_parser.tfrf.entries[index].time)
++      continue;
++
++    fragment = g_new (GstMssStreamFragment, 1);
++    fragment->number = last->number + 1;
++    fragment->repetitions = 1;
++    fragment->time = stream->fragment_parser.tfrf.entries[index].time;
++    fragment->duration = stream->fragment_parser.tfrf.entries[index].duration;
++
++    stream->fragments = g_list_append (stream->fragments, fragment);
++    GST_LOG ("Adding fragment number: %u to %s stream, time: %" G_GUINT64_FORMAT
++        ", duration: %" G_GUINT64_FORMAT ", repetitions: %u",
++        fragment->number, stream_type_name,
++        fragment->time, fragment->duration, fragment->repetitions);
++  }
++}
+diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h
+index 6b7b1f971..03b066ae5 100644
+--- a/ext/smoothstreaming/gstmssmanifest.h
++++ b/ext/smoothstreaming/gstmssmanifest.h
+@@ -26,6 +26,7 @@
+ #include <glib.h>
+ #include <gio/gio.h>
+ #include <gst/gst.h>
++#include <gst/base/gstadapter.h>
+ 
+ G_BEGIN_DECLS
+ 
+@@ -73,5 +74,11 @@ const gchar * gst_mss_stream_get_lang (GstMssStream * stream);
+ 
+ const gchar * gst_mss_stream_type_name (GstMssStreamType streamtype);
+ 
++void gst_mss_manifest_live_adapter_push(GstMssStream * stream, GstBuffer * buffer);
++gsize gst_mss_manifest_live_adapter_available(GstMssStream * stream);
++GstBuffer * gst_mss_manifest_live_adapter_take_buffer(GstMssStream * stream, gsize nbytes);
++gboolean gst_mss_stream_fragment_parsing_needed(GstMssStream * stream);
++void gst_mss_stream_parse_fragment(GstMssStream * stream, GstBuffer * buffer);
++
+ G_END_DECLS
+ #endif /* __GST_MSS_MANIFEST_H__ */
+diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
+index 634e4f388..ddca726b6 100644
+--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
++++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
+@@ -291,6 +291,9 @@ gst_adaptive_demux_wait_until (GstClock * clock, GCond * cond, GMutex * mutex,
+     GstClockTime end_time);
+ static gboolean gst_adaptive_demux_clock_callback (GstClock * clock,
+     GstClockTime time, GstClockID id, gpointer user_data);
++static gboolean
++gst_adaptive_demux_requires_periodical_playlist_update_default (GstAdaptiveDemux
++    * demux);
+ 
+ /* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
+  * method to get to the padtemplates */
+@@ -412,6 +415,9 @@ gst_adaptive_demux_class_init (GstAdaptiveDemuxClass * klass)
+   klass->data_received = gst_adaptive_demux_stream_data_received_default;
+   klass->finish_fragment = gst_adaptive_demux_stream_finish_fragment_default;
+   klass->update_manifest = gst_adaptive_demux_update_manifest_default;
++  klass->requires_periodical_playlist_update =
++      gst_adaptive_demux_requires_periodical_playlist_update_default;
++
+ }
+ 
+ static void
+@@ -686,7 +692,9 @@ gst_adaptive_demux_sink_event (GstPad * pad, GstObject * parent,
+             demux->priv->stop_updates_task = FALSE;
+             g_mutex_unlock (&demux->priv->updates_timed_lock);
+             /* Task to periodically update the manifest */
+-            gst_task_start (demux->priv->updates_task);
++            if (demux_class->requires_periodical_playlist_update (demux)) {
++              gst_task_start (demux->priv->updates_task);
++            }
+           }
+         } else {
+           /* no streams */
+@@ -2125,6 +2133,13 @@ gst_adaptive_demux_stream_data_received_default (GstAdaptiveDemux * demux,
+   return gst_adaptive_demux_stream_push_buffer (stream, buffer);
+ }
+ 
++static gboolean
++gst_adaptive_demux_requires_periodical_playlist_update_default (GstAdaptiveDemux
++    * demux)
++{
++  return TRUE;
++}
++
+ static GstFlowReturn
+ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
+ {
+@@ -3338,7 +3353,15 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)
+       GST_DEBUG_OBJECT (stream->pad, "EOS, checking to stop download loop");
+       /* we push the EOS after releasing the object lock */
+       if (gst_adaptive_demux_is_live (demux)) {
+-        if (gst_adaptive_demux_stream_wait_manifest_update (demux, stream)) {
++        GstAdaptiveDemuxClass *demux_class =
++            GST_ADAPTIVE_DEMUX_GET_CLASS (demux);
++
++        /* this might be a fragment download error, refresh the manifest, just in case */
++        if (!demux_class->requires_periodical_playlist_update (demux)) {
++          ret = gst_adaptive_demux_update_manifest (demux);
++          break;
++        } else if (gst_adaptive_demux_stream_wait_manifest_update (demux,
++                stream)) {
+           goto end;
+         }
+         gst_task_stop (stream->download_task);
+diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
+index 780f4d93f..9a1a1b7d1 100644
+--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
++++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
+@@ -459,6 +459,20 @@ struct _GstAdaptiveDemuxClass
+    * selected period.
+    */
+   GstClockTime (*get_period_start_time) (GstAdaptiveDemux *demux);
++
++  /**
++   * requires_periodical_playlist_update:
++   * @demux: #GstAdaptiveDemux
++   *
++   * Some adaptive streaming protocols allow the client to download
++   * the playlist once and build up the fragment list based on the
++   * current fragment metadata. For those protocols the demuxer
++   * doesn't need to periodically refresh the playlist. This vfunc
++   * is relevant only for live playback scenarios.
++   *
++   * Return: %TRUE if the playlist needs to be refreshed periodically by the demuxer.
++   */
++  gboolean (*requires_periodical_playlist_update) (GstAdaptiveDemux * demux);
+ };
+ 
+ GType    gst_adaptive_demux_get_type (void);
+-- 
+2.11.0
+
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
new file mode 100644
index 0000000000..76d29e151b
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch
@@ -0,0 +1,183 @@
+From e9178fa082116d4bf733b184a8b6951112c17900 Mon Sep 17 00:00:00 2001
+From: Matthew Waters <matthew@centricular.com>
+Date: Thu, 10 Nov 2016 17:18:36 +1100
+Subject: [PATCH] smoothstreaming: implement adaptivedemux's
+ get_live_seek_range()
+
+Allows seeking through the available fragments that are still available
+on the server as specified by the DVRWindowLength attribute in the
+manifest.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774178
+---
+Upstream-Status: Backport
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+
+ ext/smoothstreaming/gstmssdemux.c    | 13 ++++++
+ ext/smoothstreaming/gstmssmanifest.c | 84 ++++++++++++++++++++++++++++++++++++
+ ext/smoothstreaming/gstmssmanifest.h |  1 +
+ 3 files changed, 98 insertions(+)
+
+diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c
+index 9d0aece2b..b66e19514 100644
+--- a/ext/smoothstreaming/gstmssdemux.c
++++ b/ext/smoothstreaming/gstmssdemux.c
+@@ -138,6 +138,8 @@ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);
+ static GstFlowReturn
+ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
+     GstBuffer * buffer);
++static gboolean gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux,
++    gint64 * start, gint64 * stop);
+ 
+ static void
+ gst_mss_demux_class_init (GstMssDemuxClass * klass)
+@@ -192,6 +194,8 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)
+       gst_mss_demux_stream_update_fragment_info;
+   gstadaptivedemux_class->update_manifest_data =
+       gst_mss_demux_update_manifest_data;
++  gstadaptivedemux_class->get_live_seek_range =
++      gst_mss_demux_get_live_seek_range;
+ 
+   GST_DEBUG_CATEGORY_INIT (mssdemux_debug, "mssdemux", 0, "mssdemux plugin");
+ }
+@@ -659,3 +663,12 @@ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
+   gst_mss_manifest_reload_fragments (mssdemux->manifest, buffer);
+   return GST_FLOW_OK;
+ }
++
++static gboolean
++gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
++    gint64 * stop)
++{
++  GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
++
++  return gst_mss_manifest_get_live_seek_range (mssdemux->manifest, start, stop);
++}
+diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c
+index 1b72e8de1..317b3cef9 100644
+--- a/ext/smoothstreaming/gstmssmanifest.c
++++ b/ext/smoothstreaming/gstmssmanifest.c
+@@ -42,6 +42,7 @@ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
+ 
+ #define MSS_PROP_BITRATE              "Bitrate"
+ #define MSS_PROP_DURATION             "d"
++#define MSS_PROP_DVR_WINDOW_LENGTH    "DVRWindowLength"
+ #define MSS_PROP_LANGUAGE             "Language"
+ #define MSS_PROP_NUMBER               "n"
+ #define MSS_PROP_REPETITIONS          "r"
+@@ -94,6 +95,7 @@ struct _GstMssManifest
+   xmlNodePtr xmlrootnode;
+ 
+   gboolean is_live;
++  gint64 dvr_window;
+ 
+   GString *protection_system_id;
+   gchar *protection_data;
+@@ -330,6 +332,22 @@ gst_mss_manifest_new (GstBuffer * data)
+     xmlFree (live_str);
+   }
+ 
++  /* the entire file is always available for non-live streams */
++  if (!manifest->is_live) {
++    manifest->dvr_window = 0;
++  } else {
++    /* if 0, or non-existent, the length is infinite */
++    gchar *dvr_window_str = (gchar *) xmlGetProp (root,
++        (xmlChar *) MSS_PROP_DVR_WINDOW_LENGTH);
++    if (dvr_window_str) {
++      manifest->dvr_window = g_ascii_strtoull (dvr_window_str, NULL, 10);
++      xmlFree (dvr_window_str);
++      if (manifest->dvr_window <= 0) {
++        manifest->dvr_window = 0;
++      }
++    }
++  }
++
+   for (nodeiter = root->children; nodeiter; nodeiter = nodeiter->next) {
+     if (nodeiter->type == XML_ELEMENT_NODE
+         && (strcmp ((const char *) nodeiter->name, "StreamIndex") == 0)) {
+@@ -1406,3 +1424,69 @@ gst_mss_stream_get_lang (GstMssStream * stream)
+ {
+   return stream->lang;
+ }
++
++static GstClockTime
++gst_mss_manifest_get_dvr_window_length_clock_time (GstMssManifest * manifest)
++{
++  gint64 timescale;
++
++  /* the entire file is always available for non-live streams */
++  if (manifest->dvr_window == 0)
++    return GST_CLOCK_TIME_NONE;
++
++  timescale = gst_mss_manifest_get_timescale (manifest);
++  return (GstClockTime) gst_util_uint64_scale_round (manifest->dvr_window,
++      GST_SECOND, timescale);
++}
++
++static gboolean
++gst_mss_stream_get_live_seek_range (GstMssStream * stream, gint64 * start,
++    gint64 * stop)
++{
++  GList *l;
++  GstMssStreamFragment *fragment;
++  guint64 timescale = gst_mss_stream_get_timescale (stream);
++
++  g_return_val_if_fail (stream->active, FALSE);
++
++  /* XXX: assumes all the data in the stream is still available */
++  l = g_list_first (stream->fragments);
++  fragment = (GstMssStreamFragment *) l->data;
++  *start = gst_util_uint64_scale_round (fragment->time, GST_SECOND, timescale);
++
++  l = g_list_last (stream->fragments);
++  fragment = (GstMssStreamFragment *) l->data;
++  *stop = gst_util_uint64_scale_round (fragment->time + fragment->duration *
++      fragment->repetitions, GST_SECOND, timescale);
++
++  return TRUE;
++}
++
++gboolean
++gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start,
++    gint64 * stop)
++{
++  GSList *iter;
++  gboolean ret = FALSE;
++
++  for (iter = manifest->streams; iter; iter = g_slist_next (iter)) {
++    GstMssStream *stream = iter->data;
++
++    if (stream->active) {
++      /* FIXME: bound this correctly for multiple streams */
++      if (!(ret = gst_mss_stream_get_live_seek_range (stream, start, stop)))
++        break;
++    }
++  }
++
++  if (ret && gst_mss_manifest_is_live (manifest)) {
++    GstClockTime dvr_window =
++        gst_mss_manifest_get_dvr_window_length_clock_time (manifest);
++
++    if (GST_CLOCK_TIME_IS_VALID (dvr_window) && *stop - *start > dvr_window) {
++      *start = *stop - dvr_window;
++    }
++  }
++
++  return ret;
++}
+diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h
+index af7419c23..6b7b1f971 100644
+--- a/ext/smoothstreaming/gstmssmanifest.h
++++ b/ext/smoothstreaming/gstmssmanifest.h
+@@ -54,6 +54,7 @@ void gst_mss_manifest_reload_fragments (GstMssManifest * manifest, GstBuffer * d
+ GstClockTime gst_mss_manifest_get_min_fragment_duration (GstMssManifest * manifest);
+ const gchar * gst_mss_manifest_get_protection_system_id (GstMssManifest * manifest);
+ const gchar * gst_mss_manifest_get_protection_data (GstMssManifest * manifest);
++gboolean gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start, gint64 * stop);
+ 
+ GstMssStreamType gst_mss_stream_get_type (GstMssStream *stream);
+ GstCaps * gst_mss_stream_get_caps (GstMssStream * stream);
+-- 
+2.11.0
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-use-the-duration-from-the-list-of-fr.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-use-the-duration-from-the-list-of-fr.patch
new file mode 100644
index 0000000000..4e51040863
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-smoothstreaming-use-the-duration-from-the-list-of-fr.patch
@@ -0,0 +1,62 @@
+From 0fbee8f37427b88339194b22ba9aa210772a8613 Mon Sep 17 00:00:00 2001
+From: Matthew Waters <matthew@centricular.com>
+Date: Thu, 10 Nov 2016 17:20:27 +1100
+Subject: [PATCH] smoothstreaming: use the duration from the list of fragments
+ if not present in the manifest
+
+Provides a more accurate duration for live streams that may be minutes
+or hours in front of the earliest fragment.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774178
+---
+Upstream-Status: Backport
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+
+ ext/smoothstreaming/gstmssmanifest.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c
+index 317b3cef9..144bbb42d 100644
+--- a/ext/smoothstreaming/gstmssmanifest.c
++++ b/ext/smoothstreaming/gstmssmanifest.c
+@@ -888,6 +888,7 @@ gst_mss_manifest_get_duration (GstMssManifest * manifest)
+   gchar *duration;
+   guint64 dur = -1;
+ 
++  /* try the property */
+   duration =
+       (gchar *) xmlGetProp (manifest->xmlrootnode,
+       (xmlChar *) MSS_PROP_STREAM_DURATION);
+@@ -895,6 +896,29 @@ gst_mss_manifest_get_duration (GstMssManifest * manifest)
+     dur = g_ascii_strtoull (duration, NULL, 10);
+     xmlFree (duration);
+   }
++  /* else use the fragment list */
++  if (dur <= 0) {
++    guint64 max_dur = 0;
++    GSList *iter;
++
++    for (iter = manifest->streams; iter; iter = g_slist_next (iter)) {
++      GstMssStream *stream = iter->data;
++
++      if (stream->active) {
++        if (stream->fragments) {
++          GList *l = g_list_last (stream->fragments);
++          GstMssStreamFragment *fragment = (GstMssStreamFragment *) l->data;
++          guint64 frag_dur =
++              fragment->time + fragment->duration * fragment->repetitions;
++          max_dur = MAX (frag_dur, max_dur);
++        }
++      }
++    }
++
++    if (max_dur != 0)
++      dur = max_dur;
++  }
++
+   return dur;
+ }
+ 
+-- 
+2.11.0
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.2.bb
index e257a589ad..9bcc15f522 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.10.2.bb
@@ -15,6 +15,9 @@ SRC_URI = " \
     file://0009-glimagesink-Downrank-to-marginal.patch \
     file://0001-introspection.m4-prefix-pkgconfig-paths-with-PKG_CON.patch \
     file://0001-Prepend-PKG_CONFIG_SYSROOT_DIR-to-pkg-config-output.patch \
+    file://0001-smoothstreaming-implement-adaptivedemux-s-get_live_s.patch \
+    file://0001-smoothstreaming-use-the-duration-from-the-list-of-fr.patch \
+    file://0001-mssdemux-improved-live-playback-support.patch \
 "
 SRC_URI[md5sum] = "823f4c33fe27c61332c0122273217988"
 SRC_URI[sha256sum] = "0795ca9303a99cc7e44dda0e6e18524de02b39892e4b68eaba488f7b9db53a3a"
