tizen 2.0 init
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 21 Aug 2012 13:52:12 +0000 (22:52 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 21 Aug 2012 13:52:12 +0000 (22:52 +0900)
43 files changed:
Makefile.am [changed mode: 0644->0755]
audiotp/Makefile.am [new file with mode: 0755]
audiotp/src/Makefile.am [new file with mode: 0755]
audiotp/src/gstaudiotp.c [new file with mode: 0755]
audiotp/src/gstaudiotp.h [new file with mode: 0755]
avsystem/src/gstavsysaudiosink.c
avsystem/src/gstavsysaudiosrc.c
avsystem/src/gstavsysmemsink.c
avsystem/src/gstavsyssink.c
configure.ac
debian/changelog [deleted file]
debian/compat [deleted file]
debian/control [deleted file]
debian/copyright [deleted file]
debian/gstreamer0.10-plugins-ext.install.in [deleted file]
debian/rules [deleted file]
drmsrc/src/Makefile.am
drmsrc/src/gstdrmsrc.c
drmsrc/src/gstdrmsrc.h
evasimagesink/src/Makefile.am
evasimagesink/src/gstevasimagesink.c
evasimagesink/src/gstevasimagesink.h
packaging/gst-plugins-ext0.10.spec
pdpushsrc/src/gstpdpushsrc.c
piffdemux/Makefile.am [new file with mode: 0755]
piffdemux/src/Makefile.am [new file with mode: 0755]
piffdemux/src/piff-plugin.c [new file with mode: 0755]
piffdemux/src/piffatomparser.h [new file with mode: 0755]
piffdemux/src/piffcommon.h [new file with mode: 0755]
piffdemux/src/piffdemux.c [new file with mode: 0755]
piffdemux/src/piffdemux.h [new file with mode: 0755]
piffdemux/src/piffdemux_dump.c [new file with mode: 0755]
piffdemux/src/piffdemux_dump.h [new file with mode: 0755]
piffdemux/src/piffdemux_fourcc.h [new file with mode: 0755]
piffdemux/src/piffdemux_types.c [new file with mode: 0755]
piffdemux/src/piffdemux_types.h [new file with mode: 0755]
piffdemux/src/piffpalette.h [new file with mode: 0755]
ssdemux/Makefile.am [new file with mode: 0755]
ssdemux/src/Makefile.am [new file with mode: 0755]
ssdemux/src/gstssdemux.c [new file with mode: 0755]
ssdemux/src/gstssdemux.h [new file with mode: 0755]
ssdemux/src/ssmanifestparse.c [new file with mode: 0755]
ssdemux/src/ssmanifestparse.h [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 6b9383e..e15e0c5
@@ -5,6 +5,10 @@ aclocaldir = $(datadir)/aclocal
 
 SUBDIRS = common
 
+if GST_EXT_USE_EXT_PIFFDEMUX
+#SUBDIRS += piffdemux
+endif
+
 if GST_EXT_USE_EXT_ENCODEBIN
 SUBDIRS += encodebin
 endif
@@ -29,8 +33,22 @@ if GST_EXT_USE_EXT_AVSYSTEM
 SUBDIRS += pdpushsrc
 endif
 
+if GST_EXT_USE_EXT_AUDIOTP
+SUBDIRS += audiotp
+endif
+
+if GST_EXT_USE_EXT_SSDEMUX
+#SUBDIRS += ssdemux
+endif
+
+
+
 DIST_SUBDIRS = common
 
+if GST_EXT_USE_EXT_PIFFDEMUX
+#DIST_SUBDIRS += piffdemux
+endif
+
 if GST_EXT_USE_EXT_ENCODEBIN
 DIST_SUBDIRS += encodebin
 endif
@@ -51,6 +69,11 @@ if GST_EXT_USE_EXT_TOGGLE
 DIST_SUBDIRS += toggle
 endif
 
+if GST_EXT_USE_EXT_SSDEMUX
+#DIST_SUBDIRS += ssdemux
+endif
+
+
 
 EXTRA_DIST = \
        gstreamer.spec gstreamer.spec.in \
diff --git a/audiotp/Makefile.am b/audiotp/Makefile.am
new file mode 100755 (executable)
index 0000000..308a09c
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src\r
diff --git a/audiotp/src/Makefile.am b/audiotp/src/Makefile.am
new file mode 100755 (executable)
index 0000000..436666c
--- /dev/null
@@ -0,0 +1,26 @@
+# plugindir is set in configure
+
+##############################################################################
+# change libgstplugin.la to something more suitable, e.g. libmysomething.la  #
+##############################################################################
+plugin_LTLIBRARIES = libgstaudiotp.la
+
+##############################################################################
+# for the next set of variables, rename the prefix if you renamed the .la,   #
+#  e.g. libgstplugin_la_SOURCES => libmysomething_la_SOURCES                 #
+#       libgstplugin_la_CFLAGS  => libmysomething_la_CFLAGS                  #
+#       libgstplugin_la_LIBADD  => libmysomething_la_LIBADD                  #
+#       libgstplugin_la_LDFLAGS => libmysomething_la_LDFLAGS                 #
+##############################################################################
+
+# sources used to compile this plug-in
+libgstaudiotp_la_SOURCES = gstaudiotp.c
+
+# flags used to compile this plugin
+# add other _CFLAGS and _LIBS as needed
+libgstaudiotp_la_CFLAGS = $(GST_CFLAGS)  $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS)
+libgstaudiotp_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS)  $(GST_BASE_LIBS)
+libgstaudiotp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+# headers we need but don't want installed
+noinst_HEADERS = gstaudiotp.h
\ No newline at end of file
diff --git a/audiotp/src/gstaudiotp.c b/audiotp/src/gstaudiotp.c
new file mode 100755 (executable)
index 0000000..5b1419b
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * audiotp
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstaudiotp.h"
+
+/* Plugin Detaills for gstreamer */
+static const GstElementDetails gst_audiotp_plugin_details = GST_ELEMENT_DETAILS (
+ "Audio timestamp reversal plugin",
+ "Utility/Audio",
+ "Reverses audio timestamps for reverse playback",
+ "Samsung Electronics <www.samsung.com>"
+ );
+
+/*** GSTREAMER PROTOTYPES *****************************************************/
+
+#define STATIC_CAPS \
+GST_STATIC_CAPS ( \
+  "audio/x-raw-float, " \
+    "rate = (int) [ 1, MAX ], " \
+    "channels = (int) [ 1, MAX ], " \
+    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
+    "width = (int) 64;" \
+  "audio/x-raw-float, " \
+    "rate = (int) [ 1, MAX ], " \
+    "channels = (int) [ 1, MAX ], " \
+    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
+    "width = (int) 32;" \
+  "audio/x-raw-int, " \
+    "rate = (int) [ 1, MAX ], " \
+    "channels = (int) [ 1, MAX ], " \
+    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
+    "width = (int) 32, " \
+    "depth = (int) [ 1, 32 ], " \
+    "signed = (boolean) { true, false }; " \
+  "audio/x-raw-int, "   \
+    "rate = (int) [ 1, MAX ], " \
+    "channels = (int) [ 1, MAX ], "       \
+    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "        \
+    "width = (int) 24, "        \
+    "depth = (int) [ 1, 24 ], " "signed = (boolean) { true, false }; "  \
+  "audio/x-raw-int, " \
+    "rate = (int) [ 1, MAX ], " \
+    "channels = (int) [ 1, MAX ], " \
+    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
+    "width = (int) 16, " \
+    "depth = (int) [ 1, 16 ], " \
+    "signed = (boolean) { true, false }; " \
+  "audio/x-raw-int, " \
+    "rate = (int) [ 1, MAX ], " \
+    "channels = (int) [ 1, MAX ], " \
+    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
+    "width = (int) 8, " \
+    "depth = (int) [ 1, 8 ], " \
+    "signed = (boolean) { true, false } " \
+)
+
+/* Element sink pad template */
+static GstStaticPadTemplate gst_audiotp_sink_template = GST_STATIC_PAD_TEMPLATE (
+ "sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ STATIC_CAPS);
+
+/* Element Source Pad template */
+static GstStaticPadTemplate gst_audiotp_src_template = GST_STATIC_PAD_TEMPLATE (
+ "src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ STATIC_CAPS);
+
+
+////////////////////////////////////////////////////////
+//        Gstreamer Base Prototype                    //
+////////////////////////////////////////////////////////
+
+GST_DEBUG_CATEGORY_STATIC(gst_audiotp_debug);
+#define GST_CAT_DEFAULT gst_audiotp_debug
+#define _do_init(bla) \
+ GST_DEBUG_CATEGORY_INIT(GST_CAT_DEFAULT, "audiotp", 0, "Audio trickplay plugin"); \
+ GST_DEBUG("audiotp is registered");
+
+GST_BOILERPLATE_FULL(Gstaudiotp, gst_audiotp, GstElement, GST_TYPE_ELEMENT, _do_init);
+
+static void gst_audiotp_base_init(gpointer klass);
+static void gst_audiotp_class_init(GstaudiotpClass *klass);
+static void gst_audiotp_init(Gstaudiotp *dec, GstaudiotpClass *klass);
+static GstFlowReturn gst_audiotp_chain(GstPad *pad, GstBuffer *buf);
+static GstStateChangeReturn gst_audiotp_change_state(GstElement *element, GstStateChange transition);
+static void gst_audiotp_finalize(GObject *object);
+static gboolean gst_audiotp_sink_event (GstPad *pad, GstEvent *event);
+static GstFlowReturn gst_audiotp_push_silent_frame (Gstaudiotp *audiotp, GstBuffer *MetaDataBuf);
+
+
+
+////////////////////////////////////////////////////////
+//        Gstreamer Base Functions                    //
+////////////////////////////////////////////////////////
+
+/**
+ **
+ **  Description: The element details and pad templates are registered with the plugin
+ **  In Params    : @ gclass instance of Element class
+ **  return    : None
+ **  Comments    : 1. Adding templates of source and sink pad to element
+ **           2. Setting element class deatils to element
+ **
+ */
+static void
+gst_audiotp_base_init(gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
+
+  gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&gst_audiotp_sink_template));
+  gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&gst_audiotp_src_template));
+  gst_element_class_set_details(element_class, &gst_audiotp_plugin_details);
+}
+
+
+/**
+ **
+ **  Description: Initialization of the Element Class
+ **  In Param    : @ gclass instance of Element class
+ **  return    : None
+ **  Comments    : 1. Overwriting base class virtual functions
+ **                2. Installing the properties of the element
+ **
+ */
+static void
+gst_audiotp_class_init(GstaudiotpClass *klass)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS(klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+  parent_class = g_type_class_peek_parent(klass);
+
+  gobject_class->finalize = gst_audiotp_finalize;
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_audiotp_change_state);
+}
+
+
+/**
+ **
+ **  Description: Initialization of the Element instance
+ **  In Params    : @ audio tp element instance
+ **           @ gclass instance of Element class
+ **  return    : None
+ **  Comments    : 1. Creating new source & sink pads using templates
+ **           2. Setting the callback functions to the pads
+ **          3. Local data initialization.
+ **
+ */
+static void
+gst_audiotp_init(Gstaudiotp *audiotp, GstaudiotpClass *klass)
+{
+
+  audiotp->sinkpad = gst_pad_new_from_static_template(&gst_audiotp_sink_template, "sink");
+  audiotp->srcpad = gst_pad_new_from_static_template(&gst_audiotp_src_template, "src");
+
+  gst_pad_set_chain_function (audiotp->sinkpad, GST_DEBUG_FUNCPTR(gst_audiotp_chain));
+  gst_pad_set_event_function (audiotp->sinkpad, GST_DEBUG_FUNCPTR(gst_audiotp_sink_event));
+
+  gst_pad_use_fixed_caps(audiotp->srcpad);
+
+  gst_element_add_pad(GST_ELEMENT(audiotp), audiotp->sinkpad);
+  gst_element_add_pad(GST_ELEMENT(audiotp), audiotp->srcpad);
+
+  audiotp->reverse = g_queue_new ();
+  audiotp->head_prev = GST_CLOCK_TIME_NONE;
+  audiotp->tail_prev = GST_CLOCK_TIME_NONE;
+
+}
+
+
+/**
+ **
+ **  Description: Finalization of the Element instance (object)
+ **  In Params    : @ audiotp element instance in the form of GObject
+ **  return    : None
+ **  Comments    : 1. Local data Deinitialization.
+ **
+ **
+ */
+static void
+gst_audiotp_finalize(GObject *object)
+{
+  Gstaudiotp *audiotp = GST_AUDIOTP(object);
+
+  while (!g_queue_is_empty (audiotp->reverse)) {
+    GstMiniObject *data = g_queue_pop_head (audiotp->reverse);
+    gst_mini_object_unref (data);
+  }
+  /* freeing dealy queue */
+  g_queue_free(audiotp->reverse);
+  audiotp->reverse = NULL;
+
+  G_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+
+/**
+ **
+ **  Description: Callback function when the element's state gets changed
+ **  In Params    : @ audiotp plugin element
+ **          @ type of state change
+ **  return    : status of the state change processing
+ **  Comments    :
+ **
+ **
+ */
+static GstStateChangeReturn
+gst_audiotp_change_state(GstElement *element, GstStateChange transition)
+{
+  GstStateChangeReturn res = GST_FLOW_ERROR;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      break;
+    default:
+      break;
+  }
+
+  res = parent_class->change_state(element, transition);
+  if ( res != GST_STATE_CHANGE_SUCCESS ) {
+    GST_ERROR ("change state error in parent class\n");
+    return GST_STATE_CHANGE_FAILURE;
+  }
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  return res;
+}
+
+
+/**
+ **
+ **  Description: Callback function when sinkpad gets an event
+ **  In Params    : @ Sinkpad on which the event arrives
+ **          @ event type
+ **  return    : TRUE/FALSE on success/failure of the event processing.
+ **  Comments    : 1. Process the event and push it to the source pad.
+ **
+ **
+ */
+static gboolean
+gst_audiotp_sink_event (GstPad *pad, GstEvent *event)
+{
+  Gstaudiotp *audiotp = NULL;
+  gboolean res = FALSE;
+
+  audiotp = GST_AUDIOTP(GST_PAD_PARENT(pad));
+
+  switch (GST_EVENT_TYPE(event)) {
+    /* Arrives whenever there is a jump in the normal playback. Ex:SEEK */
+    case GST_EVENT_NEWSEGMENT: {
+      GstFormat format;
+      gdouble rate, arate;
+      gint64 start, stop, time;
+      gboolean update;
+
+      GST_INFO_OBJECT (audiotp, "GST_EVENT_NEWSEGMENT");
+      gst_event_parse_new_segment_full(event, &update, &rate, &arate, &format, &start, &stop, &time);
+
+      if (format != GST_FORMAT_TIME) {
+        GST_ERROR("Format is not supported\n");
+        res = gst_pad_push_event(audiotp->srcpad, event);
+        goto done;
+      }
+
+      GST_INFO_OBJECT (audiotp, "update: %d, rate: %0.3f, arate: %0.3f\n", update, rate, arate);
+      GST_INFO_OBJECT (audiotp, "start : %" GST_TIME_FORMAT, GST_TIME_ARGS(start));
+      GST_INFO_OBJECT (audiotp, "stop  : %" GST_TIME_FORMAT, GST_TIME_ARGS(stop));
+      GST_INFO_OBJECT (audiotp, "time  : %" GST_TIME_FORMAT, GST_TIME_ARGS(time));
+
+      /* If we receive new_segment without FLUSH events, then we will push all the frame in queue */
+      while (!g_queue_is_empty (audiotp->reverse)) {
+           GstBuffer *MetaDataBuf;
+        GstFlowReturn ret = GST_FLOW_OK;
+               if(audiotp->is_reversed)
+          MetaDataBuf = g_queue_pop_head (audiotp->reverse);
+               else
+                 MetaDataBuf = g_queue_pop_tail (audiotp->reverse);
+        ret = gst_audiotp_push_silent_frame (audiotp, MetaDataBuf);
+        if (GST_FLOW_OK != ret)
+        {
+           GST_WARNING_OBJECT (audiotp, "pad_push returned = %s", gst_flow_get_name (ret));
+        }
+      }
+      gst_segment_set_newsegment_full(&audiotp->segment, update, rate, arate, format, start, stop, time);
+      res = gst_pad_push_event(audiotp->srcpad, event);
+      break;
+    }
+
+    /* Indication of the end of the stream */
+    case GST_EVENT_EOS: {
+      /* queue all buffer timestamps till we receive next discontinuity */
+      while (!g_queue_is_empty (audiotp->reverse)) {
+           GstBuffer *MetaDataBuf;
+        GstFlowReturn ret = GST_FLOW_OK;
+               if(audiotp->is_reversed)
+          MetaDataBuf = g_queue_pop_head (audiotp->reverse);
+               else
+                 MetaDataBuf = g_queue_pop_tail (audiotp->reverse);
+        ret = gst_audiotp_push_silent_frame (audiotp, MetaDataBuf);
+        if (GST_FLOW_OK != ret) {
+          GST_WARNING_OBJECT (audiotp, "pad_push returned = %s", gst_flow_get_name (ret));
+        }
+      }
+
+      res = gst_pad_push_event(audiotp->srcpad, event);
+      break;
+    }
+
+    /* Indication of the SEEK operation start */
+    case GST_EVENT_FLUSH_START: {
+      GST_INFO_OBJECT (audiotp, "GST_EVENT_FLUSH_START");
+      res = gst_pad_push_event(audiotp->srcpad, event);
+      break;
+    }
+
+    /* Indication of the SEEK operation stop */
+    case GST_EVENT_FLUSH_STOP: {
+      GST_INFO_OBJECT (audiotp, "GST_EVENT_FLUSH_STOP");
+      /* make sure that we empty the queue */
+      while (!g_queue_is_empty (audiotp->reverse)) {
+        GST_DEBUG_OBJECT (audiotp, "Flushing buffers in reverse queue....");
+        gst_buffer_unref(g_queue_pop_head (audiotp->reverse));
+      }
+
+      res = gst_pad_push_event(audiotp->srcpad, event);
+      break;
+    }
+
+    default: {
+      res = gst_pad_push_event(audiotp->srcpad, event);
+      break;
+    }
+  }
+
+  done:
+    return res;
+}
+
+
+/**
+ **
+ **  Description: Callback function when sinkpad gets a buffer (from the previous element)
+ **  In Params    : @ Sinkpad on which the buffer arrives
+ **          @ input buffer
+ **  return    : status of the buffer processing.
+ **  Comments    : 1. Handle the buffer discontinuity ( in terms of tmestamp)
+ **          2. Push or pop buffer based on discontinuity.
+ **
+ **
+ */
+static GstFlowReturn
+gst_audiotp_chain(GstPad *pad, GstBuffer *buf)
+{
+  Gstaudiotp *audiotp = GST_AUDIOTP(GST_PAD_PARENT(pad));
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  if(buf == NULL) {
+    ret = GST_FLOW_ERROR;
+       goto error_exit;
+  }
+
+  GST_LOG_OBJECT (audiotp, "Input buffer : ts =%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT ", size=%d",
+         GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buf)),
+         GST_TIME_ARGS(GST_BUFFER_DURATION(buf)),
+         GST_BUFFER_SIZE(buf), GST_BUFFER_IS_DISCONT (buf) ? " - discont" :"");
+
+  if (audiotp->segment.rate < 0.0) {
+    goto send_reverse;
+  }
+
+
+  /* Push the input data to the next element */
+  ret = gst_pad_push(audiotp->srcpad, buf);
+  if (ret != GST_FLOW_OK ) {
+   GST_WARNING("failed to push buffer %p. reason: %s", buf, gst_flow_get_name (ret));
+   buf = NULL;
+   goto error_exit;
+  }
+  return ret;
+
+send_reverse:
+  {
+    GstBuffer *MetaDataBuf = NULL;
+    GstClockTime headbuf_ts = GST_CLOCK_TIME_NONE;
+       GstClockTime tailbuf_ts = GST_CLOCK_TIME_NONE;
+
+    /* Discont buffers is mostly due to seek, when buffers of seeked timestamp gets pushed */
+    if (GST_BUFFER_IS_DISCONT(buf)) {
+      if(!g_queue_is_empty (audiotp->reverse)) {
+        GstBuffer *headbuf = (GstBuffer*) (audiotp->reverse->head->data);
+        GstBuffer *tailbuf = (GstBuffer*) (audiotp->reverse->tail->data);
+
+        headbuf_ts = GST_BUFFER_TIMESTAMP(headbuf);
+               tailbuf_ts = GST_BUFFER_TIMESTAMP(tailbuf);
+
+        GST_DEBUG_OBJECT(audiotp,"Headbuf ts =%" GST_TIME_FORMAT ", TailBuf ts =%" GST_TIME_FORMAT "",
+            GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(headbuf)),
+            GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(tailbuf)));
+
+        /* Check if the decoder is already having the reversal logic */
+        if(GST_BUFFER_TIMESTAMP(headbuf) > GST_BUFFER_TIMESTAMP(tailbuf)) {
+          GST_INFO_OBJECT (audiotp, "Buffers arrived in reverse order, audiotp NO NEED to reverse...");
+          audiotp->is_reversed = TRUE;
+        } else {
+          GST_INFO_OBJECT (audiotp, "Buffers arrived in forward order, audiotp NEED to reverse...");
+          audiotp->is_reversed = FALSE;
+        }
+      }
+
+      while (!g_queue_is_empty (audiotp->reverse)) {
+
+        if(audiotp->is_reversed)
+          MetaDataBuf = g_queue_pop_head (audiotp->reverse);
+        else
+          MetaDataBuf = g_queue_pop_tail (audiotp->reverse);
+
+        if (NULL == MetaDataBuf) {
+          GST_ERROR_OBJECT (audiotp, "NULL pointer...");
+          ret = GST_FLOW_ERROR;
+          goto error_exit;
+        }
+
+          /* If buffers arrive in forward order, compare the MetaDatabuf with
+               * previous head buffer timestamp.
+               * If buffers arrive in reverse order, compare the MetaDataBuf with
+               * previous tail buffer timestamp */
+        if((GST_BUFFER_TIMESTAMP(MetaDataBuf) < audiotp->head_prev && !audiotp->is_reversed)
+                               || (GST_BUFFER_TIMESTAMP(MetaDataBuf) < audiotp->tail_prev && audiotp->is_reversed)) {
+          ret = gst_audiotp_push_silent_frame (audiotp, MetaDataBuf);
+          if (MetaDataBuf) {
+            gst_buffer_unref (MetaDataBuf);
+            MetaDataBuf = NULL;
+          }
+
+          if (GST_FLOW_OK != ret) {
+            GST_WARNING_OBJECT (audiotp, "pad_push returned = %s", gst_flow_get_name (ret));
+            if (buf) {
+              gst_buffer_unref (buf);
+              buf = NULL;
+            }
+            return ret;
+          }
+        } else {
+          GST_DEBUG_OBJECT(audiotp, "Dropping the buffer out of segment with time-stamp %"GST_TIME_FORMAT,
+            GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(MetaDataBuf)));
+          if (MetaDataBuf) {
+            gst_buffer_unref (MetaDataBuf);
+            MetaDataBuf = NULL;
+          }
+        }
+      }
+
+      audiotp->head_prev = headbuf_ts;
+         audiotp->tail_prev = tailbuf_ts;
+    }
+
+    MetaDataBuf = gst_buffer_new ();
+    if (NULL == MetaDataBuf) {
+      GST_ERROR_OBJECT (audiotp, "Failed to create memory...");
+      ret = GST_FLOW_ERROR;
+      goto error_exit;
+    }
+
+    /* copy buffer timestamps & FLAGS to metadata buffer */
+    gst_buffer_copy_metadata (MetaDataBuf, buf, GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_CAPS);
+    GST_BUFFER_SIZE(MetaDataBuf) = GST_BUFFER_SIZE(buf);
+    GST_DEBUG_OBJECT (audiotp, "Pushing into reverse queue data of size: %d", GST_BUFFER_SIZE(MetaDataBuf));
+
+    /* queue all buffer timestamps till we receive next discontinuity */
+    g_queue_push_tail (audiotp->reverse, MetaDataBuf);
+    if (buf) {
+      gst_buffer_unref (buf);
+      buf = NULL;
+    }
+    return GST_FLOW_OK;
+  }
+
+send_dummy:
+  {
+
+    /* Resetting the buffer data to zero */
+    memset(GST_BUFFER_DATA(buf), 0, GST_BUFFER_SIZE(buf));
+    gst_buffer_set_caps(buf, GST_PAD_CAPS(audiotp->srcpad));
+
+    ret = gst_pad_push(audiotp->srcpad, buf);
+    if (ret != GST_FLOW_OK) {
+     GST_ERROR("Failed to push buffer. reason: %s\n", gst_flow_get_name(ret));
+     buf = NULL;
+     goto error_exit;
+    }
+    return GST_FLOW_OK;
+  }
+
+error_exit:
+
+  GST_WARNING_OBJECT(audiotp, "Returning from audiotp's chain with reason - %s", gst_flow_get_name (ret));
+  if (buf) {
+   gst_buffer_unref (buf);
+   buf = NULL;
+  }
+  return ret;
+}
+
+
+static GstFlowReturn
+gst_audiotp_push_silent_frame (Gstaudiotp *audiotp, GstBuffer *MetaDataBuf)
+{
+
+  GstBuffer *out = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  out = gst_buffer_new_and_alloc(GST_BUFFER_SIZE(MetaDataBuf));
+  if(out == NULL) {
+    GST_ERROR_OBJECT (audiotp, "Failed to allocate memory...");
+    return GST_FLOW_ERROR;
+  }
+
+  /* Memset the data of the out buffer so that silent frame is sent */
+  memset(GST_BUFFER_DATA(out), 0, GST_BUFFER_SIZE(out));
+
+  gst_buffer_copy_metadata (out, MetaDataBuf, GST_BUFFER_COPY_FLAGS);
+  GST_BUFFER_OFFSET (out) = GST_BUFFER_OFFSET_END (out) = 0;
+  GST_BUFFER_SIZE(out) = GST_BUFFER_SIZE(MetaDataBuf);
+  GST_BUFFER_TIMESTAMP(out) = GST_BUFFER_TIMESTAMP(MetaDataBuf);
+  GST_BUFFER_DURATION(out) = GST_BUFFER_DURATION(MetaDataBuf);
+
+  GST_LOG_OBJECT(audiotp, "Out buffer ts =%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT ", size=%d",
+       GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(out)),
+       GST_TIME_ARGS(GST_BUFFER_DURATION(out)),
+       GST_BUFFER_SIZE(out));
+
+  gst_buffer_set_caps(out, GST_PAD_CAPS(audiotp->srcpad));
+
+  ret = gst_pad_push(audiotp->srcpad, out);
+  if (ret != GST_FLOW_OK) {
+    GST_ERROR_OBJECT (audiotp, "Failed to push buffer. reason: %s\n", gst_flow_get_name(ret));
+    out = NULL;
+  }
+
+  return ret;
+}
+
+static gboolean
+gst_audiotp_plugin_init (GstPlugin *plugin)
+{
+  if (!gst_element_register (plugin, "audiotp", GST_RANK_PRIMARY, gst_audiotp_get_type())) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+                   GST_VERSION_MINOR,
+                   "audiotp",
+                   "Audio trickplay plugin",
+                   gst_audiotp_plugin_init,
+                   VERSION,
+                   "LGPL",
+                   "Samsung Electronics Co",
+                   "http://www.samsung.com")
diff --git a/audiotp/src/gstaudiotp.h b/audiotp/src/gstaudiotp.h
new file mode 100755 (executable)
index 0000000..0b3dc92
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * audiotp
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __GST_AUDIOTP_H__
+#define __GST_AUDIOTP_H__
+
+#include <gst/gst.h>
+#include <stdlib.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIOTP             (gst_audiotp_get_type())
+#define GST_AUDIOTP(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIOTP,Gstaudiotp))
+#define GST_AUDIOTP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIOTP,GstaudiotpClass))
+#define GST_AUDIOTP_GET_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS((klass),GST_TYPE_AUDIOTP,GstaudiotpClass))
+#define GST_IS_AUDIOTP(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIOTP))
+#define GST_IS_AUDIOTP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIOTP))
+#define GST_AUDIOTP_CAST(obj)        ((Gstaudiotp *)(obj))
+
+typedef struct _Gstaudiotp Gstaudiotp;
+typedef struct _GstaudiotpClass GstaudiotpClass;
+
+struct _Gstaudiotp
+{
+  GstElement element;
+  GstPad *sinkpad;
+  GstPad *srcpad;
+  GQueue *reverse; /* used in reverse trickplay */
+  GstSegment segment;
+
+  /* Flag to indicate the new buffer recieved is discountinued in
+  its time-stamp */
+  gboolean discont;
+  gboolean is_reversed;
+  GstClockTime head_prev;
+  GstClockTime tail_prev;
+};
+
+struct _GstaudiotpClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_audiotp_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIOTP_H__ */
\ No newline at end of file
index f14c9ba..3a6f224 100644 (file)
@@ -226,23 +226,6 @@ static inline guint _time_to_sample(GstAvsysAudioSink * asink,  GstClockTime dif
 */
 
 static void
-_restore_sound_path (GstAvsysAudioSink *avsys_audio)
-{
-       avsys_audio_route_policy_t cur_policy;
-       if (avsys_audio_get_route_policy(&cur_policy) == AVSYS_STATE_SUCCESS) {
-               GST_ERROR ("audio policy = %d, cur policy = %d", avsys_audio->audio_route_policy, cur_policy);
-
-               if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_KEYTONE, AVSYS_AUDIO_PATH_EX_SPK, AVSYS_AUDIO_PATH_EX_NONE,
-                               (cur_policy == AVSYS_AUDIO_ROUTE_POLICY_HANDSET_ONLY)? AVSYS_AUDIO_PATH_OPTION_NONE : AVSYS_AUDIO_PATH_OPTION_JACK_AUTO))) {
-                       GST_ERROR_OBJECT(avsys_audio, "audio route set to current policy failed");
-
-               }
-       } else {
-               GST_ERROR ("avsys_audio_get_route_policy() failed");
-       }
-}
-
-static void
 gst_avsysaudiosink_finalise (GObject * object)
 {
     GstAvsysAudioSink *sink = NULL;
@@ -252,10 +235,6 @@ gst_avsysaudiosink_finalise (GObject * object)
     g_mutex_free (sink->avsys_audio_lock);
     g_mutex_free (sink->avsys_audio_reset_lock);
 
-    /* restore to default path */
-    if (sink->audio_route_policy == AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT) {
-               _restore_sound_path (sink);
-    }
     G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -416,27 +395,6 @@ gst_avsysaudiosink_set_property (GObject * object, guint prop_id,
                case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
                        GST_INFO_OBJECT(sink, "use external audio route setting");
                        break;
-               case AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_NORMAL:
-                       if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER, AVSYS_AUDIO_PATH_EX_SPK,
-                                       AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_OPTION_JACK_AUTO)))
-                       {
-                               GST_ERROR_OBJECT(sink, "audio route set to normal failed");
-                       }
-                       break;
-               case AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT:
-                       if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER, AVSYS_AUDIO_PATH_EX_SPK,
-                                       AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_OPTION_DUAL_OUT)))
-                       {
-                               GST_ERROR_OBJECT(sink, "audio route set to dual output failed");
-                       }
-                       break;
-               case AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY:
-                       if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER, AVSYS_AUDIO_PATH_EX_HEADSET,
-                                       AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_OPTION_NONE)))
-                       {
-                               GST_ERROR_OBJECT(sink, "audio route set to headset failed");
-                       }
-                       break;
                default:
                        g_print("AVSYSAUDIOSINK :: Unknown audio route option %d\n", sink->audio_route_policy);
                        GST_ERROR_OBJECT(sink, "Unknown audio route option %d", sink->audio_route_policy);
@@ -612,7 +570,7 @@ avsysaudiosink_parse_spec (GstAvsysAudioSink * avsys_audio, GstRingBufferSpec *
     /* set software volume table type */
     avsys_audio->audio_param.vol_type = avsys_audio->volume_type;
     avsys_audio->audio_param.priority = avsys_audio->sound_priority;
-       avsys_audio->audio_param.bluetooth = avsys_audio->user_route_policy;
+    avsys_audio->audio_param.handle_route = avsys_audio->user_route_policy;
 
     return TRUE;
 }
@@ -905,30 +863,6 @@ gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition)
                case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
                        GST_INFO_OBJECT(avsys_audio, "audio route uses external setting");
                        break;
-               case AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_NORMAL:
-                       if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER, AVSYS_AUDIO_PATH_EX_SPK,
-                                       AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_OPTION_JACK_AUTO)))
-                       {
-                               GST_ERROR_OBJECT(avsys_audio, "audio route set to normal failed");
-                               return GST_STATE_CHANGE_FAILURE;
-                       }
-                       break;
-               case AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT:
-                       if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER, AVSYS_AUDIO_PATH_EX_SPK,
-                                       AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_OPTION_DUAL_OUT)))
-                       {
-                               GST_ERROR_OBJECT(avsys_audio, "audio route set to dual output failed");
-                               return GST_STATE_CHANGE_FAILURE;
-                       }
-                       break;
-               case AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY:
-                       if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER, AVSYS_AUDIO_PATH_EX_HEADSET,
-                                       AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_OPTION_NONE)))
-                       {
-                               GST_ERROR_OBJECT(avsys_audio, "audio route set to headset failed");
-                               return GST_STATE_CHANGE_FAILURE;
-                       }
-                       break;
                default:
                        GST_ERROR_OBJECT(avsys_audio, "Unknown audio route option %d\n", avsys_audio->audio_route_policy);
                        break;
@@ -967,10 +901,6 @@ gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition)
     switch (transition)
     {
         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-                       /* restore to default path */
-                       if (avsys_audio->audio_route_policy == AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT)        {
-                               _restore_sound_path (avsys_audio);
-                       }
             break;
         case GST_STATE_CHANGE_PAUSED_TO_READY:
             break;
index 11a0bc1..3a4fdc0 100644 (file)
@@ -81,6 +81,11 @@ enum {
     PROP_AUDIO_LATENCY,
 };
 
+enum {
+       CAPTURE_UNCORK = 0,
+       CAPTURE_CORK,
+};
+
 GType
 gst_avsysaudiosrc_audio_latency_get_type (void)
 {
@@ -122,6 +127,9 @@ static guint                gst_avsysaudiosrc_read          (GstAudioSrc * asrc, gpointer data, guint
 static void            gst_avsysaudiosrc_reset         (GstAudioSrc * asrc);
 static gboolean        gst_avsysaudiosrc_avsys_close   (GstAvsysAudioSrc *src);
 static gboolean        gst_avsysaudiosrc_avsys_open    (GstAvsysAudioSrc *src);
+static gboolean        gst_avsysaudiosrc_avsys_cork    (GstAvsysAudioSrc *avsysaudiosrc, int cork);
+static gboolean        gst_avsysaudiosrc_avsys_start   (GstAvsysAudioSrc *src);
+static gboolean        gst_avsysaudiosrc_avsys_stop    (GstAvsysAudioSrc *src);
 #if defined(_USE_CAPS_)
 static GstCaps *gst_avsysaudiosrc_detect_rates (GstObject * obj, avsys_pcm_hw_params_t * hw_params, GstCaps * in_caps);
 static GstCaps *gst_avsysaudiosrc_detect_channels (GstObject * obj,avsys_pcm_hw_params_t * hw_params,  GstCaps * in_caps);
@@ -474,7 +482,6 @@ gst_avsysaudiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
 {
     GstAvsysAudioSrc *avsysaudiosrc = NULL;
        guint   p_time = 0, b_time = 0;
-//     gint    avsys_result = 0;
 
        avsysaudiosrc = GST_AVSYS_AUDIO_SRC (asrc);
 
@@ -483,7 +490,6 @@ gst_avsysaudiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
        GST_ERROR("avsysaudiosrc_parse_spec failed");
         return FALSE;
     }
-    //g_print("AVSYSAUDIOSRC :: avsysaudiosrc_parse_spec() success\n");
 
        /*open avsys audio*/
     if (!gst_avsysaudiosrc_avsys_open (avsysaudiosrc))
@@ -495,7 +501,7 @@ gst_avsysaudiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
     /* Ring buffer size */
     if (AVSYS_STATE_SUCCESS ==
        avsys_audio_get_period_buffer_time(avsysaudiosrc->audio_handle, &p_time, &b_time))
-     {
+    {
        if(p_time == 0 || b_time == 0)
                return FALSE;
 
@@ -525,7 +531,7 @@ gst_avsysaudiosrc_unprepare (GstAudioSrc * asrc)
 
     avsysaudiosrc = GST_AVSYS_AUDIO_SRC (asrc);
 
-    /*close*/
+       /*close*/
     GST_AVSYS_AUDIO_SRC_LOCK (avsysaudiosrc);
 
     if(!gst_avsysaudiosrc_avsys_close(avsysaudiosrc))
@@ -594,6 +600,10 @@ gst_avsys_src_change_state (GstElement * element, GstStateChange transition)
                case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
                {
                        GST_DEBUG ("GST_STATE_CHANGE_PAUSED_TO_PLAYING\n") ;
+                       /* Capture Start */
+                       if (!gst_avsysaudiosrc_avsys_start (avsys)) {
+                               GST_ERROR("gst_avsysaudiosrc_avsys_start failed");
+                       }
                        break ;
                }
                default:
@@ -608,6 +618,10 @@ gst_avsys_src_change_state (GstElement * element, GstStateChange transition)
                case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
                {
                        GST_DEBUG ("GST_STATE_CHANGE_PLAYING_TO_PAUSED\n") ;
+                       /* Capture Stop */
+                       if (!gst_avsysaudiosrc_avsys_stop (avsys)) {
+                               GST_ERROR("gst_avsysaudiosrc_avsys_stop failed");
+                       }
                        break ;
                }
                case GST_STATE_CHANGE_PAUSED_TO_READY:
@@ -664,6 +678,41 @@ _READ_ERROR:
 }
 
 static gboolean
+gst_avsysaudiosrc_avsys_cork (GstAvsysAudioSrc *avsysaudiosrc, int cork)
+{
+       int avsys_result = avsys_audio_cork (avsysaudiosrc->audio_handle, cork);
+       if (avsys_result != AVSYS_STATE_SUCCESS) {
+               GST_ERROR_OBJECT(avsysaudiosrc, "avsys_audio_cork() error. [0x%x]\n", avsys_result);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static gboolean
+gst_avsysaudiosrc_avsys_start (GstAvsysAudioSrc *avsysaudiosrc)
+{
+       gboolean result;
+
+       GST_AVSYS_AUDIO_SRC_LOCK (avsysaudiosrc);
+       result = gst_avsysaudiosrc_avsys_cork(avsysaudiosrc, CAPTURE_UNCORK);
+       GST_AVSYS_AUDIO_SRC_UNLOCK (avsysaudiosrc);
+
+       return result;
+}
+
+static gboolean
+gst_avsysaudiosrc_avsys_stop (GstAvsysAudioSrc *avsysaudiosrc)
+{
+       gboolean result;
+
+       GST_AVSYS_AUDIO_SRC_LOCK (avsysaudiosrc);
+       result = gst_avsysaudiosrc_avsys_cork(avsysaudiosrc, CAPTURE_CORK);
+       GST_AVSYS_AUDIO_SRC_UNLOCK (avsysaudiosrc);
+
+       return result;
+}
+
+static gboolean
 gst_avsysaudiosrc_avsys_open (GstAvsysAudioSrc *avsysaudiosrc)
 {
        int avsys_result = 0;
index 408cab0..bc4276b 100644 (file)
@@ -69,13 +69,18 @@ static GstStaticPadTemplate sink_factory =
                                 GST_PAD_SINK, GST_PAD_ALWAYS, 
                                 GST_STATIC_CAPS (
                                     "video/x-raw-yuv, "
+                                   "format = (fourcc){YV12}, "
                                     "framerate = (fraction) [ 0, MAX ], "
                                     "width = (int) [ 1, MAX ], "
-                                    "height = (int) [ 1, MAX ], "
-                                    "format = (fourcc) {YV12};"
-                                                               "video/x-raw-rgb,"
-                                    "bpp = (int)32,"
-                                    "depth = (int)24")
+                                    "height = (int) [ 1, MAX ]; "
+                                   "video/x-raw-yuv, "
+                                   "format = (fourcc){I420}, "
+                                    "framerate = (fraction) [ 0, MAX ], "
+                                    "width = (int) [ 1, MAX ], "
+                                    "height = (int) [ 1, MAX ]; "
+                                   "video/x-raw-rgb, "
+                                    "bpp = (int)32, "
+                                    "depth = (int)24 ")
                             );
 
 static GstElementDetails AvsysMemSink_details = {
index edfaabf..a1ab29e 100644 (file)
@@ -37,7 +37,7 @@ plugin_init (GstPlugin *plugin)
        gboolean error;
        /*register the exact name you can find in the framework*/
        error = gst_element_register (plugin, "avsysaudiosink",
-                                                                 GST_RANK_NONE,
+                                                                 GST_RANK_PRIMARY + 100,
                                                                  GST_TYPE_AVSYS_AUDIO_SINK);
 
        error = gst_element_register (plugin, "avsysmemsink",
index 16c6059..e525018 100755 (executable)
@@ -258,13 +258,6 @@ AC_ARG_ENABLE(ext-drmsrc, AC_HELP_STRING([--enable-ext-drmsrc], [using drmsrc]),
   ],
   [GST_EXT_USE_EXT_DRMSRC=yes])
 AM_CONDITIONAL(GST_EXT_USE_EXT_DRMSRC, test "x$GST_EXT_USE_EXT_DRMSRC" = "xyes")
-
-if test "x$GST_EXT_USE_EXT_DRMSRC" = "xyes"; then
-       PKG_CHECK_MODULES(DRM_SERVICE, drm-service)
-       AC_SUBST(DRM_SERVICE_CFLAGS)
-       AC_SUBST(DRM_SERVICE_LIBS)
-fi     
-
 dnl use ext-toggle --------------------------------------------------------------------------
 AC_ARG_ENABLE(ext-toggle, AC_HELP_STRING([--enable-ext-toggle], [using toggle]),
   [
@@ -300,6 +293,42 @@ AC_ARG_ENABLE(ext-pdpushsrc, AC_HELP_STRING([--enable-ext-pdpushsrc], [using pdp
  ],
  [GST_EXT_USE_EXT_PD_PUSHSRC=yes])
 AM_CONDITIONAL(GST_EXT_USE_EXT_PD_PUSHSRC, test "x$GST_EXT_USE_EXT_PD_PUSHSRC" = "xyes")
+dnl use ext-audiotp --------------------------------------------------------------------------
+AC_ARG_ENABLE(ext-audiotp, AC_HELP_STRING([--enable-ext-audiotp], [using audiotp]),
+[
+ case "${enableval}" in
+        yes) GST_EXT_USE_EXT_AUDIOTP=yes ;;
+        no)  GST_EXT_USE_EXT_AUDIOTP=no ;;
+        *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-audiotp) ;;
+ esac
+ ],
+ [GST_EXT_USE_EXT_AUDIOTP=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_AUDIOTP, test "x$GST_EXT_USE_EXT_AUDIOTP" = "xyes")
+
+dnl use ext-piffdemux --------------------------------------------------------------------------
+AC_ARG_ENABLE(ext-piffdemux, AC_HELP_STRING([--enable-ext-piffdemux], [using piffdemux]),
+[
+ case "${enableval}" in
+        yes) GST_EXT_USE_EXT_PIFFDEMUX=yes ;;
+        no)  GST_EXT_USE_EXT_PIFFDEMUX=no ;;
+        *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-piffdemux) ;;
+ esac
+ ],
+ [GST_EXT_USE_EXT_PIFFDEMUX=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_PIFFDEMUX, test "x$GST_EXT_USE_EXT_PIFFDEMUX" = "xyes")
+
+dnl use ext-ssdemux --------------------------------------------------------------------------
+AC_ARG_ENABLE(ext-ssdemux, AC_HELP_STRING([--enable-ext-ssdemux], [using ssdemux]),
+[
+ case "${enableval}" in
+        yes) GST_EXT_USE_EXT_SSDEMUX=yes ;;
+        no)  GST_EXT_USE_EXT_SSDEMUX=no ;;
+        *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-ssdemux) ;;
+ esac
+ ],
+ [GST_EXT_USE_EXT_SSDEMUX=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_SSDEMUX, test "x$GST_EXT_USE_EXT_SSDEMUX" = "xyes")
+
 
 AC_OUTPUT(
 Makefile
@@ -317,4 +346,10 @@ toggle/Makefile
 toggle/src/Makefile
 drmsrc/Makefile
 drmsrc/src/Makefile
+audiotp/Makefile
+audiotp/src/Makefile
+piffdemux/Makefile
+piffdemux/src/Makefile
+ssdemux/Makefile
+ssdemux/src/Makefile
 )
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100755 (executable)
index e5c70e0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-gst-plugins-ext0.10 (0.1.5-1) unstable; urgency=low
-
-  * Initial Release
-  * Git: pkgs/g/gst-plugins-ext0.10
-  * Tag: gst-plugins-ext0.10_0.1.5-1
-
- -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 07 Dec 2011 12:40:00 +0900
-
diff --git a/debian/compat b/debian/compat
deleted file mode 100644 (file)
index 7ed6ff8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-5
diff --git a/debian/control b/debian/control
deleted file mode 100755 (executable)
index a95da27..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-Source: gst-plugins-ext0.10
-Section: libs
-Priority: extra
-Maintainer: JongHyuk Choi <jhchoi.choi@samsung.com>, Seungbae Shin <seungbae.shin@samsung.com>, Younghwan Ahn <younghwan_.an@samsung.com>, Jeongmo Yang <jm80.yang@samsung.com>, Sangchul Lee <sc11.lee@samsung.com>
-Build-Depends: debhelper (>= 5), libgstreamer0.10-dev, libgstreamer-plugins-base0.10-dev, libavsystem-dev, libmm-ta-dev, drm-service-dev, libecore-dev, libevas-dev
-Standards-Version: 3.7.2
-
-Package: gstreamer0.10-plugins-ext
-Section: libs
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libgstreamer0.10-0, libgstreamer-plugins-base0.10-0, libavsystem-0, libmm-ta, drm-service-0, libcamsrcjpegenc
-Description: GStreamer extra plugins (common)
-
-Package: gstreamer0.10-plugins-ext-dbg
-Section: debug
-Architecture: armel
-Depends: ${shlibs:Depends}, ${misc:Depends}, gstreamer0.10-plugins-ext (= ${Source-Version})
-Description: GStreamer extra plugins (all) (unstripped)
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644 (file)
index bd79a0c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify it under
-the terms of the GNU Lesser 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 Lesser General Public
-License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library; if not, write to the Free Software Foundation, Inc., 51
-Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
diff --git a/debian/gstreamer0.10-plugins-ext.install.in b/debian/gstreamer0.10-plugins-ext.install.in
deleted file mode 100644 (file)
index b9de572..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@PREFIX@/lib/gstreamer-0.10/libgstavsyssink.so
-@PREFIX@/lib/gstreamer-0.10/libgstencodebin.so
-@PREFIX@/lib/gstreamer-0.10/libgsttoggle.so
-@PREFIX@/lib/gstreamer-0.10/libgstavsysaudiosrc.so
-@PREFIX@/lib/gstreamer-0.10/libgstevasimagesink.so
-@PREFIX@/lib/gstreamer-0.10/libgstdrmsrc.so
-@PREFIX@/lib/gstreamer-0.10/libgstpdpushsrc.so
diff --git a/debian/rules b/debian/rules
deleted file mode 100755 (executable)
index 49e5ea4..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_HOST_ARCH       ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
-DEB_HOST_ARCH_OS    ?= $(shell dpkg-architecture -qDEB_HOST_GNU_OS)
-
-CFLAGS += -Wall -g
-LDFLAGS ?=
-PREFIX ?= /usr
-DATADIR ?= /opt
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
-       CFLAGS += -O0
-else
-       CFLAGS += -O2
-endif
-
-MODULES=
-#      --disable-ext-evasimagesink
-
-LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed
-
-config.status: configure
-       dh_testdir
-       # Add here commands to configure the package.
-       ./autogen.sh
-       CFLAGS="$(CFLAGS) -DGST_EXT_TIME_ANALYSIS -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" " LDFLAGS="$(LDFLAGS)" ./configure $(MODULES) $(OPTION) --prefix=$(PREFIX)
-
-build: build-stamp
-
-build-stamp:  config.status
-       dh_testdir
-
-       # Add here commands to compile the package.
-       $(MAKE)
-       #docbook-to-man debian/ncurses.sgml > ncurses.1
-
-       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
-               cat $$f > $${f%.in}; \
-               sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
-               sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
-       done
-
-       touch $@
-
-clean:
-       dh_testdir
-       dh_testroot
-       rm -f build-stamp
-
-       # Add here commands to clean up after the build process.
-       -$(MAKE) distclean
-ifneq "$(wildcard /usr/share/misc/config.sub)" ""
-       cp -f /usr/share/misc/config.sub config.sub
-endif
-ifneq "$(wildcard /usr/share/misc/config.guess)" ""
-       cp -f /usr/share/misc/config.guess config.guess
-endif
-
-       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
-               rm -f $${f%.in}; \
-       done
-
-       dh_clean
-
-install: build
-       dh_testdir
-       dh_testroot
-       dh_clean -k
-       dh_installdirs -s
-
-       # Add here commands to install the package into debian/ncurses.
-       $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
-#ifneq (, $(findstring arm, $(DEB_HOST_ARCH)))
-#      execstack -c $(EXECSTACK_FILES)
-#endif
-
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
-       dh_testdir
-       dh_testroot
-       dh_installchangelogs -s
-#      dh_installdocs
-#      dh_installexamples
-       dh_install -s --list-missing --sourcedir=debian/tmp
-#      dh_installmenu
-#      dh_installdebconf
-#      dh_installlogrotate
-#      dh_installemacsen
-#      dh_installpam
-#      dh_installmime
-#      dh_python
-#      dh_installinit
-#      dh_installcron
-#      dh_installinfo
-#      dh_installman
-       dh_link -s
-       dh_strip -s --dbg-package=gstreamer0.10-plugins-ext-dbg
-       dh_compress -s
-       dh_fixperms -s
-#      dh_perl
-       dh_makeshlibs -s
-       dh_installdeb -s
-       dh_shlibdeps -s
-       dh_gencontrol -s
-       dh_md5sums -s
-       dh_builddeb -s
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install
index e6b14b3..37eb3bb 100755 (executable)
@@ -1,27 +1,27 @@
-# plugindir is set in configure\r
-\r
-##############################################################################\r
-# change libgstplugin.la to something more suitable, e.g. libmysomething.la  #\r
-##############################################################################\r
-plugin_LTLIBRARIES = libgstdrmsrc.la\r
-\r
-##############################################################################\r
-# for the next set of variables, rename the prefix if you renamed the .la,   #\r
-#  e.g. libgstplugin_la_SOURCES => libmysomething_la_SOURCES                 #\r
-#       libgstplugin_la_CFLAGS  => libmysomething_la_CFLAGS                  #\r
-#       libgstplugin_la_LIBADD  => libmysomething_la_LIBADD                  #\r
-#       libgstplugin_la_LDFLAGS => libmysomething_la_LDFLAGS                 #\r
-##############################################################################\r
-\r
-# sources used to compile this plug-in\r
-libgstdrmsrc_la_SOURCES = gstdrmsrc.c\r
-\r
-# flags used to compile this plugin\r
-# add other _CFLAGS and _LIBS as needed\r
-libgstdrmsrc_la_CFLAGS = $(GST_CFLAGS) $(DRM_SERVICE_CFLAGS) $(MMTA_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64\r
-libgstdrmsrc_la_LIBADD = $(GST_LIBS) $(DRM_SERVICE_LIBS) $(GST_BASE_LIBS) $(MMTA_LIBS)\r
-libgstdrmsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)\r
-\r
-# headers we need but don't want installed\r
-noinst_HEADERS = gstdrmsrc.h\r
-\r
+# plugindir is set in configure
+
+##############################################################################
+# change libgstplugin.la to something more suitable, e.g. libmysomething.la  #
+##############################################################################
+plugin_LTLIBRARIES = libgstdrmsrc.la
+
+##############################################################################
+# for the next set of variables, rename the prefix if you renamed the .la,   #
+#  e.g. libgstplugin_la_SOURCES => libmysomething_la_SOURCES                 #
+#       libgstplugin_la_CFLAGS  => libmysomething_la_CFLAGS                  #
+#       libgstplugin_la_LIBADD  => libmysomething_la_LIBADD                  #
+#       libgstplugin_la_LDFLAGS => libmysomething_la_LDFLAGS                 #
+##############################################################################
+
+# sources used to compile this plug-in
+libgstdrmsrc_la_SOURCES = gstdrmsrc.c
+
+# flags used to compile this plugin
+# add other _CFLAGS and _LIBS as needed
+libgstdrmsrc_la_CFLAGS = $(GST_CFLAGS) $(MMTA_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+libgstdrmsrc_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(MMTA_LIBS)
+libgstdrmsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+# headers we need but don't want installed
+noinst_HEADERS = gstdrmsrc.h
+
index 4661717..5e2776d 100755 (executable)
@@ -26,7 +26,6 @@
 #endif
 #include "gstdrmsrc.h"
 
-
 #define LOG_TRACE(message)  //g_print("DRM_SRC: %s: %d: %s - %s \n", __FILE__, __LINE__, __FUNCTION__, message);
 
 #define GST_TAG_PLAYREADY "playready_file_path"
@@ -41,8 +40,7 @@ enum
 {
        ARG_0,
        ARG_LOCATION,
-       ARG_FD,
-       IS_DRM
+       ARG_FD
 };
 static void gst_drm_src_finalize (GObject * object);
 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -53,6 +51,7 @@ static gboolean gst_drm_src_is_seekable (GstBaseSrc * src);
 static gboolean gst_drm_src_get_size (GstBaseSrc * src, guint64 * size);
 static GstFlowReturn gst_drm_src_create (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buffer);
 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
+
 /**
  * This function does the following:
  *  1. Initializes GstDrmSrc ( defines gst_drm_get_type)
@@ -123,9 +122,7 @@ static void gst_drm_src_class_init (GstDrmSrcClass * klass)
        g_object_class_install_property (gobject_class, ARG_LOCATION,
                g_param_spec_string ("location", "File Location",
                "Location of the file to read", NULL, G_PARAM_READWRITE));
-       g_object_class_install_property (gobject_class, IS_DRM,
-               g_param_spec_boolean ("is-drm", "whether selected file type is drm or not",
-               "true, false", FALSE, G_PARAM_READWRITE));      
+
        // 2. Assigns the function pointers GObject class attributes
        gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_drm_src_finalize);
        gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_drm_src_start);
@@ -157,11 +154,7 @@ static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
        src->fd = 0;
        src->uri = NULL;
        src->is_regular = FALSE;
-       src->drm_file = FALSE;
        src->seekable = FALSE;
-       src->hfile = NULL;
-       src->event_posted = FALSE;
-       src->is_playready = FALSE;
        PROFILE_INIT;
 }
 /**
@@ -283,93 +276,12 @@ static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue *
                case ARG_FD:
                        g_value_set_int (value, src->fd);
                        break;
-               case IS_DRM:
-                       g_value_set_boolean(value, src->drm_file);
-                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
        }
 }
-/**
- * This function does the following:
- *  1. Seeks to the specified position for DRM file.
- *  2. Allocates a buffer to push the data for DRM file.
- *  3. Reads from the file and sets the related params for DRM file.
- *
- * @param   i_pDrmSrc    [in]   GstDrmSrc Structure
- * @param   i_uiOffset    [in]   offset of the file to seek
- * @param   length    [in]   size of the data in bytes
- * @param   o_pBbuffer    [out]   GstBuffer to hold the contents
- *
- * @return  GstFlowReturn   Returns GST_FLOW_OK on success and ERROR on failure
- */
-static GstFlowReturn  gst_drm_src_create_read_drm_file (GstDrmSrc* i_pDrmSrc, guint64 i_uiOffset, guint length, GstBuffer ** o_pBbuffer)
-{
-       GstBuffer *buf = NULL;
-       unsigned int readSize;
-       DRM_RESULT in_res = DRM_RESULT_SUCCESS;
-PROFILE_FUNC_BEGIN;
-       // 1. Seeks to the specified position for DRM file.
-       if (G_UNLIKELY (i_pDrmSrc->read_position != i_uiOffset))
-       {
-               in_res =drm_svc_seek_file(i_pDrmSrc->hfile, i_uiOffset, DRM_SEEK_SET);
-
-               if(in_res  != DRM_RESULT_SUCCESS)
-                       goto FAILED;
-
-               i_pDrmSrc->read_position = i_uiOffset;
-       }
-       // 2. Allocates a buffer to push the data for DRM file.
-       buf = gst_buffer_new_and_alloc (length);
-       if(buf == NULL)
-       {
-               LOG_TRACE("Exit on error");
-               return GST_FLOW_ERROR;
-       }
-       // 3. Reads from the file and sets the related params for DRM file.
-       in_res = drm_svc_read_file(i_pDrmSrc->hfile, GST_BUFFER_DATA(buf), length, &readSize);
-
-       if (in_res != DRM_RESULT_SUCCESS)
-               goto FAILED;
-
-       if(readSize <= 0)
-       {
-               LOG_TRACE("Exit on error");
-               return GST_FLOW_ERROR;
-       }
-
-       #if 0 // Drm service can give lesser size block than requested thing.
-       if (G_UNLIKELY ((guint) readSize < length && i_pDrmSrc->seekable))
-       {
-               GST_ELEMENT_ERROR (i_pDrmSrc, RESOURCE, READ, (NULL),("unexpected end of file."));
-               gst_buffer_unref (buf);
-               return GST_FLOW_ERROR;
-       }
-       #endif
-
-       if (G_UNLIKELY (readSize == 0 && length > 0))
-       {
-               GST_DEBUG ("non-regular file hits EOS");
-               gst_buffer_unref (buf);
-               return GST_FLOW_UNEXPECTED;
-       }
-       length = readSize;
-       GST_BUFFER_SIZE (buf) = length;
-       GST_BUFFER_OFFSET (buf) = i_uiOffset;
-       GST_BUFFER_OFFSET_END (buf) = i_uiOffset + length;
-       *o_pBbuffer = buf;
-       i_pDrmSrc->read_position += length;
-PROFILE_FUNC_END;
-
-       return GST_FLOW_OK;
 
-FAILED:
-       {
-               GST_ELEMENT_ERROR (i_pDrmSrc, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
-               return GST_FLOW_ERROR;
-       }
-}
 /**
  * This function does the following:
  *  1. Seeks to the specified position.
@@ -444,23 +356,8 @@ static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, g
 {
        GstDrmSrc *src = GST_DRM_SRC (basesrc);
 
-       if (src->is_playready && src->event_posted == FALSE) {
-               GstTagList *tags = NULL;
-               GST_DEBUG_OBJECT (src, "posting playready tags");
-               tags =  gst_tag_list_new_full (GST_TAG_PLAYREADY, src->filename, NULL);
-               if (tags) {
-                       GstPad* src_pad = gst_element_get_static_pad (src, "src");
-                       if (src_pad) {
-                               src->event_posted = gst_pad_push_event (src_pad, gst_event_new_tag (tags) );
-                               GST_DEBUG_OBJECT (src, "posting tags returns [%d]", src->event_posted);
-                               gst_object_unref (src_pad);
-                       }
-               }
-       }
-
        // 1. Calls DRM file read chain method for drm files.
-       if(src->drm_file == TRUE)
-               return gst_drm_src_create_read_drm_file (src, offset, length, buffer);
+
        // 2. Calls normal file read chain method for standard files.
        return gst_drm_src_create_read (src, offset, length, buffer);
 }
@@ -488,21 +385,11 @@ static gboolean gst_drm_src_is_seekable (GstBaseSrc * basesrc)
 static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
 {
        struct stat stat_results;
-       GstDrmSrc *src;
-       src = GST_DRM_SRC (basesrc);
+       GstDrmSrc *src = GST_DRM_SRC (basesrc);
+       unsigned int offset;
+
        //  1. Gets the filesize for drm file by using seek oprations
-       if(src->drm_file==TRUE)
-       {
-               drm_svc_seek_file(src->hfile, 0, DRM_SEEK_END);
-               *size = drm_svc_tell_file(src->hfile);
-               drm_svc_seek_file(src->hfile, 0, DRM_SEEK_SET);
-               src->read_position = 0;
-               return TRUE;
-       }
-       if (!src->seekable)
-       {
-               return FALSE;
-       }
+
        // 2. Gets the file size for standard file by using statistics
        if (fstat (src->fd, &stat_results) < 0)
                return FALSE;
@@ -513,10 +400,6 @@ static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
  * This function does the following:
  *  1. Checks the filename
  *  2. Opens the file and check statistics of the file
- *  3. Checks whether DRM file or not.
- *  4. Checks the DRM file type (supports only for OMA) if it is DRM
- *  5. Opens the DRM file if it is DRM
- *  6. Gets the DRM_FILE_HANDLE and sets the drm, seekable and regular flag.
  *  7. Checks the seeking for standard files
  *
  * @param   basesrc    [in]   BaseSrc Structure
@@ -527,9 +410,6 @@ static gboolean gst_drm_src_start (GstBaseSrc * basesrc)
 {
        GstDrmSrc *src = GST_DRM_SRC (basesrc);
        struct stat stat_results;
-       DRM_BOOL res = DRM_TRUE;
-       DRM_FILE_TYPE type = DRM_FILE_TYPE_NONE;
-       DRM_RESULT in_res = DRM_RESULT_SUCCESS;
        off_t ret;
 PROFILE_FUNC_BEGIN;
        // 1. Checks the filename
@@ -570,62 +450,12 @@ PROFILE_FUNC_BEGIN;
                return FALSE;
        }
        src->read_position = 0;
-       /* DRM Related code */
-       // 3. Checks whether DRM file or not.
-PROFILE_BLOCK_BEGIN("drmstart");
-       res = drm_svc_is_drm_file(src->filename);
-       if(res == DRM_TRUE)
-               type = drm_svc_get_drm_type(src->filename);
-       GST_LOG_OBJECT (src, "is_drm=[%d], drm_type=[%d]", res, type);
-
-       /* We handles as DRM file if it is drm with OMA type */
-       if(res == DRM_TRUE && type == DRM_FILE_TYPE_OMA)
-       {
-#if 0 // Do not check here.
-               // 4. Checks the DRM file type (supports only for OMA) if it is DRM
-               if(drm_svc_get_drm_type(src->filename) != DRM_FILE_TYPE_OMA)
-               {
-                       GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is not OMA DRM.", src->filename), (NULL));
-                       return FALSE;
-               }
-#endif
-
-               // 5. Opens the DRM file if it is DRM
-               PROFILE_BLOCK_BEGIN("drmopen");
-               in_res=drm_svc_open_file(src->filename, DRM_PERMISSION_PLAY, &(src->hfile));
-               if(in_res != DRM_RESULT_SUCCESS)
-               {
-                       GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" open fail.", src->filename), (NULL));
-                       return FALSE;
-               }
-               PROFILE_BLOCK_END("drmopen");
-
-               // 6. Gets the DRM_FILE_HANDLE and sets the drm, seekable and regular flags.
-               res = drm_svc_is_drm_file_handle(src->hfile);
-               if(res == DRM_TRUE)
-               {
-                       drm_svc_seek_file(src->hfile, 0, DRM_SEEK_END);
-                       drm_svc_seek_file(src->hfile, 0, DRM_SEEK_SET);
-               }
-               src->seekable   = TRUE;
-               src->is_regular = TRUE;
-               src->drm_file   = TRUE;
-PROFILE_BLOCK_END("drmstart");
-
-               LOG_TRACE("Exit");
-               return TRUE;
-       }
-
-       if(res == DRM_TRUE && type == DRM_FILE_TYPE_PLAYREADY) {
-               src->is_playready = TRUE;
-               src->event_posted = FALSE;
-       }
 
        // 7. Checks the seeking for standard files
        if (S_ISREG (stat_results.st_mode))
                src->is_regular = TRUE;
        ret = lseek (src->fd, 0, SEEK_END);
-       if (res < 0)
+       if (ret < 0)
        {
                GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
                        "failed: %s", g_strerror (errno));
@@ -652,17 +482,11 @@ static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
 {
        GstDrmSrc *src = GST_DRM_SRC (basesrc);
 
-       if (src->hfile) {
-               drm_svc_close_file(src->hfile);
-               src->hfile = NULL;
-       }
        // 1. Closes the file desciptor and resets the flags
        if(src->fd > 0)
                close (src->fd);
        src->fd = 0;
        src->is_regular = FALSE;
-       src->event_posted = FALSE;
-       src->is_playready = FALSE;
 //     PROFILE_SHOW_RESULT;
        return TRUE;
 }
index 26aaac1..e47802e 100755 (executable)
@@ -28,7 +28,6 @@
 #include <sys/types.h>
 #include <gst/gst.h>
 #include <gst/base/gstbasesrc.h>
-#include "drm-service.h"
 #include <stdio.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -93,11 +92,6 @@ struct _GstDrmSrc
        guint64 read_position;  
       gboolean seekable;      
        gboolean is_regular;    
-       gboolean drm_file;          // flag indicating drm file
-       DRM_FILE_HANDLE hfile;   // drm file handler
-
-       gboolean is_playready;
-       gboolean event_posted;
 };
 
 struct _GstDrmSrcClass 
index fcc9625..8521916 100644 (file)
@@ -17,8 +17,8 @@ plugin_LTLIBRARIES = libgstevasimagesink.la
 libgstevasimagesink_la_SOURCES = gstevasimagesink.c gstevasimagesink.h
 
 # compiler and linker flags used to compile this plugin, set in configure.ac
-libgstevasimagesink_la_CFLAGS = $(GST_CFLAGS) $(GST_VIDEO_CFLAGS) $(EFL_CFLAGS)
-libgstevasimagesink_la_LIBADD = $(GST_LIBS) $(GST_VIDEO_LIBS) $(EFL_LIBS)
+libgstevasimagesink_la_CFLAGS = $(GST_CFLAGS) $(GST_VIDEO_CFLAGS) $(EFL_CFLAGS) $(MMTA_CFLAGS)
+libgstevasimagesink_la_LIBADD = $(GST_LIBS) $(GST_VIDEO_LIBS) $(EFL_LIBS) $(MMTA_LIBS)
 libgstevasimagesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstevasimagesink_la_LIBTOOLFLAGS = --tag=disable-static
 
index b199eb8..f9f9d05 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#  include <config.h>
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -63,6 +63,9 @@ enum
 #define COLOR_DEPTH 4
 #define GL_X11_ENGINE "gl_x11"
 
+GMutex *instance_lock;
+guint instance_lock_count;
+
 static inline gboolean
 is_evas_image_object (Evas_Object *obj)
 {
@@ -91,10 +94,14 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
 
 GST_BOILERPLATE (GstEvasImageSink, gst_evas_image_sink, GstVideoSink, GST_TYPE_VIDEO_SINK);
 
-static void gst_evas_image_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_evas_image_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
-static gboolean gst_evas_image_sink_set_caps (GstBaseSink * base_sink, GstCaps * caps);
-static GstFlowReturn gst_evas_image_sink_show_frame (GstVideoSink * video_sink, GstBuffer * buf);
+static void gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void gst_evas_image_sink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static gboolean gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *caps);
+static GstFlowReturn gst_evas_image_sink_show_frame (GstVideoSink *video_sink, GstBuffer *buf);
+static gboolean gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event);
+static GstStateChangeReturn gst_evas_image_sink_change_state (GstElement *element, GstStateChange transition);
+static void evas_image_sink_cb_del_eo (void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void evas_image_sink_cb_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
 
 static void
 gst_evas_image_sink_base_init (gpointer gclass)
@@ -112,15 +119,17 @@ gst_evas_image_sink_base_init (gpointer gclass)
 }
 
 static void
-gst_evas_image_sink_class_init (GstEvasImageSinkClass * klass)
+gst_evas_image_sink_class_init (GstEvasImageSinkClass *klass)
 {
        GObjectClass *gobject_class;
        GstBaseSinkClass *gstbasesink_class;
        GstVideoSinkClass *gstvideosink_class;
+       GstElementClass *gstelement_class;
 
        gobject_class = (GObjectClass *) klass;
        gstbasesink_class = GST_BASE_SINK_CLASS (klass);
        gstvideosink_class = GST_VIDEO_SINK_CLASS (klass);
+       gstelement_class = (GstElementClass *) klass;
 
        gobject_class->set_property = gst_evas_image_sink_set_property;
        gobject_class->get_property = gst_evas_image_sink_get_property;
@@ -130,23 +139,32 @@ gst_evas_image_sink_class_init (GstEvasImageSinkClass * klass)
        g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT_SHOW,
                g_param_spec_boolean ("visible", "Show Evas Object", "When disabled, evas object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-       gstvideosink_class->show_frame = gst_evas_image_sink_show_frame;
-       gstbasesink_class->set_caps = gst_evas_image_sink_set_caps;
+       gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evas_image_sink_show_frame);
+       gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evas_image_sink_set_caps);
+       gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evas_image_sink_event);
+       gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_evas_image_sink_change_state);
 }
 
 static void
 gst_evas_image_sink_fini (gpointer data, GObject *obj)
 {
+       GST_INFO ("enter");
+
        GstEvasImageSink *esink = GST_EVASIMAGESINK (obj);
        if (!esink) {
                return;
        }
-       if (esink->epipe) {
-               ecore_pipe_del (esink->epipe);
-       }
        if (esink->oldbuf) {
                gst_buffer_unref (esink->oldbuf);
        }
+
+       g_mutex_lock (instance_lock);
+       instance_lock_count--;
+       g_mutex_unlock (instance_lock);
+       if (instance_lock_count == 0) {
+               g_mutex_free (instance_lock);
+               instance_lock = NULL;
+       }
 }
 
 static void
@@ -165,26 +183,44 @@ evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
        if (!esink->eo) {
                return;
        }
+       if (GST_STATE(esink) < GST_STATE_PAUSED) {
+               GST_WARNING ("WRONG-STATE(%d) for rendering, skip this frame", GST_STATE(esink));
+               return;
+       }
 
        memcpy (&buf, buffer, sizeof (GstBuffer *));
        if (!buf) {
-               GST_ERROR ("There is no buffer\n");
+               GST_ERROR ("There is no buffer");
+               return;
+       }
+       if (esink->present_data_addr == -1) {
+               /* if present_data_addr is -1, we don't use this member variable */
+       } else if (esink->present_data_addr != GST_BUFFER_DATA (buf)) {
+               GST_WARNING ("skip rendering this buffer, present_data_addr:%x, GST_BUFFER_DATA(buf):%x", esink->present_data_addr,GST_BUFFER_DATA(buf));
                return;
        }
 
+       MMTA_ACUM_ITEM_BEGIN("eavsimagesink _cb_pipe total", FALSE);
+
+       if ( !esink->is_evas_object_size_set && esink->w > 0 && esink->h > 0) {
+                       evas_object_image_size_set (esink->eo, esink->w, esink->h);
+                       GST_DEBUG("evas_object_image_size_set(), width(%d),height(%d)",esink->w,esink->h);
+                       esink->is_evas_object_size_set = TRUE;
+       }
        if (esink->gl_zerocopy) {
                img_data = evas_object_image_data_get (esink->eo, EINA_TRUE);
                if (!img_data || !GST_BUFFER_DATA(buf)) {
-                       GST_WARNING ("Cannot get image data from evas object or cannot get gstbuffer data\n");
+                       GST_WARNING ("Cannot get image data from evas object or cannot get gstbuffer data");
                        evas_object_image_data_set(esink->eo, img_data);
                } else {
                        GST_DEBUG ("img_data(%x), GST_BUFFER_DATA(buf):%x, esink->w(%d),esink->h(%d)",img_data,GST_BUFFER_DATA(buf),esink->w,esink->h);
-                       memcpy (img_data, GST_BUFFER_DATA (buf), esink->w * esink->h * COLOR_DEPTH);
+                       __ta__("evasimagesink memcpy in _cb_pipe", memcpy (img_data, GST_BUFFER_DATA (buf), esink->w * esink->h * COLOR_DEPTH););
                        evas_object_image_pixels_dirty_set (esink->eo, 1);
                        evas_object_image_data_set(esink->eo, img_data);
                }
                gst_buffer_unref (buf);
        } else {
+               GST_DEBUG ("GST_BUFFER_DATA(buf):%x",GST_BUFFER_DATA(buf));
                evas_object_image_data_set (esink->eo, GST_BUFFER_DATA (buf));
                evas_object_image_pixels_dirty_set (esink->eo, 1);
                if (esink->oldbuf) {
@@ -192,12 +228,29 @@ evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
                }
                esink->oldbuf = buf;
        }
+
+       MMTA_ACUM_ITEM_END("eavsimagesink _cb_pipe total", FALSE);
 }
 
 static void
-gst_evas_image_sink_init (GstEvasImageSink * esink, GstEvasImageSinkClass * gclass)
+gst_evas_image_sink_init (GstEvasImageSink *esink, GstEvasImageSinkClass *gclass)
 {
+       GST_INFO ("enter");
+
        esink->eo = NULL;
+       esink->epipe = NULL;
+       esink->object_show = FALSE;
+       esink->gl_zerocopy = FALSE;
+       esink->is_evas_object_size_set = FALSE;
+       esink->present_data_addr = -1;
+
+       if(!instance_lock) {
+               instance_lock = g_mutex_new();
+       }
+       g_mutex_lock (instance_lock);
+       instance_lock_count++;
+       g_mutex_unlock (instance_lock);
+
        g_object_weak_ref (G_OBJECT (esink), gst_evas_image_sink_fini, NULL);
 }
 
@@ -208,13 +261,32 @@ evas_image_sink_cb_del_eo (void *data, Evas *e, Evas_Object *obj, void *event_in
        if (!esink) {
                return;
        }
+
+       evas_object_event_callback_del (esink->eo, EVAS_CALLBACK_RESIZE, evas_image_sink_cb_resize_event);
        if (esink->oldbuf) {
                gst_buffer_unref (esink->oldbuf);
                esink->oldbuf = NULL;
                esink->eo = NULL;
        }
-       ecore_pipe_del (esink->epipe);
-       esink->epipe = NULL;
+}
+
+static void
+evas_image_sink_cb_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       int w = 0;
+       int h = 0;
+       GstEvasImageSink *esink = data;
+       if (!esink) {
+               return;
+       }
+
+       evas_object_geometry_get(esink->eo, NULL, NULL, &w, &h);
+       if (!w || !h) {
+               GST_WARNING ("evas object size (w:%d,h:%d) was not set",w,h);
+       } else {
+               evas_object_image_fill_set(esink->eo, 0, 0, w, h);
+               GST_DEBUG ("evas object fill set (w:%d,h:%d)",w,h);
+       }
 }
 
 static int
@@ -278,36 +350,151 @@ is_zerocopy_supported (Evas *e)
        return FALSE;
 }
 
+static int
+evas_image_sink_event_parse_data (GstEvasImageSink *esink, GstEvent *event)
+{
+       const GstStructure *st;
+       guint st_data_addr = 0;
+       gint st_data_width = 0;
+       gint st_data_height = 0;
+
+       g_return_val_if_fail (event != NULL, FALSE);
+       g_return_val_if_fail (esink != NULL, FALSE);
+
+       if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM_OOB) {
+               GST_WARNING ("it's not a custom downstream oob event");
+               return -1;
+       }
+       st = gst_event_get_structure (event);
+       if (st == NULL || !gst_structure_has_name (st, "GstStructureForCustomEvent")) {
+               GST_WARNING ("structure in a given event is not proper");
+               return -1;
+       }
+       if (!gst_structure_get_uint (st, "data-addr", &st_data_addr)) {
+               GST_WARNING ("parsing data-addr failed");
+               return -1;
+       }
+       esink->present_data_addr = st_data_addr;
+
+       return 0;
+}
+
+static gboolean
+gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event)
+{
+       GstEvasImageSink *esink = GST_EVASIMAGESINK (sink);
+       GstMessage *msg;
+       gchar *str;
+
+       switch (GST_EVENT_TYPE (event)) {
+               case GST_EVENT_FLUSH_START:
+                       GST_DEBUG ("GST_EVENT_FLUSH_START");
+                       break;
+               case GST_EVENT_FLUSH_STOP:
+                       GST_DEBUG ("GST_EVENT_FLUSH_STOP");
+                       break;
+               case GST_EVENT_EOS:
+                       GST_DEBUG ("GST_EVENT_EOS");
+                       break;
+               case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
+                       if(!evas_image_sink_event_parse_data(esink, event)) {
+                               GST_DEBUG ("GST_EVENT_CUSTOM_DOWNSTREAM_OOB, present_data_addr:%x",esink->present_data_addr);
+                       } else {
+                               GST_ERROR ("evas_image_sink_event_parse_data() failed");
+                       }
+                       break;
+               default:
+                       break;
+       }
+       if (GST_BASE_SINK_CLASS (parent_class)->event) {
+               return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
+       } else {
+               return TRUE;
+       }
+}
+
+static GstStateChangeReturn
+gst_evas_image_sink_change_state (GstElement *element, GstStateChange transition)
+{
+       GstStateChangeReturn ret_state = GST_STATE_CHANGE_SUCCESS;
+       GstEvasImageSink *esink = NULL;
+       esink = GST_EVASIMAGESINK(element);
+       int ret = 0;
+
+       if(!esink) {
+               GST_ERROR("can not get evasimagesink from element");
+       }
+       switch (transition) {
+               case GST_STATE_CHANGE_NULL_TO_READY:
+                       GST_INFO ("*** STATE_CHANGE_NULL_TO_READY ***");
+                       break;
+               case GST_STATE_CHANGE_READY_TO_PAUSED:
+                       GST_INFO ("*** STATE_CHANGE_READY_TO_PAUSED ***");
+                       break;
+               case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+                       GST_INFO ("*** STATE_CHANGE_PAUSED_TO_PLAYING ***");
+                       break;
+               default:
+                       break;
+       }
+
+       ret_state = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+       switch (transition) {
+               case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+                       GST_INFO ("*** STATE_CHANGE_PLAYING_TO_PAUSED ***");
+                       break;
+               case GST_STATE_CHANGE_PAUSED_TO_READY:
+                       GST_INFO ("*** STATE_CHANGE_PAUSED_TO_READY ***");
+                       break;
+               case GST_STATE_CHANGE_READY_TO_NULL:
+                       GST_INFO ("*** STATE_CHANGE_READY_TO_NULL ***");
+                       evas_object_event_callback_del(esink->eo, EVAS_CALLBACK_DEL, evas_image_sink_cb_del_eo);
+                       evas_object_event_callback_del(esink->eo, EVAS_CALLBACK_RESIZE, evas_image_sink_cb_resize_event);
+                       if (esink->epipe) {
+                               ecore_pipe_del (esink->epipe);
+                               esink->epipe = NULL;
+                       }
+                       break;
+               default:
+                       break;
+       }
+
+       return ret_state;
+}
+
 static void
-gst_evas_image_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
+gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
        GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
        Evas_Object *eo;
 
+       g_mutex_lock (instance_lock);
+
        switch (prop_id) {
        case PROP_EVAS_OBJECT:
                eo = g_value_get_pointer (value);
                if (is_evas_image_object (eo)) {
-                       esink->eo = eo;
-                       evas_object_event_callback_add (esink->eo, EVAS_CALLBACK_DEL, evas_image_sink_cb_del_eo, esink);
-                       if (esink->w > 0 && esink->h >0) {
-                               evas_object_image_size_set (esink->eo, esink->w, esink->h);
-                       }
-                       esink->gl_zerocopy = is_zerocopy_supported (evas_object_evas_get (eo));
-                       if (esink->gl_zerocopy) {
-                               evas_object_image_content_hint_set (esink->eo, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
-                               GST_DEBUG("Enable gl zerocopy");
-                       }
-                       if (!esink->epipe) {
-                               esink->epipe = ecore_pipe_add (evas_image_sink_cb_pipe, esink);
+                       if (eo != esink->eo) {
+                               /* delete evas object callbacks registrated on a former evas image object */
+                               evas_object_event_callback_del (esink->eo, EVAS_CALLBACK_DEL, evas_image_sink_cb_del_eo);
+                               evas_object_event_callback_del (esink->eo, EVAS_CALLBACK_RESIZE, evas_image_sink_cb_resize_event);
+
+                               esink->eo = eo;
+
+                               /* add evas object callbacks on a new evas image object */
+                               evas_object_event_callback_add (esink->eo, EVAS_CALLBACK_DEL, evas_image_sink_cb_del_eo, esink);
+                               evas_object_event_callback_add (esink->eo, EVAS_CALLBACK_RESIZE, evas_image_sink_cb_resize_event, esink);
+
+                               esink->gl_zerocopy = is_zerocopy_supported (evas_object_evas_get (eo));
+                               if (esink->gl_zerocopy) {
+                                       evas_object_image_content_hint_set (esink->eo, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
+                                       GST_DEBUG("Enable gl zerocopy");
+                               }
+                               GST_DEBUG("Evas Image Object(%x) is set",esink->eo);
+                               evas_object_show(esink->eo);
+                               esink->object_show = TRUE;
                        }
-                       if (!esink->epipe) {
-                               GST_ERROR ("Cannot set evas-object property: pipe create failed");
-                       }
-                       GST_DEBUG("property set, Evas Object is set");
-                       evas_object_show(esink->eo);
-                       esink->object_show = TRUE;
-                       GST_INFO ("object show..");
                } else {
                        GST_ERROR ("Cannot set evas-object property: value is not an evas image object");
                }
@@ -332,10 +519,12 @@ gst_evas_image_sink_set_property (GObject * object, guint prop_id, const GValue
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
        }
+
+       g_mutex_unlock (instance_lock);
 }
 
 static void
-gst_evas_image_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
+gst_evas_image_sink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
        GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
 
@@ -353,42 +542,59 @@ gst_evas_image_sink_get_property (GObject * object, guint prop_id, GValue * valu
 }
 
 static gboolean
-gst_evas_image_sink_set_caps (GstBaseSink * base_sink, GstCaps * caps)
+gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *caps)
 {
        int r;
        int w, h;
        GstEvasImageSink *esink = GST_EVASIMAGESINK (base_sink);
 
+       esink->is_evas_object_size_set = FALSE;
        r = evas_image_sink_get_size_from_caps (caps, &w, &h);
        if (!r) {
-               if (esink->eo) {
-                       evas_object_image_size_set (esink->eo, w, h);
-                       GST_DEBUG ("evas_object_image_size_set: w(%d) h(%d)", w, h);
-               }
                esink->w = w;
                esink->h = h;
+               GST_DEBUG ("set size w(%d), h(%d)", w, h);
        }
        return TRUE;
 }
 
 static GstFlowReturn
-gst_evas_image_sink_show_frame (GstVideoSink * video_sink, GstBuffer * buf)
+gst_evas_image_sink_show_frame (GstVideoSink *video_sink, GstBuffer *buf)
 {
        GstEvasImageSink *esink = GST_EVASIMAGESINK (video_sink);
        Eina_Bool r;
-       if (esink->epipe && esink->object_show) {
+
+       g_mutex_lock (instance_lock);
+       if (esink->present_data_addr == -1) {
+               /* if present_data_addr is -1, we don't use this member variable */
+       } else if (esink->present_data_addr != GST_BUFFER_DATA (buf)) {
+               GST_WARNING ("skip rendering this buffer, present_data_addr:%x, GST_BUFFER_DATA(buf):%x", esink->present_data_addr,GST_BUFFER_DATA(buf));
+               g_mutex_unlock (instance_lock);
+               return;
+       }
+       if (!esink->epipe) {
+               esink->epipe = ecore_pipe_add (evas_image_sink_cb_pipe, esink);
+               if (!esink->epipe) {
+                       GST_ERROR ("ecore-pipe create failed");
+                       return GST_FLOW_ERROR;
+               }
+       }
+       if (esink->object_show) {
                gst_buffer_ref (buf);
-               r = ecore_pipe_write (esink->epipe, &buf, sizeof (GstBuffer *));
+               __ta__("evasimagesink ecore_pipe_write", r = ecore_pipe_write (esink->epipe, &buf, sizeof (GstBuffer *)););
                if (r == EINA_FALSE)  {
                        gst_buffer_unref (buf);
                }
                GST_DEBUG ("after ecore_pipe_write()");
+       } else {
+               GST_DEBUG ("skip ecore_pipe_write()");
        }
+       g_mutex_unlock (instance_lock);
        return GST_FLOW_OK;
 }
 
 static gboolean
-evas_image_sink_init (GstPlugin * evasimagesink)
+evas_image_sink_init (GstPlugin *evasimagesink)
 {
        GST_DEBUG_CATEGORY_INIT (gst_evas_image_sink_debug, "evasimagesink", 0, "Evas image object based videosink");
 
index 9239ee6..1e2e19b 100644 (file)
@@ -28,6 +28,7 @@
 #include <gst/video/gstvideosink.h>
 #include <Evas.h>
 #include <Ecore.h>
+#include <mm_ta.h>
 
 G_BEGIN_DECLS
 
@@ -49,15 +50,18 @@ typedef struct _GstEvasImageSinkClass GstEvasImageSinkClass;
 struct _GstEvasImageSink
 {
        GstVideoSink element;
-       GstPad *sinkpad, *srcpad;
 
        Evas_Object *eo;
        Ecore_Pipe *epipe;
        Evas_Coord w;
        Evas_Coord h;
-       GstBuffer *oldbuf;
-       gboolean gl_zerocopy;
        gboolean object_show;
+       gboolean gl_zerocopy;
+
+       GstBuffer *oldbuf;
+
+       gboolean is_evas_object_size_set;
+       guint present_data_addr;
 };
 
 struct _GstEvasImageSinkClass
index 6380efd..8ac79ae 100644 (file)
@@ -1,19 +1,19 @@
+#sbs-git:slp/pkgs/g/gst-plugins-ext0.10 gst-plugins-ext0.10 0.1.7 1784a2d9c9fb90be7fe99857215c2a6154adaacb
 Name:       gst-plugins-ext0.10
-Version:    0.1.5
-Summary:    GStreamer extra plugins (common) Version:    1.0
-Release:    2
+Version:    0.2.3
+Summary:    GStreamer extra plugins (common)
+Release:    5
 Group:      TO_BE/FILLED_IN
-License:    LGPLv2+
+License:    TO BE FILLED IN
 Source0:    %{name}-%{version}.tar.gz
 BuildRequires:  pkgconfig(avsysaudio)
 BuildRequires:  pkgconfig(camsrcjpegenc)
-BuildRequires:  pkgconfig(drm-service)
 BuildRequires:  pkgconfig(ecore)
 BuildRequires:  pkgconfig(ecore-x)
 BuildRequires:  pkgconfig(evas)
 BuildRequires:  pkgconfig(mm-ta)
 BuildRequires:  pkgconfig(gstreamer-plugins-base-0.10)
-BuildRequires:  pkgconfig(gstreamer-0.10)
+BuildRequires:  pkgconfig(gstreamer-0.10)  
 BuildRequires:  pkgconfig(libexif)
 
 %description
@@ -37,5 +37,5 @@ rm -rf %{buildroot}
 
 
 %files
-%defattr(-,root,root,-)
+%defattr(-,root,root,-)  
 %{_libdir}/gstreamer-0.10/*.so
index c7c1ad5..a5ed22f 100755 (executable)
@@ -808,7 +808,7 @@ gst_pd_pushsrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
 static gboolean
 gst_pd_pushsrc_plugin_init (GstPlugin *plugin)
 {
-    if (!gst_element_register (plugin, "pdpushsrc", GST_RANK_PRIMARY, gst_pd_pushsrc_get_type()))
+    if (!gst_element_register (plugin, "pdpushsrc", GST_RANK_NONE, gst_pd_pushsrc_get_type()))
     {
         return FALSE;
     }
diff --git a/piffdemux/Makefile.am b/piffdemux/Makefile.am
new file mode 100755 (executable)
index 0000000..308a09c
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src\r
diff --git a/piffdemux/src/Makefile.am b/piffdemux/src/Makefile.am
new file mode 100755 (executable)
index 0000000..c51b0a8
--- /dev/null
@@ -0,0 +1,46 @@
+
+plugin_LTLIBRARIES = libgstpiff.la
+
+libgstpiffincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/
+
+libgstpiff_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+
+libgstpiff_la_LIBADD = \
+    $(GST_PLUGINS_BASE_LIBS) \
+    -lgstriff-@GST_MAJORMINOR@ \
+    -lgstaudio-@GST_MAJORMINOR@ \
+    -lgsttag-@GST_MAJORMINOR@ \
+    -lgstpbutils-@GST_MAJORMINOR@ \
+    $(GST_BASE_LIBS) $(GST_LIBS) $(ZLIB_LIBS)
+
+libgstpiff_la_LDFLAGS = ${GST_PLUGIN_LDFLAGS}
+
+libgstpiff_la_SOURCES = piff-plugin.c \
+               piffdemux.c \
+               piffdemux_types.c \
+               piffdemux_dump.c
+
+libgstpiff_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = \
+       piffatomparser.h   \
+       piffdemux_types.h  \
+       piffdemux_dump.h   \
+       piffdemux_fourcc.h \
+       piffpalette.h
+
+libgstpiffinclude_HEADERS = piffcommon.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+       androgenizer \
+       -:PROJECT libgstpiff -:SHARED libgstpiff \
+        -:TAGS eng debug \
+         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+        -:SOURCES $(libgstpiff_la_SOURCES) \
+        -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(CPPFLAGS) $(libgstpiff_la_CFLAGS) \
+        -:LDFLAGS $(libgstpiff_la_LDFLAGS) \
+                  $(libgstpiff_la_LIBADD) \
+                  -ldl \
+        -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+                      LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+       > $@
diff --git a/piffdemux/src/piff-plugin.c b/piffdemux/src/piff-plugin.c
new file mode 100755 (executable)
index 0000000..8afff31
--- /dev/null
@@ -0,0 +1,23 @@
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+//#include "gst/gst-i18n-plugin.h"
+#include "piffdemux.h"
+#include <gst/pbutils/pbutils.h>
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "piffdemux", GST_RANK_PRIMARY, GST_TYPE_PIFFDEMUX))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "piffdemux",
+    "ISO base media file format support (PIFF)",
+    plugin_init, VERSION, "Proprietary",  "Samsung Electronics Co", "http://www.samsung.com");
diff --git a/piffdemux/src/piffatomparser.h b/piffdemux/src/piffatomparser.h
new file mode 100755 (executable)
index 0000000..f90d5db
--- /dev/null
@@ -0,0 +1,139 @@
+/* GStreamer QuickTime atom parser
+ * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.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 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef QT_ATOM_PARSER_H
+#define QT_ATOM_PARSER_H
+
+#include <gst/base/gstbytereader.h>
+
+/* our inlined version of GstByteReader */
+
+static inline gboolean
+piff_atom_parser_has_remaining (GstByteReader * parser, guint64 bytes_needed)
+{
+  return G_LIKELY (parser->size >= bytes_needed) &&
+      G_LIKELY ((parser->size - bytes_needed) >= parser->byte);
+}
+
+static inline gboolean
+piff_atom_parser_has_chunks (GstByteReader * parser, guint32 n_chunks,
+    guint32 chunk_size)
+{
+  /* assumption: n_chunks and chunk_size are 32-bit, we cast to 64-bit here
+   * to avoid overflows, to handle e.g. (guint32)-1 * size correctly */
+  return piff_atom_parser_has_remaining (parser, (guint64) n_chunks * chunk_size);
+}
+
+static inline gboolean
+piff_atom_parser_peek_sub (GstByteReader * parser, guint offset, guint size,
+    GstByteReader * sub)
+{
+  *sub = *parser;
+
+  if (G_UNLIKELY (!gst_byte_reader_skip (sub, offset)))
+    return FALSE;
+
+  return (gst_byte_reader_get_remaining (sub) >= size);
+}
+
+static inline gboolean
+piff_atom_parser_skipn_and_get_uint32 (GstByteReader * parser,
+    guint bytes_to_skip, guint32 * val)
+{
+  if (G_UNLIKELY (gst_byte_reader_get_remaining (parser) < (bytes_to_skip + 4)))
+    return FALSE;
+
+  gst_byte_reader_skip_unchecked (parser, bytes_to_skip);
+  *val = gst_byte_reader_get_uint32_be_unchecked (parser);
+  return TRUE;
+}
+
+/* off_size must be either 4 or 8 */
+static inline gboolean
+piff_atom_parser_get_offset (GstByteReader * parser, guint off_size,
+    guint64 * val)
+{
+  if (G_UNLIKELY (gst_byte_reader_get_remaining (parser) < off_size))
+    return FALSE;
+
+  if (off_size == sizeof (guint64)) {
+    *val = gst_byte_reader_get_uint64_be_unchecked (parser);
+  } else {
+    *val = gst_byte_reader_get_uint32_be_unchecked (parser);
+  }
+  return TRUE;
+}
+
+/* off_size must be either 4 or 8 */
+static inline guint64
+piff_atom_parser_get_offset_unchecked (GstByteReader * parser, guint off_size)
+{
+  if (off_size == sizeof (guint64)) {
+    return gst_byte_reader_get_uint64_be_unchecked (parser);
+  } else {
+    return gst_byte_reader_get_uint32_be_unchecked (parser);
+  }
+}
+
+/* size must be from 1 to 4 */
+static inline guint32
+piff_atom_parser_get_uint_with_size_unchecked (GstByteReader * parser,
+    guint size)
+{
+  switch (size) {
+  case 1:
+    return gst_byte_reader_get_uint8_unchecked (parser);
+  case 2:
+    return gst_byte_reader_get_uint16_be_unchecked (parser);
+  case 3:
+    return gst_byte_reader_get_uint24_be_unchecked (parser);
+  case 4:
+    return gst_byte_reader_get_uint32_be_unchecked (parser);
+  default:
+    g_assert_not_reached ();
+    gst_byte_reader_skip_unchecked (parser, size);
+    break;
+  }
+  return 0;
+}
+
+static inline gboolean
+piff_atom_parser_get_fourcc (GstByteReader * parser, guint32 * fourcc)
+{
+  guint32 f_be;
+
+  if (G_UNLIKELY (gst_byte_reader_get_remaining (parser) < 4))
+    return FALSE;
+
+  f_be = gst_byte_reader_get_uint32_be_unchecked (parser);
+  *fourcc = GUINT32_SWAP_LE_BE (f_be);
+  return TRUE;
+}
+
+static inline guint32
+piff_atom_parser_get_fourcc_unchecked (GstByteReader * parser)
+{
+  guint32 fourcc;
+
+  fourcc = gst_byte_reader_get_uint32_be_unchecked (parser);
+  return GUINT32_SWAP_LE_BE (fourcc);
+}
+
+#endif /* QT_ATOM_PARSER_H */
diff --git a/piffdemux/src/piffcommon.h b/piffdemux/src/piffcommon.h
new file mode 100755 (executable)
index 0000000..e24a19c
--- /dev/null
@@ -0,0 +1,29 @@
+
+#ifndef __GST_PIFFCOMMON_H__
+#define __GST_PIFFCOMMON_H__
+
+G_BEGIN_DECLS
+
+typedef struct _piff_fragment_longtime_info_t
+{
+  guint64 ts;
+  guint64 duration;
+}piff_fragment_longtime_info;
+
+typedef struct _piff_fragment_time_info_t
+{
+  guint32 ts;
+  guint32 duration;
+}piff_fragment_time_info;
+
+typedef struct _live_param_t
+{
+  gboolean is_eos; /* is live session ended */
+  guint count; /*  fragment parameters count */
+  gchar *media_type;
+  piff_fragment_time_info *info;
+  piff_fragment_longtime_info *long_info;
+}piff_live_param_t;
+G_END_DECLS
+
+#endif /* __GST_PIFFPALETTE_H__ */
diff --git a/piffdemux/src/piffdemux.c b/piffdemux/src/piffdemux.c
new file mode 100755 (executable)
index 0000000..d8d78ce
--- /dev/null
@@ -0,0 +1,3083 @@
+\r
+\r
+#ifdef HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+\r
+#include "piffdemux.h"\r
+#include <glib/gprintf.h>\r
+#include <gst/tag/tag.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <piffatomparser.h>\r
+#include <piffdemux_fourcc.h>\r
+#include <piffpalette.h>\r
+#include <piffdemux_types.h>\r
+#include <piffdemux_dump.h>\r
+\r
+#define PIFF_DEFAULT_TRACKID   -1\r
+#define PIFF_DEFAULT_FOURCC   0\r
+#define PIFF_DEFAULT_TIMESCALE 10000000\r
+#define PIFF_DEFAULT_DURATION -1\r
+#define PIFF_DEFAULT_START_TS 0\r
+#define PIFF_DEFAULT_START_TS 0\r
+\r
+#define PIFF_DEFAULT_WIDTH 16\r
+#define PIFF_DEFAULT_HEIGHT 16\r
+#define PIFF_DEFAULT_BPS 16\r
+\r
+#undef DEC_OUT_FRAME_DUMP\r
+\r
+#ifdef DEC_OUT_FRAME_DUMP\r
+#include <stdio.h>\r
+FILE *piffdump = NULL;\r
+#endif\r
+\r
+#define PIFFDEMUX_RB16(x)      ((((const unsigned char*)(x))[0] << 8) | ((const unsigned char*)(x))[1])\r
+/* max. size considered 'sane' for non-mdat atoms */\r
+#define PIFFDEMUX_MAX_ATOM_SIZE (25*1024*1024)\r
+\r
+/* if the sample index is larger than this, something is likely wrong */\r
+#define PIFFDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)\r
+\r
+GST_DEBUG_CATEGORY (piffdemux_debug);\r
+\r
+typedef struct _PiffDemuxSegment PiffDemuxSegment;\r
+typedef struct _PiffDemuxSample PiffDemuxSample;\r
+typedef struct _PiffDemuxSubSampleEncryption PiffDemuxSubSampleEncryption;\r
+typedef struct _PiffDemuxSubSampleEntryInfo PiffDemuxSubSampleEntryInfo;\r
+\r
+enum\r
+{\r
+  PROR_PIFF_0,\r
+  PROP_PIFF_MEDIA_CAPS,\r
+  PROP_PIFF_MEDIA_TIMESCALE,\r
+  PROP_PIFF_MEDIA_DURATION,\r
+  PROP_PIFF_MEDIA_START_TIMESTAMP,\r
+  PROP_PIFF_IS_LIVE,\r
+  PROP_PIFF_LOOKAHEAD_COUNT,\r
+  PROP_PIFF_AVG_FRAME_DUR,\r
+};\r
+\r
+enum\r
+{\r
+  SIGNAL_LIVE_PARAM,\r
+  LAST_SIGNAL\r
+};\r
+\r
+static guint gst_piffdemux_signals[LAST_SIGNAL] = { 0 };\r
+\r
+struct _PiffDemuxSubSampleEntryInfo\r
+{\r
+  guint16 LenofClearData;\r
+  guint32 LenofEncryptData;\r
+};\r
+\r
+struct _PiffDemuxSubSampleEncryption\r
+{\r
+  guint16 n_entries;\r
+  PiffDemuxSubSampleEntryInfo *sub_entry;\r
+};\r
+\r
+struct _PiffDemuxSample\r
+{\r
+  guint32 size;\r
+  gint32 pts_offset;            /* Add this value to timestamp to get the pts */\r
+  guint64 offset;\r
+  guint64 timestamp;            /* DTS In mov time */\r
+  guint32 duration;             /* In mov time */\r
+  gboolean keyframe;            /* TRUE when this packet is a keyframe */\r
+  guint8 *iv;                          /* initialization vector for decryption*/\r
+  PiffDemuxSubSampleEncryption *sub_encry;\r
+};\r
+\r
+/* timestamp is the DTS */\r
+#define PIFFSAMPLE_DTS(stream,sample) gst_util_uint64_scale ((sample)->timestamp,\\r
+    GST_SECOND, (stream)->timescale)\r
+/* timestamp + offset is the PTS */\r
+#define PIFFSAMPLE_PTS(stream,sample) gst_util_uint64_scale ((sample)->timestamp + \\r
+    (sample)->pts_offset, GST_SECOND, (stream)->timescale)\r
+/* timestamp + duration - dts is the duration */\r
+#define PIFFSAMPLE_DUR_DTS(stream,sample,dts) (gst_util_uint64_scale ((sample)->timestamp + \\r
+    (sample)->duration, GST_SECOND, (stream)->timescale) - (dts));\r
+/* timestamp + offset + duration - pts is the duration */\r
+#define PIFFSAMPLE_DUR_PTS(stream,sample,pts) (gst_util_uint64_scale ((sample)->timestamp + \\r
+    (sample)->pts_offset + (sample)->duration, GST_SECOND, (stream)->timescale) - (pts));\r
+\r
+#define PIFFSAMPLE_KEYFRAME(stream,sample) ((sample)->keyframe);\r
+\r
+typedef char uuid_t[16];\r
+\r
+static const uuid_t tfxd_uuid = { 0x6d, 0x1d, 0x9b, 0x05,\r
+                                               0x42, 0xd5, 0x44, 0xe6,\r
+                                               0x80, 0xe2, 0x14, 0x1d,\r
+                                               0xaf, 0xf7, 0x57, 0xb2 };\r
+\r
+static const uuid_t tfrf_uuid = { 0xd4, 0x80, 0x7e, 0xf2,\r
+                                              0xca, 0x39, 0x46, 0x95,\r
+                                              0x8e, 0x54, 0x26, 0xcb,\r
+                                              0x9e, 0x46, 0xa7, 0x9f };\r
+\r
+static const uuid_t encrypt_uuid = {  0xa2, 0x39, 0x4f, 0x52,\r
+                                                        0x5a, 0x9b, 0x4f, 0x14,\r
+                                                        0xa2, 0x44, 0x6c, 0x42,\r
+                                                        0x7c, 0x64, 0x8d, 0xf4 };\r
+\r
+#define SE_OVERRIDE_TE_FLAGS 0x000001\r
+#define SE_USE_SUBSAMPLE_ENCRYPTION 0x000002\r
+\r
+typedef enum\r
+{\r
+  UUID_UNKNOWN = -1,\r
+  UUID_TFXD,\r
+  UUID_TFRF,\r
+  UUID_SAMPLE_ENCRYPT,\r
+}uuid_type_t;\r
+\r
+struct _PiffDemuxSegment\r
+{\r
+  /* global time and duration, all gst time */\r
+  guint64 time;\r
+  guint64 stop_time;\r
+  guint64 duration;\r
+  /* media time of trak, all gst time */\r
+  guint64 media_start;\r
+  guint64 media_stop;\r
+  gdouble rate;\r
+};\r
+\r
+\r
+struct _PiffDemuxStream\r
+{\r
+  /* stream type */\r
+  guint32 subtype;\r
+  GstCaps *caps;\r
+  guint32 fourcc;\r
+\r
+  /* duration/scale */\r
+  guint64 duration;             /* in timescale */\r
+  guint32 timescale;\r
+\r
+  /* our samples */\r
+  guint32 n_samples;\r
+  PiffDemuxSample *samples;\r
+  guint32 min_duration;         /* duration in timescale of first sample, used for figuring out\r
+                                   the framerate, in timescale units */\r
+\r
+  /* if we use chunks or samples */\r
+  gboolean sampled;\r
+  guint padding;\r
+\r
+  /* when a discontinuity is pending */\r
+  gboolean discont;\r
+\r
+  /* list of buffers to push first */\r
+  GSList *buffers;\r
+\r
+  /* buffer needs some custom processing, e.g. subtitles */\r
+  gboolean need_process;\r
+\r
+    /* current position */\r
+  guint32 segment_index;\r
+  guint32 sample_index;\r
+  guint64 time_position;        /* in gst time */\r
+\r
+  /* the Gst segment we are processing out, used for clipping */\r
+  GstSegment segment;\r
+\r
+  /* last GstFlowReturn */\r
+  GstFlowReturn last_ret;\r
+\r
+\r
+  /* quicktime segments */\r
+  guint32 n_segments;\r
+  PiffDemuxSegment *segments;\r
+  guint32 from_sample;\r
+  guint32 to_sample;\r
+\r
+  gboolean sent_eos;\r
+  GstTagList *pending_tags;\r
+  gboolean send_global_tags;\r
+\r
+  GstEvent *pending_event;\r
+\r
+  gboolean sent_nsevent;\r
+\r
+  guint64 start_ts;\r
+\r
+  guint64 avg_dur; /* average frame duration */\r
+};\r
+\r
+\r
+enum PiffDemuxState\r
+{\r
+  PIFFDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */\r
+  PIFFDEMUX_STATE_HEADER,         /* Parsing the header */\r
+  PIFFDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */\r
+  PIFFDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */\r
+};\r
+\r
+\r
+static GNode *piffdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);\r
+static GNode *piffdemux_tree_get_child_by_type_full (GNode * node,\r
+    guint32 fourcc, GstByteReader * parser);\r
+static GNode *piffdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);\r
+static GNode *piffdemux_tree_get_sibling_by_type_full (GNode * node,\r
+    guint32 fourcc, GstByteReader * parser);\r
+\r
+static GstStaticPadTemplate gst_piffdemux_sink_template =\r
+    GST_STATIC_PAD_TEMPLATE ("sink",\r
+    GST_PAD_SINK,\r
+    GST_PAD_ALWAYS,\r
+    GST_STATIC_CAPS ("application/x-piff")\r
+    );\r
+\r
+static GstStaticPadTemplate gst_piffdemux_src_template =\r
+GST_STATIC_PAD_TEMPLATE ("src",\r
+    GST_PAD_SRC,\r
+    GST_PAD_ALWAYS,\r
+    GST_STATIC_CAPS_ANY);\r
+\r
+\r
+GST_BOILERPLATE (GstPiffDemux, gst_piffdemux, GstPiffDemux, GST_TYPE_ELEMENT);\r
+\r
+static void gst_piffdemux_dispose (GObject * object);\r
+\r
+static GstStateChangeReturn gst_piffdemux_change_state (GstElement * element,\r
+    GstStateChange transition);\r
+static void\r
+gst_piffdemux_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);\r
+static void\r
+gst_piffdemux_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);\r
+static GstFlowReturn gst_piffdemux_chain (GstPad * sinkpad, GstBuffer * inbuf);\r
+static gboolean gst_piffdemux_handle_sink_event (GstPad * pad, GstEvent * event);\r
+static gboolean piffdemux_parse_node (GstPiffDemux * piffdemux, GNode * node, const guint8 * buffer, guint length);\r
+static gboolean piffdemux_parse_sample_encryption(GstPiffDemux * piffdemux, GstByteReader *sample_encrypt, PiffDemuxStream * stream);\r
+static gboolean piffdemux_parse_mfhd (GstPiffDemux * piffdemux, GstByteReader * mfhd);\r
+static gboolean gst_piffdemux_handle_src_event (GstPad * pad, GstEvent * event);\r
+static const GstQueryType *gst_piffdemux_get_src_query_types (GstPad * pad);\r
+static gboolean gst_piffdemux_handle_src_query (GstPad * pad, GstQuery * query);\r
+\r
+\r
+static gboolean\r
+ConvertH264_MetaDCI_to_3GPPDCI(unsigned char *dci_meta_buf, unsigned int dci_meta_size, unsigned char **dci_3gpp_buf, unsigned int *dci_3gpp_size);\r
+void\r
+__gst_piffdemux_marshal_BOOLEAN__OBJECT (GClosure *closure,\r
+                                   GValue       *return_value G_GNUC_UNUSED,\r
+                                   guint         n_param_values,\r
+                                   const GValue *param_values,\r
+                                   gpointer      invocation_hint G_GNUC_UNUSED,\r
+                                   gpointer      marshal_data);\r
+\r
+static void\r
+gst_piffdemux_base_init (gpointer klass)\r
+{\r
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);\r
+\r
+  gst_element_class_add_pad_template (element_class,\r
+      gst_static_pad_template_get (&gst_piffdemux_sink_template));\r
+  gst_element_class_add_pad_template (element_class,\r
+      gst_static_pad_template_get (&gst_piffdemux_src_template));\r
+  gst_element_class_set_details_simple (element_class, "PIFF demuxer",\r
+      "Codec/Parser",\r
+      "Parser for PIFF file format",\r
+      "naveen ch <naveen.ch@samsung.com>");\r
+\r
+  GST_DEBUG_CATEGORY_INIT (piffdemux_debug, "piffdemux", 0, "piffdemux plugin");\r
+}\r
+\r
+static void\r
+gst_piffdemux_class_init (GstPiffDemuxClass * klass)\r
+{\r
+  GObjectClass *gobject_class;\r
+  GstElementClass *gstelement_class;\r
+\r
+  gobject_class = (GObjectClass *) klass;\r
+  gstelement_class = (GstElementClass *) klass;\r
+\r
+  parent_class = g_type_class_peek_parent (klass);\r
+\r
+  gobject_class->dispose = gst_piffdemux_dispose;\r
+  gobject_class->set_property = gst_piffdemux_set_property;\r
+  gobject_class->get_property = gst_piffdemux_get_property;\r
+\r
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_piffdemux_change_state);\r
+\r
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_CAPS,\r
+      g_param_spec_boxed ("caps", "Caps",\r
+      "The allowed caps for the src pad", GST_TYPE_CAPS,\r
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));\r
\r
+  /* timescale of media to be set by application */\r
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_TIMESCALE,\r
+      g_param_spec_uint64 ("timescale", "media timescale",\r
+      "media timescale in PIFF Manifest", 0, G_MAXUINT64,\r
+      PIFF_DEFAULT_TIMESCALE,\r
+      G_PARAM_READWRITE));\r
+\r
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_DURATION,\r
+      g_param_spec_int64 ("duration", "Duration of media",\r
+      "Total duration of the content", -1, G_MAXINT64,\r
+      PIFF_DEFAULT_DURATION,\r
+      G_PARAM_READWRITE));\r
+\r
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_START_TIMESTAMP,\r
+      g_param_spec_uint64 ("start-ts", "expected start timestamp",\r
+      "expected start timestamp to avoid reset", 0, G_MAXUINT64,\r
+      PIFF_DEFAULT_START_TS,\r
+      G_PARAM_READWRITE));\r
+\r
+  g_object_class_install_property (gobject_class, PROP_PIFF_IS_LIVE,\r
+      g_param_spec_boolean ("is-live", "Is presentation is Live or VOD",\r
+      "If Presentation is Live (true) else VOD (false)",\r
+      FALSE,\r
+      G_PARAM_READWRITE));\r
+\r
+  g_object_class_install_property (gobject_class, PROP_PIFF_LOOKAHEAD_COUNT,\r
+      g_param_spec_uint ("lookahead-count", "Lookahead count value",\r
+      "Look ahead count used in case of Live presentation", 0, G_MAXUINT,\r
+      0,\r
+      G_PARAM_READWRITE));\r
+\r
+  g_object_class_install_property (gobject_class, PROP_PIFF_AVG_FRAME_DUR,\r
+      g_param_spec_uint64 ("frame-dur", "Average frame duration",\r
+      "Average frame duration", 0, G_MAXUINT64,\r
+      G_MAXUINT64,\r
+      G_PARAM_READABLE));\r
+\r
+  gst_piffdemux_signals[SIGNAL_LIVE_PARAM] =\r
+      g_signal_new ("live-param", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,\r
+          G_STRUCT_OFFSET (GstPiffDemuxClass, live_param), NULL, NULL,\r
+          g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);\r
+\r
+}\r
+\r
+static void\r
+gst_piffdemux_init (GstPiffDemux * piffdemux, GstPiffDemuxClass * klass)\r
+{\r
+  /* sink pad */\r
+  piffdemux->sinkpad = gst_pad_new_from_static_template (&gst_piffdemux_sink_template, "sink");\r
+  gst_pad_set_chain_function (piffdemux->sinkpad, gst_piffdemux_chain);\r
+  gst_pad_set_event_function (piffdemux->sinkpad, gst_piffdemux_handle_sink_event);\r
+  gst_element_add_pad (GST_ELEMENT_CAST (piffdemux), piffdemux->sinkpad);\r
+\r
+  /* source pad */\r
+  piffdemux->srcpad = gst_pad_new_from_static_template (&gst_piffdemux_src_template, "src");\r
+  gst_pad_set_event_function (piffdemux->srcpad, gst_piffdemux_handle_src_event);\r
+  gst_pad_use_fixed_caps (piffdemux->srcpad);\r
+  gst_pad_set_query_type_function (piffdemux->srcpad, gst_piffdemux_get_src_query_types);\r
+  gst_pad_set_query_function (piffdemux->srcpad, gst_piffdemux_handle_src_query);\r
+  gst_element_add_pad (GST_ELEMENT_CAST (piffdemux), piffdemux->srcpad);\r
+\r
+  piffdemux->stream = g_new0 (PiffDemuxStream, 1);\r
+  piffdemux->stream->fourcc = PIFF_DEFAULT_FOURCC;\r
+  piffdemux->stream->timescale = PIFF_DEFAULT_TIMESCALE;\r
+  piffdemux->stream->duration = PIFF_DEFAULT_DURATION;\r
+  piffdemux->stream->caps = NULL;\r
+  piffdemux->stream->discont = TRUE;\r
+  piffdemux->stream->need_process = FALSE;\r
+  piffdemux->stream->segment_index = -1;\r
+  piffdemux->stream->time_position = 0;\r
+  piffdemux->stream->sample_index = -1;\r
+  piffdemux->stream->last_ret = GST_FLOW_OK;\r
+  piffdemux->stream->sent_nsevent = FALSE;\r
+  piffdemux->stream->start_ts = PIFF_DEFAULT_START_TS;\r
+  piffdemux->stream->avg_dur = -1;\r
+\r
+  piffdemux->state = PIFFDEMUX_STATE_INITIAL;\r
+  piffdemux->neededbytes = 16;\r
+  piffdemux->todrop = 0;\r
+  piffdemux->adapter = gst_adapter_new ();\r
+  piffdemux->offset = 0;\r
+  piffdemux->first_mdat = -1;\r
+  piffdemux->mdatoffset = GST_CLOCK_TIME_NONE;\r
+  piffdemux->mdatbuffer = NULL;\r
+  piffdemux->moof_rcvd = FALSE;\r
+  piffdemux->is_live = FALSE;\r
+  piffdemux->lookahead_cnt = 0;\r
+\r
+#ifdef DEC_OUT_FRAME_DUMP\r
+    piffdump = fopen ("/opt/media/piff_out_dump.dmp", "w+");\r
+    if (piffdump == NULL)\r
+    {\r
+        g_print ("\nNot able to create frame dump file\n");\r
+    }\r
+#endif\r
+\r
+  gst_segment_init (&piffdemux->segment, GST_FORMAT_TIME);\r
+}\r
+\r
+static void\r
+gst_piffdemux_dispose (GObject * object)\r
+{\r
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (object);\r
+\r
+  if (piffdemux->adapter) {\r
+    g_object_unref (G_OBJECT (piffdemux->adapter));\r
+    piffdemux->adapter = NULL;\r
+  }\r
+\r
+#ifdef DEC_OUT_FRAME_DUMP\r
+    {\r
+        fclose (piffdump);\r
+        piffdump = NULL;\r
+    }\r
+#endif\r
+  G_OBJECT_CLASS (parent_class)->dispose (object);\r
+}\r
+\r
+\r
+static void\r
+gst_piffdemux_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)\r
+{\r
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (object);\r
+\r
+  switch (prop_id) {\r
+    case PROP_PIFF_MEDIA_CAPS: {\r
+        if (piffdemux->stream->caps)\r
+          gst_caps_unref(piffdemux->stream->caps);\r
+        piffdemux->stream->caps = gst_caps_copy (gst_value_get_caps (value));\r
+        GST_DEBUG_OBJECT (piffdemux, "stream caps = %s", gst_caps_to_string(piffdemux->stream->caps));\r
+        if (!gst_pad_set_caps(piffdemux->srcpad, piffdemux->stream->caps)) {\r
+          GST_ERROR_OBJECT (piffdemux, "not able to set caps...");\r
+        }\r
+        break;\r
+      }\r
+    case PROP_PIFF_MEDIA_TIMESCALE:\r
+      piffdemux->stream->timescale = g_value_get_uint64(value);\r
+      break;\r
+    case PROP_PIFF_MEDIA_DURATION:\r
+      piffdemux->stream->duration = g_value_get_int64(value);\r
+      break;\r
+    case PROP_PIFF_MEDIA_START_TIMESTAMP:\r
+      piffdemux->stream->start_ts = g_value_get_uint64(value);\r
+      GST_INFO_OBJECT (piffdemux, "start_ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(piffdemux->stream->start_ts));\r
+      break;\r
+    case PROP_PIFF_IS_LIVE:\r
+      piffdemux->is_live = g_value_get_boolean(value);\r
+      break;\r
+    case PROP_PIFF_LOOKAHEAD_COUNT:\r
+      piffdemux->lookahead_cnt = g_value_get_uint(value);\r
+      GST_DEBUG_OBJECT (piffdemux, "Look ahead count = %d", piffdemux->lookahead_cnt);\r
+      break;\r
+    default:\r
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);\r
+      break;\r
+    }\r
+}\r
+\r
+\r
+static void\r
+gst_piffdemux_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)\r
+{\r
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (object);\r
+\r
+  switch (prop_id) {\r
+     case PROP_PIFF_MEDIA_CAPS:\r
+      gst_value_set_caps (value, piffdemux->stream->caps);\r
+      break;\r
+    case PROP_PIFF_MEDIA_TIMESCALE:\r
+      g_value_set_uint64 (value, piffdemux->stream->timescale);\r
+      break;\r
+    case PROP_PIFF_MEDIA_DURATION:\r
+      g_value_set_int64 (value, piffdemux->stream->duration);\r
+      break;\r
+    case PROP_PIFF_MEDIA_START_TIMESTAMP:\r
+      g_value_set_uint64 (value, piffdemux->stream->start_ts);\r
+      break;\r
+    case PROP_PIFF_IS_LIVE:\r
+      g_value_set_boolean(value, piffdemux->is_live);\r
+      break;\r
+    case PROP_PIFF_LOOKAHEAD_COUNT:\r
+      g_value_set_uint (value, piffdemux->lookahead_cnt);\r
+      break;\r
+    case PROP_PIFF_AVG_FRAME_DUR:\r
+      g_value_set_uint64 (value, piffdemux->stream->avg_dur);\r
+      break;\r
+    default:\r
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);\r
+      break;\r
+    }\r
+}\r
+\r
+\r
+static void\r
+gst_piffdemux_post_no_playable_stream_error (GstPiffDemux * piffdemux)\r
+{\r
+  if (piffdemux->posted_redirect) {\r
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,\r
+        ("This file contains no playable streams."),\r
+        ("no known streams found, a redirect message has been posted"));\r
+  } else {\r
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,\r
+        ("This file contains no playable streams."),\r
+        ("no known streams found"));\r
+  }\r
+\r
+}\r
+\r
+static gboolean\r
+gst_piffdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,\r
+    GstFormat dest_format, gint64 * dest_value)\r
+{\r
+  gboolean res = TRUE;\r
+  PiffDemuxStream *stream = gst_pad_get_element_private (pad);\r
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (gst_pad_get_parent (pad));\r
+\r
+  if (stream->subtype != FOURCC_vide) {\r
+    res = FALSE;\r
+    goto done;\r
+  }\r
+\r
+  switch (src_format) {\r
+    case GST_FORMAT_TIME:\r
+      switch (dest_format) {\r
+        case GST_FORMAT_BYTES:{\r
+\r
+          break;\r
+        }\r
+        default:\r
+          res = FALSE;\r
+          break;\r
+      }\r
+      break;\r
+    case GST_FORMAT_BYTES:\r
+      switch (dest_format) {\r
+        case GST_FORMAT_TIME:{\r
+\r
+          break;\r
+        }\r
+        default:\r
+          res = FALSE;\r
+          break;\r
+      }\r
+      break;\r
+    default:\r
+      res = FALSE;\r
+  }\r
+\r
+done:\r
+  gst_object_unref (piffdemux);\r
+\r
+  return res;\r
+}\r
+\r
+static const GstQueryType *\r
+gst_piffdemux_get_src_query_types (GstPad * pad)\r
+{\r
+  static const GstQueryType src_types[] = {\r
+    GST_QUERY_POSITION,\r
+    GST_QUERY_DURATION,\r
+    GST_QUERY_CONVERT,\r
+    GST_QUERY_FORMATS,\r
+    GST_QUERY_SEEKING,\r
+    0\r
+  };\r
+\r
+  return src_types;\r
+}\r
+\r
+static gboolean\r
+gst_piffdemux_get_duration (GstPiffDemux * piffdemux, gint64 * duration)\r
+{\r
+  gboolean res = TRUE;\r
+\r
+  *duration = GST_CLOCK_TIME_NONE;\r
+\r
+  if (piffdemux->stream->duration != 0) {\r
+    if (piffdemux->stream->duration != G_MAXINT64 && piffdemux->stream->timescale != 0) {\r
+      *duration = gst_util_uint64_scale (piffdemux->stream->duration,\r
+          GST_SECOND, piffdemux->stream->timescale);\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+static gboolean\r
+gst_piffdemux_handle_src_query (GstPad * pad, GstQuery * query)\r
+{\r
+  gboolean res = FALSE;\r
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (gst_pad_get_parent (pad));\r
+\r
+  GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));\r
+\r
+  switch (GST_QUERY_TYPE (query)) {\r
+    case GST_QUERY_POSITION:\r
+      GST_ERROR ("Querying POSITION from piffdemux....");\r
+      if (GST_CLOCK_TIME_IS_VALID (piffdemux->segment.last_stop)) {\r
+        gst_query_set_position (query, GST_FORMAT_TIME,\r
+            piffdemux->segment.last_stop);\r
+        res = TRUE;\r
+      }\r
+      break;\r
+    case GST_QUERY_DURATION:{\r
+      GstFormat fmt;\r
+      GST_ERROR ("Querying DURATION from piffdemux....");\r
+\r
+      gst_query_parse_duration (query, &fmt, NULL);\r
+      if (fmt == GST_FORMAT_TIME) {\r
+        gint64 duration = -1;\r
+\r
+        gst_piffdemux_get_duration (piffdemux, &duration);\r
+        if (duration > 0) {\r
+          gst_query_set_duration (query, GST_FORMAT_TIME, duration);\r
+          res = TRUE;\r
+        }\r
+      }\r
+      break;\r
+    }\r
+    case GST_QUERY_CONVERT:{\r
+      GstFormat src_fmt, dest_fmt;\r
+      gint64 src_value, dest_value = 0;\r
+\r
+      gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);\r
+\r
+      res = gst_piffdemux_src_convert (pad,\r
+          src_fmt, src_value, dest_fmt, &dest_value);\r
+      if (res) {\r
+        gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);\r
+        res = TRUE;\r
+      }\r
+      break;\r
+    }\r
+    case GST_QUERY_FORMATS:\r
+      gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);\r
+      res = TRUE;\r
+      break;\r
+    case GST_QUERY_SEEKING:{\r
+\r
+      break;\r
+    }\r
+    default:\r
+      res = gst_pad_query_default (pad, query);\r
+      break;\r
+  }\r
+\r
+  gst_object_unref (piffdemux);\r
+\r
+  return res;\r
+}\r
+\r
+\r
+static void\r
+gst_piffdemux_push_tags (GstPiffDemux * piffdemux, PiffDemuxStream * stream)\r
+{\r
+  if (G_UNLIKELY (stream->pending_tags)) {\r
+    GST_DEBUG_OBJECT (piffdemux, "Sending tags %" GST_PTR_FORMAT,\r
+        stream->pending_tags);\r
+    gst_pad_push_event (piffdemux->srcpad,\r
+        gst_event_new_tag (stream->pending_tags));\r
+    stream->pending_tags = NULL;\r
+  }\r
+\r
+  if (G_UNLIKELY (stream->send_global_tags && piffdemux->tag_list)) {\r
+    GST_DEBUG_OBJECT (piffdemux, "Sending global tags %" GST_PTR_FORMAT,\r
+        piffdemux->tag_list);\r
+    gst_pad_push_event (piffdemux->srcpad,\r
+        gst_event_new_tag (gst_tag_list_copy (piffdemux->tag_list)));\r
+    stream->send_global_tags = FALSE;\r
+  }\r
+}\r
+\r
+\r
+static void\r
+gst_piffdemux_push_event (GstPiffDemux * piffdemux, GstEvent * event)\r
+{\r
+  GstEventType etype = GST_EVENT_TYPE (event);\r
+\r
+  GST_DEBUG_OBJECT (piffdemux, "pushing %s event on source pad",\r
+      GST_EVENT_TYPE_NAME (event));\r
+\r
+  if (piffdemux->stream->sent_eos) {\r
+    GST_INFO_OBJECT (piffdemux, "already sent eos");\r
+    return;\r
+  }\r
+\r
+  if (!gst_pad_push_event (piffdemux->srcpad, event)) {\r
+    GST_ERROR_OBJECT (piffdemux, "error in sending event to srcpad...");\r
+  }\r
+\r
+  if (etype == GST_EVENT_EOS)\r
+    piffdemux->stream->sent_eos = TRUE;\r
+}\r
+\r
+\r
+/* find the segment for @time_position for @stream\r
+ *\r
+ * Returns -1 if the segment cannot be found.\r
+ */\r
+static guint32\r
+gst_piffdemux_find_segment (GstPiffDemux * piffdemux, PiffDemuxStream * stream,\r
+    guint64 time_position)\r
+{\r
+  gint i;\r
+  guint32 seg_idx;\r
+\r
+  GST_LOG_OBJECT (piffdemux, "finding segment for %" GST_TIME_FORMAT,\r
+      GST_TIME_ARGS (time_position));\r
+\r
+  /* find segment corresponding to time_position if we are looking\r
+   * for a segment. */\r
+  seg_idx = -1;\r
+  for (i = 0; i < stream->n_segments; i++) {\r
+    PiffDemuxSegment *segment = &stream->segments[i];\r
+\r
+    GST_LOG_OBJECT (piffdemux,\r
+        "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,\r
+        GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));\r
+\r
+    /* For the last segment we include stop_time in the last segment */\r
+    if (i < stream->n_segments - 1) {\r
+      if (segment->time <= time_position && time_position < segment->stop_time) {\r
+        GST_LOG_OBJECT (piffdemux, "segment %d matches", i);\r
+        seg_idx = i;\r
+        break;\r
+      }\r
+    } else {\r
+      if (segment->time <= time_position && time_position <= segment->stop_time) {\r
+        GST_LOG_OBJECT (piffdemux, "segment %d matches", i);\r
+        seg_idx = i;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  return seg_idx;\r
+}\r
+\r
+\r
+static gboolean\r
+gst_piffdemux_handle_src_event (GstPad * pad, GstEvent * event)\r
+{\r
+  gboolean res = TRUE;\r
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (gst_pad_get_parent (pad));\r
+\r
+  switch (GST_EVENT_TYPE (event)) {\r
+    case GST_EVENT_QOS:\r
+    case GST_EVENT_NAVIGATION:\r
+      res = FALSE;\r
+      gst_event_unref (event);\r
+      break;\r
+    case GST_EVENT_SEEK:\r
+    default:\r
+      res = gst_pad_event_default (pad, event);\r
+      break;\r
+  }\r
+\r
+  gst_object_unref (piffdemux);\r
+\r
+  return res;\r
+}\r
+\r
+\r
+static void\r
+gst_piffdemux_move_stream (GstPiffDemux * piffdemux, PiffDemuxStream * str,\r
+    guint32 index)\r
+{\r
+  /* no change needed */\r
+  if (index == str->sample_index)\r
+    return;\r
+\r
+  GST_DEBUG_OBJECT (piffdemux, "moving to sample %u of %u", index,\r
+      str->n_samples);\r
+\r
+  /* position changed, we have a discont */\r
+  str->sample_index = index;\r
+  /* Each time we move in the stream we store the position where we are\r
+   * starting from */\r
+  str->from_sample = index;\r
+  str->discont = TRUE;\r
+}\r
+\r
+// TODO: need to check more on this below function\r
+/* stream/index return sample that is min/max w.r.t. byte position,\r
+ * time is min/max w.r.t. time of samples,\r
+ * the latter need not be time of the former sample */\r
+static void\r
+gst_piffdemux_find_sample (GstPiffDemux * piffdemux, gint64 byte_pos, gboolean fw,\r
+    gboolean set, PiffDemuxStream ** _stream, gint * _index, gint64 * _time)\r
+{\r
+  gint i, index;\r
+  gint64 time, min_time;\r
+  PiffDemuxStream *stream;\r
+  PiffDemuxStream *str = piffdemux->stream;\r
+  gint inc;\r
+  gboolean set_sample;\r
+\r
+  min_time = -1;\r
+  stream = NULL;\r
+  index = -1;\r
+\r
+  set_sample = !set;\r
+  if (fw) {\r
+    i = 0;\r
+    inc = 1;\r
+  } else {\r
+    i = str->n_samples - 1;\r
+    inc = -1;\r
+  }\r
+\r
+  for (; (i >= 0) && (i < str->n_samples); i += inc) {\r
+    if (str->samples[i].size &&\r
+    ((fw && (str->samples[i].offset >= byte_pos)) ||\r
+    (!fw &&\r
+    (str->samples[i].offset + str->samples[i].size <=\r
+    byte_pos)))) {\r
+      /* move stream to first available sample */\r
+      if (set) {\r
+        gst_piffdemux_move_stream (piffdemux, str, i);\r
+        set_sample = TRUE;\r
+      }\r
+      /* determine min/max time */\r
+      time = str->samples[i].timestamp + str->samples[i].pts_offset;\r
+      time = gst_util_uint64_scale (time, GST_SECOND, str->timescale);\r
+      if (min_time == -1 || (!fw && time > min_time) ||\r
+      (fw && time < min_time)) {\r
+        min_time = time;\r
+      }\r
+      index = i;\r
+      break;\r
+    }\r
+  }\r
+  /* no sample for this stream, mark eos */\r
+  if (!set_sample)\r
+    gst_piffdemux_move_stream (piffdemux, str, str->n_samples);\r
+\r
+  if (_time)\r
+    *_time = min_time;\r
+  if (_stream)\r
+    *_stream = str;\r
+  if (_index)\r
+    *_index = index;\r
+}\r
+\r
+\r
+static gboolean\r
+gst_piffdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)\r
+{\r
+  GstPiffDemux *demux = GST_PIFFDEMUX (GST_PAD_PARENT (sinkpad));\r
+  gboolean res;\r
+\r
+  GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));\r
+\r
+  switch (GST_EVENT_TYPE (event)) {\r
+    case GST_EVENT_NEWSEGMENT:\r
+    {\r
+      GstFormat format;\r
+      gdouble rate, arate;\r
+      gint64 start, stop, time, offset = 0;\r
+      PiffDemuxStream *stream;\r
+      gint idx;\r
+      gboolean update;\r
+      GstSegment segment;\r
+\r
+      /* some debug output */\r
+      gst_segment_init (&segment, GST_FORMAT_UNDEFINED);\r
+      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,\r
+          &start, &stop, &time);\r
+      gst_segment_set_newsegment_full (&segment, update, rate, arate, format,\r
+          start, stop, time);\r
+      GST_ERROR_OBJECT (demux,\r
+          "received format %d newsegment %" GST_SEGMENT_FORMAT, format,\r
+          &segment);\r
+\r
+      /* chain will send initial newsegment after pads have been added */\r
+      if (demux->state != PIFFDEMUX_STATE_MOVIE ) {\r
+        GST_DEBUG_OBJECT (demux, "still starting, eating event");\r
+        goto exit;\r
+      }\r
+\r
+      /* we only expect a BYTE segment, e.g. following a seek */\r
+      if (format == GST_FORMAT_BYTES) {\r
+        if (start > 0) {\r
+          gint64 requested_seek_time;\r
+          guint64 seek_offset;\r
+\r
+          offset = start;\r
+\r
+          GST_OBJECT_LOCK (demux);\r
+          requested_seek_time = demux->requested_seek_time;\r
+          seek_offset = demux->seek_offset;\r
+          demux->requested_seek_time = -1;\r
+          demux->seek_offset = -1;\r
+          GST_OBJECT_UNLOCK (demux);\r
+\r
+          if (offset == seek_offset) {\r
+            start = requested_seek_time;\r
+          } else {\r
+            gst_piffdemux_find_sample (demux, start, TRUE, FALSE, NULL, NULL,\r
+                &start);\r
+            start = MAX (start, 0);\r
+          }\r
+        }\r
+        if (stop > 0) {\r
+          gst_piffdemux_find_sample (demux, stop, FALSE, FALSE, NULL, NULL,\r
+              &stop);\r
+          /* keyframe seeking should already arrange for start >= stop,\r
+           * but make sure in other rare cases */\r
+          stop = MAX (stop, start);\r
+        }\r
+      }\r
+#if 0\r
+      else if (format == GST_FORMAT_TIME) {\r
+          // Supporting TIME_FORMAT for new_segment\r
+          //gst_piffdemux_push_event (demux,event);\r
+        PiffDemuxStream *stream = NULL;\r
+        int i = -1;\r
+\r
+          demux->neededbytes = 16;\r
+          demux->state = PIFFDEMUX_STATE_INITIAL;\r
+          demux->offset = 0;\r
+\r
+        /* Figure out which stream this is packet belongs to */\r
+        for (i = 0; i < demux->n_streams; i++) {\r
+          stream = demux->streams[i];\r
+          stream->last_ts = start;\r
+          stream->discont = TRUE;\r
+          stream->sample_index = stream->n_samples;\r
+        }\r
+\r
+           /* accept upstream's notion of segment and distribute along */\r
+          gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,\r
+              GST_FORMAT_TIME, start, stop, start);\r
+          GST_ERROR_OBJECT (demux, "Pushing newseg update %d, rate %g, "\r
+              "applied rate %g, format %d, start %" GST_TIME_FORMAT ", "\r
+              "stop %" GST_TIME_FORMAT, update, rate, arate, GST_FORMAT_TIME,\r
+              GST_TIME_ARGS (start), GST_TIME_ARGS (stop));\r
+\r
+          gst_piffdemux_push_event (demux,\r
+              gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME, start, stop, start));\r
+\r
+           /* clear leftover in current segment, if any */\r
+          gst_adapter_clear (demux->adapter);\r
+\r
+          goto exit;\r
+      }\r
+#endif\r
+      else {\r
+        GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");\r
+        goto exit;\r
+      }\r
+\r
+      /* accept upstream's notion of segment and distribute along */\r
+      gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,\r
+          GST_FORMAT_TIME, start, stop, start);\r
+      GST_ERROR_OBJECT (demux, "Pushing newseg update %d, rate %g, "\r
+          "applied rate %g, format %d, start %" GST_TIME_FORMAT ", "\r
+          "stop %" GST_TIME_FORMAT, update, rate, arate, GST_FORMAT_TIME,\r
+          GST_TIME_ARGS (start), GST_TIME_ARGS (stop));\r
+\r
+      gst_piffdemux_push_event (demux,\r
+          gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME,\r
+              start, stop, start));\r
+\r
+      /* clear leftover in current segment, if any */\r
+      gst_adapter_clear (demux->adapter);\r
+      /* set up streaming thread */\r
+      gst_piffdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx, NULL);\r
+      demux->offset = offset;\r
+      if (stream) {\r
+        demux->todrop = stream->samples[idx].offset - offset;\r
+        demux->neededbytes = demux->todrop + stream->samples[idx].size;\r
+      } else {\r
+        /* set up for EOS */\r
+        demux->neededbytes = -1;\r
+        demux->todrop = 0;\r
+      }\r
+    exit:\r
+      gst_event_unref (event);\r
+      res = TRUE;\r
+      goto drop;\r
+      break;\r
+    }\r
+    case GST_EVENT_FLUSH_STOP:\r
+    {\r
+      /* clean up, force EOS if no more info follows */\r
+      gst_adapter_clear (demux->adapter);\r
+      demux->offset = 0;\r
+      demux->neededbytes = -1;\r
+      /* reset flow return, e.g. following seek */\r
+      demux->stream->last_ret = GST_FLOW_OK;\r
+      demux->stream->sent_eos = FALSE;\r
+      break;\r
+    }\r
+    case GST_EVENT_EOS:\r
+      break;\r
+    default:\r
+      break;\r
+  }\r
+\r
+  res = gst_pad_event_default (demux->sinkpad, event);\r
+\r
+drop:\r
+  return res;\r
+}\r
+\r
+\r
+static void\r
+gst_piffdemux_stream_free (GstPiffDemux * piffdemux, PiffDemuxStream * stream)\r
+{\r
+  while (stream->buffers) {\r
+    gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));\r
+    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);\r
+  }\r
+  g_free (stream->samples);\r
+  if (stream->caps)\r
+    gst_caps_unref (stream->caps);\r
+  g_free (stream->segments);\r
+  if (stream->pending_tags)\r
+    gst_tag_list_free (stream->pending_tags);\r
+  g_free (stream);\r
+}\r
+\r
+\r
+static GstStateChangeReturn\r
+gst_piffdemux_change_state (GstElement * element, GstStateChange transition)\r
+{\r
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (element);\r
+  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;\r
+\r
+  switch (transition) {\r
+    case GST_STATE_CHANGE_PAUSED_TO_READY:\r
+      break;\r
+    default:\r
+      break;\r
+  }\r
+\r
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);\r
+\r
+  switch (transition) {\r
+    case GST_STATE_CHANGE_PAUSED_TO_READY:{\r
+      piffdemux->state = PIFFDEMUX_STATE_INITIAL;\r
+      piffdemux->neededbytes = 16;\r
+      piffdemux->todrop = 0;\r
+      piffdemux->posted_redirect = FALSE;\r
+      piffdemux->offset = 0;\r
+      piffdemux->first_mdat = -1;\r
+      piffdemux->mdatoffset = GST_CLOCK_TIME_NONE;\r
+      if (piffdemux->mdatbuffer)\r
+        gst_buffer_unref (piffdemux->mdatbuffer);\r
+      piffdemux->mdatbuffer = NULL;\r
+      if (piffdemux->tag_list)\r
+        gst_tag_list_free (piffdemux->tag_list);\r
+      piffdemux->tag_list = NULL;\r
+      gst_adapter_clear (piffdemux->adapter);\r
+      gst_segment_init (&piffdemux->segment, GST_FORMAT_TIME);\r
+      break;\r
+    }\r
+    default:\r
+      break;\r
+  }\r
+\r
+  return result;\r
+}\r
+\r
+static void\r
+piffdemux_post_global_tags (GstPiffDemux * piffdemux)\r
+{\r
+  if (piffdemux->tag_list) {\r
+    /* all header tags ready and parsed, push them */\r
+    GST_INFO_OBJECT (piffdemux, "posting global tags: %" GST_PTR_FORMAT,\r
+        piffdemux->tag_list);\r
+    /* post now, send event on pads later */\r
+    gst_element_post_message (GST_ELEMENT (piffdemux),\r
+        gst_message_new_tag (GST_OBJECT (piffdemux),\r
+            gst_tag_list_copy (piffdemux->tag_list)));\r
+  }\r
+}\r
+\r
+\r
+/* caller verifies at least 8 bytes in buf */\r
+static void\r
+extract_initial_length_and_fourcc (const guint8 * data, guint size,\r
+    guint64 * plength, guint32 * pfourcc)\r
+{\r
+  guint64 length;\r
+  guint32 fourcc;\r
+\r
+  length = PIFF_UINT32 (data);\r
+  GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);\r
+  fourcc = PIFF_FOURCC (data + 4);\r
+  GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));\r
+\r
+  if (length == 0) {\r
+    length = G_MAXUINT32;\r
+  } else if (length == 1 && size >= 16) {\r
+    /* this means we have an extended size, which is the 64 bit value of\r
+     * the next 8 bytes */\r
+    length = PIFF_UINT64 (data + 8);\r
+    GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);\r
+  }\r
+\r
+  if (plength)\r
+    *plength = length;\r
+  if (pfourcc)\r
+    *pfourcc = fourcc;\r
+}\r
+\r
+static gboolean\r
+piffdemux_update_sample_offset (GstPiffDemux * piffdemu, PiffDemuxStream * stream, gint64 uuid_offset)\r
+{\r
+  PiffDemuxSample *sample;\r
+  gint i;\r
+\r
+  sample = stream->samples ;\r
+  for (i = 0; i < stream->n_samples; i++)\r
+  {\r
+    sample->offset = sample->offset + uuid_offset;\r
+    sample++;\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+static uuid_type_t\r
+piffdemux_get_uuid_type(GstPiffDemux * piffdemux, GstByteReader *uuid_data, gint64 *uuid_offset)\r
+{\r
+  uuid_type_t uuid_type = UUID_UNKNOWN;\r
+  guint32 box_len = 0;\r
+  guint64 box_long_len = 0;\r
+  gchar uuid[16] = {0,};\r
+  int i = 0;\r
+\r
+  if (!gst_byte_reader_get_uint32_be (uuid_data, &box_len))\r
+    goto invalid_uuid;\r
+\r
+  /* Skipping fourcc */\r
+  if (!gst_byte_reader_skip (uuid_data, 4))\r
+    goto invalid_uuid;\r
+\r
+  if (box_len == 1)\r
+  {\r
+    GST_WARNING ("TfxdBoxLongLength field is present...");\r
+    if (!gst_byte_reader_get_uint64_be (uuid_data, &box_long_len))\r
+      goto invalid_uuid;\r
+    GST_DEBUG ("tfxd long length = %llu", box_long_len);\r
+\r
+    *uuid_offset = box_long_len;\r
+  }\r
+  else\r
+  {\r
+    GST_DEBUG ("Box Len = %d", box_len);\r
+    *uuid_offset = box_len;\r
+  }\r
+\r
+  //g_print ("\n\n\n 0x");\r
+  for (i = 0; i < sizeof (uuid); i++)\r
+  {\r
+    if (!gst_byte_reader_get_uint8 (uuid_data, &(uuid[i])))\r
+      goto invalid_uuid;\r
+    //g_print ("%02x", uuid[i]);\r
+  }\r
+  //g_print ("\n\n\n");\r
+\r
+  if (!memcmp(uuid, tfxd_uuid, sizeof (uuid_t)))\r
+  {\r
+    GST_INFO ("Found TFXD box");\r
+    return UUID_TFXD;\r
+  }\r
+  else if (!memcmp(uuid, tfrf_uuid, sizeof (uuid_t)))\r
+  {\r
+    GST_INFO ("Found TFRF box");\r
+    return UUID_TFRF;\r
+  }\r
+  else if (!memcmp(uuid, encrypt_uuid, sizeof (uuid_t)))\r
+  {\r
+    GST_INFO ("Found sample encryption box");\r
+    return UUID_SAMPLE_ENCRYPT;\r
+  }\r
+  else\r
+  {\r
+    GST_WARNING ("Not an valid UUID box..");\r
+    goto invalid_uuid;\r
+  }\r
+  return uuid_type;\r
+\r
+invalid_uuid:\r
+  GST_ERROR ("Error in parsing UUID atom...");\r
+  return UUID_UNKNOWN;\r
+}\r
+\r
+static gboolean\r
+piffdemux_parse_sample_encryption(GstPiffDemux * piffdemux, GstByteReader *sample_encrypt, PiffDemuxStream * stream)\r
+{\r
+  guint32 flags = 0;\r
+  guint32 sample_count = 0;\r
+  guint32 i = 0;\r
+  guint32 algo_id;\r
+  guint8 iv_size = 0;\r
+\r
+  if (!gst_byte_reader_skip (sample_encrypt, 1) ||\r
+      !gst_byte_reader_get_uint24_be (sample_encrypt, &flags))\r
+    goto invalid_encryption;\r
+\r
+  if (flags & SE_OVERRIDE_TE_FLAGS) {\r
+    /* get algorithm id */\r
+    if (!gst_byte_reader_get_uint32_be (sample_encrypt, &algo_id))\r
+      goto invalid_encryption;\r
+\r
+    /* get IV size */\r
+    if (!gst_byte_reader_get_uint8 (sample_encrypt, &iv_size))\r
+      goto invalid_encryption;\r
+\r
+    // TODO: need to add reading of KID\r
+    } else {\r
+    GST_INFO_OBJECT (piffdemux, "Override flags are not present... taking default IV_Size = 8");\r
+    iv_size = 8;\r
+  }\r
+\r
+  /* Get sample count*/\r
+  if (!gst_byte_reader_get_uint32_be (sample_encrypt, &sample_count))\r
+    goto invalid_encryption;\r
+\r
+  GST_INFO_OBJECT (piffdemux, "Sample count = %d", sample_count);\r
+\r
+  if (sample_count != stream->n_samples) {\r
+    GST_ERROR_OBJECT (piffdemux, "Not all samples has IV vectors... Don't know how to handle. sample_cnt = %d and stream->n_samples = %d",\r
+        sample_count, stream->n_samples);\r
+    goto invalid_encryption;\r
+  }\r
+\r
+  for (i = 0; i < stream->n_samples; i++) {\r
+    guint8 iv_idx = iv_size;\r
+\r
+    /* resetting entire IV array */\r
+    stream->samples[i].iv = (guint8 *)malloc (iv_size);\r
+    if (NULL == stream->samples[i].iv) {\r
+      GST_ERROR ("Failed to allocate memory...\n");\r
+      goto invalid_encryption;\r
+    }\r
+\r
+    memset (stream->samples[i].iv, 0x00, iv_size);\r
+\r
+    iv_idx = 0;\r
+    while (iv_idx < iv_size) {\r
+      /* get IV byte */\r
+      if (!gst_byte_reader_get_uint8 (sample_encrypt, &(stream->samples[i].iv[iv_idx])))\r
+        goto invalid_encryption;\r
+\r
+      iv_idx++;\r
+    }\r
+\r
+#ifdef DEBUG_IV\r
+  {\r
+    guint8 tmp_idx = 0;\r
+    g_print ("sample[%d] : 0x ", i);\r
+\r
+    while (tmp_idx < iv_size ) {\r
+      g_print ("%02x ", stream->samples[i].iv[tmp_idx]);\r
+      tmp_idx++;\r
+    }\r
+    g_print ("\n");\r
+  }\r
+#endif\r
+\r
+    if (flags & SE_USE_SUBSAMPLE_ENCRYPTION) {\r
+      guint16 n_entries;\r
+      guint16 n_idx;\r
+\r
+      /* NumberofEntries in SubSampleEncryption */\r
+      if (!gst_byte_reader_get_uint16_be (sample_encrypt, &n_entries))\r
+        goto invalid_encryption;\r
+\r
+      stream->samples[i].sub_encry = (PiffDemuxSubSampleEncryption *)malloc (sizeof (PiffDemuxSubSampleEncryption));\r
+      if (NULL == stream->samples[i].sub_encry) {\r
+        GST_ERROR ("Failed to allocate memory...\n");\r
+        goto invalid_encryption;\r
+      }\r
+\r
+      stream->samples[i].sub_encry->sub_entry = g_try_new0 (PiffDemuxSubSampleEntryInfo, n_entries);\r
+      if (NULL == stream->samples[i].sub_encry->sub_entry)\r
+      {\r
+        GST_ERROR_OBJECT (piffdemux, "Failed to allocate memory...");\r
+        goto invalid_encryption;\r
+      }\r
+\r
+      stream->samples[i].sub_encry->n_entries = n_entries;\r
+\r
+      GST_DEBUG_OBJECT (piffdemux,"No. of subsample entries = %d", stream->samples[i].sub_encry->n_entries);\r
+\r
+      for (n_idx = 0; n_idx < n_entries; n_idx++) {\r
+        if (!gst_byte_reader_get_uint16_be (sample_encrypt, &(stream->samples[i].sub_encry->sub_entry[n_idx].LenofClearData)))\r
+          goto invalid_encryption;\r
+\r
+       GST_DEBUG_OBJECT (piffdemux,"entry[%d] and lengthofClearData = %d", n_idx, stream->samples[i].sub_encry->sub_entry[n_idx].LenofClearData);\r
+\r
+        if (!gst_byte_reader_get_uint32_be (sample_encrypt, &(stream->samples[i].sub_encry->sub_entry[n_idx].LenofEncryptData)))\r
+          goto invalid_encryption;\r
+\r
+        GST_DEBUG_OBJECT (piffdemux,"entry[%d] and lengthofEncryptData = %d", n_idx, stream->samples[i].sub_encry->sub_entry[n_idx].LenofEncryptData);\r
+      }\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+\r
+invalid_encryption:\r
+  {\r
+    GST_WARNING_OBJECT (piffdemux, "invalid sample encryption header");\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+\r
+static gboolean\r
+piffdemux_parse_trun (GstPiffDemux * piffdemux, GstByteReader * trun,\r
+    PiffDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,\r
+    guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,\r
+    gint64 * base_offset, gint64 * running_offset)\r
+{\r
+  guint64 timestamp;\r
+  gint32 data_offset = 0;\r
+  guint32 flags = 0, first_flags = 0, samples_count = 0;\r
+  gint i;\r
+  guint8 *data;\r
+  guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;\r
+  PiffDemuxSample *sample;\r
+  gboolean ismv = FALSE;\r
+  guint64 total_duration = 0;\r
+\r
+  GST_LOG_OBJECT (piffdemux, "parsing trun stream ; "\r
+      "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT,\r
+       d_sample_duration, d_sample_size, d_sample_flags,\r
+      *base_offset);\r
+\r
+  //Resetting the samples\r
+  stream->n_samples = 0;\r
+\r
+  if (!gst_byte_reader_skip (trun, 1) ||\r
+      !gst_byte_reader_get_uint24_be (trun, &flags))\r
+    goto fail;\r
+\r
+  if (!gst_byte_reader_get_uint32_be (trun, &samples_count))\r
+    goto fail;\r
+\r
+  if (flags & TR_DATA_OFFSET) {\r
+    /* note this is really signed */\r
+    if (!gst_byte_reader_get_int32_be (trun, &data_offset))\r
+      goto fail;\r
+    GST_LOG_OBJECT (piffdemux, "trun data offset %d", data_offset);\r
+    /* default base offset = first byte of moof */\r
+    if (*base_offset == -1) {\r
+      GST_LOG_OBJECT (piffdemux, "base_offset at moof and moof_offset = %"G_GINT64_FORMAT, moof_offset);\r
+      *base_offset = moof_offset;\r
+    }\r
+    *running_offset = *base_offset + data_offset;\r
+  } else {\r
+    /* if no offset at all, that would mean data starts at moof start,\r
+     * which is a bit wrong and is ismv crappy way, so compensate\r
+     * assuming data is in mdat following moof */\r
+    if (*base_offset == -1) {\r
+      *base_offset = moof_offset + moof_length + 8;\r
+      GST_LOG_OBJECT (piffdemux, "base_offset assumed in mdat after moof");\r
+      ismv = TRUE;\r
+    }\r
+    if (*running_offset == -1)\r
+      *running_offset = *base_offset;\r
+  }\r
+\r
+  GST_LOG_OBJECT (piffdemux, "running offset now %" G_GINT64_FORMAT,\r
+      *running_offset);\r
+  GST_LOG_OBJECT (piffdemux, "trun offset %d, flags 0x%x, entries %d",\r
+      data_offset, flags, samples_count);\r
+\r
+  if (flags & TR_FIRST_SAMPLE_FLAGS) {\r
+    if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {\r
+      GST_DEBUG_OBJECT (piffdemux,\r
+          "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");\r
+      flags ^= TR_FIRST_SAMPLE_FLAGS;\r
+    } else {\r
+      if (!gst_byte_reader_get_uint32_be (trun, &first_flags))\r
+        goto fail;\r
+      GST_LOG_OBJECT (piffdemux, "first flags: 0x%x", first_flags);\r
+    }\r
+  }\r
+\r
+  /* FIXME ? spec says other bits should also be checked to determine\r
+   * entry size (and prefix size for that matter) */\r
+  entry_size = 0;\r
+  dur_offset = size_offset = 0;\r
+  if (flags & TR_SAMPLE_DURATION) {\r
+    GST_LOG_OBJECT (piffdemux, "entry duration present");\r
+    dur_offset = entry_size;\r
+    entry_size += 4;\r
+  }\r
+  if (flags & TR_SAMPLE_SIZE) {\r
+    GST_LOG_OBJECT (piffdemux, "entry size present");\r
+    size_offset = entry_size;\r
+    entry_size += 4;\r
+  }\r
+  if (flags & TR_SAMPLE_FLAGS) {\r
+    GST_LOG_OBJECT (piffdemux, "entry flags present");\r
+    flags_offset = entry_size;\r
+    entry_size += 4;\r
+  }\r
+  if (flags & TR_COMPOSITION_TIME_OFFSETS) {\r
+    GST_LOG_OBJECT (piffdemux, "entry ct offset present");\r
+    ct_offset = entry_size;\r
+    entry_size += 4;\r
+  }\r
+\r
+  if (!piff_atom_parser_has_chunks (trun, samples_count, entry_size))\r
+    goto fail;\r
+  data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);\r
+\r
+  if (stream->n_samples >=\r
+      PIFFDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (PiffDemuxSample))\r
+    goto index_too_big;\r
+\r
+  GST_DEBUG_OBJECT (piffdemux, "allocating n_samples %u * %u (%.2f MB)",\r
+      stream->n_samples, (guint) sizeof (PiffDemuxSample),\r
+      stream->n_samples * sizeof (PiffDemuxSample) / (1024.0 * 1024.0));\r
+\r
+  /* create a new array of samples if it's the first sample parsed */\r
+  if (stream->n_samples == 0)\r
+    stream->samples = g_try_new0 (PiffDemuxSample, samples_count);\r
+  /* or try to reallocate it with space enough to insert the new samples */\r
+  else\r
+    stream->samples = g_try_renew (PiffDemuxSample, stream->samples,\r
+        stream->n_samples + samples_count);\r
+  if (stream->samples == NULL)\r
+    goto out_of_memory;\r
+\r
+  if (G_UNLIKELY (stream->n_samples == 0)) {\r
+    /* the timestamp of the first sample is also provided by the tfra entry\r
+     * but we shouldn't rely on it as it is at the end of files */\r
+    timestamp = 0;\r
+  } else {\r
+    /* subsequent fragments extend stream */\r
+    timestamp =\r
+        stream->samples[stream->n_samples - 1].timestamp +\r
+        stream->samples[stream->n_samples - 1].duration;\r
+  }\r
+  sample = stream->samples + stream->n_samples;\r
+  for (i = 0; i < samples_count; i++) {\r
+    guint32 dur, size, sflags, ct;\r
+\r
+    /* first read sample data */\r
+    if (flags & TR_SAMPLE_DURATION) {\r
+      dur = PIFF_UINT32 (data + dur_offset);\r
+    } else {\r
+      dur = d_sample_duration;\r
+    }\r
+    if (flags & TR_SAMPLE_SIZE) {\r
+      size = PIFF_UINT32 (data + size_offset);\r
+    } else {\r
+      size = d_sample_size;\r
+    }\r
+\r
+    GST_DEBUG_OBJECT(piffdemux,"Size of sample %d is %d", i, size);\r
+\r
+    if (flags & TR_FIRST_SAMPLE_FLAGS) {\r
+      if (i == 0) {\r
+        sflags = first_flags;\r
+      } else {\r
+        sflags = d_sample_flags;\r
+      }\r
+    } else if (flags & TR_SAMPLE_FLAGS) {\r
+      sflags = PIFF_UINT32 (data + flags_offset);\r
+    } else {\r
+      sflags = d_sample_flags;\r
+    }\r
+    if (flags & TR_COMPOSITION_TIME_OFFSETS) {\r
+      ct = PIFF_UINT32 (data + ct_offset);\r
+    } else {\r
+      ct = 0;\r
+    }\r
+    data += entry_size;\r
+\r
+    /* fill the sample information */\r
+    sample->offset = *running_offset;\r
+    sample->pts_offset = ct;\r
+    sample->size = size;\r
+    sample->timestamp = timestamp;\r
+    sample->duration = dur;\r
+    /* sample-is-difference-sample */\r
+    /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,\r
+     * now idea how it relates to bitfield other than massive LE/BE confusion */\r
+    sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);\r
+    sample->iv = NULL;\r
+    sample->sub_encry = NULL;\r
+\r
+    stream->samples[i] = *sample;\r
+\r
+    *running_offset += size;\r
+    timestamp += dur;\r
+    sample++;\r
+\r
+    /* calculate total duration of the present fragment */\r
+    total_duration += gst_util_uint64_scale (dur, GST_SECOND, stream->timescale);\r
+  }\r
+\r
+  stream->sample_index = 0;\r
+\r
+  stream->n_samples += samples_count;\r
+\r
+  /* calculate avg fps based on avg frame duration */\r
+  stream->avg_dur = total_duration/samples_count;\r
+  g_print ("total dur = %"GST_TIME_FORMAT", avg_dur = %"GST_TIME_FORMAT"count = %d\n",\r
+    GST_TIME_ARGS(total_duration), GST_TIME_ARGS(stream->avg_dur), samples_count);\r
+\r
+  return TRUE;\r
+\r
+fail:\r
+  {\r
+    GST_WARNING_OBJECT (piffdemux, "failed to parse trun");\r
+    return FALSE;\r
+  }\r
+out_of_memory:\r
+  {\r
+    GST_WARNING_OBJECT (piffdemux, "failed to allocate %d samples",\r
+        stream->n_samples);\r
+    return FALSE;\r
+  }\r
+index_too_big:\r
+  {\r
+    GST_WARNING_OBJECT (piffdemux, "not allocating index of %d samples, would "\r
+        "be larger than %uMB (broken file?)", stream->n_samples,\r
+        PIFFDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+static gboolean\r
+piffdemux_parse_mfhd (GstPiffDemux * piffdemux, GstByteReader * mfhd)\r
+{\r
+  guint32 seq_num = 0;\r
+\r
+  if (!gst_byte_reader_skip (mfhd, 4))\r
+    goto invalid_mfhd;\r
+\r
+  if (!gst_byte_reader_get_uint32_be (mfhd, &seq_num))\r
+    goto invalid_mfhd;\r
+\r
+  GST_DEBUG_OBJECT (piffdemux, "sequence number present in mfhd = %d", seq_num);\r
+\r
+  return TRUE;\r
+\r
+invalid_mfhd:\r
+  {\r
+    GST_WARNING_OBJECT (piffdemux, "invalid movie fragment header");\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+\r
+static gboolean\r
+piffdemux_parse_tfhd (GstPiffDemux * piffdemux, GstByteReader * tfhd,\r
+    guint32 * default_sample_duration,\r
+    guint32 * default_sample_size, guint32 * default_sample_flags,\r
+    gint64 * base_offset)\r
+{\r
+  guint32 flags = 0;\r
+  guint32 track_id = 0;\r
+\r
+  if (!gst_byte_reader_skip (tfhd, 1) ||\r
+      !gst_byte_reader_get_uint24_be (tfhd, &flags))\r
+    goto invalid_track;\r
+\r
+  if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))\r
+    goto invalid_track;\r
+\r
+  GST_DEBUG_OBJECT (piffdemux, "trackID = %d", track_id);\r
+\r
+  if (flags & TF_BASE_DATA_OFFSET) {\r
+    if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))\r
+      goto invalid_track;\r
+    GST_DEBUG ("BaseData Offset = %"G_GUINT64_FORMAT, base_offset);\r
+  }\r
+\r
+  /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */\r
+  if (flags & TF_SAMPLE_DESCRIPTION_INDEX)\r
+    if (!gst_byte_reader_skip (tfhd, 4))\r
+      goto invalid_track;\r
+\r
+  if (flags & TF_DEFAULT_SAMPLE_DURATION)\r
+    if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))\r
+      goto invalid_track;\r
+\r
+  if (flags & TF_DEFAULT_SAMPLE_SIZE)\r
+    if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))\r
+      goto invalid_track;\r
+\r
+  if (flags & TF_DEFAULT_SAMPLE_FLAGS)\r
+    if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))\r
+      goto invalid_track;\r
+\r
+  return TRUE;\r
+\r
+invalid_track:\r
+  {\r
+    GST_WARNING_OBJECT (piffdemux, "invalid track fragment header");\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+static gboolean\r
+piffdemux_parse_tfxd (GstPiffDemux * piffdemux, PiffDemuxStream *stream,GstByteReader * tfxd)\r
+{\r
+  guint8 version = 0;\r
+\r
+  // TODO: In my opinion, tfxd will be mainly useful when lookahead count = 0. In this case, based on this duration, next fragment timstamp can be calculted.. Need to test this using our server\r
+\r
+  if (!gst_byte_reader_get_uint8 (tfxd, &version))\r
+    goto invalid_tfxd;\r
+\r
+  if (!gst_byte_reader_skip (tfxd, 3))\r
+    goto invalid_tfxd;\r
+\r
+  if (!piffdemux->lookahead_cnt) {\r
+    piffdemux->param = (piff_live_param_t *)malloc (sizeof (piff_live_param_t));\r
+    if (NULL == piffdemux->param) {\r
+      GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");\r
+      return FALSE;\r
+    }\r
+    piffdemux->param->count = 1;\r
+    piffdemux->param->long_info = NULL;\r
+    piffdemux->param->info = NULL;\r
+    piffdemux->param->is_eos = FALSE;\r
+\r
+    // TODO: presentation will be ended based on timeout in souphttpsrc in lookaheadcnt = 0 case\r
+  }\r
+\r
+  if (version == 1) {\r
+    guint64 duration = 0;\r
+    guint64 timestamp = 0;\r
+\r
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 64-bit format...");\r
+    if (!gst_byte_reader_get_uint64_be (tfxd, &timestamp))\r
+      goto invalid_tfxd;\r
+    if (!gst_byte_reader_get_uint64_be (tfxd, &duration))\r
+      goto invalid_tfxd;\r
+\r
+    GST_DEBUG_OBJECT (piffdemux, "tfxd : absolute timestamp = %"G_GUINT64_FORMAT" and duration of fragment = %"G_GUINT64_FORMAT,\r
+        timestamp, duration);\r
+\r
+    if (!piffdemux->lookahead_cnt) {\r
+      piffdemux->param->long_info = (piff_fragment_longtime_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_longtime_info));\r
+      if (NULL == piffdemux->param->long_info) {\r
+        GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");\r
+        return FALSE;\r
+      }\r
+\r
+      /* Calculate next fragment's timestamp using current fragment's timestamp + duration */\r
+      piffdemux->param->long_info->duration = GST_CLOCK_TIME_NONE;\r
+      piffdemux->param->long_info->ts = timestamp +duration;\r
+    }\r
+  } else if (version == 0) {\r
+    guint32 duration = 0;\r
+    guint32 timestamp = 0;\r
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 32-bit format...");\r
+\r
+    if (!gst_byte_reader_get_uint32_be (tfxd, &timestamp))\r
+      goto invalid_tfxd;\r
+\r
+    if (!gst_byte_reader_get_uint32_be (tfxd, &duration))\r
+      goto invalid_tfxd;\r
+\r
+    GST_DEBUG_OBJECT (piffdemux, "tfxd : absolute timestamp = %"G_GUINT32_FORMAT" and duration of fragment = %"G_GUINT32_FORMAT,\r
+        timestamp, duration);\r
+\r
+    if (!piffdemux->lookahead_cnt) {\r
+      piffdemux->param->info = (piff_fragment_time_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_time_info));\r
+      if (NULL == piffdemux->param->info) {\r
+        GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");\r
+        return FALSE;\r
+      }\r
+      /* Calculate next fragment's timestamp using current fragment's timestamp + duration */\r
+      piffdemux->param->info->duration = GST_CLOCK_TIME_NONE;\r
+      piffdemux->param->info->ts = timestamp +duration;\r
+    }\r
+  } else {\r
+    GST_ERROR_OBJECT (piffdemux, "Invalid Version in tfxd...");\r
+    return FALSE;\r
+  }\r
+\r
+  if (!piffdemux->lookahead_cnt) {\r
+    GST_DEBUG_OBJECT (piffdemux, "Emitting live-param signal...");\r
+    g_signal_emit (piffdemux, gst_piffdemux_signals[SIGNAL_LIVE_PARAM], 0, piffdemux->param);\r
+  }\r
+\r
+  return TRUE;\r
+\r
+invalid_tfxd:\r
+  GST_ERROR ("Invalid TFXD atom...");\r
+  return FALSE;\r
+}\r
+\r
+\r
+static gboolean\r
+piffdemux_parse_tfrf (GstPiffDemux * piffdemux, PiffDemuxStream *stream,GstByteReader * tfrf)\r
+{\r
+  guint8 version = 0;\r
+  guint8 frag_cnt = 0;\r
+  guint8 i = 0;\r
+\r
+  /* Getting version info */\r
+  if (!gst_byte_reader_get_uint8 (tfrf, &version))\r
+    goto invalid_tfrf;\r
+\r
+  /* skipping reserved flags */\r
+  if (!gst_byte_reader_skip (tfrf, 3))\r
+    goto invalid_tfrf;\r
+\r
+  if (!gst_byte_reader_get_uint8 (tfrf, &frag_cnt))\r
+    goto invalid_tfrf;\r
+\r
+  GST_INFO_OBJECT (piffdemux, "Subsequent fragments info count = %d", frag_cnt);\r
+\r
+  piffdemux->param = (piff_live_param_t *)malloc(sizeof (piff_live_param_t));\r
+  if (NULL == piffdemux->param) {\r
+    GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");\r
+    return FALSE;\r
+  }\r
+\r
+  piffdemux->param->count = frag_cnt;\r
+  piffdemux->param->long_info = NULL;\r
+  piffdemux->param->info = NULL;\r
+  piffdemux->param->is_eos = FALSE;\r
+\r
+  // TODO: Duration and timestamp values need to be posted to msl using g_signal_emit\r
+\r
+  if (version == 1) {\r
+    guint64 duration = 0;\r
+    guint64 timestamp = 0;\r
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 64-bit format...");\r
+\r
+    piffdemux->param->long_info = (piff_fragment_longtime_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_longtime_info));\r
+    if (NULL == piffdemux->param->long_info) {\r
+      GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");\r
+      return FALSE;\r
+    }\r
+\r
+    for (i = 0; i < frag_cnt; i++) {\r
+      if (!gst_byte_reader_get_uint64_be (tfrf, &timestamp))\r
+        goto invalid_tfrf;\r
+      if (!gst_byte_reader_get_uint64_be (tfrf, &duration))\r
+        goto invalid_tfrf;\r
+      GST_DEBUG_OBJECT (piffdemux, "tfrf long: absolute timestamp = %"G_GUINT64_FORMAT" and duration of fragment = %"G_GUINT64_FORMAT"\n",\r
+               timestamp, duration);\r
+      (piffdemux->param->long_info[i]).ts = timestamp;\r
+      (piffdemux->param->long_info[i]).duration = duration;\r
+    }\r
+  } else if (version == 0) {\r
+    guint32 duration = 0;\r
+    guint32 timestamp = 0;\r
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 32-bit format...");\r
+\r
+    piffdemux->param->info = (piff_fragment_time_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_time_info));\r
+    if (NULL == piffdemux->param->info) {\r
+      GST_ERROR ("Memory not available...\n");\r
+      return FALSE;\r
+    }\r
+\r
+    for (i = 0; i < frag_cnt; i++) {\r
+      if (!gst_byte_reader_get_uint32_be (tfrf, &timestamp))\r
+        goto invalid_tfrf;\r
+      if (!gst_byte_reader_get_uint32_be (tfrf, &duration))\r
+        goto invalid_tfrf;\r
+\r
+      GST_DEBUG_OBJECT (piffdemux, "tfrf int: absolute timestamp = %"G_GUINT32_FORMAT" and duration of fragment = %"G_GUINT32_FORMAT,\r
+          timestamp, duration);\r
+      (piffdemux->param->info[i]).ts = timestamp;\r
+      (piffdemux->param->info[i]).duration = duration;\r
+    }\r
+  } else {\r
+    GST_ERROR_OBJECT (piffdemux, "Invalid Version in tfrf...");\r
+    return FALSE;\r
+  }\r
+\r
+  g_print ("Signalling from TFRF box..\n");\r
+  g_signal_emit (piffdemux, gst_piffdemux_signals[SIGNAL_LIVE_PARAM], 0, piffdemux->param);\r
+\r
+  return TRUE;\r
+\r
+invalid_tfrf:\r
+  GST_ERROR_OBJECT (piffdemux, "Invalid TFRF atom...");\r
+  return FALSE;\r
+}\r
+\r
+\r
+static gboolean\r
+piffdemux_parse_moof (GstPiffDemux * piffdemux, const guint8 * buffer, guint length,\r
+    guint64 moof_offset, PiffDemuxStream * stream)\r
+{\r
+  GNode *moof_node, *mfhd_node, *traf_node, *tfhd_node, *trun_node, *uuid_node;\r
+  GstByteReader mfhd_data, trun_data, tfhd_data, uuid_data;\r
+  guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;\r
+  gint64 base_offset, running_offset;\r
+  gint64 uuid_offset = 0;\r
+  gboolean found_tfxd = FALSE;\r
+  gboolean found_tfrf = FALSE;\r
+\r
+  /* NOTE @stream ignored */\r
+\r
+  moof_node = g_node_new ((guint8 *) buffer);\r
+  piffdemux_parse_node (piffdemux, moof_node, buffer, length);\r
+  //piffdemux_node_dump (piffdemux, moof_node);\r
+\r
+  /* unknown base_offset to start with */\r
+  base_offset = running_offset = -1;\r
+\r
+  mfhd_node = piffdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);\r
+  if (!mfhd_node)\r
+    goto missing_mfhd;\r
+\r
+  if (!piffdemux_parse_mfhd (piffdemux, &mfhd_data))\r
+    goto missing_mfhd;\r
+\r
+  traf_node = piffdemux_tree_get_child_by_type (moof_node, FOURCC_traf);\r
+  while (traf_node) {\r
+    /* Fragment Header node */\r
+    tfhd_node =\r
+        piffdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,\r
+        &tfhd_data);\r
+    if (!tfhd_node)\r
+      goto missing_tfhd;\r
+    if (!piffdemux_parse_tfhd (piffdemux, &tfhd_data, &ds_duration,\r
+            &ds_size, &ds_flags, &base_offset))\r
+      goto missing_tfhd;\r
+\r
+    if (G_UNLIKELY (base_offset < -1))\r
+      goto lost_offset;\r
+\r
+    /* Track Run node */\r
+    trun_node =\r
+        piffdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,\r
+        &trun_data);\r
+    while (trun_node) {\r
+      piffdemux_parse_trun (piffdemux, &trun_data, stream,\r
+          ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,\r
+          &running_offset);\r
+      /* iterate all siblings */\r
+      trun_node = piffdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,\r
+          &trun_data);\r
+    }\r
+\r
+    uuid_node =  piffdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);\r
+    while (uuid_node) {\r
+      uuid_type_t uuid_type;\r
+      guint8 *buffer = (guint8 *) uuid_node->data;\r
+\r
+      gst_byte_reader_init (&uuid_data, buffer, PIFF_UINT32 (buffer));\r
+\r
+      uuid_type = piffdemux_get_uuid_type (piffdemux, &uuid_data, &uuid_offset);\r
+\r
+      if ((UUID_TFXD == uuid_type) && piffdemux->is_live) {\r
+        // TODO: Dont know, why we should not consider tfxd offset...if we use tfxd offset also, not working.. PIFF doc does not say anything :(\r
+        found_tfxd = TRUE;\r
+        if (!piffdemux_parse_tfxd (piffdemux, stream, &uuid_data))\r
+          goto fail;\r
+      } else if ((UUID_TFRF == uuid_type) && piffdemux->is_live && piffdemux->lookahead_cnt) {\r
+        found_tfrf = TRUE;\r
+        if (!piffdemux_parse_tfrf (piffdemux, stream, &uuid_data))\r
+          goto fail;\r
+        piffdemux_update_sample_offset (piffdemux, stream, uuid_offset);\r
+        running_offset += uuid_offset;\r
+      } else if (UUID_SAMPLE_ENCRYPT == uuid_type) {\r
+        if (!piffdemux_parse_sample_encryption (piffdemux, &uuid_data, stream))\r
+          goto fail;\r
+      } else {\r
+        GST_WARNING_OBJECT (piffdemux, "Ignoring Wrong UUID...");\r
+      }\r
+\r
+      /* iterate all siblings */\r
+      uuid_node = piffdemux_tree_get_sibling_by_type (uuid_node, FOURCC_uuid);\r
+    }\r
+\r
+    if (piffdemux->is_live) {\r
+      if (!found_tfxd) {\r
+        GST_ERROR_OBJECT (piffdemux, "TFXD box is not present for live stream");\r
+        goto fail;\r
+      }\r
+\r
+      if (!found_tfrf && piffdemux->lookahead_cnt) {\r
+        /* when lookahead count is non-zero in manifest & if tfrf box is not present., means EOS */\r
+        GST_INFO_OBJECT (piffdemux, "Reached Endof Live presentation..");\r
+\r
+        piffdemux->param = (piff_live_param_t *)malloc (sizeof (piff_live_param_t));\r
+        if (NULL == piffdemux->param) {\r
+          GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");\r
+          goto fail;\r
+        }\r
+        piffdemux->param->count = 0;\r
+        piffdemux->param->long_info = NULL;\r
+        piffdemux->param->info = NULL;\r
+        piffdemux->param->is_eos = TRUE; /* marking EOS */\r
+        g_signal_emit (piffdemux, gst_piffdemux_signals[SIGNAL_LIVE_PARAM], 0, piffdemux->param);\r
+      }\r
+    }\r
+\r
+    /* if no new base_offset provided for next traf,\r
+     * base is end of current traf */\r
+    base_offset = running_offset;\r
+    running_offset = -1;\r
+\r
+    /* iterate all siblings */\r
+    traf_node = piffdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);\r
+  }\r
+  g_node_destroy (moof_node);\r
+  return TRUE;\r
+\r
+missing_mfhd:\r
+  {\r
+    GST_DEBUG_OBJECT (piffdemux, "missing mfhd box");\r
+    goto fail;\r
+  }\r
+\r
+missing_tfhd:\r
+  {\r
+    GST_DEBUG_OBJECT (piffdemux, "missing tfhd box");\r
+    goto fail;\r
+  }\r
+lost_offset:\r
+  {\r
+    GST_DEBUG_OBJECT (piffdemux, "lost offset");\r
+    goto fail;\r
+  }\r
+fail:\r
+  {\r
+    g_node_destroy (moof_node);\r
+\r
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,\r
+        ("This file is corrupt and cannot be played."), (NULL));\r
+\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+\r
+/* activate the given segment number @seg_idx of @stream at time @offset.\r
+ * @offset is an absolute global position over all the segments.\r
+ *\r
+ * This will push out a NEWSEGMENT event with the right values and\r
+ * position the stream index to the first decodable sample before\r
+ * @offset.\r
+ */\r
+static gboolean\r
+gst_piffdemux_activate_segment (GstPiffDemux * piffdemux, PiffDemuxStream * stream,\r
+    guint32 seg_idx, guint64 offset)\r
+{\r
+  GstEvent *event;\r
+  PiffDemuxSegment *segment;\r
+  guint64 seg_time;\r
+  guint64 start, stop, time;\r
+  gdouble rate;\r
+\r
+  GST_LOG_OBJECT (piffdemux, "activate segment %d, offset %" G_GUINT64_FORMAT,\r
+      seg_idx, offset);\r
+\r
+  /* update the current segment */\r
+  stream->segment_index = seg_idx;\r
+\r
+  /* get the segment */\r
+  segment = &stream->segments[seg_idx];\r
+\r
+  if (G_UNLIKELY (offset < segment->time)) {\r
+    GST_WARNING_OBJECT (piffdemux, "offset < segment->time %" G_GUINT64_FORMAT,\r
+        segment->time);\r
+    return FALSE;\r
+  }\r
+\r
+  /* segment lies beyond total indicated duration */\r
+  if (G_UNLIKELY (piffdemux->segment.duration != -1 &&\r
+          segment->time > piffdemux->segment.duration)) {\r
+    GST_WARNING_OBJECT (piffdemux, "file duration %" G_GINT64_FORMAT\r
+        " < segment->time %" G_GUINT64_FORMAT, piffdemux->segment.duration,\r
+        segment->time);\r
+    return FALSE;\r
+  }\r
+\r
+  /* get time in this segment */\r
+  seg_time = offset - segment->time;\r
+\r
+  GST_LOG_OBJECT (piffdemux, "seg_time %" GST_TIME_FORMAT,\r
+      GST_TIME_ARGS (seg_time));\r
+\r
+  if (G_UNLIKELY (seg_time > segment->duration)) {\r
+    GST_LOG_OBJECT (piffdemux, "seg_time > segment->duration %" GST_TIME_FORMAT,\r
+        GST_TIME_ARGS (segment->duration));\r
+    return FALSE;\r
+  }\r
+\r
+  /* piffdemux->segment.stop is in outside-time-realm, whereas\r
+   * segment->media_stop is in track-time-realm.\r
+   *\r
+   * In order to compare the two, we need to bring segment.stop\r
+   * into the track-time-realm */\r
+\r
+  stop = piffdemux->segment.stop;\r
+  if (stop == -1)\r
+    stop = piffdemux->segment.duration;\r
+  if (stop == -1)\r
+    stop = segment->media_stop;\r
+  else\r
+    stop =\r
+        MIN (segment->media_stop, stop - segment->time + segment->media_start);\r
+\r
+  if (piffdemux->segment.rate >= 0) {\r
+    start = MIN (segment->media_start + seg_time, stop);\r
+    time = offset;\r
+  } else {\r
+    if (segment->media_start >= piffdemux->segment.start) {\r
+      start = segment->media_start;\r
+      time = segment->time;\r
+    } else {\r
+      start = piffdemux->segment.start;\r
+      time = segment->time + (piffdemux->segment.start - segment->media_start);\r
+    }\r
+\r
+    start = MAX (segment->media_start, piffdemux->segment.start);\r
+    stop = MIN (segment->media_start + seg_time, stop);\r
+  }\r
+\r
+  GST_DEBUG_OBJECT (piffdemux, "newsegment %d from %" GST_TIME_FORMAT\r
+      " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,\r
+      GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));\r
+\r
+  /* combine global rate with that of the segment */\r
+  rate = segment->rate * piffdemux->segment.rate;\r
+\r
+  /* update the segment values used for clipping */\r
+  gst_segment_init (&stream->segment, GST_FORMAT_TIME);\r
+  gst_segment_set_newsegment (&stream->segment, FALSE, rate, GST_FORMAT_TIME,\r
+      start, stop, time);\r
+\r
+  /* now prepare and send the segment */\r
+  event = gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,\r
+      start, stop, time);\r
+  gst_pad_push_event (piffdemux->srcpad, event);\r
+  /* assume we can send more data now */\r
+  stream->last_ret = GST_FLOW_OK;\r
+  /* clear to send tags on this pad now */\r
+  gst_piffdemux_push_tags (piffdemux, stream);\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/* prepare to get the current sample of @stream, getting essential values.\r
+ *\r
+ * This function will also prepare and send the segment when needed.\r
+ *\r
+ * Return FALSE if the stream is EOS.\r
+ */\r
+static gboolean\r
+gst_piffdemux_prepare_current_sample (GstPiffDemux * piffdemux,\r
+    PiffDemuxStream * stream, guint64 * offset, guint * size, guint64 * timestamp,\r
+    guint64 * duration, gboolean * keyframe)\r
+{\r
+  PiffDemuxSample *sample;\r
+  guint64 time_position;\r
+  guint32 seg_idx;\r
+\r
+  g_return_val_if_fail (stream != NULL, FALSE);\r
+\r
+  time_position = stream->time_position;\r
+  if (G_UNLIKELY (time_position == -1))\r
+    goto eos;\r
+\r
+  seg_idx = stream->segment_index;\r
+  if (G_UNLIKELY (seg_idx == -1)) {\r
+    /* find segment corresponding to time_position if we are looking\r
+     * for a segment. */\r
+    seg_idx = gst_piffdemux_find_segment (piffdemux, stream, time_position);\r
+\r
+    /* nothing found, we're really eos */\r
+    if (seg_idx == -1)\r
+      goto eos;\r
+  }\r
+\r
+  /* different segment, activate it, sample_index will be set. */\r
+  if (G_UNLIKELY (stream->segment_index != seg_idx))\r
+    gst_piffdemux_activate_segment (piffdemux, stream, seg_idx, time_position);\r
+\r
+  GST_LOG_OBJECT (piffdemux, "segment active, index = %u of %u",\r
+      stream->sample_index, stream->n_samples);\r
+\r
+  if (G_UNLIKELY (stream->sample_index >= stream->n_samples))\r
+    goto eos;\r
+\r
+\r
+  /* now get the info for the sample we're at */\r
+  sample = &stream->samples[stream->sample_index];\r
+\r
+  *timestamp = PIFFSAMPLE_PTS (stream, sample);\r
+  *offset = sample->offset;\r
+  *size = sample->size;\r
+  *duration = PIFFSAMPLE_DUR_PTS (stream, sample, *timestamp);\r
+  *keyframe = PIFFSAMPLE_KEYFRAME (stream, sample);\r
+\r
+  return TRUE;\r
+\r
+  /* special cases */\r
+eos:\r
+  {\r
+    stream->time_position = -1;\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/* the input buffer metadata must be writable,\r
+ * but time/duration etc not yet set and need not be preserved */\r
+static GstBuffer *\r
+gst_piffdemux_process_buffer (GstPiffDemux * piffdemux, PiffDemuxStream * stream,\r
+    GstBuffer * buf)\r
+{\r
+  guint8 *data;\r
+  guint size, nsize = 0;\r
+  gchar *str;\r
+\r
+  data = GST_BUFFER_DATA (buf);\r
+  size = GST_BUFFER_SIZE (buf);\r
+\r
+  if (G_UNLIKELY (stream->subtype != FOURCC_text)) {\r
+    return buf;\r
+  }\r
+\r
+  if (G_LIKELY (size >= 2)) {\r
+    nsize = GST_READ_UINT16_BE (data);\r
+    nsize = MIN (nsize, size - 2);\r
+  }\r
+\r
+  GST_LOG_OBJECT (piffdemux, "3GPP timed text subtitle: %d/%d", nsize, size);\r
+\r
+  /* takes care of UTF-8 validation or UTF-16 recognition,\r
+   * no other encoding expected */\r
+  str = gst_tag_freeform_string_to_utf8 ((gchar *) data + 2, nsize, NULL);\r
+  if (str) {\r
+    gst_buffer_unref (buf);\r
+    buf = gst_buffer_new ();\r
+    GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = (guint8 *) str;\r
+    GST_BUFFER_SIZE (buf) = strlen (str);\r
+  } else {\r
+    /* may be 0-size subtitle, which is also sent to keep pipeline going */\r
+    GST_BUFFER_DATA (buf) = data + 2;\r
+    GST_BUFFER_SIZE (buf) = nsize;\r
+  }\r
+\r
+  /* FIXME ? convert optional subsequent style info to markup */\r
+\r
+  return buf;\r
+}\r
+\r
+/* Sets a buffer's attributes properly and pushes it downstream.\r
+ * Also checks for additional actions and custom processing that may\r
+ * need to be done first.\r
+ */\r
+static gboolean\r
+gst_piffdemux_decorate_and_push_buffer (GstPiffDemux * piffdemux,\r
+    PiffDemuxStream * stream, GstBuffer * buf,\r
+    guint64 timestamp, guint64 duration, gboolean keyframe, guint64 position,\r
+    guint64 byte_position)\r
+{\r
+  GstFlowReturn ret = GST_FLOW_OK;\r
+\r
+  if (!stream->caps) {\r
+    GST_WARNING_OBJECT (piffdemux, "caps are empty...creat any caps");\r
+    stream->caps = gst_caps_new_any();\r
+    if (!stream->caps) {\r
+      GST_ERROR_OBJECT (piffdemux, "failed to create caps...");\r
+      ret = GST_FLOW_ERROR;\r
+      goto exit;\r
+    }\r
+  }\r
+\r
+  /* position reporting */\r
+  if (piffdemux->segment.rate >= 0) {\r
+   // TODO: Segment fault is coming here for Audio stream.. need to check\r
+    gst_segment_set_last_stop (&piffdemux->segment, GST_FORMAT_TIME, position);\r
+    //gst_piffdemux_sync_streams (piffdemux);\r
+  }\r
+\r
+  /* send out pending buffers */\r
+  while (stream->buffers) {\r
+    GstBuffer *buffer = (GstBuffer *) stream->buffers->data;\r
+\r
+    if (G_UNLIKELY (stream->discont)) {\r
+      GST_LOG_OBJECT (piffdemux, "marking discont buffer");\r
+      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);\r
+      stream->discont = FALSE;\r
+    }\r
+    gst_buffer_set_caps (buffer, stream->caps);\r
+\r
+    gst_pad_push (piffdemux->srcpad, buffer);\r
+\r
+    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);\r
+  }\r
+\r
+  /* we're going to modify the metadata */\r
+  buf = gst_buffer_make_metadata_writable (buf);\r
+\r
+  /* for subtitle processing */\r
+  if (G_UNLIKELY (stream->need_process))\r
+    buf = gst_piffdemux_process_buffer (piffdemux, stream, buf);\r
+\r
+  GST_BUFFER_TIMESTAMP (buf) = timestamp;\r
+  GST_BUFFER_DURATION (buf) = duration;\r
+  GST_BUFFER_OFFSET (buf) = -1;\r
+  GST_BUFFER_OFFSET_END (buf) = -1;\r
+\r
+  if (G_UNLIKELY (stream->padding)) {\r
+    GST_BUFFER_DATA (buf) += stream->padding;\r
+    GST_BUFFER_SIZE (buf) -= stream->padding;\r
+  }\r
+\r
+  if (G_UNLIKELY (buf == NULL))\r
+    goto exit;\r
+\r
+  if (G_UNLIKELY (stream->discont)) {\r
+    GST_LOG_OBJECT (piffdemux, "marking discont buffer");\r
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);\r
+    stream->discont = FALSE;\r
+  }\r
+\r
+  if (!keyframe)\r
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);\r
+\r
+ //g_print ("\n\npad caps : %s\n\n", gst_caps_to_string (gst_pad_get_caps (stream->pad)));\r
+\r
+  //gst_buffer_set_caps (buf, stream->caps); // commenting to avoid caps by setting properties\r
+\r
+\r
+  // TODO: need to see how resolution switch will work\r
+  gst_buffer_set_caps (buf, stream->caps);\r
+\r
+  GST_LOG_OBJECT (piffdemux,\r
+      "Pushing buffer of size = %d with time %" GST_TIME_FORMAT ", duration %"\r
+      GST_TIME_FORMAT, GST_BUFFER_SIZE(buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),\r
+      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));\r
+\r
+#ifdef DEC_OUT_FRAME_DUMP\r
+    {\r
+        int written = 0;\r
+        written = fwrite (GST_BUFFER_DATA (buf), sizeof (unsigned char), GST_BUFFER_SIZE (buf), piffdump);\r
+        g_print ("PIFFDEMUX: written = %d\n", written);\r
+        fflush (piffdump);\r
+    }\r
+#endif\r
+\r
+  ret = gst_pad_push (piffdemux->srcpad, buf);\r
+\r
+exit:\r
+  return ret;\r
+}\r
+\r
+\r
+/*\r
+ * next_entry_size\r
+ *\r
+ * Returns the size of the first entry at the current offset.\r
+ * If -1, there are none (which means EOS or empty file).\r
+ */\r
+static guint64\r
+next_entry_size (GstPiffDemux * demux)\r
+{\r
+  PiffDemuxStream *stream = demux->stream;\r
+  PiffDemuxSample *sample;\r
+\r
+  GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,\r
+      demux->offset);\r
+\r
+  GST_DEBUG_OBJECT (demux, "demux->sample_index = %d", stream->sample_index);\r
+\r
+  if (stream->sample_index == -1)\r
+    stream->sample_index = 0;\r
+\r
+  if (stream->sample_index >= stream->n_samples) {\r
+    GST_LOG_OBJECT (demux, "stream %d samples exhausted n_samples = %d",\r
+               stream->sample_index, stream->n_samples);\r
+    return -1;\r
+  }\r
+\r
+  sample = &stream->samples[stream->sample_index];\r
+\r
+  GST_LOG_OBJECT (demux,\r
+      "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT\r
+      " / size:%" G_GUINT32_FORMAT ")", stream->sample_index, stream->sample_index,\r
+      sample->offset, sample->size);\r
+\r
+  GST_LOG_OBJECT (demux, "stream : demux->offset :%"G_GUINT64_FORMAT, demux->offset);\r
+\r
+  stream = demux->stream;\r
+  sample = &stream->samples[stream->sample_index];\r
+\r
+  if (sample->offset >= demux->offset) {\r
+    demux->todrop = sample->offset - demux->offset;\r
+    return sample->size + demux->todrop;\r
+  }\r
+\r
+  GST_DEBUG_OBJECT (demux,\r
+      "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);\r
+  return -1;\r
+}\r
+\r
+static void\r
+gst_piffdemux_post_progress (GstPiffDemux * demux, gint num, gint denom)\r
+{\r
+  gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);\r
+\r
+  gst_element_post_message (GST_ELEMENT_CAST (demux),\r
+      gst_message_new_element (GST_OBJECT_CAST (demux),\r
+          gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));\r
+}\r
+\r
+static gboolean\r
+piffdemux_seek_offset (GstPiffDemux * demux, guint64 offset)\r
+{\r
+  GstEvent *event;\r
+  gboolean res = 0;\r
+\r
+  GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);\r
+\r
+  event =\r
+      gst_event_new_seek (1.0, GST_FORMAT_BYTES,\r
+      GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,\r
+      GST_SEEK_TYPE_NONE, -1);\r
+\r
+  res = gst_pad_push_event (demux->sinkpad, event);\r
+\r
+  return res;\r
+}\r
+\r
+static GstFlowReturn\r
+gst_piffdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)\r
+{\r
+  GstPiffDemux *demux;\r
+  GstFlowReturn ret = GST_FLOW_OK;\r
+  demux = GST_PIFFDEMUX (gst_pad_get_parent (sinkpad));\r
+\r
+  gst_adapter_push (demux->adapter, inbuf);\r
+\r
+  /* we never really mean to buffer that much */\r
+  if (demux->neededbytes == -1)\r
+    goto eos;\r
+\r
+  GST_DEBUG_OBJECT (demux, "pushing in inbuf %p, neededbytes:%u, available:%u",\r
+      inbuf, demux->neededbytes, gst_adapter_available (demux->adapter));\r
+\r
+  while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&\r
+      (ret == GST_FLOW_OK)) {\r
+\r
+    GST_DEBUG_OBJECT (demux,\r
+        "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,\r
+        demux->state, demux->neededbytes, demux->offset);\r
+\r
+    switch (demux->state) {\r
+      case PIFFDEMUX_STATE_INITIAL:{\r
+        const guint8 *data;\r
+        guint32 fourcc;\r
+        guint64 size;\r
+\r
+        data = gst_adapter_peek (demux->adapter, demux->neededbytes);\r
+\r
+        /* get fourcc/length, set neededbytes */\r
+        extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,\r
+            &size, &fourcc);\r
+        GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "\r
+            "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);\r
+        if (size == 0) {\r
+          GST_ELEMENT_ERROR (demux, STREAM, DEMUX,\r
+              ("This file is invalid and cannot be played."),\r
+              ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",\r
+                  GST_FOURCC_ARGS (fourcc)));\r
+\r
+          ret = GST_FLOW_ERROR;\r
+          break;\r
+        }\r
+\r
+        if (fourcc == FOURCC_mdat) {\r
+          if (demux->moof_rcvd) {\r
+            /* we have the headers, start playback */\r
+            demux->state = PIFFDEMUX_STATE_MOVIE;\r
+            demux->neededbytes = next_entry_size (demux);\r
+            demux->mdatleft = size;\r
+\r
+            /* Only post, event on pads is done after newsegment */\r
+            piffdemux_post_global_tags (demux);\r
+          } else {\r
+             GST_ERROR_OBJECT (demux, "mdata received before moof.. not handled");\r
+             goto unknown_stream;\r
+          }\r
+        } else if (G_UNLIKELY (size > PIFFDEMUX_MAX_ATOM_SIZE)) {\r
+          GST_ELEMENT_ERROR (demux, STREAM, DEMUX,\r
+              ("This file is invalid and cannot be played."),\r
+              ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,\r
+                  GST_FOURCC_ARGS (fourcc), size));\r
+          ret = GST_FLOW_ERROR;\r
+          break;\r
+        } else {\r
+          demux->neededbytes = size;\r
+          demux->state = PIFFDEMUX_STATE_HEADER;\r
+        }\r
+        break;\r
+      }\r
+      case PIFFDEMUX_STATE_HEADER:{\r
+        const guint8 *data;\r
+        guint32 fourcc;\r
+\r
+        GST_DEBUG_OBJECT (demux, "In header");\r
+\r
+        data = gst_adapter_peek (demux->adapter, demux->neededbytes);\r
+\r
+        /* parse the header */\r
+        extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,\r
+            &fourcc);\r
+        if (fourcc == FOURCC_moof) {\r
+            GST_DEBUG_OBJECT (demux, "Parsing [moof]");\r
+            if (!piffdemux_parse_moof (demux, data, demux->neededbytes,\r
+                    demux->offset, demux->stream)) {\r
+              ret = GST_FLOW_ERROR;\r
+              goto done;\r
+            }\r
+            demux->moof_rcvd = TRUE;\r
+        }  else {\r
+          GST_WARNING_OBJECT (demux,\r
+              "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,\r
+              GST_FOURCC_ARGS (fourcc));\r
+          /* Let's jump that one and go back to initial state */\r
+        }\r
+\r
+        if (demux->mdatbuffer) {\r
+          /* the mdat was before the header */\r
+          GST_DEBUG_OBJECT (demux, "We have mdatbuffer:%p",\r
+             demux->mdatbuffer);\r
+          gst_adapter_clear (demux->adapter);\r
+          demux->mdatbuffer = NULL;\r
+          demux->offset = demux->mdatoffset;\r
+          demux->neededbytes = next_entry_size (demux);\r
+          demux->state = PIFFDEMUX_STATE_MOVIE;\r
+          demux->mdatleft = gst_adapter_available (demux->adapter);\r
+\r
+          /* Only post, event on pads is done after newsegment */\r
+          piffdemux_post_global_tags (demux);\r
+        } else {\r
+          GST_DEBUG_OBJECT (demux, "Carrying on normally");\r
+          gst_adapter_flush (demux->adapter, demux->neededbytes);\r
+            demux->offset += demux->neededbytes;\r
+          demux->neededbytes = 16;\r
+          demux->state = PIFFDEMUX_STATE_INITIAL;\r
+        }\r
+\r
+        break;\r
+      }\r
+      case PIFFDEMUX_STATE_BUFFER_MDAT:{\r
+        GstBuffer *buf;\r
+\r
+        GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,\r
+            demux->offset);\r
+        buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);\r
+        GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,\r
+            GST_FOURCC_ARGS (PIFF_FOURCC (GST_BUFFER_DATA (buf) + 4)));\r
+        if (demux->mdatbuffer)\r
+          demux->mdatbuffer = gst_buffer_join (demux->mdatbuffer, buf);\r
+        else\r
+          demux->mdatbuffer = buf;\r
+        demux->offset += demux->neededbytes;\r
+        demux->neededbytes = 16;\r
+        demux->state = PIFFDEMUX_STATE_INITIAL;\r
+        gst_piffdemux_post_progress (demux, 1, 1);\r
+\r
+        break;\r
+      }\r
+      case PIFFDEMUX_STATE_MOVIE:{\r
+        GstBuffer *outbuf;\r
+        PiffDemuxStream *stream = demux->stream;\r
+        PiffDemuxSample *sample;\r
+        guint64 timestamp, duration, position;\r
+        gboolean keyframe;\r
+\r
+        GST_DEBUG_OBJECT (demux,\r
+            "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);\r
+\r
+        if (demux->fragmented) {\r
+          GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,\r
+              demux->mdatleft);\r
+          if (G_LIKELY (demux->todrop < demux->mdatleft)) {\r
+            /* if needed data starts within this atom,\r
+             * then it should not exceed this atom */\r
+            if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {\r
+\r
+              GST_ELEMENT_ERROR (demux, STREAM, DEMUX,\r
+                  ("This file is invalid and cannot be played."),\r
+                  ("sample data crosses atom boundary"));\r
+\r
+              ret = GST_FLOW_ERROR;\r
+              break;\r
+            }\r
+            demux->mdatleft -= demux->neededbytes;\r
+          } else {\r
+            GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");\r
+            /* so we are dropping more than left in this atom */\r
+            demux->todrop -= demux->mdatleft;\r
+            demux->neededbytes -= demux->mdatleft;\r
+            demux->mdatleft = 0;\r
+            /* need to resume atom parsing so we do not miss any other pieces */\r
+            demux->state = PIFFDEMUX_STATE_INITIAL;\r
+            demux->neededbytes = 16;\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (demux->todrop) {\r
+          GST_LOG_OBJECT (demux, "Dropping %d bytes", demux->todrop);\r
+          gst_adapter_flush (demux->adapter, demux->todrop);\r
+          demux->neededbytes -= demux->todrop;\r
+          demux->offset += demux->todrop;\r
+        }\r
+\r
+        if ( !stream->sent_nsevent) {\r
+          //TODO: better to parse sink event function and send that new_segment\r
+#if 1\r
+               demux->pending_newsegment = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,\r
+                                       demux->stream->start_ts, -1, demux->stream->start_ts);\r
+#else\r
+               demux->pending_newsegment = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,\r
+                                       0, gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale), 0);\r
+#endif\r
+\r
+               GST_INFO_OBJECT (demux, "New segment event : start = %"GST_TIME_FORMAT", stop = %" GST_TIME_FORMAT,\r
+                       GST_TIME_ARGS (demux->stream->start_ts), GST_TIME_ARGS(gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale)));\r
+\r
+          if (!gst_pad_push_event (demux->srcpad, demux->pending_newsegment)) {\r
+            GST_ERROR_OBJECT (demux, "failding to send new segment...");\r
+            goto newsegment_error;\r
+          }\r
+          stream->sent_nsevent = TRUE;\r
+       }\r
+\r
+        /* Put data in a buffer, set timestamps, caps, ... */\r
+        outbuf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);\r
+\r
+        GST_DEBUG_OBJECT (demux, "Taken %d size buffer from adapter...", outbuf ? GST_BUFFER_SIZE (outbuf) : 0);\r
+        GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (stream->fourcc));\r
+\r
+        g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);\r
+\r
+        sample = &stream->samples[stream->sample_index];\r
+\r
+        GST_DEBUG_OBJECT (demux, "start_ts = %"GST_TIME_FORMAT" ts : %"GST_TIME_FORMAT" ts = %llu, pts_offset = %u, scale = %d\n",\r
+                       GST_TIME_ARGS(stream->start_ts),GST_TIME_ARGS(sample->timestamp), sample->timestamp,\r
+                       sample->pts_offset,stream->timescale);\r
+\r
+        position = PIFFSAMPLE_DTS (stream, sample);\r
+        timestamp = PIFFSAMPLE_PTS (stream, sample) + stream->start_ts; // Adding to avoid resetting of timestamp\r
+        duration = PIFFSAMPLE_DUR_DTS (stream, sample, position);\r
+        keyframe = PIFFSAMPLE_KEYFRAME (stream, sample);\r
+\r
+        ret = gst_piffdemux_decorate_and_push_buffer (demux, stream, outbuf,\r
+            timestamp, duration, keyframe, position, demux->offset);\r
+\r
+        stream->sample_index++;\r
+\r
+        /* update current offset and figure out size of next buffer */\r
+        GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",\r
+            demux->offset, demux->neededbytes);\r
+        demux->offset += demux->neededbytes;\r
+        GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,\r
+            demux->offset);\r
+\r
+        if ((demux->neededbytes = next_entry_size (demux)) == -1) {\r
+          GST_DEBUG_OBJECT (demux, "finished parsing mdat, need to search next moof atom");\r
+          demux->neededbytes = 16;\r
+          demux->state = PIFFDEMUX_STATE_INITIAL;\r
+          GST_DEBUG ("\n\n Storing %s last_ts %"GST_TIME_FORMAT"\n\n", stream->subtype == FOURCC_vide ? "video" : "audio", GST_TIME_ARGS(timestamp));\r
+          stream->start_ts = timestamp + duration;\r
+          //goto eos;\r
+        }\r
+        break;\r
+      }\r
+      default:\r
+        goto invalid_state;\r
+    }\r
+  }\r
+\r
+  /* when buffering movie data, at least show user something is happening */\r
+  if (ret == GST_FLOW_OK && demux->state == PIFFDEMUX_STATE_BUFFER_MDAT &&\r
+      gst_adapter_available (demux->adapter) <= demux->neededbytes) {\r
+    gst_piffdemux_post_progress (demux, gst_adapter_available (demux->adapter),\r
+        demux->neededbytes);\r
+  }\r
+done:\r
+  gst_object_unref (demux);\r
+\r
+  return ret;\r
+\r
+  /* ERRORS */\r
+unknown_stream:\r
+  {\r
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));\r
+    ret = GST_FLOW_ERROR;\r
+    goto done;\r
+  }\r
+eos:\r
+  {\r
+    GST_DEBUG_OBJECT (demux, "no next entry, EOS");\r
+    ret = GST_FLOW_UNEXPECTED;\r
+    goto done;\r
+  }\r
+invalid_state:\r
+  {\r
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED,\r
+        (NULL), ("piffdemuxer invalid state %d", demux->state));\r
+    ret = GST_FLOW_ERROR;\r
+    goto done;\r
+  }\r
+newsegment_error:\r
+  {\r
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED,\r
+        (NULL), ("could not send newsegment event"));\r
+    ret = GST_FLOW_ERROR;\r
+    goto done;\r
+  }\r
+}\r
+\r
+static gboolean\r
+piffdemux_parse_container (GstPiffDemux * piffdemux, GNode * node, const guint8 * buf,\r
+    const guint8 * end)\r
+{\r
+  while (G_UNLIKELY (buf < end)) {\r
+    GNode *child;\r
+    guint32 len;\r
+\r
+    if (G_UNLIKELY (buf + 4 > end)) {\r
+      GST_LOG_OBJECT (piffdemux, "buffer overrun");\r
+      break;\r
+    }\r
+    len = PIFF_UINT32 (buf);\r
+    if (G_UNLIKELY (len == 0)) {\r
+      GST_LOG_OBJECT (piffdemux, "empty container");\r
+      break;\r
+    }\r
+    if (G_UNLIKELY (len < 8)) {\r
+      GST_WARNING_OBJECT (piffdemux, "length too short (%d < 8)", len);\r
+      break;\r
+    }\r
+    if (G_UNLIKELY (len > (end - buf))) {\r
+      GST_WARNING_OBJECT (piffdemux, "length too long (%d > %d)", len,\r
+          (gint) (end - buf));\r
+      break;\r
+    }\r
+\r
+    child = g_node_new ((guint8 *) buf);\r
+    g_node_append (node, child);\r
+    GST_LOG_OBJECT (piffdemux, "adding new node of len %d", len);\r
+    piffdemux_parse_node (piffdemux, child, buf, len);\r
+\r
+    buf += len;\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+\r
+static gboolean\r
+piffdemux_parse_node (GstPiffDemux * piffdemux, GNode * node, const guint8 * buffer,\r
+    guint length)\r
+{\r
+  guint32 fourcc = 0;\r
+  guint32 node_length = 0;\r
+  const PiffNodeType *type;\r
+  const guint8 *end;\r
+\r
+  GST_LOG_OBJECT (piffdemux, "piffdemux_parse buffer %p length %u", buffer, length);\r
+\r
+  if (G_UNLIKELY (length < 8))\r
+    goto not_enough_data;\r
+\r
+  node_length = PIFF_UINT32 (buffer);\r
+  fourcc = PIFF_FOURCC (buffer + 4);\r
+\r
+  /* ignore empty nodes */\r
+  if (G_UNLIKELY (fourcc == 0 || node_length == 8))\r
+    return TRUE;\r
+\r
+  type = piffdemux_type_get (fourcc);\r
+\r
+  end = buffer + length;\r
+\r
+  GST_LOG_OBJECT (piffdemux,\r
+      "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",\r
+      GST_FOURCC_ARGS (fourcc), node_length, type->name);\r
+\r
+  if (node_length > length)\r
+    goto broken_atom_size;\r
+\r
+  if (type->flags & PIFF_FLAG_CONTAINER) {\r
+    piffdemux_parse_container (piffdemux, node, buffer + 8, end);\r
+  }\r
+  GST_LOG_OBJECT (piffdemux, "parsed '%" GST_FOURCC_FORMAT "'",\r
+      GST_FOURCC_ARGS (fourcc));\r
+  return TRUE;\r
+\r
+/* ERRORS */\r
+not_enough_data:\r
+  {\r
+\r
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,\r
+        ("This file is corrupt and cannot be played."),\r
+        ("Not enough data for an atom header, got only %u bytes", length));\r
+\r
+    return FALSE;\r
+  }\r
+broken_atom_size:\r
+  {\r
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,\r
+        ("This file is corrupt and cannot be played."),\r
+        ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "\r
+            "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,\r
+            length));\r
+\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+\r
+static GNode *\r
+piffdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)\r
+{\r
+  GNode *child;\r
+  guint8 *buffer;\r
+  guint32 child_fourcc;\r
+\r
+  for (child = g_node_first_child (node); child;\r
+      child = g_node_next_sibling (child)) {\r
+    buffer = (guint8 *) child->data;\r
+\r
+    child_fourcc = PIFF_FOURCC (buffer + 4);\r
+\r
+    if (G_UNLIKELY (child_fourcc == fourcc)) {\r
+      return child;\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+static GNode *\r
+piffdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,\r
+    GstByteReader * parser)\r
+{\r
+  GNode *child;\r
+  guint8 *buffer;\r
+  guint32 child_fourcc, child_len;\r
+\r
+  for (child = g_node_first_child (node); child;\r
+      child = g_node_next_sibling (child)) {\r
+    buffer = (guint8 *) child->data;\r
+\r
+    child_len = PIFF_UINT32 (buffer);\r
+    child_fourcc = PIFF_FOURCC (buffer + 4);\r
+\r
+    if (G_UNLIKELY (child_fourcc == fourcc)) {\r
+      if (G_UNLIKELY (child_len < (4 + 4)))\r
+        return NULL;\r
+      /* FIXME: must verify if atom length < parent atom length */\r
+      gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));\r
+      return child;\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+static GNode *\r
+piffdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,\r
+    GstByteReader * parser)\r
+{\r
+  GNode *child;\r
+  guint8 *buffer;\r
+  guint32 child_fourcc, child_len;\r
+\r
+  for (child = g_node_next_sibling (node); child;\r
+      child = g_node_next_sibling (child)) {\r
+    buffer = (guint8 *) child->data;\r
+\r
+    child_fourcc = PIFF_FOURCC (buffer + 4);\r
+\r
+    if (child_fourcc == fourcc) {\r
+      if (parser) {\r
+        child_len = PIFF_UINT32 (buffer);\r
+        if (G_UNLIKELY (child_len < (4 + 4)))\r
+          return NULL;\r
+        /* FIXME: must verify if atom length < parent atom length */\r
+        gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));\r
+      }\r
+      return child;\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+static GNode *\r
+piffdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)\r
+{\r
+  return piffdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);\r
+}\r
+\r
+#define _codec(name) \\r
+  do { \\r
+    if (codec_name) { \\r
+      *codec_name = g_strdup (name); \\r
+    } \\r
+  } while (0)\r
+\r
+void\r
+gst_piffdemux_set_video_params (GstPiffDemux * piffdemux, guint fourcc,\r
+                                       guint width, guint height,\r
+                                       guint fps_n, guint fps_d, unsigned char *codec_data, unsigned int codec_data_len)\r
+{\r
+  GstCaps *caps = NULL;\r
+  GstBuffer *dci = NULL;\r
+\r
+  if (codec_data && codec_data_len) {\r
+    dci = gst_buffer_new_and_alloc (codec_data_len);\r
+    if (!dci) {\r
+      GST_ERROR_OBJECT (piffdemux, "failed to create codec data buffer...");\r
+    } else {\r
+      memcpy (GST_BUFFER_DATA(dci), codec_data, codec_data_len);\r
+    }\r
+  }\r
+\r
+  switch (fourcc) {\r
+\r
+    case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):\r
+      caps = gst_caps_new_simple ("video/x-h264",\r
+                                                  "width", G_TYPE_INT, width,\r
+                                                  "height", G_TYPE_INT, height,\r
+                                                  "framerate", GST_TYPE_FRACTION, fps_n, fps_d,\r
+                                                  "stream-format", G_TYPE_STRING, "avc",\r
+                                                  "alignment", G_TYPE_STRING, "au",\r
+                                                  "codec_data", GST_TYPE_BUFFER, dci,\r
+                                                  NULL);\r
+      break;\r
+\r
+    case FOURCC_ovc1:\r
+      caps = gst_caps_new_simple ("video/x-wmv",\r
+                                                   "width", G_TYPE_INT, width,\r
+                                                  "height", G_TYPE_INT, height,\r
+                                                  "framerate", GST_TYPE_FRACTION, fps_n, fps_d,\r
+                                                  "wmvversion", G_TYPE_INT, 3,\r
+                                                  "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),\r
+                                                  "codec_data", GST_TYPE_BUFFER, dci,\r
+                                                  NULL);\r
+      break;\r
+\r
+    default: {\r
+      char *s;\r
+      s = g_strdup_printf ("video/x-gst-fourcc-%" GST_FOURCC_FORMAT,\r
+          GST_FOURCC_ARGS (fourcc));\r
+      caps = gst_caps_new_simple (s,\r
+                                                 "width", G_TYPE_INT, width,\r
+                                                 "height", G_TYPE_INT, height,\r
+                                                 "framerate", GST_TYPE_FRACTION, fps_n, fps_d,\r
+                                                  "codec_data", GST_TYPE_BUFFER, dci,\r
+                                                 NULL);\r
+      break;\r
+    }\r
+  }\r
+\r
+  piffdemux->stream->caps = caps;\r
+  GST_INFO_OBJECT (piffdemux, "prepared video caps : %s", gst_caps_to_string(caps));\r
+}\r
+\r
+void\r
+gst_piffdemux_set_audio_params (GstPiffDemux * piffdemux, guint fourcc,\r
+                                       guint sampling_rate, guint bps, guint channels, unsigned char *codec_data, unsigned int codec_data_len)\r
+{\r
+  GstCaps *caps = NULL;\r
+  GstBuffer *dci = NULL;\r
+\r
+  if (codec_data && codec_data_len) {\r
+    dci = gst_buffer_new_and_alloc (codec_data_len);\r
+    if (!dci) {\r
+      GST_ERROR_OBJECT (piffdemux, "failed to create codec data buffer...");\r
+    } else {\r
+      memcpy (GST_BUFFER_DATA(dci), codec_data, codec_data_len);\r
+    }\r
+  }\r
+\r
+  switch (fourcc) {\r
+\r
+    case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):\r
+      caps = gst_caps_new_simple ("audio/mpeg",\r
+                                                  "mpegversion", G_TYPE_INT, 4,\r
+                                                  "framed", G_TYPE_BOOLEAN, TRUE,\r
+                                                  "stream-format", G_TYPE_STRING, "raw",\r
+                                                  "rate", G_TYPE_INT, (int) sampling_rate,\r
+                                                  "channels", G_TYPE_INT, channels,\r
+                                                  NULL);\r
+      break;\r
+\r
+    case FOURCC_owma:\r
+      caps = gst_caps_new_simple ("audio/x-wma",\r
+                                                   "rate", G_TYPE_INT, (int) sampling_rate,\r
+                                                  "channels", G_TYPE_INT, channels,\r
+                                                   NULL);\r
+      break;\r
+\r
+    default: {\r
+      char *s;\r
+      s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,\r
+          GST_FOURCC_ARGS (fourcc));\r
+      caps = gst_caps_new_simple (s,\r
+                                                   "rate", G_TYPE_INT, (int) sampling_rate,\r
+                                                  "channels", G_TYPE_INT, channels,\r
+                                                 NULL);\r
+      break;\r
+    }\r
+  }\r
+\r
+  piffdemux->stream->caps = caps;\r
+  GST_INFO_OBJECT (piffdemux, "prepared audio caps : %s", gst_caps_to_string(caps));\r
+\r
+}\r
+\r
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)\r
+\r
+void\r
+__gst_piffdemux_marshal_BOOLEAN__OBJECT (GClosure *closure,\r
+                                   GValue       *return_value G_GNUC_UNUSED,\r
+                                   guint         n_param_values,\r
+                                   const GValue *param_values,\r
+                                   gpointer      invocation_hint G_GNUC_UNUSED,\r
+                                   gpointer      marshal_data)\r
+{\r
+  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT) (gpointer  data1,\r
+                                                    gpointer      arg_1,\r
+                                                    gpointer     data2);\r
+  register GMarshalFunc_BOOLEAN__OBJECT callback;\r
+  register GCClosure *cc = (GCClosure*) closure;\r
+  register gpointer data1, data2;\r
+  gboolean v_return;\r
+\r
+  g_return_if_fail (return_value != NULL);\r
+  g_return_if_fail (n_param_values == 2);\r
+\r
+  if (G_CCLOSURE_SWAP_DATA (closure))\r
+  {\r
+    data1 = closure->data;\r
+    data2 = g_value_peek_pointer (param_values + 0);\r
+  }\r
+  else\r
+  {\r
+    data1 = g_value_peek_pointer (param_values + 0);\r
+    data2 = closure->data;\r
+  }\r
+  callback = (GMarshalFunc_BOOLEAN__OBJECT) (marshal_data ? marshal_data : cc->callback);\r
+\r
+  v_return = callback (data1,\r
+                       g_marshal_value_peek_object (param_values + 1),\r
+                       data2);\r
+\r
+  g_value_set_boolean (return_value, v_return);\r
+}\r
+\r
+#define PIFFDEMUX_SPSPPS_LENGTH_SIZE     2\r
+\r
+static gboolean\r
+ConvertH264_MetaDCI_to_3GPPDCI(unsigned char *dci_meta_buf, unsigned int dci_meta_size, unsigned char **dci_3gpp_buf, unsigned int *dci_3gpp_size)\r
+{\r
+  unsigned short unit_size = 0;\r
+  unsigned int total_size = 0;\r
+  unsigned char unit_nb = 0;\r
+  unsigned char sps_done = 0;\r
+  const unsigned char *extradata = NULL;\r
+  unsigned int h264_nal_length_size = 0;\r
+  unsigned char *out = NULL;\r
+  //g_print ("\n\nConvertH264_MetaDCI_to_3GPPDCI Entering.............\n");\r
+\r
+  /* nothing to filter */\r
+  if ((dci_meta_buf == NULL) || (dci_meta_size < 6))\r
+  {\r
+    GST_ERROR ("Insufficient codec data...\n");\r
+    return FALSE;\r
+  }\r
+\r
+  /* Removing unnecessary info in meta data */\r
+  extradata = (unsigned char *)dci_meta_buf + 4;\r
+\r
+  /* retrieve Length of Length*/\r
+  h264_nal_length_size = (*extradata++ & 0x03) + 1;\r
+\r
+  GST_LOG ("Length Of Length is %d\n", h264_nal_length_size);\r
+  if (h264_nal_length_size == 3)\r
+  {\r
+    GST_ERROR ("LengthOfLength is WRONG...\n");\r
+    return FALSE;\r
+  }\r
+\r
+  /* retrieve sps and pps unit(s) */\r
+  unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */\r
+  GST_LOG ("No. of SPS units = %u\n", unit_nb);\r
+\r
+  if (!unit_nb)\r
+  {\r
+    GST_ERROR ("SPS is not present....\n");\r
+    return FALSE;\r
+  }\r
+\r
+  while (unit_nb--)\r
+  {\r
+    /* get SPS/PPS data Length*/\r
+    unit_size = PIFFDEMUX_RB16(extradata);\r
+\r
+    GST_LOG ("SPS size = %d", unit_size);\r
+\r
+    /* Extra 4 bytes for adding size of the packet */\r
+    total_size += unit_size + h264_nal_length_size;\r
+\r
+    /* Check if SPS/PPS Data Length crossed buffer Length */\r
+    if ((extradata + 2 + unit_size) > (dci_meta_buf + dci_meta_size))\r
+    {\r
+      GST_ERROR ("SPS Length is wrong in DCI...\n");\r
+      return FALSE;\r
+    }\r
+    out = realloc(out, total_size);\r
+    if (!out)\r
+    {\r
+      GST_ERROR ("realloc FAILED...\n");\r
+      return FALSE;\r
+    }\r
+    /* Copy length of SPS header */\r
+   // tmp = (unsigned int *)(out + total_size - unit_size - h264_nal_length_size);\r
+   // *tmp = unit_size; \r
+   (out + total_size - unit_size - h264_nal_length_size)[0] = 0;\r
+   (out + total_size - unit_size - h264_nal_length_size)[1] = 0;\r
+   (out + total_size - unit_size - h264_nal_length_size)[2] = 0;\r
+   (out + total_size - unit_size - h264_nal_length_size)[3] = (unsigned char)unit_size;\r
+\r
+   // memcpy(out + total_size - unit_size - h264_nal_length_size, &unit_size, h264_nal_length_size);\r
+    //g_print ("out[0] = %02x, out[1] = %02x, out[2] = %02x = out[3] = %02x\n",\r
+       //      out[total_size - unit_size - h264_nal_length_size],  out[total_size - unit_size - h264_nal_length_size+1],\r
+       //      out[total_size - unit_size - h264_nal_length_size + 2],  out[total_size - unit_size - h264_nal_length_size + 3]);\r
+\r
+    /* Copy SPS/PPS Length and data */\r
+    memcpy(out + total_size - unit_size,  extradata + PIFFDEMUX_SPSPPS_LENGTH_SIZE, unit_size);\r
+\r
+    extradata += (PIFFDEMUX_SPSPPS_LENGTH_SIZE + unit_size);\r
+\r
+    if (!unit_nb && !sps_done++)\r
+    {\r
+      /* Completed reading SPS data, now read PPS data */\r
+      unit_nb = *extradata++; /* number of pps unit(s) */\r
+      GST_DEBUG ("No. of PPS units = %d\n", unit_nb);\r
+    }\r
+  }\r
+\r
+  *dci_3gpp_buf = malloc (total_size);\r
+  if (NULL == *dci_3gpp_buf)\r
+  {\r
+    GST_ERROR ("Memory Allocation FAILED...\n");\r
+    free (out);\r
+    return FALSE;\r
+  }\r
+\r
+  memcpy(*dci_3gpp_buf, out, total_size);\r
+  *dci_3gpp_size = total_size;\r
+\r
+  GST_DEBUG ("SPS_PPS size = %d\n", total_size);\r
+\r
+  if (out)\r
+  {\r
+    free(out);\r
+  }\r
+  return TRUE;\r
+ }\r
+\r
diff --git a/piffdemux/src/piffdemux.h b/piffdemux/src/piffdemux.h
new file mode 100755 (executable)
index 0000000..d23926b
--- /dev/null
@@ -0,0 +1,125 @@
+/* GStreamer\r
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Library General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2 of the License, or (at your option) any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Library General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Library General Public\r
+ * License along with this library; if not, write to the\r
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+ * Boston, MA 02111-1307, USA.\r
+ */\r
+\r
+\r
+#ifndef __GST_PIFFDEMUX_H__\r
+#define __GST_PIFFDEMUX_H__\r
+\r
+#include <gst/gst.h>\r
+#include <gst/base/gstadapter.h>\r
+#include "piffcommon.h"\r
+\r
+G_BEGIN_DECLS\r
+\r
+GST_DEBUG_CATEGORY_EXTERN (piffdemux_debug);\r
+#define GST_CAT_DEFAULT piffdemux_debug\r
+\r
+#define GST_TYPE_PIFFDEMUX \\r
+  (gst_piffdemux_get_type())\r
+#define GST_PIFFDEMUX(obj) \\r
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PIFFDEMUX,GstPiffDemux))\r
+#define GST_PIFFDEMUX_CLASS(klass) \\r
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PIFFDEMUX,GstPiffDemuxClass))\r
+#define GST_IS_PIFFDEMUX(obj) \\r
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIFFDEMUX))\r
+#define GST_IS_PIFFDEMUX_CLASS(klass) \\r
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIFFDEMUX))\r
+\r
+#define GST_PIFFDEMUX_CAST(obj) ((GstPiffDemux *)(obj))\r
+\r
+/* piffdemux produces these for atoms it cannot parse */\r
+#define GST_PIFF_DEMUX_PRIVATE_TAG "private-piff-tag"\r
+#define GST_PIFF_DEMUX_CLASSIFICATION_TAG "classification"\r
+\r
+#define GST_PIFFDEMUX_MAX_STREAMS         8\r
+\r
+typedef struct _GstPiffDemux GstPiffDemux;\r
+typedef struct _GstPiffDemuxClass GstPiffDemuxClass;\r
+typedef struct _PiffDemuxStream PiffDemuxStream;\r
+\r
+struct _GstPiffDemux {\r
+  GstElement element;\r
+\r
+  /* pads */\r
+  GstPad *sinkpad;\r
+  GstPad *srcpad;\r
+\r
+  PiffDemuxStream *stream;\r
+\r
+  guint32 timescale;\r
+  gint64 duration;\r
+\r
+  gboolean fragmented;\r
+\r
+  guint64 moof_offset;\r
+\r
+  gint state;\r
+\r
+  gboolean posted_redirect;\r
+\r
+  /* push based variables */\r
+  guint neededbytes;\r
+  guint todrop;\r
+  GstAdapter *adapter;\r
+  GstBuffer *mdatbuffer;\r
+  guint64 mdatleft;\r
+\r
+  /* offset of the media data (i.e.: Size of header) */\r
+  guint64 offset;\r
+  /* offset of the mdat atom */\r
+  guint64 mdatoffset;\r
+  guint64 first_mdat;\r
+\r
+  GstTagList *tag_list;\r
+\r
+  /* configured playback region */\r
+  GstSegment segment;\r
+  gboolean segment_running;\r
+  GstEvent *pending_newsegment;\r
+\r
+  /* gst index support */\r
+  GstIndex *element_index;\r
+  gint index_id;\r
+\r
+  gint64 requested_seek_time;\r
+  guint64 seek_offset;\r
+  gboolean moof_rcvd;\r
+\r
+  /* live specific params */\r
+  piff_live_param_t *param;\r
+  guint lookahead_cnt;\r
+  gboolean is_live;\r
+};\r
+\r
+struct _GstPiffDemuxClass {\r
+  GstElementClass parent_class;\r
+  void (*live_param)   (GstPiffDemux *piff, const piff_live_param_t *param);\r
+};\r
+\r
+GType gst_piffdemux_get_type (void);\r
+\r
+/* prepares video caps based on input params */\r
+void gst_piffdemux_set_video_params (GstPiffDemux * piffdemux, guint fourcc, guint width, guint height, guint fps_n, guint fps_d, unsigned char *codec_data, unsigned int codec_data_len);\r
+/* prepares audio caps based on input params */\r
+void gst_piffdemux_set_audio_params (GstPiffDemux * piffdemux, guint fourcc,\r
+                                       guint sampling_rate, guint bps, guint channels, unsigned char *codec_data, unsigned int codec_data_len);\r
+G_END_DECLS\r
+\r
+#endif /* __GST_PIFFDEMUX_H__ */\r
+\r
diff --git a/piffdemux/src/piffdemux_dump.c b/piffdemux/src/piffdemux_dump.c
new file mode 100755 (executable)
index 0000000..b2d55f7
--- /dev/null
@@ -0,0 +1,325 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.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 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "piffdemux_types.h"
+#include "piffdemux_dump.h"
+
+#include "piffatomparser.h"
+
+#include <string.h>
+
+#define GET_UINT8(data)   gst_byte_reader_get_uint8_unchecked(data)
+#define GET_UINT16(data)  gst_byte_reader_get_uint16_be_unchecked(data)
+#define GET_UINT32(data)  gst_byte_reader_get_uint32_be_unchecked(data)
+#define GET_UINT64(data)  gst_byte_reader_get_uint64_be_unchecked(data)
+#define GET_FP32(data)   (gst_byte_reader_get_uint32_be_unchecked(data)/65536.0)
+#define GET_FP16(data)   (gst_byte_reader_get_uint16_be_unchecked(data)/256.0)
+#define GET_FOURCC(data)  piff_atom_parser_get_fourcc_unchecked(data)
+
+gboolean
+piffdemux_dump_vmhd (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  if (!piff_atom_parser_has_remaining (data, 4 + 4))
+    return FALSE;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", GET_UINT32 (data));
+  GST_LOG ("%*s  mode/color:    %08x", depth, "", GET_UINT32 (data));
+  return TRUE;
+}
+
+
+gboolean
+piffdemux_dump_mfro (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  if (!piff_atom_parser_has_remaining (data, 4))
+    return FALSE;
+
+  GST_LOG ("%*s  size: %d", depth, "", GET_UINT32 (data));
+  return TRUE;
+}
+
+gboolean
+piffdemux_dump_tfra (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  guint64 time = 0, moof_offset = 0;
+  guint32 len = 0, num_entries = 0, ver_flags = 0, track_id = 0, i;
+  guint value_size, traf_size, trun_size, sample_size;
+
+  if (!gst_byte_reader_get_uint32_be (data, &ver_flags))
+    return FALSE;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
+
+  if (!gst_byte_reader_get_uint32_be (data, &track_id) ||
+      gst_byte_reader_get_uint32_be (data, &len) ||
+      gst_byte_reader_get_uint32_be (data, &num_entries))
+    return FALSE;
+
+  GST_LOG ("%*s  track ID:      %u", depth, "", track_id);
+  GST_LOG ("%*s  length:        0x%x", depth, "", len);
+  GST_LOG ("%*s  n entries:     %u", depth, "", num_entries);
+
+  value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
+  sample_size = (len & 3) + 1;
+  trun_size = ((len & 12) >> 2) + 1;
+  traf_size = ((len & 48) >> 4) + 1;
+
+  if (!piff_atom_parser_has_chunks (data, num_entries,
+          value_size + value_size + traf_size + trun_size + sample_size))
+    return FALSE;
+
+  for (i = 0; i < num_entries; i++) {
+    piff_atom_parser_get_offset (data, value_size, &time);
+    piff_atom_parser_get_offset (data, value_size, &moof_offset);
+    GST_LOG ("%*s    time:          %" G_GUINT64_FORMAT, depth, "", time);
+    GST_LOG ("%*s    moof_offset:   %" G_GUINT64_FORMAT,
+        depth, "", moof_offset);
+    GST_LOG ("%*s    traf_number:   %u", depth, "",
+        piff_atom_parser_get_uint_with_size_unchecked (data, traf_size));
+    GST_LOG ("%*s    trun_number:   %u", depth, "",
+        piff_atom_parser_get_uint_with_size_unchecked (data, trun_size));
+    GST_LOG ("%*s    sample_number: %u", depth, "",
+        piff_atom_parser_get_uint_with_size_unchecked (data, sample_size));
+  }
+
+  return TRUE;
+}
+
+gboolean
+piffdemux_dump_tfhd (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  guint32 flags = 0, n = 0, track_id = 0;
+  guint64 base_data_offset = 0;
+
+  if (!gst_byte_reader_skip (data, 1) ||
+      !gst_byte_reader_get_uint24_be (data, &flags))
+    return FALSE;
+  GST_LOG ("%*s  flags: %08x", depth, "", flags);
+
+  if (!gst_byte_reader_get_uint32_be (data, &track_id))
+    return FALSE;
+  GST_LOG ("%*s  track_id: %u", depth, "", track_id);
+
+  if (flags & TF_BASE_DATA_OFFSET) {
+    if (!gst_byte_reader_get_uint64_be (data, &base_data_offset))
+      return FALSE;
+    GST_LOG ("%*s    base-data-offset: %" G_GUINT64_FORMAT,
+        depth, "", base_data_offset);
+  }
+
+  if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
+    if (!gst_byte_reader_get_uint32_be (data, &n))
+      return FALSE;
+    GST_LOG ("%*s    sample-description-index: %u", depth, "", n);
+  }
+
+  if (flags & TF_DEFAULT_SAMPLE_DURATION) {
+    if (!gst_byte_reader_get_uint32_be (data, &n))
+      return FALSE;
+    GST_LOG ("%*s    default-sample-duration:  %u", depth, "", n);
+  }
+
+  if (flags & TF_DEFAULT_SAMPLE_SIZE) {
+    if (!gst_byte_reader_get_uint32_be (data, &n))
+      return FALSE;
+    GST_LOG ("%*s    default-sample-size:  %u", depth, "", n);
+  }
+
+  if (flags & TF_DEFAULT_SAMPLE_FLAGS) {
+    if (!gst_byte_reader_get_uint32_be (data, &n))
+      return FALSE;
+    GST_LOG ("%*s    default-sample-flags:  %u", depth, "", n);
+  }
+
+  GST_LOG ("%*s    duration-is-empty:     %s", depth, "",
+      flags & TF_DURATION_IS_EMPTY ? "yes" : "no");
+
+  return TRUE;
+}
+
+gboolean
+piffdemux_dump_trun (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  guint32 flags = 0, samples_count = 0, data_offset = 0, first_sample_flags = 0;
+  guint32 sample_duration = 0, sample_size = 0, sample_flags =
+      0, composition_time_offsets = 0;
+  int i = 0;
+
+  if (!gst_byte_reader_skip (data, 1) ||
+      !gst_byte_reader_get_uint24_be (data, &flags))
+    return FALSE;
+
+  GST_LOG ("%*s  flags: %08x", depth, "", flags);
+
+  if (!gst_byte_reader_get_uint32_be (data, &samples_count))
+    return FALSE;
+  GST_LOG ("%*s  samples_count: %u", depth, "", samples_count);
+
+  if (flags & TR_DATA_OFFSET) {
+    if (!gst_byte_reader_get_uint32_be (data, &data_offset))
+      return FALSE;
+    GST_LOG ("%*s    data-offset: %u", depth, "", data_offset);
+  }
+
+  if (flags & TR_FIRST_SAMPLE_FLAGS) {
+    if (!gst_byte_reader_get_uint32_be (data, &first_sample_flags))
+      return FALSE;
+    GST_LOG ("%*s    first-sample-flags: %u", depth, "", first_sample_flags);
+  }
+
+  for (i = 0; i < samples_count; i++) {
+    if (flags & TR_SAMPLE_DURATION) {
+      if (!gst_byte_reader_get_uint32_be (data, &sample_duration))
+        return FALSE;
+      GST_LOG ("%*s    sample-duration:  %u", depth, "", sample_duration);
+    }
+
+    if (flags & TR_SAMPLE_SIZE) {
+      if (!gst_byte_reader_get_uint32_be (data, &sample_size))
+        return FALSE;
+      GST_LOG ("%*s    sample-size:  %u", depth, "", sample_size);
+    }
+
+    if (flags & TR_SAMPLE_FLAGS) {
+      if (!gst_byte_reader_get_uint32_be (data, &sample_flags))
+        return FALSE;
+      GST_LOG ("%*s    sample-flags:  %u", depth, "", sample_flags);
+    }
+
+    if (flags & TR_COMPOSITION_TIME_OFFSETS) {
+      if (!gst_byte_reader_get_uint32_be (data, &composition_time_offsets))
+        return FALSE;
+      GST_LOG ("%*s    composition_time_offsets:  %u", depth, "",
+          composition_time_offsets);
+    }
+  }
+
+  return TRUE;
+}
+
+gboolean
+piffdemux_dump_trex (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  if (!piff_atom_parser_has_remaining (data, 4 + 4 + 4 + 4 + 4 + 4))
+    return FALSE;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", GET_UINT32 (data));
+  GST_LOG ("%*s  track ID:      %08x", depth, "", GET_UINT32 (data));
+  GST_LOG ("%*s  default sample desc. index: %08x", depth, "",
+      GET_UINT32 (data));
+  GST_LOG ("%*s  default sample duration:    %08x", depth, "",
+      GET_UINT32 (data));
+  GST_LOG ("%*s  default sample size:        %08x", depth, "",
+      GET_UINT32 (data));
+  GST_LOG ("%*s  default sample flags:       %08x", depth, "",
+      GET_UINT32 (data));
+
+  return TRUE;
+}
+
+
+gboolean
+piffdemux_dump_sdtp (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  guint32 version;
+  guint8 val;
+  guint i = 1;
+
+  version = GET_UINT32 (data);
+  GST_LOG ("%*s  version/flags: %08x", depth, "", version);
+
+  /* the sample_count is specified in the stsz or stz2 box.
+   * the information for a sample is stored in a single byte,
+   * so we read until there are no remaining bytes */
+  while (piff_atom_parser_has_remaining (data, 1)) {
+    val = GET_UINT8 (data);
+    GST_LOG ("%*s     sample number: %d", depth, "", i);
+    GST_LOG ("%*s     sample_depends_on: %d", depth, "",
+        ((guint16) (val)) & 0x3);
+    GST_LOG ("%*s     sample_is_depended_on: %d", depth, "",
+        ((guint16) (val >> 2)) & 0x3);
+    GST_LOG ("%*s     sample_has_redundancy: %d", depth, "",
+        ((guint16) (val >> 4)) & 0x3);
+    ++i;
+  }
+  return TRUE;
+}
+
+gboolean
+piffdemux_dump_unknown (GstPiffDemux * piffdemux, GstByteReader * data, int depth)
+{
+  int len;
+
+  len = gst_byte_reader_get_remaining (data);
+  GST_LOG ("%*s  length: %d", depth, "", len);
+
+  GST_MEMDUMP_OBJECT (piffdemux, "unknown atom data",
+      gst_byte_reader_peek_data_unchecked (data), len);
+  return TRUE;
+}
+
+static gboolean
+piffdemux_node_dump_foreach (GNode * node, gpointer piffdemux)
+{
+  GstByteReader parser;
+  guint8 *buffer = (guint8 *) node->data;       /* FIXME: move to byte reader */
+  guint32 node_length;
+  guint32 fourcc;
+  const PiffNodeType *type;
+  int depth;
+
+  node_length = GST_READ_UINT32_BE (buffer);
+  fourcc = GST_READ_UINT32_LE (buffer + 4);
+
+  g_warn_if_fail (node_length >= 8);
+
+  gst_byte_reader_init (&parser, buffer + 8, node_length - 8);
+
+  type = piffdemux_type_get (fourcc);
+
+  depth = (g_node_depth (node) - 1) * 2;
+  GST_LOG ("%*s'%" GST_FOURCC_FORMAT "', [%d], %s",
+      depth, "", GST_FOURCC_ARGS (fourcc), node_length, type->name);
+
+  if (type->dump) {
+    gboolean ret;
+
+    ret = type->dump (GST_PIFFDEMUX_CAST (piffdemux), &parser, depth);
+
+    if (!ret) {
+      GST_WARNING ("%*s  not enough data parsing atom %" GST_FOURCC_FORMAT,
+          depth, "", GST_FOURCC_ARGS (fourcc));
+    }
+  }
+
+  return FALSE;
+}
+
+gboolean
+piffdemux_node_dump (GstPiffDemux * piffdemux, GNode * node)
+{
+  if (__gst_debug_min < GST_LEVEL_LOG)
+    return TRUE;
+
+  g_node_traverse (node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+      piffdemux_node_dump_foreach, piffdemux);
+  return TRUE;
+}
diff --git a/piffdemux/src/piffdemux_dump.h b/piffdemux/src/piffdemux_dump.h
new file mode 100755 (executable)
index 0000000..5f34b50
--- /dev/null
@@ -0,0 +1,49 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.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 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_PIFFDEMUX_DUMP_H__
+#define __GST_PIFFDEMUX_DUMP_H__
+
+#include <gst/gst.h>
+#include <piffdemux.h>
+
+G_BEGIN_DECLS
+
+gboolean piffdemux_dump_vmhd (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+gboolean piffdemux_dump_mfro (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+gboolean piffdemux_dump_tfra (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+gboolean piffdemux_dump_tfhd (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+gboolean piffdemux_dump_trun (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+gboolean piffdemux_dump_trex (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+gboolean piffdemux_dump_sdtp (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+gboolean piffdemux_dump_unknown (GstPiffDemux * piffdemux, GstByteReader * data,
+    int depth);
+
+gboolean piffdemux_node_dump (GstPiffDemux * piffdemux, GNode * node);
+
+G_END_DECLS
+#endif /* __GST_PIFFDEMUX_DUMP_H__ */
diff --git a/piffdemux/src/piffdemux_fourcc.h b/piffdemux/src/piffdemux_fourcc.h
new file mode 100755 (executable)
index 0000000..7ce7a7a
--- /dev/null
@@ -0,0 +1,86 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_QTDEMUX_FOURCC_H__
+#define __GST_QTDEMUX_FOURCC_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define FOURCC_vide     GST_MAKE_FOURCC('v','i','d','e')
+#define FOURCC_soun     GST_MAKE_FOURCC('s','o','u','n')
+#define FOURCC_subp     GST_MAKE_FOURCC('s','u','b','p')
+#define FOURCC_hint     GST_MAKE_FOURCC('h','i','n','t')
+#define FOURCC_mp4a     GST_MAKE_FOURCC('m','p','4','a')
+#define FOURCC_mp4v     GST_MAKE_FOURCC('m','p','4','v')
+#define FOURCC_MP4V     GST_MAKE_FOURCC('M','P','4','V')
+#define FOURCC_fmp4     GST_MAKE_FOURCC('f','m','p','4')
+#define FOURCC_FMP4     GST_MAKE_FOURCC('F','M','P','4')
+
+#define FOURCC_meta     GST_MAKE_FOURCC('m','e','t','a')
+
+#define FOURCC_____     GST_MAKE_FOURCC('-','-','-','-')
+
+#define FOURCC_free     GST_MAKE_FOURCC('f','r','e','e')
+
+#define FOURCC_drms     GST_MAKE_FOURCC('d','r','m','s')
+#define FOURCC_drmi     GST_MAKE_FOURCC('d','r','m','i')
+#define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
+#define FOURCC_avcC     GST_MAKE_FOURCC('a','v','c','C')
+
+#define FOURCC_ulaw     GST_MAKE_FOURCC('u','l','a','w')
+#define FOURCC_alaw     GST_MAKE_FOURCC('a','l','a','w')
+
+#define FOURCC_raw_     GST_MAKE_FOURCC('r','a','w',' ')
+
+#define FOURCC_alac     GST_MAKE_FOURCC('a','l','a','c')
+#define FOURCC_samr     GST_MAKE_FOURCC('s','a','m','r')
+#define FOURCC_sawb     GST_MAKE_FOURCC('s','a','w','b')
+#define FOURCC_mdat     GST_MAKE_FOURCC('m','d','a','t')
+#define FOURCC_in24     GST_MAKE_FOURCC('i','n','2','4')
+
+#define FOURCC_text     GST_MAKE_FOURCC('t','e','x','t')
+#define FOURCC_tx3g     GST_MAKE_FOURCC('t','x','3','g')
+#define FOURCC_mp4s     GST_MAKE_FOURCC('m','p','4','s')
+#define FOURCC_uuid     GST_MAKE_FOURCC('u','u','i','d')
+
+/* Fragmented MP4 */
+
+#define FOURCC_mfhd     GST_MAKE_FOURCC('m','f','h','d')
+#define FOURCC_mfra     GST_MAKE_FOURCC('m','f','r','a')
+#define FOURCC_mfro     GST_MAKE_FOURCC('m','f','r','o')
+#define FOURCC_moof     GST_MAKE_FOURCC('m','o','o','f')
+#define FOURCC_mvex     GST_MAKE_FOURCC('m','v','e','x')
+#define FOURCC_sdtp     GST_MAKE_FOURCC('s','d','t','p')
+#define FOURCC_tfhd     GST_MAKE_FOURCC('t','f','h','d')
+#define FOURCC_tfxd     GST_MAKE_FOURCC('t','f','x','d')
+#define FOURCC_tfra     GST_MAKE_FOURCC('t','f','r','a')
+#define FOURCC_traf     GST_MAKE_FOURCC('t','r','a','f')
+#define FOURCC_trex     GST_MAKE_FOURCC('t','r','e','x')
+#define FOURCC_trun     GST_MAKE_FOURCC('t','r','u','n')
+#define FOURCC_ovc1     GST_MAKE_FOURCC('o','v','c','1')
+#define FOURCC_owma     GST_MAKE_FOURCC('o','w','m','a')
+#define FOURCC_uuid     GST_MAKE_FOURCC('u','u','i','d')
+#define FOURCC_tfrf    GST_MAKE_FOURCC('t','f','r','f')
+
+G_END_DECLS
+
+#endif /* __GST_QTDEMUX_FOURCC_H__ */
diff --git a/piffdemux/src/piffdemux_types.c b/piffdemux/src/piffdemux_types.c
new file mode 100755 (executable)
index 0000000..2fa8ea8
--- /dev/null
@@ -0,0 +1,76 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "piffdemux_types.h"
+#include "piffdemux_dump.h"
+#include "piffdemux_fourcc.h"
+
+static const PiffNodeType piff_node_types[] = {
+  {FOURCC_vide, "video media", 0},
+  {FOURCC_hint, "hint", 0,},
+  {FOURCC_mp4a, "mp4a", 0,},
+  {FOURCC_mp4v, "mp4v", 0,},
+  {FOURCC_alac, "alac", 0,},
+  {FOURCC_meta, "meta", 0, piffdemux_dump_unknown},
+  {FOURCC_____, "----", PIFF_FLAG_CONTAINER,},
+  {FOURCC_free, "free", 0,},
+  {FOURCC_mfra, "movie fragment random access",
+      PIFF_FLAG_CONTAINER,},
+  {FOURCC_tfra, "track fragment random access", 0,
+      piffdemux_dump_tfra},
+  {FOURCC_mfro, "movie fragment random access offset", 0,
+      piffdemux_dump_mfro},
+  {FOURCC_moof, "movie fragment", PIFF_FLAG_CONTAINER,},
+  {FOURCC_mfhd, "movie fragment header", 0,},
+  {FOURCC_traf, "track fragment", PIFF_FLAG_CONTAINER,},
+  {FOURCC_tfhd, "track fragment header", 0,
+      piffdemux_dump_tfhd},
+  {FOURCC_sdtp, "independent and disposable samples", 0,
+      piffdemux_dump_sdtp},
+  {FOURCC_trun, "track fragment run", 0, piffdemux_dump_trun},
+  {FOURCC_mdat, "moovie data", 0, piffdemux_dump_unknown},
+  {FOURCC_trex, "moovie data", 0, piffdemux_dump_trex},
+  {FOURCC_mvex, "mvex", PIFF_FLAG_CONTAINER,},
+  {FOURCC_ovc1, "ovc1", 0},
+  {FOURCC_owma, "owma", 0},
+  {FOURCC_tfxd, "tfxd", 0},
+  {FOURCC_tfrf, "tfrf", 0},
+  {FOURCC_uuid, "uuid", 0},
+
+  {0, "unknown", 0,},
+};
+
+static const int n_piff_node_types =
+    sizeof (piff_node_types) / sizeof (piff_node_types[0]);
+
+const PiffNodeType *
+piffdemux_type_get (guint32 fourcc)
+{
+  int i;
+
+  for (i = 0; i < n_piff_node_types; i++) {
+    if (G_UNLIKELY (piff_node_types[i].fourcc == fourcc))
+      return piff_node_types + i;
+  }
+
+  GST_WARNING ("unknown QuickTime node type %" GST_FOURCC_FORMAT,
+      GST_FOURCC_ARGS (fourcc));
+
+  return piff_node_types + n_piff_node_types - 1;
+}
diff --git a/piffdemux/src/piffdemux_types.h b/piffdemux/src/piffdemux_types.h
new file mode 100755 (executable)
index 0000000..2c94887
--- /dev/null
@@ -0,0 +1,67 @@
+
+#ifndef __GST_PIFFDEMUX_TYPES_H__
+#define __GST_PIFFDEMUX_TYPES_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbytereader.h>
+
+#include "piffdemux.h"
+
+G_BEGIN_DECLS
+
+typedef gboolean (*PiffDumpFunc) (GstPiffDemux * piffdemux, GstByteReader * data, int depth);
+
+typedef struct _PiffNodeType PiffNodeType;
+
+#define PIFF_UINT32(a)  (GST_READ_UINT32_BE(a))
+#define PIFF_UINT24(a)  (GST_READ_UINT32_BE(a) >> 8)
+#define PIFF_UINT16(a)  (GST_READ_UINT16_BE(a))
+#define PIFF_UINT8(a)   (GST_READ_UINT8(a))
+#define PIFF_FP32(a)    ((GST_READ_UINT32_BE(a))/65536.0)
+#define PIFF_SFP32(a)   (((gint)(GST_READ_UINT32_BE(a)))/65536.0)
+#define PIFF_FP16(a)    ((GST_READ_UINT16_BE(a))/256.0)
+#define PIFF_FOURCC(a)  (GST_READ_UINT32_LE(a))
+#define PIFF_UINT64(a)  ((((guint64)PIFF_UINT32(a))<<32)|PIFF_UINT32(((guint8 *)a)+4))
+
+typedef enum {
+  PIFF_FLAG_NONE      = (0),
+  PIFF_FLAG_CONTAINER = (1 << 0)
+} PiffFlags;
+
+struct _PiffNodeType {
+  guint32      fourcc;
+  const gchar *name;
+  PiffFlags      flags;
+  PiffDumpFunc   dump;
+};
+
+enum TfFlags
+{
+  TF_BASE_DATA_OFFSET         = 0x000001,   /* base-data-offset-present */
+  TF_SAMPLE_DESCRIPTION_INDEX = 0x000002,   /* sample-description-index-present */
+  TF_DEFAULT_SAMPLE_DURATION  = 0x000008,   /* default-sample-duration-present */
+  TF_DEFAULT_SAMPLE_SIZE      = 0x000010,   /* default-sample-size-present */
+  TF_DEFAULT_SAMPLE_FLAGS     = 0x000020,   /* default-sample-flags-present */
+  TF_DURATION_IS_EMPTY        = 0x100000    /* duration-is-empty */
+};
+
+enum TrFlags
+{
+  TR_DATA_OFFSET              = 0x000001,   /* data-offset-present */
+  TR_FIRST_SAMPLE_FLAGS       = 0x000004,   /* first-sample-flags-present */
+  TR_SAMPLE_DURATION          = 0x000100,   /* sample-duration-present */
+  TR_SAMPLE_SIZE              = 0x000200,   /* sample-size-present */
+  TR_SAMPLE_FLAGS             = 0x000400,   /* sample-flags-present */
+  TR_COMPOSITION_TIME_OFFSETS = 0x000800    /* sample-composition-time-offsets-presents */
+};
+
+enum SEFlags
+{
+  SE_OVERRIDE_TE_FLAGS              = 0x000001,   /* override existing track encryption parameters */
+  SE_USE_SUBSAMPLE_ENCRYPTION       = 0x000002,   /* Use SubSample Encryption */
+};
+const PiffNodeType *piffdemux_type_get (guint32 fourcc);
+
+G_END_DECLS
+
+#endif /* __GST_PIFFDEMUX_TYPES_H__ */
diff --git a/piffdemux/src/piffpalette.h b/piffdemux/src/piffpalette.h
new file mode 100755 (executable)
index 0000000..d3b4552
--- /dev/null
@@ -0,0 +1,137 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_PIFFPALLETE_H__
+#define __GST_PIFFPALLETE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+static const guint32 ff_piff_default_palette_2[2] = {
+  0xffffff, 0x000000
+};
+
+static const guint32 ff_piff_default_palette_4[4] = {
+  0x93655e, 0xffffff, 0xdfd0ab, 0x000000
+};
+
+static const guint32 ff_piff_default_palette_16[16] = {
+  0xfffbff, 0xefd9bb, 0xe8c9b1, 0x93655e,
+  0xfcdee8, 0x9d8891, 0xffffff, 0xffffff,
+  0xffffff, 0x474837, 0x7a5e55, 0xdfd0ab,
+  0xfffbf9, 0xe8cac5, 0x8a7c77, 0x000000
+};
+static const guint32 ff_piff_default_palette_256[256] = {
+  0xFFFFFF, 0xFFFFCC, 0xFFFF99, 0xFFFF66, 0xFFFF33, 0xFFFF00,
+  0xFFCCFF, 0xFFCCCC, 0xFFCC99, 0xFFCC66, 0xFFCC33, 0xFFCC00,
+  0xFF99FF, 0xFF99CC, 0xFF9999, 0xFF9966, 0xFF9933, 0xFF9900,
+  0xFF66FF, 0xFF66CC, 0xFF6699, 0xFF6666, 0xFF6633, 0xFF6600,
+  0xFF33FF, 0xFF33CC, 0xFF3399, 0xFF3366, 0xFF3333, 0xFF3300,
+  0xFF00FF, 0xFF00CC, 0xFF0099, 0xFF0066, 0xFF0033, 0xFF0000,
+  0xCCFFFF, 0xCCFFCC, 0xCCFF99, 0xCCFF66, 0xCCFF33, 0xCCFF00,
+  0xCCCCFF, 0xCCCCCC, 0xCCCC99, 0xCCCC66, 0xCCCC33, 0xCCCC00,
+  0xCC99FF, 0xCC99CC, 0xCC9999, 0xCC9966, 0xCC9933, 0xCC9900,
+  0xCC66FF, 0xCC66CC, 0xCC6699, 0xCC6666, 0xCC6633, 0xCC6600,
+  0xCC33FF, 0xCC33CC, 0xCC3399, 0xCC3366, 0xCC3333, 0xCC3300,
+  0xCC00FF, 0xCC00CC, 0xCC0099, 0xCC0066, 0xCC0033, 0xCC0000,
+  0x99FFFF, 0x99FFCC, 0x99FF99, 0x99FF66, 0x99FF33, 0x99FF00,
+  0x99CCFF, 0x99CCCC, 0x99CC99, 0x99CC66, 0x99CC33, 0x99CC00,
+  0x9999FF, 0x9999CC, 0x999999, 0x999966, 0x999933, 0x999900,
+  0x9966FF, 0x9966CC, 0x996699, 0x996666, 0x996633, 0x996600,
+  0x9933FF, 0x9933CC, 0x993399, 0x993366, 0x993333, 0x993300,
+  0x9900FF, 0x9900CC, 0x990099, 0x990066, 0x990033, 0x990000,
+  0x66FFFF, 0x66FFCC, 0x66FF99, 0x66FF66, 0x66FF33, 0x66FF00,
+  0x66CCFF, 0x66CCCC, 0x66CC99, 0x66CC66, 0x66CC33, 0x66CC00,
+  0x6699FF, 0x6699CC, 0x669999, 0x669966, 0x669933, 0x669900,
+  0x6666FF, 0x6666CC, 0x666699, 0x666666, 0x666633, 0x666600,
+  0x6633FF, 0x6633CC, 0x663399, 0x663366, 0x663333, 0x663300,
+  0x6600FF, 0x6600CC, 0x660099, 0x660066, 0x660033, 0x660000,
+  0x33FFFF, 0x33FFCC, 0x33FF99, 0x33FF66, 0x33FF33, 0x33FF00,
+  0x33CCFF, 0x33CCCC, 0x33CC99, 0x33CC66, 0x33CC33, 0x33CC00,
+  0x3399FF, 0x3399CC, 0x339999, 0x339966, 0x339933, 0x339900,
+  0x3366FF, 0x3366CC, 0x336699, 0x336666, 0x336633, 0x336600,
+  0x3333FF, 0x3333CC, 0x333399, 0x333366, 0x333333, 0x333300,
+  0x3300FF, 0x3300CC, 0x330099, 0x330066, 0x330033, 0x330000,
+  0x00FFFF, 0x00FFCC, 0x00FF99, 0x00FF66, 0x00FF33, 0x00FF00,
+  0x00CCFF, 0x00CCCC, 0x00CC99, 0x00CC66, 0x00CC33, 0x00CC00,
+  0x0099FF, 0x0099CC, 0x009999, 0x009966, 0x009933, 0x009900,
+  0x0066FF, 0x0066CC, 0x006699, 0x006666, 0x006633, 0x006600,
+  0x0033FF, 0x0033CC, 0x003399, 0x003366, 0x003333, 0x003300,
+  0x0000FF, 0x0000CC, 0x000099, 0x000066, 0x000033, 0xEE0000,
+  0xDD0000, 0xBB0000, 0xAA0000, 0x880000, 0x770000, 0x550000,
+  0x440000, 0x220000, 0x110000, 0x00EE00, 0x00DD00, 0x00BB00,
+  0x00AA00, 0x008800, 0x007700, 0x005500, 0x004400, 0x002200,
+  0x001100, 0x0000EE, 0x0000DD, 0x0000BB, 0x0000AA, 0x000088,
+  0x000077, 0x000055, 0x000044, 0x000022, 0x000011, 0xEEEEEE,
+  0xDDDDDD, 0xBBBBBB, 0xAAAAAA, 0x888888, 0x777777, 0x555555,
+  0x444444, 0x222222, 0x111111, 0x000000
+};
+
+static const guint32 ff_piff_grayscale_palette_16[16] = {
+  0xffffff, 0xeeeeee, 0xdddddd, 0xcccccc,
+  0xbbbbbb, 0xaaaaaa, 0x999999, 0x888888,
+  0x777777, 0x666666, 0x555555, 0x444444,
+  0x333333, 0x222222, 0x111111, 0x000000
+};
+
+static const guint32 ff_piff_grayscale_palette_256[256] = {
+  0xffffff, 0xfefefe, 0xfdfdfd, 0xfcfcfc, 0xfbfbfb, 0xfafafa, 0xf9f9f9,
+  0xf8f8f8, 0xf7f7f7, 0xf6f6f6, 0xf5f5f5, 0xf4f4f4, 0xf3f3f3, 0xf2f2f2,
+  0xf1f1f1, 0xf0f0f0, 0xefefef, 0xeeeeee, 0xededed, 0xececec, 0xebebeb,
+  0xeaeaea, 0xe9e9e9, 0xe8e8e8, 0xe7e7e7, 0xe6e6e6, 0xe5e5e5, 0xe4e4e4,
+  0xe3e3e3, 0xe2e2e2, 0xe1e1e1, 0xe0e0e0, 0xdfdfdf, 0xdedede, 0xdddddd,
+  0xdcdcdc, 0xdbdbdb, 0xdadada, 0xd9d9d9, 0xd8d8d8, 0xd7d7d7, 0xd6d6d6,
+  0xd5d5d5, 0xd4d4d4, 0xd3d3d3, 0xd2d2d2, 0xd1d1d1, 0xd0d0d0, 0xcfcfcf,
+  0xcecece, 0xcdcdcd, 0xcccccc, 0xcbcbcb, 0xcacaca, 0xc9c9c9, 0xc8c8c8,
+  0xc7c7c7, 0xc6c6c6, 0xc5c5c5, 0xc4c4c4, 0xc3c3c3, 0xc2c2c2, 0xc1c1c1,
+  0xc0c0c0, 0xbfbfbf, 0xbebebe, 0xbdbdbd, 0xbcbcbc, 0xbbbbbb, 0xbababa,
+  0xb9b9b9, 0xb8b8b8, 0xb7b7b7, 0xb6b6b6, 0xb5b5b5, 0xb4b4b4, 0xb3b3b3,
+  0xb2b2b2, 0xb1b1b1, 0xb0b0b0, 0xafafaf, 0xaeaeae, 0xadadad, 0xacacac,
+  0xababab, 0xaaaaaa, 0xa9a9a9, 0xa8a8a8, 0xa7a7a7, 0xa6a6a6, 0xa5a5a5,
+  0xa4a4a4, 0xa3a3a3, 0xa2a2a2, 0xa1a1a1, 0xa0a0a0, 0x9f9f9f, 0x9e9e9e,
+  0x9d9d9d, 0x9c9c9c, 0x9b9b9b, 0x9a9a9a, 0x999999, 0x989898, 0x979797,
+  0x969696, 0x959595, 0x949494, 0x939393, 0x929292, 0x919191, 0x909090,
+  0x8f8f8f, 0x8e8e8e, 0x8d8d8d, 0x8c8c8c, 0x8b8b8b, 0x8a8a8a, 0x898989,
+  0x888888, 0x878787, 0x868686, 0x858585, 0x848484, 0x838383, 0x828282,
+  0x818181, 0x808080, 0x7f7f7f, 0x7e7e7e, 0x7d7d7d, 0x7c7c7c, 0x7b7b7b,
+  0x7a7a7a, 0x797979, 0x787878, 0x777777, 0x767676, 0x757575, 0x747474,
+  0x737373, 0x727272, 0x717171, 0x707070, 0x6f6f6f, 0x6e6e6e, 0x6d6d6d,
+  0x6c6c6c, 0x6b6b6b, 0x6a6a6a, 0x696969, 0x686868, 0x676767, 0x666666,
+  0x656565, 0x646464, 0x636363, 0x626262, 0x616161, 0x606060, 0x5f5f5f,
+  0x5e5e5e, 0x5d5d5d, 0x5c5c5c, 0x5b5b5b, 0x5a5a5a, 0x595959, 0x585858,
+  0x575757, 0x565656, 0x555555, 0x545454, 0x535353, 0x525252, 0x515151,
+  0x505050, 0x4f4f4f, 0x4e4e4e, 0x4d4d4d, 0x4c4c4c, 0x4b4b4b, 0x4a4a4a,
+  0x494949, 0x484848, 0x474747, 0x464646, 0x454545, 0x444444, 0x434343,
+  0x424242, 0x414141, 0x404040, 0x3f3f3f, 0x3e3e3e, 0x3d3d3d, 0x3c3c3c,
+  0x3b3b3b, 0x3a3a3a, 0x393939, 0x383838, 0x373737, 0x363636, 0x353535,
+  0x343434, 0x333333, 0x323232, 0x313131, 0x303030, 0x2f2f2f, 0x2e2e2e,
+  0x2d2d2d, 0x2c2c2c, 0x2b2b2b, 0x2a2a2a, 0x292929, 0x282828, 0x272727,
+  0x262626, 0x252525, 0x242424, 0x232323, 0x222222, 0x212121, 0x202020,
+  0x1f1f1f, 0x1e1e1e, 0x1d1d1d, 0x1c1c1c, 0x1b1b1b, 0x1a1a1a, 0x191919,
+  0x181818, 0x171717, 0x161616, 0x151515, 0x141414, 0x131313, 0x121212,
+  0x111111, 0x101010, 0x0f0f0f, 0x0e0e0e, 0x0d0d0d, 0x0c0c0c, 0x0b0b0b,
+  0x0a0a0a, 0x090909, 0x080808, 0x070707, 0x060606, 0x050505, 0x040404,
+  0x030303, 0x020202, 0x010101, 0x000000
+};
+
+G_END_DECLS
+
+#endif /* __GST_PIFFPALETTE_H__ */
diff --git a/ssdemux/Makefile.am b/ssdemux/Makefile.am
new file mode 100755 (executable)
index 0000000..308a09c
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src\r
diff --git a/ssdemux/src/Makefile.am b/ssdemux/src/Makefile.am
new file mode 100755 (executable)
index 0000000..5647e01
--- /dev/null
@@ -0,0 +1,26 @@
+# plugindir is set in configure
+
+##############################################################################
+# change libgstplugin.la to something more suitable, e.g. libmysomething.la  #
+##############################################################################
+plugin_LTLIBRARIES = libgstssdemux.la
+
+##############################################################################
+# for the next set of variables, rename the prefix if you renamed the .la,   #
+#  e.g. libgstplugin_la_SOURCES => libmysomething_la_SOURCES                 #
+#       libgstplugin_la_CFLAGS  => libmysomething_la_CFLAGS                  #
+#       libgstplugin_la_LIBADD  => libmysomething_la_LIBADD                  #
+#       libgstplugin_la_LDFLAGS => libmysomething_la_LDFLAGS                 #
+##############################################################################
+
+# sources used to compile this plug-in
+libgstssdemux_la_SOURCES = gstssdemux.c ssmanifestparse.c
+
+# flags used to compile this plugin
+# add other _CFLAGS and _LIBS as needed
+libgstssdemux_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(SOUP_CFLAGS) $(XML2_CFLAGS) $(GST_APP_CFLAGS) -I$(srcdir)/../../piffdemux/src
+libgstssdemux_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(SOUP_LIBS) $(XML2_LIBS) $(GST_APP_LIBS) -lgstapp-0.10
+libgstssdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+# headers we need but don't want installed
+noinst_HEADERS = gstssdemux.h ssmanifestparse.h
diff --git a/ssdemux/src/gstssdemux.c b/ssdemux/src/gstssdemux.c
new file mode 100755 (executable)
index 0000000..6bec15f
--- /dev/null
@@ -0,0 +1,1235 @@
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
+#include <string.h>
+//#include <gst/glib-compat-private.h>
+#include "gstssdemux.h"
+
+enum
+{
+  PROP_0,
+  PROP_COOKIES,
+  PROP_ALLOW_AUDIO_ONLY,
+  PROP_FRAGMENTS_CACHE,
+  PROP_BITRATE_SWITCH_TOLERANCE,
+  PROP_LAST
+};
+
+static GstStaticPadTemplate ssdemux_videosrc_template =
+GST_STATIC_PAD_TEMPLATE ("video",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate ssdemux_audiosrc_template =
+GST_STATIC_PAD_TEMPLATE ("audio",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate ssdemux_subsrc_template =
+GST_STATIC_PAD_TEMPLATE ("subtitle",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate ssdemux_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-ss")); // Need to decide source mimetype
+
+GST_DEBUG_CATEGORY_STATIC (gst_ss_demux_debug);
+#define GST_CAT_DEFAULT gst_ss_demux_debug
+
+#undef SIMULATE_AUDIO_ONLY /* enable to simulate audio only case forcibly */
+
+static void
+_do_init (GType type)
+{
+  GST_DEBUG_CATEGORY_INIT (gst_ss_demux_debug, "ssdemux", 0,
+      "ssdemux element");
+}
+
+GST_BOILERPLATE_FULL (GstSSDemux, gst_ss_demux, GstElement,
+    GST_TYPE_ELEMENT, _do_init);
+
+#define DEFAULT_FRAGMENTS_CACHE 0
+#define DEFAULT_BITRATE_SWITCH_TOLERANCE 0.4
+
+struct _GstSSDemuxStream
+{
+  /* Streaming task */
+  void *parent;
+  GstPad *pad;
+  gchar *name;
+  SS_STREAM_TYPE type;
+  GstTask *stream_task;
+  GStaticRecMutex stream_lock;
+  GstElement *pipe;
+  GstElement *urisrc;
+  GstElement *parser;
+  GstElement *sink;
+  GstBus *bus;
+  GMutex *lock;
+  GCond *cond;
+  guint frag_cnt;
+  GQueue *queue;
+  gchar *uri;
+  guint64 start_ts;
+  gboolean sent_ns;
+  GstCaps *caps;
+  guint64 switch_ts;
+  guint64 avg_dur;
+};
+
+static void gst_ss_demux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_ss_demux_get_property (GObject * object, guint prop_id,
+       GValue * value, GParamSpec * pspec);
+static gboolean gst_ss_demux_sink_event (GstPad * pad, GstEvent * event);
+static GstStateChangeReturn gst_ss_demux_change_state (GstElement * element, GstStateChange transition);
+static void gst_ss_demux_dispose (GObject * obj);
+static GstFlowReturn gst_ss_demux_chain (GstPad * pad, GstBuffer * buf);
+static void gst_ss_demux_stream_loop (GstSSDemux * demux);
+static gboolean gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data);
+static void gst_ss_demux_stream_init (GstSSDemux *demux, GstSSDemuxStream *stream, SS_STREAM_TYPE stream_type);
+static void gst_ss_demux_stream_free (GstSSDemux * demux, GstSSDemuxStream * stream);
+static void gst_ssm_demux_on_new_buffer (GstElement * appsink, void* data);
+static gboolean gst_ss_demux_download_fragment (GstSSDemux *demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts);
+static gboolean gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts);
+static void gst_ss_demux_stop (GstSSDemux * demux, GstSSDemuxStream *stream);
+static gboolean gst_ss_demux_create_dummy_pipe (GstSSDemux * demux, GstSSDemuxStream *stream);
+static gboolean gst_ss_demux_create_dummy_sender(GstSSDemux *demux, GstSSDemuxStream *stream);
+
+static void
+gst_ss_demux_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&ssdemux_videosrc_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&ssdemux_audiosrc_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&ssdemux_subsrc_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&ssdemux_sink_template));
+
+  gst_element_class_set_details_simple (element_class,
+      "SS Demuxer",
+      "Demuxer/URIList",
+      "Smooth Streaming demuxer",
+      "Naveen Cherukuri<naveen.ch@samsung.com>");
+}
+
+static void
+gst_ss_demux_class_init (GstSSDemuxClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = gst_ss_demux_set_property;
+  gobject_class->get_property = gst_ss_demux_get_property;
+  gobject_class->dispose = gst_ss_demux_dispose;
+
+  /* to share cookies with other sessions */
+  g_object_class_install_property (gobject_class, PROP_COOKIES,
+      g_param_spec_boxed ("cookies", "Cookies", "HTTP request cookies",
+          G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /* will be considered only in LIVE case */
+  g_object_class_install_property (gobject_class, PROP_ALLOW_AUDIO_ONLY,
+      g_param_spec_boolean ("allow-audio-only", "Allow audio only when downloadrate is less in live case",
+          "Allow audio only stream download in live case when download rate is less",
+          TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /* no.of fragments to cache */
+  g_object_class_install_property (gobject_class, PROP_FRAGMENTS_CACHE,
+      g_param_spec_uint ("fragments-cache", "Fragments cache",
+          "Number of fragments needed to be cached to start playing",
+          0, G_MAXUINT, DEFAULT_FRAGMENTS_CACHE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_BITRATE_SWITCH_TOLERANCE,
+      g_param_spec_float ("bitrate-switch-tolerance",
+          "Bitrate switch tolerance",
+          "Tolerance with respect of the fragment duration to switch to "
+          "a different bitrate if the client is too slow/fast.",
+          0, 1, DEFAULT_BITRATE_SWITCH_TOLERANCE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_ss_demux_change_state);
+}
+
+static void
+gst_ss_demux_init (GstSSDemux * demux, GstSSDemuxClass * klass)
+{
+  /* sink pad */
+  demux->sinkpad = gst_pad_new_from_static_template (&ssdemux_sink_template, "sink");
+  gst_pad_set_chain_function (demux->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_ss_demux_chain));
+  gst_pad_set_event_function (demux->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_ss_demux_sink_event));
+  gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
+
+  demux->need_cache = TRUE;
+  demux->fragments_cache = DEFAULT_FRAGMENTS_CACHE;
+  demux->cancelled = FALSE;
+  demux->cookies = NULL;
+  demux->ss_mode = SS_MODE_NO_SWITCH;
+  demux->switch_eos = FALSE;
+}
+
+static void
+gst_ss_demux_dispose (GObject * obj)
+{
+  GstSSDemux *demux = GST_SS_DEMUX (obj);
+  int n =0;
+
+  for (n = 0; n < SS_STREAM_NUM; n++) {
+    if (demux->streams[n]) {
+      gst_ss_demux_stream_free (demux, demux->streams[n]);
+      demux->streams[n] = NULL;
+    }
+  }
+
+  if (demux->parser) {
+    gst_ssm_parse_free (demux->parser);
+    demux->parser = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+gst_ss_demux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstSSDemux *demux = GST_SS_DEMUX (object);
+
+  switch (prop_id) {
+     case PROP_COOKIES:
+      g_strfreev (demux->cookies);
+      demux->cookies = g_strdupv (g_value_get_boxed (value));
+      break;
+    case PROP_ALLOW_AUDIO_ONLY:
+      demux->allow_audio_only = g_value_get_boolean (value);
+      break;
+    case PROP_FRAGMENTS_CACHE:
+      demux->fragments_cache = g_value_get_uint (value);
+      break;
+    case PROP_BITRATE_SWITCH_TOLERANCE:
+      demux->bitrate_switch_tol = g_value_get_float (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_ss_demux_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstSSDemux *demux = GST_SS_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_COOKIES:
+      g_value_set_boxed (value, g_strdupv (demux->cookies));
+      break;
+    case PROP_ALLOW_AUDIO_ONLY:
+      g_value_set_boolean (value, demux->allow_audio_only);
+      break;
+    case PROP_FRAGMENTS_CACHE:
+      g_value_set_uint (value, demux->fragments_cache);
+      break;
+    case PROP_BITRATE_SWITCH_TOLERANCE:
+      g_value_set_float (value, demux->bitrate_switch_tol);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_ss_demux_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstSSDemux *demux = GST_SS_DEMUX (gst_pad_get_parent (pad));
+  GstQuery *query;
+  gboolean ret;
+  gchar *uri;
+
+  switch (event->type) {
+    case GST_EVENT_EOS: {
+      int i = 0;
+      if (demux->manifest == NULL) {
+        GST_WARNING_OBJECT (demux, "Received EOS without a manifest.");
+        break;
+      }
+
+      GST_DEBUG_OBJECT (demux, "Got EOS on the sink pad: mainifest file fetched");
+
+      query = gst_query_new_uri ();
+      ret = gst_pad_peer_query (demux->sinkpad, query);
+      if (ret) {
+        gst_query_parse_uri (query, &uri);
+        demux->parser = gst_ssm_parse_new (uri);
+        g_free (uri);
+      } else {
+        GST_ERROR_OBJECT (demux, "failed to query URI from upstream");
+        return FALSE;
+      }
+      gst_query_unref (query);
+
+      GST_LOG_OBJECT (demux, "data = %p & size = %d", GST_BUFFER_DATA(demux->manifest), GST_BUFFER_SIZE(demux->manifest));
+      if (!gst_ssm_parse_manifest (demux->parser, (char *)GST_BUFFER_DATA(demux->manifest), GST_BUFFER_SIZE(demux->manifest))) {
+        /* In most cases, this will happen if we set a wrong url in the
+         * source element and we have received the 404 HTML response instead of
+         * the playlist */
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."),
+            (NULL));
+        return FALSE;
+      }
+
+      for( i = 0; i < SS_STREAM_NUM; i++) {
+        if (gst_ssm_parse_check_stream (demux->parser, i)) {
+          GstSSDemuxStream *stream = g_new0 (GstSSDemuxStream, 1);
+
+          // Add pad emission of the stream
+          gst_ss_demux_stream_init (demux, stream, i);
+          g_static_rec_mutex_init (&stream->stream_lock);
+          stream->stream_task = gst_task_create ((GstTaskFunction) gst_ss_demux_stream_loop, demux);
+          gst_task_set_lock (stream->stream_task, &stream->stream_lock);
+          demux->streams[i] = stream;
+          g_print ("Starting stream - %d task loop...\n", i);
+          gst_task_start (stream->stream_task);
+        }
+      }
+
+      gst_event_unref (event);
+      return TRUE;
+    }
+    case GST_EVENT_NEWSEGMENT:
+      /* Swallow newsegments, we'll push our own */
+      gst_event_unref (event);
+      return TRUE;
+    default:
+      break;
+  }
+
+  return gst_pad_event_default (pad, event);
+}
+
+static gboolean
+gst_ss_demux_handle_src_query (GstPad * pad, GstQuery * query)
+{
+  gboolean res = FALSE;
+  GstSSDemux *ssdemux = GST_SS_DEMUX (gst_pad_get_parent (pad));
+
+  GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
+
+  // TODO: need to add other query types as well
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_DURATION:{
+      GstFormat fmt;
+
+      gst_query_parse_duration (query, &fmt, NULL);
+      if (fmt == GST_FORMAT_TIME) {
+        gint64 duration = -1;
+
+        duration = gst_util_uint64_scale (GST_SSM_PARSE_GET_DURATION(ssdemux->parser), GST_SECOND,
+               GST_SSM_PARSE_GET_TIMESCALE(ssdemux->parser));
+        if (duration > 0) {
+          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+          res = TRUE;
+        }
+      }
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, query);
+      break;
+  }
+
+  gst_object_unref (ssdemux);
+
+  return res;
+}
+
+
+static gboolean
+gst_ss_demux_handle_src_event (GstPad * pad, GstEvent * event)
+{
+  GstSSDemux *demux = GST_SS_DEMUX (gst_pad_get_parent (pad));
+
+  switch (event->type) {
+    case GST_EVENT_SEEK:
+    {
+      gdouble rate;
+      GstFormat format;
+      GstSeekFlags flags;
+      GstSeekType start_type, stop_type;
+      gint64 start, stop;
+      gint i = 0;
+      GstSSDemuxStream *stream = NULL;
+
+      GST_INFO_OBJECT (demux, "Received GST_EVENT_SEEK");
+
+      // TODO: should be able to seek in DVR window
+      if (GST_SSM_PARSE_IS_LIVE_PRESENTATION (demux->parser)) {
+        GST_WARNING_OBJECT (demux, "Received seek event for live stream");
+        return FALSE;
+      }
+
+      gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
+          &stop_type, &stop);
+
+      if (format != GST_FORMAT_TIME) {
+        GST_WARNING_OBJECT (demux, "Only time format is supported in seek");
+        return FALSE;
+      }
+
+      GST_DEBUG_OBJECT (demux, "seek event, rate: %f start: %" GST_TIME_FORMAT
+          " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
+          GST_TIME_ARGS (stop));
+
+
+      for( i = 0; i < SS_STREAM_NUM; i++) {
+        if (stream = demux->streams[i]) {
+          g_cond_signal (stream->cond);
+          gst_task_stop (stream->stream_task);
+        }
+      }
+
+      if (flags & GST_SEEK_FLAG_FLUSH) {
+        GST_INFO_OBJECT (demux, "sending flush start");
+
+        for( i = 0; i < SS_STREAM_NUM; i++) {
+          if (stream = demux->streams[i]) {
+            gst_pad_push_event (stream->pad, gst_event_new_flush_start ());
+          }
+        }
+      }
+
+      gst_ssm_parse_seek_manifest (demux->parser, start);
+
+      if (flags & GST_SEEK_FLAG_FLUSH) {
+        GST_INFO_OBJECT (demux, "sending flush stop");
+        for( i = 0; i < SS_STREAM_NUM; i++) {
+          if (stream = demux->streams[i]) {
+            gst_pad_push_event (stream->pad, gst_event_new_flush_stop ());
+            GST_LOG_OBJECT (stream->pad, "Starting pad TASK again...\n");
+            stream->sent_ns = FALSE;
+            stream->frag_cnt = 0; /*resetting to start buffering on SEEK */
+            gst_task_start (stream->stream_task);
+          }
+        }
+      }
+
+      return TRUE;
+    }
+    default:
+      break;
+  }
+
+  return gst_pad_event_default (pad, event);
+}
+
+static GstStateChangeReturn
+gst_ss_demux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      break;
+    default:
+      break;
+  }
+  return ret;
+}
+
+
+static GstFlowReturn
+gst_ss_demux_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstSSDemux *demux = GST_SS_DEMUX (gst_pad_get_parent (pad));
+
+  if (demux->manifest == NULL)
+    demux->manifest = buf;
+  else
+    demux->manifest = gst_buffer_join (demux->manifest, buf);
+  gst_object_unref (demux);
+
+  return GST_FLOW_OK;
+}
+
+
+static gboolean
+gst_ss_demux_get_next_fragment (GstSSDemux * demux, SS_STREAM_TYPE stream_type)
+{
+  GstSSDemuxStream *stream = demux->streams[stream_type];
+  gchar *next_fragment_uri = NULL;
+  guint64 start_ts = 0;
+
+  if (!gst_ssm_parse_get_next_fragment_url (demux->parser, stream_type, &next_fragment_uri, &start_ts )) {
+    GST_INFO_OBJECT (demux, "This Manifest does not contain more fragments");
+    goto end_of_list;
+  }
+
+  GST_ERROR_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);
+
+  stream->uri = g_strdup(next_fragment_uri);
+  stream->start_ts = start_ts;
+
+  if (!gst_ss_demux_download_fragment (demux, stream, next_fragment_uri, start_ts)) {
+    GST_ERROR_OBJECT (demux, "failed to download fragment...");
+    goto error;
+  }
+
+  return TRUE;
+
+error:
+  {
+    gst_ss_demux_stop (demux, stream);
+    return FALSE;
+  }
+end_of_list:
+  {
+    GST_INFO_OBJECT (demux, "Reached end of playlist, sending EOS");
+    gst_pad_push_event (stream->pad, gst_event_new_eos ());
+    gst_ss_demux_stop (demux, stream);
+    return TRUE;
+  }
+}
+
+static void
+gst_ss_demux_stream_loop (GstSSDemux * demux)
+{
+  GThread *self = NULL;
+  int stream_type = 0;
+  GstSSDemuxStream *stream = NULL;
+
+  self = g_thread_self ();
+
+  for (stream_type = 0; stream_type < SS_STREAM_NUM; stream_type++) {
+    if (demux->streams[stream_type]->stream_task->abidata.ABI.thread == self) {
+      stream = demux->streams[stream_type];
+      break;
+    }
+  }
+
+  /* download next fragment of stream_type */
+  if (!gst_ss_demux_get_next_fragment (demux, stream_type)) {
+    GST_ERROR_OBJECT (demux, "failed to get next fragment...");
+    goto error;
+  }
+
+  return;
+
+error:
+  {
+    gst_task_pause (stream->stream_task);
+    GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
+          ("could not download fragments"), (NULL));
+      gst_ss_demux_stop (demux, stream);
+    return;
+  }
+}
+
+static gboolean
+gst_ss_demux_download_fragment (GstSSDemux *demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts)
+{
+  GstStateChangeReturn ret;
+
+  g_print ("Going to download fragment : %s\n", uri);
+  if (!gst_ss_demux_create_download_pipe (demux, stream, uri, start_ts)) {
+    GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+    return FALSE;
+  }
+
+  ret = gst_element_set_state (stream->pipe, GST_STATE_PLAYING);
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    GST_ERROR_OBJECT (demux, "set_state failed...");
+    return FALSE;
+  }
+
+  if (stream->pipe && demux->ss_mode == SS_MODE_AONLY &&
+    stream->type == SS_STREAM_VIDEO) {
+
+    GST_DEBUG_OBJECT (demux, "Waiting to fetch the URI");
+    g_mutex_lock (stream->lock);
+    g_cond_wait (stream->cond, stream->lock);
+    GST_INFO_OBJECT (stream->pad, "Recived signal to shutdown...");
+    g_mutex_unlock (stream->lock);
+
+    /* put live pipeline to PAUSED state to unlink urisrc & piffdemux */
+    gst_element_set_state (stream->pipe, GST_STATE_NULL);
+    gst_element_get_state (stream->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+
+    stream->pipe = NULL;
+
+    stream->switch_ts = stream->start_ts;
+
+    /* create dummy frame sender */
+    if (!gst_ss_demux_create_dummy_sender (demux, stream)) {
+      GST_ERROR_OBJECT (demux, "failed to create dummy sender pipeline...");
+      GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("Unable to create dummy pipe."), (NULL));
+      return FALSE;
+    }
+  }
+
+  /* wait until:
+   *   - the download succeed (EOS)
+   *   - the download failed (Error message on the fetcher bus)
+   *   - the download was canceled
+   */
+  GST_DEBUG_OBJECT (demux, "Waiting to fetch the URI");
+  g_mutex_lock (stream->lock);
+  g_cond_wait (stream->cond, stream->lock);
+  GST_INFO_OBJECT (stream->pad, "Recived signal to shutdown...");
+  g_mutex_unlock (stream->lock);
+
+  gst_element_set_state (stream->pipe, GST_STATE_NULL);
+  gst_element_get_state (stream->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+  stream->pipe = NULL;
+
+  return TRUE;
+}
+
+static gboolean
+gst_ss_demux_create_dummy_sender(GstSSDemux *demux, GstSSDemuxStream *stream)
+{
+  GstStateChangeReturn ret;
+
+  if (!gst_ss_demux_create_dummy_pipe (demux, stream)) {
+    GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+    return FALSE;
+  }
+
+  ret = gst_element_set_state (stream->pipe, GST_STATE_PLAYING);
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    GST_ERROR_OBJECT (demux, "set_state failed...");
+    return FALSE;
+  }
+
+#if 0
+  GST_DEBUG_OBJECT (demux, "Waiting to download next video URI");
+  g_mutex_lock (stream->lock);
+  g_cond_wait (stream->cond, stream->lock);
+  if (stream->pipe) {
+    gst_element_set_state (stream->pipe, GST_STATE_NULL);
+    gst_element_get_state (stream->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+    stream->pipe = NULL;
+  }
+  g_mutex_unlock (stream->lock);
+#endif
+
+  return TRUE;
+}
+
+static void
+gst_ss_demux_append_live_params(GstElement *piffparser, piff_live_param_t *param, gpointer data)
+{
+  GstSSDemuxStream *stream = (GstSSDemuxStream *)data;
+  GstSSDemux *demux = stream->parent;
+  int i =0;
+  guint64 timestamp = 0;
+  guint64 duration = 0;
+
+  GST_LOG_OBJECT (demux, "received signal structs count = %d\n", param->count);
+
+  for (i = 0 ; i< param->count; i++) {
+    if (param->long_info) {
+      piff_fragment_longtime_info *info = &(param->long_info[i]);
+      timestamp = info->ts;
+      duration = info->duration;
+    } else if (param->info) {
+      piff_fragment_time_info *info = &(param->info[i]);
+      timestamp = info->ts;
+      duration = info->duration;
+    }
+
+    GST_LOG_OBJECT (demux, "Received ts = %llu and dur = %llu\n", timestamp, duration);
+
+    if (!gst_ssm_parse_append_next_fragment (demux->parser, stream->type, timestamp, duration)) {
+      GST_ERROR_OBJECT (demux, "failed to append new fragment");
+      GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("fragment allocation failed..."), (NULL));
+      return;
+    }
+  }
+
+  if (param->long_info) {
+    free (param->long_info);
+    param->long_info = NULL;
+  }
+
+  if (param->info) {
+    free (param->info);
+    param->info = NULL;
+  }
+
+  free (param);
+
+  if ((stream->type == SS_STREAM_VIDEO) && (demux->ss_mode == SS_MODE_AONLY)) {
+    g_print ("\n\n\t\tSignalling download pipe shutdonw....\n\n");
+
+    g_object_get (stream->parser, "frame-dur", &stream->avg_dur, NULL);
+    g_print ("frame duration = %"GST_TIME_FORMAT"\n\n\n", GST_TIME_ARGS(stream->avg_dur));
+    g_cond_signal (stream->cond);
+  }
+
+}
+
+static gboolean
+gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts)
+{
+  gchar *name = NULL;
+  GstCaps *caps = NULL;
+
+  if (!gst_uri_is_valid (uri))
+    return FALSE;
+
+  name = g_strdup_printf("%s-%s", stream->name, "downloader");
+
+  stream->pipe = gst_pipeline_new (name);
+  if (!stream->pipe) {
+    GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    return FALSE;
+  }
+  g_free(name);
+
+  name = g_strdup_printf("%s-%s", stream->name, "httpsrc");
+  GST_DEBUG ("Creating source element for the URI:%s", uri);
+  stream->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, name);
+  if (!stream->urisrc) {
+    GST_ERROR_OBJECT (demux, "failed to create urisrc");
+    return FALSE;
+  }
+  g_free(name);
+
+  if (GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser))
+    g_object_set (G_OBJECT (stream->urisrc), "is-live", TRUE, NULL);
+  else
+    g_object_set (G_OBJECT (stream->urisrc), "is-live", FALSE, NULL);
+
+  name = g_strdup_printf("%s-%s", stream->name, "parser");
+  stream->parser = gst_element_factory_make ("piffdemux", name);
+  if (!stream->parser) {
+    GST_ERROR_OBJECT (demux, "failed to create piffdemux element");
+    return FALSE;
+  }
+
+  caps = ssm_parse_get_stream_caps (demux->parser, stream->type);
+  GST_INFO_OBJECT (stream->pad, "prepare caps = %s", gst_caps_to_string(caps));
+
+  g_object_set (G_OBJECT (stream->parser), "caps", caps, NULL);
+  g_object_set (G_OBJECT (stream->parser), "start-ts", start_ts, NULL);
+  g_object_set (G_OBJECT (stream->parser), "duration", GST_SSM_PARSE_GET_DURATION(demux->parser), NULL);
+  g_object_set (G_OBJECT (stream->parser), "is-live", GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser), NULL);
+  g_object_set (G_OBJECT (stream->parser), "lookahead-count", GST_SSM_PARSE_LOOKAHEAD_COUNT(demux->parser), NULL);
+  g_signal_connect (stream->parser, "live-param",  G_CALLBACK (gst_ss_demux_append_live_params), stream);
+
+  g_free(name);
+
+  name = g_strdup_printf("%s-%s", stream->name, "sink");
+  stream->sink = gst_element_factory_make ("appsink", name);
+  if (!stream->sink) {
+    GST_ERROR_OBJECT (demux, "failed to create appsink element");
+    return FALSE;
+  }
+  g_object_set (G_OBJECT (stream->sink), "emit-signals", TRUE, "sync", FALSE, NULL);
+  g_signal_connect (stream->sink, "new-buffer",  G_CALLBACK (gst_ssm_demux_on_new_buffer), stream);
+
+  g_free(name);
+
+  gst_bin_add_many (GST_BIN (stream->pipe), stream->urisrc, stream->parser, stream->sink, NULL);
+  if (!gst_element_link_many (stream->urisrc, stream->parser, stream->sink, NULL)) {
+    GST_ERROR ("failed to link elements...");
+    return FALSE;
+  }
+
+  stream->bus = gst_pipeline_get_bus (GST_PIPELINE (stream->pipe));
+  gst_bus_add_watch (stream->bus, (GstBusFunc)gst_ss_demux_download_bus_cb, stream);
+  gst_object_unref (stream->bus);
+
+  return TRUE;
+}
+
+#if 0
+static gboolean
+gst_ss_demux_create_dummy_pipe (GstSSDemux * demux, GstSSDemuxStream *stream)
+{
+  gchar *name = NULL;
+  GstCaps *caps = NULL;
+  GstElement *capsfilter = NULL;
+  GstElement *enc = NULL;
+  guint64 avg_dur = -1;
+  guint frame_rate = 0;
+
+  name = g_strdup_printf("%s-%s", stream->name, "dummy");
+
+  stream->pipe = gst_pipeline_new (name);
+  if (!stream->pipe) {
+    GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    return FALSE;
+  }
+  g_free(name);
+
+  /* create dummy sender source */
+  name = g_strdup_printf("%s-%s", stream->name, "dummysrc");
+  stream->urisrc = gst_element_factory_make ("imagereader", name);
+  if (!stream->urisrc) {
+    GST_ERROR_OBJECT (demux,"failed to create filesrc element");
+    return FALSE;
+  }
+  g_free(name);
+  g_object_set (G_OBJECT (stream->urisrc), "location", "/opt/home/root/aonly_VGA_1frame_I420.yuv", NULL);
+  g_object_set (G_OBJECT (stream->urisrc), "framerate", 25, NULL);
+  g_object_set (G_OBJECT (stream->urisrc), "num-buffers", 60, NULL);
+
+  /* caps filter */
+  capsfilter = gst_element_factory_make ("capsfilter", NULL);
+  if (!capsfilter) {
+    GST_ERROR_OBJECT (demux, "failed to create capsfilter element");
+    return FALSE;
+  }
+  caps = gst_caps_new_simple ("video/x-raw-yuv",
+                  "width", G_TYPE_INT, 640,
+                  "height", G_TYPE_INT, 480,
+                  "framerate",GST_TYPE_FRACTION, 25,1,
+                  "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
+                  NULL);
+  g_object_set (G_OBJECT (capsfilter), "caps", caps,  NULL);
+
+  /* create h264parse element */
+  enc = gst_element_factory_make ("savsenc_h264", "H264 encoder");
+  if (!enc) {
+    GST_ERROR_OBJECT (demux, "failed to create h264 parse element");
+    return FALSE;
+  }
+  name = g_strdup_printf("%s-%s", stream->name, "sink");
+  stream->sink = gst_element_factory_make ("appsink", name);
+  if (!stream->sink) {
+    GST_ERROR_OBJECT (demux, "failed to create appsink element");
+    return FALSE;
+  }
+  g_free(name);
+  g_object_set (G_OBJECT (stream->sink), "emit-signals", TRUE, "sync", FALSE, NULL);
+  g_signal_connect (stream->sink, "new-buffer",  G_CALLBACK (gst_ssm_demux_on_new_buffer), stream);
+
+  /* add to pipeline & link all elements */
+  gst_bin_add_many (GST_BIN (stream->pipe), stream->urisrc, capsfilter, enc, stream->sink, NULL);
+
+  if (!gst_element_link_many (stream->urisrc, capsfilter, enc, stream->sink, NULL)) {
+    GST_ERROR_OBJECT (demux,"failed to link dummy pipe elements...");
+    return FALSE;
+  }
+
+  stream->bus = gst_pipeline_get_bus (GST_PIPELINE (stream->pipe));
+  gst_bus_add_watch (stream->bus, (GstBusFunc)gst_ss_demux_download_bus_cb, stream);
+  gst_object_unref (stream->bus);
+
+  return TRUE;
+}
+#else
+static gboolean
+gst_ss_demux_create_dummy_pipe (GstSSDemux * demux, GstSSDemuxStream *stream)
+{
+  gchar *name = NULL;
+  GstBus *bus = NULL;
+  GstCaps *caps = NULL;
+
+  name = g_strdup_printf("%s-%s", stream->name, "dummy");
+
+  stream->pipe = gst_pipeline_new (name);
+  if (!stream->pipe) {
+    GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    return FALSE;
+  }
+  g_free(name);
+
+  /* create dummy sender source */
+  name = g_strdup_printf("%s-%s", stream->name, "dummysrc");
+  stream->urisrc = gst_element_factory_make ("filesrc", name);
+  if (!stream->urisrc) {
+    GST_ERROR_OBJECT (demux,"failed to create filesrc element");
+    return FALSE;
+  }
+  g_free(name);
+  g_object_set (G_OBJECT (stream->urisrc), "location", "/opt/home/root/sound_2sec.264", NULL);
+
+  /* create appsink element */
+  name = g_strdup_printf("%s-%s", stream->name, "parser");
+  stream->parser= gst_element_factory_make ("legacyh264parse", name);
+  if (!stream->parser) {
+    GST_ERROR_OBJECT (demux, "failed to create h264 parse element");
+    return FALSE;
+  }
+  g_object_set (G_OBJECT (stream->parser), "output-format", 1, NULL);
+
+  /* create appsink element */
+  name = g_strdup_printf("%s-%s", stream->name, "sink");
+  stream->sink = gst_element_factory_make ("appsink", name);
+  if (!stream->sink) {
+    GST_ERROR_OBJECT (demux, "failed to create appsink element");
+    return FALSE;
+  }
+  g_object_set (G_OBJECT (stream->sink), "emit-signals", TRUE, "sync", FALSE, NULL);
+
+  caps = gst_caps_new_simple ("video/x-h264",
+                  "width", G_TYPE_INT, 640,
+                  "height", G_TYPE_INT, 480,
+                  "stream-format", G_TYPE_STRING, "byte-stream",
+                  NULL);
+  g_object_set (G_OBJECT (stream->sink), "caps", caps, NULL);
+
+  g_signal_connect (stream->sink, "new-buffer",  G_CALLBACK (gst_ssm_demux_on_new_buffer), stream);
+  g_free(name);
+
+  /* add to pipeline & link all elements */
+  gst_bin_add_many (GST_BIN (stream->pipe), stream->urisrc, stream->parser, stream->sink, NULL);
+  if (!gst_element_link_many (stream->urisrc, stream->parser, stream->sink, NULL)) {
+    GST_ERROR_OBJECT (demux,"failed to link elements...");
+    return FALSE;
+  }
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (stream->pipe));
+  gst_bus_add_watch (bus, (GstBusFunc)gst_ss_demux_download_bus_cb, stream);
+  gst_object_unref (bus);
+
+  return TRUE;
+}
+
+
+#endif
+static gboolean
+gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
+{
+  GstSSDemuxStream *stream = (GstSSDemuxStream *)data;
+  GstSSDemux *demux = stream->parent;
+
+  switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_EOS: {
+      guint64 download_rate = -1;
+
+      GST_INFO_OBJECT (stream->pad, "received EOS on download pipe..");
+      // increase the fragment count on EOS
+      stream->frag_cnt++;
+
+      if (g_strrstr (gst_element_get_name(stream->urisrc), "http")) {
+        g_object_get (stream->urisrc, "download-rate", &download_rate, NULL);
+        g_print("*********** '%s' download rate = %d bps **************\n", stream->name, download_rate);
+      }
+
+      // TODO: need to remove download_rate> 0 check.. make it generic
+      if ((stream->type == SS_STREAM_VIDEO) && (demux->ss_mode != SS_MODE_AONLY) && (download_rate >= 0)) {
+        if (stream->frag_cnt >= demux->fragments_cache) {
+          /* for switching, we are considering video download rate only */
+          demux->ss_mode = gst_ssm_parse_switch_qualitylevel (demux->parser, download_rate);
+        }
+      } else if (stream->type == SS_STREAM_AUDIO && (demux->ss_mode == SS_MODE_AONLY)) {
+        /* when video is not present using audio download rate to calculate switching */
+         demux->ss_mode = gst_ssm_parse_switch_qualitylevel (demux->parser, download_rate);
+         if (demux->ss_mode != SS_MODE_AONLY) {
+           g_print ("\n\nMoving to AV mode by audio considering audio download rate\n\n\n\n");
+         }
+      }
+
+      g_cond_signal (stream->cond);
+
+#ifdef SIMULATE_AUDIO_ONLY
+      /* when fragment count is multiple of 4, switch to audio only case */
+      if ((stream->frag_cnt % 4 == 0) && (stream->type == SS_STREAM_VIDEO) &&
+               GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser)) {
+        g_print ("\n\t ######## Forcibly switching to audio only for testing ##########\n");
+        demux->ss_mode = SS_MODE_AONLY;
+      }
+  #endif
+      GST_DEBUG_OBJECT (stream->pad, "Signalling eos condition...");
+
+      GST_DEBUG_OBJECT (demux, "number of fragments downloaded = %d", stream->frag_cnt);
+      break;
+    }
+    case GST_MESSAGE_ERROR: {
+      GError *error = NULL;
+      gchar* debug = NULL;
+
+      g_print ("Error from %s\n", gst_element_get_name (GST_MESSAGE_SRC(msg)));
+
+      gst_message_parse_error( msg, &error, &debug );
+      if (error)
+        GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error= %s\n", error->message);
+
+      GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s\n", debug);
+
+      /* handling error, when client requests url, which is yet to be prepared by server */
+      if ((!strncmp(error->message, "Precondition Failed", strlen("Precondition Failed"))) && (5 == error->code)) {
+        GstStateChangeReturn ret;
+
+        /* wait for 1sec & request the url again */
+        // TODO: need to make wait time as generic or Adding loop count to request again & again
+        GST_INFO_OBJECT (demux, "ERROR : code = %d, msg = %s, NEED to request again", error->code, error->message);
+        usleep (1000000); // 1 sec
+
+        /* put the current pipeline to NULL state */
+        gst_element_set_state (stream->pipe, GST_STATE_NULL);
+        gst_element_get_state (stream->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+        stream->pipe = stream->urisrc = stream->parser = stream->sink = NULL;
+
+        g_print ("Going to download fragment AGAIN : %s\n", stream->uri);
+        if (!gst_ss_demux_create_download_pipe (demux, stream, stream->uri, stream->start_ts)) {
+          GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+          if (!gst_element_post_message (GST_ELEMENT(demux), msg)) {
+            GST_ERROR_OBJECT (demux, "failed to post error");
+            return FALSE;
+          }
+        }
+
+        ret = gst_element_set_state (stream->pipe, GST_STATE_PLAYING);
+        if (ret == GST_STATE_CHANGE_FAILURE) {
+          if (!gst_element_post_message (GST_ELEMENT(demux), msg)) {
+            GST_ERROR_OBJECT (demux, "failed to post error");
+            return FALSE;
+          }
+        }
+
+        } else {
+          if (error)
+          g_print ("GST_MESSAGE_ERROR: error= %s\n", error->message);
+
+          g_print ("GST_MESSAGE_ERROR: debug = %s\n", debug);
+          if (!gst_element_post_message (GST_ELEMENT(demux), msg)) {
+            GST_ERROR_OBJECT (demux, "failed to post error");
+            gst_ss_demux_stop (demux, stream);
+            g_free( debug);
+            debug = NULL;
+            g_error_free( error);
+            return FALSE;
+        }
+        gst_ss_demux_stop (demux, stream);
+      }
+
+      g_free( debug);
+      debug = NULL;
+      g_error_free( error);
+      break;
+    }
+    case GST_MESSAGE_WARNING: {
+      char* debug = NULL;
+      GError* error = NULL;
+      gst_message_parse_warning(msg, &error, &debug);
+      GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
+      GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
+      g_error_free( error );
+      g_free( debug);
+      break;
+    }
+    default : {
+      GST_LOG_OBJECT(demux, "unhandled message : %s\n", gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
+      break;
+    }
+  }
+
+  return TRUE;
+}
+
+static void
+gst_ssm_demux_on_new_buffer (GstElement * appsink, void* data)
+{
+  GstSSDemuxStream *stream = (GstSSDemuxStream *)data;
+  GstSSDemux *demux = stream->parent;
+  GstBuffer *inbuf = NULL;
+  GstFlowReturn fret = GST_FLOW_OK;
+
+  inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
+  if (!inbuf) {
+    GST_WARNING_OBJECT (demux, "Input buffer not available.,..\n");
+    return;
+  }
+
+  GST_LOG_OBJECT (stream->pad, "Inbuf : size = %d, ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+      GST_BUFFER_SIZE(inbuf), GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(inbuf)), GST_TIME_ARGS(GST_BUFFER_DURATION(inbuf)));
+
+  // Queue the buffers till fragment cache reached... after reaching start pushing data to respective port
+  if ( stream->frag_cnt < demux->fragments_cache ) {
+    GST_LOG_OBJECT (demux, "queuing data till caching finished...");
+    g_queue_push_tail (stream->queue, inbuf);
+    return;
+  }
+
+  if (!stream->sent_ns) {
+    guint64 duration = GST_CLOCK_TIME_NONE;
+    guint64 start = GST_CLOCK_TIME_NONE;
+    GstEvent *event = NULL;
+
+    duration = gst_util_uint64_scale (GST_SSM_PARSE_GET_DURATION(demux->parser), GST_SECOND,
+               GST_SSM_PARSE_GET_TIMESCALE(demux->parser));
+
+    start = gst_util_uint64_scale (GST_SSM_PARSE_NS_START(demux->parser), GST_SECOND,
+               GST_SSM_PARSE_GET_TIMESCALE(demux->parser));
+
+    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+                                       start, duration, start);
+
+    GST_DEBUG_OBJECT(demux," new_segment start = %"GST_TIME_FORMAT, GST_TIME_ARGS(start));
+
+    if (!gst_pad_push_event (stream->pad, event)) {
+      GST_ERROR_OBJECT (demux, "failed to push newsegment event");
+      return;
+    }
+    stream->sent_ns = TRUE;
+  }
+
+  while (!g_queue_is_empty(stream->queue)) {
+    GstBuffer *cache_buf = g_queue_pop_head (stream->queue);
+
+    fret = gst_pad_push (stream->pad, cache_buf);
+    if (fret != GST_FLOW_OK) {
+      GST_ERROR_OBJECT (demux, "failed to push data, reason : %s", gst_flow_get_name (fret));
+      goto error;
+    }
+  }
+
+  if (stream->type == SS_STREAM_VIDEO && demux->ss_mode == SS_MODE_AONLY) {
+    GST_BUFFER_TIMESTAMP (inbuf) = stream->switch_ts;
+    GST_BUFFER_DURATION (inbuf) = ((float)1/25) * GST_SECOND;
+    stream->switch_ts = GST_BUFFER_TIMESTAMP (inbuf) + GST_BUFFER_DURATION (inbuf);
+    g_print ("Dummy buffers ts : %"GST_TIME_FORMAT" and dur : %"GST_TIME_FORMAT"\n",
+               GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (inbuf)), GST_TIME_ARGS(GST_BUFFER_DURATION (inbuf)));
+
+    g_print ("caps : %s\n", gst_caps_to_string(GST_BUFFER_CAPS(inbuf)));
+  }
+
+  /* push data to downstream*/
+  fret = gst_pad_push (stream->pad, inbuf);
+  if (fret != GST_FLOW_OK) {
+    GST_ERROR_OBJECT (demux, "failed to push data, reason : %s", gst_flow_get_name (fret));
+    goto error;
+  }
+
+error:
+  return;
+}
+
+static void
+gst_ss_demux_stop (GstSSDemux * demux, GstSSDemuxStream *stream)
+{
+  if (GST_TASK_STATE (stream->stream_task) != GST_TASK_STOPPED)
+    gst_task_stop (stream->stream_task);
+}
+
+static void
+gst_ss_demux_stream_init (GstSSDemux *demux, GstSSDemuxStream *stream, SS_STREAM_TYPE stream_type)
+{
+  stream->cond = g_cond_new ();
+  stream->lock = g_mutex_new ();
+  stream->queue = g_queue_new ();
+  stream->parent = demux;
+  stream->pipe = NULL;
+  stream->urisrc = NULL;
+  stream->parser = NULL;
+  stream->sink = NULL;
+  stream->frag_cnt = 0;
+  stream->type = stream_type ;
+  stream->uri = NULL;
+  stream->start_ts = -1;
+  stream->sent_ns = FALSE;
+  stream->switch_ts = GST_CLOCK_TIME_NONE;
+  stream->avg_dur = GST_CLOCK_TIME_NONE;
+
+  if (stream->type == SS_STREAM_VIDEO) {
+    stream->pad = gst_pad_new_from_static_template (&ssdemux_videosrc_template, "video");
+    stream->name = g_strdup("video");
+  } else if (stream->type == SS_STREAM_AUDIO) {
+    stream->pad = gst_pad_new_from_static_template (&ssdemux_audiosrc_template, "audio");
+    stream->name = g_strdup("audio");
+  } else if (stream->type == SS_STREAM_TEXT) {
+    stream->pad = gst_pad_new_from_static_template (&ssdemux_subsrc_template, "subtitle");
+    stream->name = g_strdup("text");
+  }
+
+  GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
+
+  gst_pad_use_fixed_caps (stream->pad);
+  gst_pad_set_event_function (stream->pad, gst_ss_demux_handle_src_event);
+  gst_pad_set_query_function (stream->pad, gst_ss_demux_handle_src_query);
+
+  stream->caps = ssm_parse_get_stream_caps (demux->parser, stream->type);
+  g_print ("prepare video caps = %s", gst_caps_to_string(stream->caps));
+
+  GST_DEBUG_OBJECT (demux, "setting caps %" GST_PTR_FORMAT, stream->caps);
+  gst_pad_set_caps (stream->pad, stream->caps);
+
+  GST_DEBUG_OBJECT (demux, "adding pad %s %p to demux %p", GST_OBJECT_NAME (stream->pad), stream->pad, demux);
+  gst_pad_set_active (stream->pad, TRUE);
+  gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
+}
+
+static void
+gst_ss_demux_stream_free (GstSSDemux * demux, GstSSDemuxStream * stream)
+{
+  if (stream->queue) {
+    while (!g_queue_is_empty(stream->queue)) {
+      gst_buffer_unref (g_queue_pop_head (stream->queue));
+    }
+    g_queue_free (stream->queue);
+    stream->queue = NULL;
+  }
+
+  if (stream->pad) {
+    gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
+    stream->pad = NULL;
+  }
+  if (stream->cond) {
+    g_cond_free (stream->cond);
+    stream->cond = NULL;
+  }
+  if (stream->lock) {
+    g_mutex_free (stream->lock);
+    stream->lock = NULL;
+  }
+
+  g_free (stream);
+}
+static gboolean
+ssdemux_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "ssdemux", GST_RANK_PRIMARY,
+          GST_TYPE_SS_DEMUX) || FALSE)
+    return FALSE;
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "ssdemux",
+    "Smooth streaming demux plugin",
+    ssdemux_init, VERSION, "LGPL", PACKAGE_NAME, "http://www.samsung.com/")
+
diff --git a/ssdemux/src/gstssdemux.h b/ssdemux/src/gstssdemux.h
new file mode 100755 (executable)
index 0000000..adc5525
--- /dev/null
@@ -0,0 +1,68 @@
+\r
+#ifndef __GST_SS_DEMUX_H__\r
+#define __GST_SS_DEMUX_H__\r
+\r
+#include <gst/gst.h>\r
+#include <gst/base/gstadapter.h>\r
+#include <gst/app/gstappsrc.h>\r
+#include <gst/app/gstappsink.h>\r
+#include "ssmanifestparse.h"\r
+#include "piffcommon.h"\r
+\r
+G_BEGIN_DECLS\r
+#define GST_TYPE_SS_DEMUX \\r
+  (gst_ss_demux_get_type())\r
+#define GST_SS_DEMUX(obj) \\r
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_SS_DEMUX, GstSSDemux))\r
+#define GST_SS_DEMUX_CLASS(klass) \\r
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SS_DEMUX,GstSSDemuxClass))\r
+#define GST_IS_SS_DEMUX(obj) \\r
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SS_DEMUX))\r
+#define GST_IS_SS_DEMUX_CLASS(klass) \\r
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SS_DEMUX))\r
+\r
+typedef struct _GstSSDemux GstSSDemux;\r
+typedef struct _GstSSDemuxClass GstSSDemuxClass;\r
+typedef struct _GstSSDemuxStream GstSSDemuxStream;\r
+\r
+\r
+/**\r
+ * GstSSDemux:\r
+ *\r
+ * Opaque #GstSSDemux data structure.\r
+ */\r
+struct _GstSSDemux\r
+{\r
+  GstElement parent;\r
+\r
+  GstPad *sinkpad;\r
+\r
+  /* Properties */\r
+  gchar **cookies;             /* HTTP request cookies. */\r
+  gboolean allow_audio_only;  /*In LIVE case, allow audio only download when downloadrate is less */\r
+  guint fragments_cache;        /* number of fragments needed to be cached to start playing */\r
+  gfloat bitrate_switch_tol;    /* tolerance with respect to the fragment duration to switch the bitarate*/\r
+  gboolean need_cache;\r
+  gboolean cancelled;\r
+  guint download_rate;\r
+  GstBuffer *manifest;\r
+  GstSSMParse *parser; /* manifest parser */\r
+\r
+  GstSSDemuxStream *streams[SS_STREAM_NUM];\r
+  SS_BW_MODE ss_mode;\r
+  gboolean switch_eos;\r
+};\r
+\r
+struct _GstSSDemuxClass\r
+{\r
+  GstElementClass parent_class;\r
+};\r
+\r
+GType gst_ss_demux_get_type (void);\r
+\r
+G_END_DECLS\r
+#endif /* __GST_SS_DEMUX_H__ */\r
+\r
+\r
+\r
+\r
diff --git a/ssdemux/src/ssmanifestparse.c b/ssdemux/src/ssmanifestparse.c
new file mode 100755 (executable)
index 0000000..fd0f41c
--- /dev/null
@@ -0,0 +1,1607 @@
+#include "ssmanifestparse.h"
+
+static gboolean ssm_parse_root_node (GstSSMParse *parser, xmlNodePtr root_node);
+GstCaps * ssm_prepare_video_caps (GstSSMParse *parser, GstSSMStreamNode *stream);
+GstCaps * ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream);
+GstCaps *ssm_prepare_text_caps (GstSSMParse *parser, GstSSMStreamNode *stream);
+static gboolean convert_NALUnitDCI_to_PacktizedDCI (unsigned char *nalu_dci, unsigned char **packetized_dci, unsigned int *packetized_dci_len);
+
+#define MANIFEST_LOCK(parser) g_mutex_lock(parser->lock)
+#define MANIFEST_UNLOCK(parser) g_mutex_unlock(parser->lock)
+#define START_TS_MAX(a,b) ((a)>(b) ? (a) : (b))
+
+const gchar *
+ssm_parse_get_stream_name(SS_STREAM_TYPE type)
+{
+  if (type == SS_STREAM_VIDEO) return "video"; \
+  else if (type == SS_STREAM_AUDIO) return "audio"; \
+  else if (type == SS_STREAM_TEXT) return "text"; \
+  else return "unknown";
+}
+
+
+static gboolean
+int_from_string (gchar * ptr, gchar ** endptr, gint * val, gint base)
+{
+  gchar *end;
+  g_return_val_if_fail (ptr != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  errno = 0;
+  *val = strtol (ptr, &end, base);
+  if ((errno == ERANGE && (*val == LONG_MAX || *val == LONG_MIN)) || (errno != 0 && *val == 0)) {
+    g_print ("Error in strtol : %s\n", strerror(errno));
+    return FALSE;
+  }
+
+  if (endptr)
+    *endptr = end;
+
+  return end != ptr;
+}
+
+static gboolean
+ssm_parse_get_xml_prop_boolean (GstSSMParse *parser, xmlNode * node,
+    const gchar * property)
+{
+  xmlChar *prop_string;
+  gboolean prop_bool = FALSE;
+
+  prop_string = xmlGetProp (node, (const xmlChar *) property);
+  if (prop_string) {
+    if ((xmlStrcmp (prop_string, (xmlChar *) "false") == 0) ||
+       (xmlStrcmp (prop_string, (xmlChar *) "FALSE") == 0)) {
+      GST_LOG (" - %s: false", property);
+    } else if ((xmlStrcmp (prop_string, (xmlChar *) "true") == 0) ||
+       (xmlStrcmp (prop_string, (xmlChar *) "TRUE") == 0)) {
+      GST_LOG(" - %s: true", property);
+      prop_bool = TRUE;
+    } else {
+      GST_WARNING("failed to parse boolean property %s from xml string %s", property, prop_string);
+    }
+    xmlFree (prop_string);
+  }
+
+  return prop_bool;
+}
+
+static guint
+ssm_parse_get_xml_prop_uint (GstSSMParse *parser,
+    xmlNode * node, const gchar * property, guint default_val)
+{
+  xmlChar *prop_string;
+  guint prop_uint = default_val;
+
+  prop_string = xmlGetProp (node, (const xmlChar *) property);
+  if (prop_string) {
+    if (sscanf ((gchar *) prop_string, "%u", &prop_uint)) {
+      GST_LOG (" - %s: %u", property, prop_uint);
+    } else {
+      GST_WARNING("failed to parse unsigned integer property %s from xml string %s",
+          property, prop_string);
+    }
+    xmlFree (prop_string);
+  }
+
+  return prop_uint;
+}
+
+static guint64
+ssm_parse_get_xml_prop_uint64 (GstSSMParse *parser,
+    xmlNode * node, const gchar * property, guint64 default_val)
+{
+  xmlChar *prop_string;
+  guint64 prop_uint64 = default_val;
+
+  prop_string = xmlGetProp (node, (const xmlChar *) property);
+  if (prop_string) {
+    if (sscanf ((gchar *) prop_string, "%llu", &prop_uint64)) {
+      GST_LOG (" - %s: %s[%"G_GUINT64_FORMAT"]", property, prop_string, prop_uint64);
+    } else {
+      GST_WARNING("failed to parse unsigned integer property %s from xml string %s",
+          property, prop_string);
+    }
+    xmlFree (prop_string);
+  }
+
+  return prop_uint64;
+} 
+
+static gint
+ssm_parser_sort_qualitylevels_by_bitrate (gconstpointer a, gconstpointer b)
+{
+       return ((GstSSMQualityNode *) (a))->bitrate - ((GstSSMQualityNode *) (b))->bitrate; //sorting in ascending order
+       //return ((GstSSMQualityNode *) (b))->bitrate - ((GstSSMQualityNode *) (a))->bitrate; // sorting in descending order
+}
+
+
+static void
+gst_ssm_parse_free_quality_node (GstSSMQualityNode *qualitynode)
+{
+  if (qualitynode) {
+    g_free (qualitynode->codec_data);
+    g_free (qualitynode->fourcc);
+    g_slice_free (GstSSMQualityNode, qualitynode);
+  }
+}
+
+static void
+gst_ssm_parse_free_fragment_node (GstSSMFragmentNode*fragnode)
+{
+  if (fragnode) {
+    g_slice_free (GstSSMFragmentNode, fragnode);
+  }
+}
+
+
+static void
+gst_ssm_parse_free_stream_node (GstSSMStreamNode *streamnode)
+{
+  if (streamnode) {
+    if (streamnode->quality_lists) {
+      streamnode->quality_lists = g_list_first (streamnode->quality_lists);
+      g_list_foreach (streamnode->quality_lists, (GFunc) gst_ssm_parse_free_quality_node, NULL);
+      g_list_free (streamnode->quality_lists);
+      streamnode->quality_lists = NULL;
+    }
+    if (streamnode->fragment_lists) {
+      streamnode->fragment_lists = g_list_first (streamnode->fragment_lists);
+      g_list_foreach (streamnode->fragment_lists, (GFunc) gst_ssm_parse_free_fragment_node, NULL);
+      g_list_free (streamnode->fragment_lists);
+      streamnode->fragment_lists = NULL;
+    }
+    if (streamnode->StreamType) {
+      g_free(streamnode->StreamType);
+      streamnode->StreamType = NULL;
+    }
+    if (streamnode->StreamUrl) {
+      g_free(streamnode->StreamUrl);
+      streamnode->StreamUrl = NULL;
+    }
+    if (streamnode->StreamSubType) {
+      g_free(streamnode->StreamSubType);
+      streamnode->StreamSubType = NULL;
+    }
+    if (streamnode->StreamName) {
+      g_free(streamnode->StreamName);
+      streamnode->StreamName = NULL;
+    }
+    if (streamnode->frag_cond) {
+      g_cond_free (streamnode->frag_cond);
+      streamnode->frag_cond = NULL;
+    }
+    if (streamnode->frag_lock) {
+      g_mutex_free (streamnode->frag_lock);
+      streamnode->frag_lock = NULL;
+    }
+    g_slice_free (GstSSMStreamNode, streamnode);
+  }
+}
+
+GstSSMParse *
+gst_ssm_parse_new (const gchar * uri)
+{
+  GstSSMParse *parser;
+  gchar *tmp = NULL;
+
+  g_return_val_if_fail (uri != NULL, NULL);
+
+  parser = g_new0 (GstSSMParse, 1);
+
+  parser->uri = g_strdup (uri);
+  parser->lock = g_mutex_new();
+  tmp = strrchr(uri, '/');
+  tmp = tmp+1;
+  parser->presentation_uri = (gchar *) malloc (tmp - uri + 1);
+  if (NULL == parser->presentation_uri) {
+    GST_ERROR ("Failed to allocate memory..\n");
+    return NULL;
+  }
+
+  strncpy (parser->presentation_uri, uri, tmp - uri);
+  parser->presentation_uri[tmp-uri] = '\0';
+  parser->ns_start = GST_CLOCK_TIME_NONE;
+  GST_INFO ("Presentation URI : %s", parser->presentation_uri);
+  return parser;
+}
+
+void
+gst_ssm_parse_free (GstSSMParse *parser)
+{
+  int i =0;
+
+  g_return_if_fail (parser != NULL);
+
+  g_mutex_free(parser->lock);
+
+  // TODO: cleanup memory allocated.....
+  if (parser->RootNode) {
+    for (i = 0; i < SS_STREAM_NUM; i++) {
+      if (parser->RootNode->streams[i]) {
+        g_list_foreach (parser->RootNode->streams[i], (GFunc) gst_ssm_parse_free_stream_node, NULL);
+        parser->RootNode->streams[i] = NULL;
+      }
+    }
+    if (parser->RootNode->ProtectNode) {
+      g_slice_free (GstSSMProtectionNode, parser->RootNode->ProtectNode);
+      parser->RootNode->ProtectNode = NULL;
+    }
+    g_slice_free (GstSSMRootNode, parser->RootNode);
+    parser->RootNode = NULL;
+  }
+
+  g_free (parser);
+}
+
+
+static gboolean
+ssm_parse_quality_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr quality_node)
+{
+  GstSSMQualityNode *quality_level = NULL;
+
+  g_return_val_if_fail (parser != NULL, FALSE);
+  g_return_val_if_fail (quality_node != NULL, FALSE);
+  g_return_val_if_fail (stream != NULL, FALSE);
+
+  quality_level = g_slice_new0 (GstSSMQualityNode);
+  if (quality_level == NULL) {
+    GST_ERROR ("Allocation of quality_level node failed!");
+    return FALSE;
+  }
+
+  quality_level->codec_data = NULL;
+  quality_level->fourcc = NULL;
+
+  quality_level->index = ssm_parse_get_xml_prop_uint (parser, quality_node, "Index", -1);
+  GST_DEBUG("Quality Index = %d", quality_level->index);
+  if (SS_STREAM_VIDEO == stream->type && (quality_level->index == -1)) {
+    GST_ERROR ("Index attribute is not present for VIDEO stream...");
+    return FALSE;
+  }
+
+  /* MANDATORY : parsing Bitrate attribute */
+  quality_level->bitrate = ssm_parse_get_xml_prop_uint (parser, quality_node, "Bitrate", -1);
+  GST_DEBUG("Bitrate = %d", quality_level->bitrate);
+  if (quality_level->bitrate == -1) {
+    GST_ERROR ("bitrate attribute is not present...");
+    return FALSE;
+  }
+
+  /* MANDATORY for video: parsing MaxWidth attribute */
+  quality_level->max_width = ssm_parse_get_xml_prop_uint (parser, quality_node, "MaxWidth", -1);
+  GST_DEBUG("MaxWidth = %d", quality_level->max_width);
+  if (SS_STREAM_VIDEO == stream->type && (quality_level->max_width == -1)) {
+    GST_ERROR ("max_width attribute is not present in VIDEO...");
+    return FALSE;
+  }
+
+  /* MANDATORY for video: parsing MaxHeight attribute */
+  quality_level->max_height = ssm_parse_get_xml_prop_uint (parser, quality_node, "MaxHeight", -1);
+  GST_DEBUG("MaxWidth = %d", quality_level->max_height);
+  if (SS_STREAM_VIDEO == stream->type && (quality_level->max_height == -1)) {
+    GST_ERROR ("max_height attribute is not present in VIDEO...");
+    return FALSE;
+  }
+
+  /* MANDATORY for audio: parsing SamplingRate attribute */
+  quality_level->samplingrate = ssm_parse_get_xml_prop_uint (parser, quality_node, "SamplingRate", -1);
+  GST_DEBUG("SamplingRate = %d", quality_level->samplingrate);
+  if (SS_STREAM_AUDIO == stream->type && (quality_level->samplingrate == -1)) {
+    GST_ERROR ("SamplingRate attribute is not present for AUDIO...");
+    return FALSE;
+  }
+
+  /* MANDATORY for audio: parsing Channels attribute */
+  quality_level->channels = ssm_parse_get_xml_prop_uint (parser, quality_node, "Channels", -1);
+  GST_DEBUG("SamplingRate = %d", quality_level->channels);
+  if (SS_STREAM_AUDIO == stream->type && (quality_level->channels == -1)) {
+    GST_ERROR ("Channels attribute is not present for AUDIO...");
+    return FALSE;
+  }
+
+  /* MANDATORY for audio: parsing BitsPerSample attribute */
+  quality_level->bps = ssm_parse_get_xml_prop_uint (parser, quality_node, "BitsPerSample", -1);
+  GST_DEBUG("BitsPerSample = %d", quality_level->bps);
+  if (SS_STREAM_AUDIO == stream->type && (quality_level->bps == -1)) {
+    GST_ERROR ("BitsPerSample attribute is not present for AUDIO...");
+    return FALSE;
+  }
+
+  /* MANDATORY for audio: parsing PacketSize attribute */
+  quality_level->packet_size = ssm_parse_get_xml_prop_uint (parser, quality_node, "PacketSize", -1);
+  GST_DEBUG("PacketSize = %d", quality_level->packet_size);
+  if (SS_STREAM_AUDIO == stream->type && (quality_level->packet_size == -1)) {
+    GST_ERROR ("PacketSize attribute is not present for AUDIO...");
+    return FALSE;
+  }
+
+
+  /* MANDATORY for audio: parsing AudioTag attribute */
+  quality_level->audio_tag = ssm_parse_get_xml_prop_uint (parser, quality_node, "AudioTag", -1);
+  GST_DEBUG("AudioTag = %d", quality_level->audio_tag);
+  if (SS_STREAM_AUDIO == stream->type && (quality_level->audio_tag == -1)) {
+    GST_ERROR ("AudioTag attribute is not present for AUDIO...");
+    return FALSE;
+  }
+
+  /* MANDATORY for audio & video: parsing FourCC attribute */
+  quality_level->fourcc = (gchar *)xmlGetProp(quality_node, (const xmlChar *) "FourCC");
+  if (!quality_level->fourcc && ((SS_STREAM_AUDIO == stream->type) || (SS_STREAM_VIDEO == stream->type))) {
+    GST_ERROR ("failed to parse fourcc from quality node");
+    return FALSE;
+  }
+
+  if (!((!strncmp ((char *)quality_level->fourcc, "AACL", 4)) || !strncmp ((char *)quality_level->fourcc, "WMAP", 4) ||
+  (!strncmp ((char *)quality_level->fourcc, "H264", 4)) || !strncmp ((char *)quality_level->fourcc, "WVC1", 4) ||
+  (!strncmp ((char *)quality_level->fourcc, "TTML", 4)))) {
+    GST_INFO ("Not a proper Fourcc Code...If possible take from SubType\n\n\n");
+    if (quality_level->fourcc) {
+      free (quality_level->fourcc);
+      quality_level->fourcc = NULL;
+    }
+    GST_DEBUG ("Subtype = %s\n\n",stream->StreamSubType);
+    quality_level->fourcc = g_strdup (stream->StreamSubType);
+    if (!((!strncmp ((char *)quality_level->fourcc, "AACL", 4)) || !strncmp ((char *)quality_level->fourcc, "WMAP", 4) ||
+    (!strncmp ((char *)quality_level->fourcc, "H264", 4)) || !strncmp ((char *)quality_level->fourcc, "WVC1", 4))) {
+      GST_ERROR ("Subtype also does not contain valid fourcc code...ERROR\n");
+      return FALSE;
+    }
+  }
+
+  GST_DEBUG("FourCC = %s", quality_level->fourcc);
+
+  // TODO: need to check whether it is required for all video & audio
+
+  /* MANDATORY for audio & video: parsing CodecPrivateData attribute */
+  quality_level->codec_data = (gchar *)xmlGetProp(quality_node, (const xmlChar *) "CodecPrivateData");
+  if (!quality_level->codec_data && ((SS_STREAM_AUDIO == stream->type) || (SS_STREAM_VIDEO == stream->type))) {
+    GST_ERROR ("failed to get codec data from quality node");
+    return FALSE;
+  }
+
+  /* Optional for VIDEO H264: parsing NALUnitLengthField attribute */
+  quality_level->NALULengthofLength = ssm_parse_get_xml_prop_uint (parser, quality_node, "NALUnitLengthField", 4);
+  GST_DEBUG("NALUnitLengthField = %d", quality_level->NALULengthofLength);
+
+  stream->quality_lists = g_list_append (stream->quality_lists, quality_level);
+
+  GST_LOG ("Appened quality level to stream...");
+
+  return TRUE;
+
+}
+
+static gboolean
+ssm_parse_fragment_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr fragment_node)
+{
+  GstSSMFragmentNode *fragment = NULL;
+  gboolean found_time = FALSE;
+  gboolean found_duration = FALSE;
+
+  g_return_val_if_fail (parser != NULL, FALSE);
+  g_return_val_if_fail (fragment_node != NULL, FALSE);
+  g_return_val_if_fail (stream != NULL, FALSE);
+
+  fragment = g_slice_new0 (GstSSMFragmentNode);
+  if (fragment == NULL) {
+    GST_ERROR ("Allocation of fragment failed!");
+    return FALSE;
+  }
+
+  /*parsing fragmentnumber attribute */
+  fragment->num = ssm_parse_get_xml_prop_uint (parser, fragment_node, "n", -1);
+  GST_DEBUG ("fragment number = %d", fragment->num);
+
+  /*parsing duration attribute */
+  fragment->dur = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "d", -1);
+  if (fragment->dur == -1 && !fragment_node->next) {
+    GST_ERROR ("Fragment Duration for last fragment is mandatory");
+    return FALSE;
+  } else if (fragment->dur != -1) {
+    GST_DEBUG ("Fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (fragment->dur));
+    found_duration = TRUE;
+  }
+
+  /*parsing time attribute */
+  fragment->time = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "t", -1);
+  if (fragment->time != -1) {
+    GST_DEBUG ("Fragment time = %"GST_TIME_FORMAT, GST_TIME_ARGS(fragment->time));
+    found_time = TRUE;
+  }
+
+  if (!found_time && !found_duration) {
+    GST_ERROR ("Both time & duration attributes are NOT present.. ERROR");
+    return FALSE;
+  } else if (!found_time && found_duration) {
+    GList *prev_fragment_list = NULL;
+    GstSSMFragmentNode *prev_fragment = NULL;
+
+    GST_DEBUG ("Only Duration attribute is present...");
+    if (stream->fragment_lists) {
+    prev_fragment_list = g_list_last(stream->fragment_lists);
+    if (NULL == prev_fragment_list) {
+      GST_ERROR ("Error last fragment lists are not present..\n");
+      return FALSE;
+    }
+    prev_fragment = (GstSSMFragmentNode *)prev_fragment_list->data;
+    fragment->time = prev_fragment->time +  prev_fragment->dur;
+    GST_DEBUG ("Fragment time = %llu", fragment->time);
+    } else {
+      GST_INFO ("Frament list is empty, assuming it as first fragment...");
+      fragment->time = 0;
+    }
+  } else if (found_time && !found_duration) {
+    xmlNodePtr next_fragment_node = NULL;
+    guint64 next_ts = 0;
+
+    GST_DEBUG ("Only time attribute is present...");
+
+    next_fragment_node = fragment_node->next;
+    if (next_fragment_node) {
+      next_ts = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "t", -1);
+      if (next_ts == -1) {
+        GST_ERROR ("Next fragment time not present to calculate duration of present fragment...");
+        return FALSE;
+      } else {
+        fragment->dur = next_ts - fragment->time;
+        GST_DEBUG ("Current fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(fragment->dur));
+      }
+    } else {
+      GST_ERROR ("Next fragment not present to calculate duration of present fragment...");
+      return FALSE;
+    }
+  }
+
+#if 1
+  /*error check for timestamps as specified in spec */
+  {
+    xmlNodePtr next_fragment_node = NULL;
+    unsigned long long next_ts = 0;
+
+    next_fragment_node = fragment_node->next;
+    if (next_fragment_node) {
+      next_ts = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "t", -1);
+      if (next_ts != -1) {
+        GST_DEBUG ("Next Fragment time = %llu and Current fragment time = %llu\n", next_ts,  fragment->time);
+
+        if ( next_ts < fragment->time) {
+          GST_ERROR ("Error in timestamp sequence...");
+          return FALSE;
+        }
+      }
+    }
+  }
+#endif
+
+  stream->stream_duration += fragment->dur;
+
+  stream->fragment_lists = g_list_append (stream->fragment_lists, fragment);
+  GST_DEBUG ("Added fragment node to list...");
+  // TODO: Need to invetigate on TrackFragmentIndex Attribute
+
+  return TRUE;
+}
+
+static gboolean
+ssm_parse_stream_index_node (GstSSMParse *parser, xmlNodePtr stream_node)
+{
+  GstSSMStreamNode *stream = NULL;
+  xmlNodePtr stream_children = NULL;
+
+  g_return_val_if_fail (parser != NULL, FALSE);
+  g_return_val_if_fail (stream_node != NULL, FALSE);
+
+  stream = g_slice_new0 (GstSSMStreamNode);
+  if (stream == NULL) {
+    GST_WARNING ("Allocation of stream node failed!");
+    return FALSE;
+  }
+
+  stream->frag_lock = g_mutex_new ();
+  stream->frag_cond = g_cond_new ();
+
+  /* Type, Chunks, QualityLevels are MUST attributes */
+  stream->StreamType = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Type");
+  if (NULL == stream->StreamType) {
+    GST_ERROR ("Type attribute is not present");
+    return FALSE;
+  }
+  GST_DEBUG ("Type = %s", stream->StreamType);
+
+  if (!strncmp ((char *)stream->StreamType, "video", 5))
+    stream->type = SS_STREAM_VIDEO;
+  else if (!strncmp ((char *)stream->StreamType, "audio", 5))
+    stream->type = SS_STREAM_AUDIO;
+  else if (!strncmp ((char *)stream->StreamType, "text", 4))
+    stream->type = SS_STREAM_TEXT;
+  else {
+    GST_ERROR ("UnKnown Stream type...");
+    return FALSE;
+  }
+
+  /* Optional SubType Attribute */
+  stream->StreamSubType = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Subtype");
+  if (stream->StreamSubType)
+    GST_DEBUG ("StreamSubType = %s", stream->StreamSubType);
+
+  stream->StreamTimeScale = ssm_parse_get_xml_prop_uint64 (parser, stream_node, "TimeScale", parser->RootNode->TimeScale);
+  GST_LOG("StreamTimeScale = %"G_GUINT64_FORMAT, stream->StreamTimeScale);
+
+  /* Optional StreamName Attribute */
+  stream->StreamName = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Name");
+  if (stream->StreamName)
+    GST_DEBUG ("StreamName = %s", stream->StreamName);
+
+  // TODO: need to understand more on this chunks whether mandatory or not in LIVE case
+  stream->nChunks = ssm_parse_get_xml_prop_uint (parser, stream_node, "Chunks", 0);
+  if (!stream->nChunks && !parser->RootNode->PresentationIsLive) {
+    GST_ERROR ("nChunks is zero in VOD case...ERROR");
+    return FALSE;
+  }
+  GST_DEBUG("nChunks = %d", stream->nChunks);
+
+  stream->nQualityLevels = ssm_parse_get_xml_prop_uint (parser, stream_node, "QualityLevels", 0);
+  GST_DEBUG("nQualityLevels = %d", stream->nQualityLevels);
+
+  stream->StreamUrl = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Url");
+  if (NULL == stream->StreamUrl) {
+    GST_ERROR ("Url Pattern attribute is not present");
+    return FALSE;
+  }
+  GST_DEBUG ("Url = %s", stream->StreamUrl);
+
+  if (stream->type == SS_STREAM_VIDEO) {
+    /* Video stream specific attributes */
+    stream->MaxWidth = ssm_parse_get_xml_prop_uint (parser, stream_node, "MaxWidth", 0);
+    GST_DEBUG("MaxWidth = %d", stream->MaxWidth);
+
+    stream->MaxHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "MaxHeight", 0);
+    GST_DEBUG("MaxHeight = %d", stream->MaxHeight);
+
+    stream->DisplayWidth = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayWidth", 0);
+    GST_DEBUG("DisplayWidth = %d", stream->DisplayWidth);
+
+    stream->DisplayHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayHeight", 0);
+    GST_DEBUG("DisplayHeight = %d", stream->DisplayHeight);
+  }
+
+  /* get the children nodes */
+  stream_children = stream_node->xmlChildrenNode;
+  if (NULL == stream_children) {
+    GST_ERROR ("No Children for StreamIndex Node...\n");
+    return FALSE;
+  }
+
+  /* Parse StreamIndex Children Nodes i.e. QualityLevel */
+  while (stream_children) {
+    if ( xmlIsBlankNode (stream_children)) {/* skip blank nodes */
+      stream_children = stream_children->next;
+      continue;
+    }
+    if (!xmlStrcmp(stream_children->name, (const xmlChar *) "QualityLevel")) {
+      if (!ssm_parse_quality_node (parser, stream, stream_children)) {
+        GST_ERROR ("failed to parse quality node");
+        return FALSE;
+      }
+    } else if (!xmlStrcmp(stream_children->name, (const xmlChar *) "c")) {
+      if (!ssm_parse_fragment_node (parser, stream, stream_children)) {
+        GST_ERROR ("failed to parse fragment node");
+        return FALSE;
+      }
+    } else {
+      GST_WARNING (" ==== >>>>>> Unknow ChildrenNode in StreamNode : %s", stream_children->name);
+    }
+    stream_children = stream_children->next;
+  }
+
+  /* sort the quality lists */
+  if (stream->quality_lists && (g_list_length(stream->quality_lists) > 1)) {
+    stream->quality_lists =  g_list_sort (stream->quality_lists,  (GCompareFunc) ssm_parser_sort_qualitylevels_by_bitrate);
+  }
+
+  parser->RootNode->streams[stream->type] = g_list_append (parser->RootNode->streams[stream->type], stream);
+
+  return TRUE;
+
+}
+
+
+static gboolean
+ssm_parse_protection_node (GstSSMParse *parser, xmlNodePtr protection_node)
+{
+  xmlChar *xml_string = NULL;
+
+  g_return_val_if_fail (parser != NULL, FALSE);
+  g_return_val_if_fail (protection_node != NULL, FALSE);
+
+  parser->RootNode->ProtectNode = g_slice_new0 (GstSSMFragmentNode);
+  if (NULL == parser->RootNode->ProtectNode) {
+    GST_ERROR ("Failed to allocate memory...\n");
+    return FALSE;
+  }
+
+  parser->RootNode->ProtectNode->SystemID = NULL;
+  parser->RootNode->ProtectNode->Content = NULL;
+  parser->RootNode->ProtectNode->ContentSize = 0;
+
+  if (!xmlStrcmp(protection_node->name, (const xmlChar *) "ProtectionHeader")) {
+    parser->RootNode->ProtectNode->SystemID = (unsigned char *) xmlGetProp(protection_node, (const xmlChar *) "SystemID");
+    if (NULL == parser->RootNode->ProtectNode->SystemID) {
+      GST_ERROR ("System ID is not present... need to decide ERROR or NOT... returning ERROR now\n");
+      return FALSE;
+    }
+
+    GST_DEBUG ("system ID = %s\n", parser->RootNode->ProtectNode->SystemID);
+
+    if (!strncasecmp ((char *)parser->RootNode->ProtectNode->SystemID,
+           "9A04F079-9840-4286-AB92-E65BE0885F95",
+           36)) {
+      g_print ("======== >>>>>>>. Content is encrypted using PLAYREADY\n");
+    } else {
+      GST_ERROR ("\n\n ******** UN-supported encrypted content... *********\n\n");
+      return FALSE;
+    }
+
+    xml_string = xmlNodeGetContent(protection_node);
+    if (NULL == xml_string) {
+      GST_ERROR ("Content is not present... need to decide ERROR or NOT\n");
+      return FALSE;
+    } else {
+      gsize content_size = 0;
+
+      g_print ("Content = %s\n", xml_string);
+
+      parser->RootNode->ProtectNode->Content = g_base64_decode ((gchar*)xml_string, &content_size);
+      if (NULL == parser->RootNode->ProtectNode->Content) {
+        GST_ERROR ("Failed to do base64 decoding...\n");
+        free (xml_string);
+        xml_string = NULL;
+        return FALSE;
+      }
+
+      parser->RootNode->ProtectNode->ContentSize = content_size;
+      free (xml_string);
+      xml_string = NULL;
+
+      GST_DEBUG ("ProtectionNode content = %s and size = %d\n", parser->RootNode->ProtectNode->Content, content_size);
+    }
+  } else {
+    GST_ERROR ("ProtectionHeader is NOT PRESENT in Protection node...ERROR\n");
+    return FALSE;
+  }
+
+  GST_LOG ("successfully parsed protectionheader node...");
+  return TRUE;
+}
+
+static gboolean
+ssm_parse_root_node (GstSSMParse *parser, xmlNodePtr root_node)
+{
+  int i = 0;
+
+  g_return_val_if_fail (parser != NULL, FALSE);
+  g_return_val_if_fail (root_node != NULL, FALSE);
+
+  parser->RootNode = g_slice_new0 (GstSSMRootNode);
+  if (parser->RootNode == NULL) {
+    GST_WARNING ("Allocation of root node failed!");
+    return FALSE;
+  }
+
+  for (i = 0; i < SS_STREAM_NUM; i++) {
+    parser->RootNode->streams[i] = NULL;
+  }
+
+  parser->RootNode->ProtectNode = NULL;
+
+  /* MANDATORY : parsing MajorVersion attribute */
+  parser->RootNode->MajorVersion = ssm_parse_get_xml_prop_uint (parser, root_node, "MajorVersion", -1);
+  if (parser->RootNode->MajorVersion != 2) {
+    GST_ERROR("Majorversion should be 2");
+    return FALSE;
+  }
+  GST_LOG("SmoothStreamingMedia :: Majorversion = %d", parser->RootNode->MajorVersion);
+
+  /* MANDATORY : parsing MinorVersion attribute */
+  parser->RootNode->MinorVersion = ssm_parse_get_xml_prop_uint (parser, root_node, "MinorVersion", 0);
+  GST_LOG("SmoothStreamingMedia :: MinorVersion = %d", parser->RootNode->MinorVersion);
+
+  parser->RootNode->TimeScale = ssm_parse_get_xml_prop_uint64 (parser, root_node, "TimeScale", 10000000);
+  GST_LOG("SmoothStreamingMedia :: TimeScale = %"G_GUINT64_FORMAT, parser->RootNode->TimeScale);
+
+  parser->RootNode->Duration = ssm_parse_get_xml_prop_uint64 (parser, root_node, "Duration", -1);
+  GST_LOG("SmoothStreamingMedia :: Duration = %"G_GUINT64_FORMAT, parser->RootNode->Duration);
+
+  parser->RootNode->PresentationIsLive = ssm_parse_get_xml_prop_boolean (parser, root_node, "IsLive");
+  GST_LOG("SmoothStreamingMedia :: IsLive = %d", parser->RootNode->PresentationIsLive);
+
+  /* valid for live presentation only*/
+  if (parser->RootNode->PresentationIsLive) {
+
+    parser->RootNode->LookAheadCount = ssm_parse_get_xml_prop_uint (parser, root_node, "LookaheadCount", -1);
+    GST_LOG("SmoothStreamingMedia :: LookaheadCount = %d", parser->RootNode->LookAheadCount);
+
+    if (parser->RootNode->LookAheadCount == -1) {
+     GST_INFO ("fallback case of lookaheadcount...");
+     parser->RootNode->LookAheadCount = ssm_parse_get_xml_prop_uint (parser, root_node, "LookAheadFragmentCount", -1);
+     GST_LOG("SmoothStreamingMedia :: LookAheadFragmentCount = %d", parser->RootNode->LookAheadCount);
+    }
+
+    parser->RootNode->DVRWindowLength = ssm_parse_get_xml_prop_uint64 (parser, root_node, "DVRWindowLength", 0);
+    GST_LOG("SmoothStreamingMedia :: DVRWindowLength = %"G_GUINT64_FORMAT, parser->RootNode->DVRWindowLength);
+    if (parser->RootNode->DVRWindowLength == 0)
+      GST_INFO ("DVR Window Length is zero...means INFINITE");
+  }
+
+  return TRUE;
+}
+
+
+gboolean
+gst_ssm_parse_manifest (GstSSMParse *parser, char *data, unsigned int size)
+{
+  xmlNodePtr root = NULL;
+  xmlNodePtr curnode = NULL;
+  xmlDocPtr doc;
+  int i;
+
+  g_return_val_if_fail (parser != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (size != 0, FALSE);
+
+  /* parse manifest xml file */
+  doc = xmlReadMemory ((gchar *) data, size, NULL, NULL, 0);
+  if (doc == NULL ) {
+    GST_ERROR("failed to parse manifest file...");
+    goto error;
+  }
+
+  /* Get the root element */
+  root = xmlDocGetRootElement(doc);
+  if (root == NULL) {
+    GST_ERROR("no ROOT node in manifest file...");
+    goto error;
+  }
+
+  if (!xmlStrcmp(root->name, (const xmlChar *) "SmoothStreamingMedia"))  {
+    /* parsing of ROOT Node SmoothStreamingMedia attributes */
+    if (!ssm_parse_root_node (parser, root)) {
+      GST_ERROR("failed to parse root node...");
+      goto error;
+    }
+    GST_DEBUG ("Parsing ROOT element is successful");
+  } else {
+    GST_ERROR ("SmoothStreamingMedia ROOT element is not present...");
+    goto error;
+  }
+
+  /* moving to children nodes */
+  curnode = root->xmlChildrenNode;
+
+  while (curnode) {
+    if (xmlIsBlankNode (curnode)) {/* skip blank node */
+      curnode = curnode->next;
+      continue;
+    }
+
+    if (!xmlStrcmp(curnode->name, (const xmlChar *)"StreamIndex")) {
+      /* Parsing Stream Node */
+      if (!ssm_parse_stream_index_node (parser, curnode)) {
+        GST_ERROR ("failed to parse stream index node...");
+        return FALSE;
+      }
+    } else if (!xmlStrcmp(curnode->name, (const xmlChar *) "Protection")) {
+      xmlNodePtr protect_node;
+
+      /* get the children */
+      protect_node = curnode->xmlChildrenNode;
+      if (NULL == protect_node) {
+        GST_ERROR ("No Children for Protection Node...\n");
+        return FALSE;
+      } else {
+        if (!ssm_parse_protection_node (parser, protect_node)) {
+          GST_ERROR ("failed to parse protectionheader node");
+          return FALSE;
+        }
+      }
+    }
+    curnode = curnode->next;
+  }
+
+  /* Move to last fragment when presentation is LIVE */
+  if (parser->RootNode->PresentationIsLive) {
+    for (i = 0; i < SS_STREAM_NUM; i++) {
+      if (parser->RootNode->streams[i]) {
+        GST_INFO ("Live presentation, so moved to last node...");
+        ((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists =
+                       g_list_last (((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists);
+      }
+    }
+  }
+
+  parser->ns_start = 0;
+
+  /* get new segment start */
+  for (i = 0; i < SS_STREAM_NUM; i++) {
+    GstSSMStreamNode *stream = NULL;
+    GList *frag_list = NULL;
+    guint64 start_ts = GST_CLOCK_TIME_NONE;
+
+    if (parser->RootNode->streams[i]) {
+      /* Move to last fragment when presentation is LIVE */
+      if (parser->RootNode->PresentationIsLive) {
+        GST_INFO ("Live presentation, so moved to last node...");
+        ((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists =
+            g_list_last (((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists);
+      }
+
+      stream = (parser->RootNode->streams[i])->data;
+      frag_list = stream->fragment_lists;
+      start_ts = ((GstSSMFragmentNode *)frag_list->data)->time;
+
+      GST_LOG ("ns_start = %"G_GUINT64_FORMAT" and start_ts[%s] = %"G_GUINT64_FORMAT,
+          parser->ns_start, ssm_parse_get_stream_name(i), start_ts);
+
+      /* take MAX of stream's start as new_segment start */
+      parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
+    }
+  }
+
+  GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
+
+  if (doc) {
+    xmlFreeDoc(doc);
+    doc = NULL;
+  }
+
+  GST_DEBUG ("successfully parsed manifest");
+
+  return TRUE;
+
+error:
+  if (doc) {
+    xmlFreeDoc(doc);
+    doc = NULL;
+  }
+
+  return FALSE;
+}
+
+/* Only supporting url in 'QualityLevels({bitrate})/Fragments(xxxxxx={start time})'
+  * FIXME : Add support for any */
+gboolean
+gst_ssm_parse_get_next_fragment_url (GstSSMParse *parser, SS_STREAM_TYPE stream_type, gchar **uri, guint64 *start_ts)
+{
+  GstSSMStreamNode *stream = NULL;
+  GList *frag_list = NULL;
+  GPtrArray *strs;
+  guint64 time = 0;
+  gchar **splitter1 = NULL;
+  gchar **splitter2 = NULL;
+  gchar **splitter3 = NULL;
+
+  MANIFEST_LOCK(parser);
+  stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
+  g_mutex_lock (stream->frag_lock);
+
+  if (stream->fraglist_eos) {
+    if (parser->RootNode->PresentationIsLive) {
+      /* Live Presentation need to wait for next uri */
+      g_print ("waiting for next URI in LIVE presentation...\n");
+      g_cond_wait (stream->frag_cond, stream->frag_lock);
+      g_print ("Received signal after appending new URI...move to next now\n");
+     ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists =
+        g_list_next (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists);
+    } else {
+      /* VOD presentation reached EOS */
+      GST_INFO("Fragment list is empty in VOD case...");
+      g_mutex_unlock (stream->frag_lock);
+      MANIFEST_UNLOCK(parser);
+      return FALSE;
+    }
+  }
+
+  stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
+
+  frag_list = stream->fragment_lists;
+
+  strs = g_ptr_array_new ();
+
+  /* adding presentation uri */
+  g_ptr_array_add (strs, g_strdup(parser->presentation_uri));
+
+  splitter1 = g_strsplit (stream->StreamUrl, "{", 3);
+
+  /* add stream url till first '{' */
+  g_ptr_array_add (strs, g_strdup(splitter1[0]));
+
+  /* adding bitrate param */
+  g_ptr_array_add (strs, g_strdup_printf ("%d", ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate));
+
+  /* tokenize based on '}' */
+  splitter2 = g_strsplit (splitter1[1], "}", 2);
+
+  g_ptr_array_add (strs, g_strdup(splitter2[1]));
+
+  time = ((GstSSMFragmentNode *)frag_list->data)->time;
+
+  /* adding fragment time */
+  g_ptr_array_add (strs, g_strdup_printf ("%llu", time));
+
+  *start_ts = gst_util_uint64_scale (time, GST_SECOND, parser->RootNode->TimeScale);
+
+  /* tokenize based on '}' */
+  splitter3 = g_strsplit (splitter1[2], "}", 2);
+
+  g_ptr_array_add (strs, g_strdup(splitter3[1]));
+
+  /* add a terminating NULL */
+  g_ptr_array_add (strs, NULL);
+
+  if (frag_list = g_list_next (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists)) {
+    ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists = frag_list;
+  } else {
+    GST_INFO ("Reached end of fragment list...\n");
+    ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fraglist_eos = TRUE;
+  }
+
+  *uri = g_strjoinv (NULL, (gchar **) strs->pdata);
+  g_strfreev ((gchar **) g_ptr_array_free (strs, FALSE));
+
+  g_mutex_unlock (stream->frag_lock);
+
+  MANIFEST_UNLOCK(parser);
+
+  return TRUE;
+}
+
+GstCaps *
+ssm_parse_get_stream_caps (GstSSMParse *parser, SS_STREAM_TYPE stream_type)
+{
+  GstSSMStreamNode *stream = NULL;
+  MANIFEST_LOCK(parser);
+
+  stream = parser->RootNode->streams[stream_type]->data;
+  GstCaps *caps = NULL;
+  if (stream_type == SS_STREAM_VIDEO) {
+    caps =  ssm_prepare_video_caps (parser, stream);
+  } else if (stream_type == SS_STREAM_AUDIO) {
+    caps =  ssm_prepare_audio_caps (parser, stream);
+  } else if (stream_type == SS_STREAM_TEXT) {
+    caps =  ssm_prepare_text_caps (parser, stream);
+  }
+  MANIFEST_UNLOCK(parser);
+  return caps;
+}
+
+GstCaps *
+ssm_prepare_video_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
+{
+  GstSSMQualityNode *cur_quality_node =  (GstSSMQualityNode *)(stream->quality_lists->data);
+  GstBuffer *codec_data = NULL;
+  GstCaps *caps = NULL;
+
+  codec_data = gst_buffer_new ();
+  if (!codec_data) {
+    GST_ERROR ("failed to allocate buffer");
+    return NULL;
+  }
+
+  if (!strncmp ((char *)cur_quality_node->fourcc, "H264", 4)) {
+    /* converting NALU codec data to 3GPP codec data format */
+    if (!convert_NALUnitDCI_to_PacktizedDCI (cur_quality_node->codec_data, &(GST_BUFFER_DATA(codec_data)), &GST_BUFFER_SIZE(codec_data))) {
+      GST_ERROR ("Error in converting NALUDCI to Packetized DCI...\n");
+      return NULL;
+    }
+    GST_BUFFER_MALLOCDATA(codec_data) = GST_BUFFER_DATA(codec_data);
+  } else if (!strncmp ((char *)cur_quality_node->fourcc, "WVC1", 4)) {
+    unsigned char *codec_data = cur_quality_node->codec_data;
+    unsigned int DCI_len = strlen ((char *)cur_quality_node->codec_data);
+    gchar tmp[3] = {0, };
+    gint val = 0;
+    gint codec_data_len = 0;
+    gint idx = 0;
+
+    codec_data_len = (DCI_len >>1);
+
+    codec_data = gst_buffer_new_and_alloc (codec_data_len);
+    if (!codec_data) {
+      GST_ERROR ("Failed to allocate memory..\n");
+      return FALSE;
+    }
+
+    /* copy codec data */
+    while (DCI_len) {
+      memset (tmp, 0x00, 3);
+      strncpy ((char*)tmp, (char*)codec_data, 2);
+      tmp[2] = '\0';
+      if (!int_from_string ((char*)tmp, NULL, &val, 16)) {
+        GST_ERROR ("Failed to int from string...");
+        return NULL;
+      }
+      (GST_BUFFER_DATA(codec_data))[idx] = val;
+      codec_data += 2;
+      DCI_len = DCI_len - 2;
+      idx++;
+    }
+  }
+
+  if (!strncmp ((char *)cur_quality_node->fourcc, "H264", 4)) {
+    /* prepare H264 caps */
+    caps = gst_caps_new_simple ("video/x-h264",
+                  "width", G_TYPE_INT, cur_quality_node->max_width,
+                  "height", G_TYPE_INT, cur_quality_node->max_height,
+                  "framerate", GST_TYPE_FRACTION, 30, 1,
+                  "stream-format", G_TYPE_STRING, "avc",
+                  "alignment", G_TYPE_STRING, "au",
+                  "codec_data", GST_TYPE_BUFFER, codec_data,
+                  NULL);
+  } else if (!strncmp ((char *)cur_quality_node->fourcc, "WVC1", 4)) {
+    /* prepare VC1 caps */
+    caps = gst_caps_new_simple ("video/x-wmv",
+                  "width", G_TYPE_INT, cur_quality_node->max_width,
+                    "height", G_TYPE_INT, cur_quality_node->max_height,
+                    "framerate", GST_TYPE_FRACTION, 30, 1,
+                    "wmvversion", G_TYPE_INT, 3,
+                    "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
+                    "codec_data", GST_TYPE_BUFFER, codec_data,
+                    NULL);
+  } else {
+    char *s;
+    /* prepare gst generic caps caps */
+    GST_ERROR ("Wrong VIDEO fourcc...");
+    s = g_strdup_printf ("video/x-gst-fourcc-%s", "unknown");
+    caps = gst_caps_new_simple (s,
+                     "width", G_TYPE_INT, cur_quality_node->max_width,
+                     "height", G_TYPE_INT, cur_quality_node->max_height,
+                     "framerate", GST_TYPE_FRACTION, 30, 1,
+                      "codec_data", GST_TYPE_BUFFER, codec_data,
+                     NULL);
+  }
+
+  GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
+
+   return caps;
+}
+
+GstCaps *
+ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
+{
+  GstSSMQualityNode *cur_quality_node =  (GstSSMQualityNode *)(stream->quality_lists->data);
+  GstBuffer *codec_data = NULL;
+  GstCaps *caps = NULL;
+
+  if ((!strncmp ((char *)cur_quality_node->fourcc, "AACL", 4)) || !strncmp ((char *)cur_quality_node->fourcc, "WMAP", 4)) {
+    guint DCI_len = strlen ((char *)cur_quality_node->codec_data);
+    gchar tmp[3] = {0, };
+    gint val = 0;
+    gint codec_data_len = (DCI_len >>1);
+    gint idx = 0;
+
+    codec_data = gst_buffer_new_and_alloc (codec_data_len);
+    if (NULL == codec_data) {
+      GST_ERROR ("Failed to allocate memory..\n");
+      return NULL;
+    }
+
+    /* copy codec data */
+    while (DCI_len) {
+      memset (tmp, 0x00, 3);
+      strncpy ((char*)tmp, (char*)cur_quality_node->codec_data, 2);
+      tmp[2] = '\0';
+      if (!int_from_string ((char*)tmp, NULL, &val , 16)) {
+        GST_ERROR ("Failed to int from string...");
+        return NULL;
+      }
+      (GST_BUFFER_DATA(codec_data))[idx] = val;
+      cur_quality_node->codec_data += 2;
+      DCI_len = DCI_len - 2;
+      //g_print ("val = 0x%02x, codec_data_length = %d, idx = %d\n", val, DCI_len, idx);
+      idx++;
+    }
+  } else {
+    GST_ERROR ("\n\n\nUnsupported Audio Codec Fourcc...\n\n\n");
+    return NULL;
+  }
+
+  if (!strncmp ((char *)cur_quality_node->fourcc, "AACL", 4)) {
+    caps = gst_caps_new_simple ("audio/mpeg",
+                          "mpegversion", G_TYPE_INT, 4,
+                          "framed", G_TYPE_BOOLEAN, TRUE,
+                          "stream-format", G_TYPE_STRING, "raw",
+                          "rate", G_TYPE_INT, (int) cur_quality_node->samplingrate,
+                          "channels", G_TYPE_INT, cur_quality_node->channels,
+                          NULL);
+  } else if (!strncmp ((char *)cur_quality_node->fourcc, "WMAP", 4)) {
+    caps = gst_caps_new_simple ("audio/x-wma",
+                        "rate", G_TYPE_INT, (int) cur_quality_node->samplingrate,
+                         "channels", G_TYPE_INT, cur_quality_node->channels,
+                        NULL);
+  } else {
+    char *s;
+
+    GST_ERROR ("Wrong Audio fourcc...");
+    s = g_strdup_printf ("audio/x-gst-fourcc-%s", "unknown");
+    caps = gst_caps_new_simple (s,
+                            "rate", G_TYPE_INT, (int) cur_quality_node->samplingrate,
+                             "channels", G_TYPE_INT, cur_quality_node->channels,
+                             NULL);
+  }
+  GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
+
+  return caps;
+}
+
+GstCaps *
+ssm_prepare_text_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
+{
+  // TODO: Yet to add support for text caps
+  return NULL;
+}
+
+SS_BW_MODE
+gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate)
+{
+  GstSSMStreamNode *stream =  parser->RootNode->streams[SS_STREAM_VIDEO]->data;
+  guint bitrate = ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate;
+  SS_BW_MODE ret = SS_MODE_NO_SWITCH;
+
+  /* check for upward transition */
+  while (drate > (bitrate + BITRATE_SWITCH_UPPER_THRESHOLD * bitrate)) {
+    if (g_list_next (stream->quality_lists)) {
+      stream->quality_lists = g_list_next (stream->quality_lists);
+      g_print ("Move to next quality level : drate = %d and bitrate = %d\n", drate, ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate);
+      ret = SS_MODE_AV;
+    } else {
+      g_print ("Already at MAX Bitrate possible...\n");
+      ret = SS_MODE_NO_SWITCH;
+      break;
+    }
+  }
+
+  /* check for downward transition */
+  while (drate < (bitrate + BITRATE_SWITCH_LOWER_THRESHOLD * bitrate)) {
+    if (g_list_previous (stream->quality_lists)) {
+      stream->quality_lists = g_list_previous (stream->quality_lists);
+      g_print ("Move to previous quality level : drate = %d and bitrate = %d\n", drate, ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate);
+    } else {
+      g_print ("Reached MIN video bitrate possible...\n");
+      if (GST_SSM_PARSE_IS_LIVE_PRESENTATION(parser)) {
+        g_print ("Going to audio-only because of LIVE...\n");
+        ret = SS_MODE_AONLY;
+      } else {
+        ret = SS_MODE_AV;
+      }
+      break;
+    }
+  }
+
+  return ret;
+}
+
+gboolean
+gst_ssm_parse_append_next_fragment (GstSSMParse *parser, SS_STREAM_TYPE stream_type, guint64 timestamp, guint64 duration)
+{
+  GstSSMStreamNode *stream = NULL;
+  GstSSMFragmentNode *new_fragment = NULL;
+  GstSSMFragmentNode *last_fragment = NULL;
+  GList *last_node = NULL;
+
+  g_return_val_if_fail (parser != NULL, FALSE);
+
+  /*get current stream based on stream_type */
+  stream = (parser->RootNode->streams[stream_type])->data;
+
+  g_return_val_if_fail (stream->fragment_lists, FALSE);
+
+  g_mutex_lock (stream->frag_lock);
+
+  last_node = g_list_last(stream->fragment_lists);
+
+  last_fragment = (GstSSMFragmentNode *)(last_node->data);
+
+  if (last_fragment->time < timestamp) {
+
+    GST_LOG ("+++++ last_fragment time = %llu and current recd = %llu +++++\n", last_fragment->time, timestamp);
+
+    /* allocate new fragment node */
+    new_fragment = g_slice_new0 (GstSSMFragmentNode);
+    if (new_fragment == NULL) {
+      GST_ERROR ("Allocation of fragment failed!");
+      return FALSE;
+    }
+
+    if (duration == GST_CLOCK_TIME_NONE) {
+      /* useful when lookahead count is zero */
+      // TODO: need to check how to handle, when there is discontinuity
+      duration = timestamp - last_fragment->time;
+    }
+
+    // TODO: need to handle when either time or duration present OR if both are non proper values
+    new_fragment->dur = duration;
+    new_fragment->time = timestamp;
+    new_fragment->num = 0;
+
+    /* add the new fragment duration to total stream duration */
+    stream->stream_duration += duration;
+
+    /* append new fragment list to stream fragment list */
+   ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists =
+        g_list_append (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists, new_fragment);
+
+    GST_DEBUG ("+++++ Appened new '%s' URL and signaling the condition and duration = %llu ++++++\n",
+        ssm_parse_get_stream_name(stream_type), stream->stream_duration);
+
+    if (stream->fraglist_eos) {
+      GST_INFO ("Need to move the list now to next.. as we received new one\n");
+      ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists =
+        g_list_next (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists);
+      stream->fraglist_eos = FALSE;
+    }
+    /* signal fragment wait */
+    g_cond_signal (stream->frag_cond);
+
+  } else {
+    g_print ("--------- Received '%s' fragment is less than Last fragment in the list -----------\n", ssm_parse_get_stream_name(stream_type));
+  }
+
+  g_mutex_unlock (stream->frag_lock);
+
+  return TRUE;
+}
+
+gboolean
+gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_time)
+{
+  gint i = 0;
+  GstSSMStreamNode *stream = NULL;
+  guint64 stream_time = -1;
+  guint64 start_ts = -1;
+
+  parser->ns_start = 0;
+
+  for (i = 0; i < SS_STREAM_NUM; i++) {
+    if (parser->RootNode->streams[i]) {
+      stream = parser->RootNode->streams[i]->data; // get current stream
+      stream_time = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
+      stream_time = gst_util_uint64_scale (stream_time, GST_SECOND,
+          GST_SSM_PARSE_GET_TIMESCALE(parser));
+
+      if (seek_time > stream_time) {
+        /* forward seek */
+        while (seek_time > stream_time) {
+          stream->fragment_lists = g_list_next (stream->fragment_lists);
+          stream_time = gst_util_uint64_scale (((GstSSMFragmentNode *)stream->fragment_lists->data)->time, GST_SECOND,
+              GST_SSM_PARSE_GET_TIMESCALE(parser));
+          GST_LOG ("seek time = %"GST_TIME_FORMAT", cur_time = %"GST_TIME_FORMAT,
+              GST_TIME_ARGS(seek_time), GST_TIME_ARGS(stream_time));
+        }
+
+        /* moving to fragment before our seeked time */
+        stream->fragment_lists = g_list_previous (stream->fragment_lists);
+        start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
+      } else if (seek_time < stream_time) {
+        /* backward seek */
+        while (seek_time < stream_time) {
+          stream->fragment_lists = g_list_previous (stream->fragment_lists);
+          stream_time = gst_util_uint64_scale (((GstSSMFragmentNode *)stream->fragment_lists->data)->time, GST_SECOND,
+                                              GST_SSM_PARSE_GET_TIMESCALE(parser));
+          GST_LOG ("seek time = %"GST_TIME_FORMAT", cur_time = %"GST_TIME_FORMAT,
+          GST_TIME_ARGS(seek_time), GST_TIME_ARGS(stream_time));
+        }
+        start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
+      } else {
+        /* rare case */
+        start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
+      }
+
+      if (stream->type == SS_STREAM_VIDEO) {
+        /* move to least possible bitrate variant*/
+        stream->quality_lists = g_list_first (stream->quality_lists);
+      }
+
+      GST_INFO ("SEEK : ns_start = %"G_GUINT64_FORMAT" and start_ts[%s] = %"G_GUINT64_FORMAT,
+        parser->ns_start, ssm_parse_get_stream_name(i), start_ts);
+
+      /* take max of stream's start as new_segment start */
+      parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
+    }
+  }
+
+  GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
+
+  return TRUE;
+}
+
+static gboolean
+convert_NALUnitDCI_to_PacktizedDCI (unsigned char *nalu_dci, unsigned char **packetized_dci, unsigned int *packetized_dci_len)
+{
+#ifndef CHECK_NALU_OUT
+       gboolean bret = TRUE;
+       unsigned char *pps_start = NULL;
+       unsigned char *pps_end = NULL;
+       unsigned int sps_len = 0;
+       unsigned int pps_len = 0;
+       unsigned char *sps_data = NULL;
+       unsigned char *pps_data = NULL;
+       unsigned char *tmp_sps_ptr = NULL;
+       unsigned char *tmp_pps_ptr = NULL;
+       unsigned char tmp[3] = {0, };
+       int val;
+       unsigned int idx = 0;
+
+       // TODO: need to generalize this logic for finding multiple SPS and PPS sets and finding SPS/PPS by ANDing 0x1F
+
+       pps_start = strstr ((char*)nalu_dci, "0000000168");
+       pps_end = nalu_dci + strlen ((char *)nalu_dci);
+       GST_DEBUG ("nalu_dci length= %d\n", strlen ((char *)nalu_dci));
+
+       sps_len = pps_start - nalu_dci;
+
+       GST_DEBUG ("sps length = %d\n", sps_len);
+
+       sps_data = (unsigned char*) malloc (sps_len + 1);
+       if (NULL == sps_data)
+       {
+               GST_ERROR ("Failed to allocate memory..\n");
+               bret = FALSE;
+               goto exit;
+       }
+
+       /* Copy SPS data */
+       strncpy ((char*)sps_data, (char *)nalu_dci, sps_len);
+       sps_data[sps_len] = '\0';
+
+       tmp_sps_ptr = sps_data;
+
+       GST_DEBUG ("SPS data = %s\n", sps_data);
+
+       pps_len = pps_end - pps_start;
+       GST_DEBUG ("pps length = %d\n", pps_len);
+
+       pps_data = (unsigned char*)malloc (pps_len + 1);
+       if (NULL == pps_data)
+       {
+               GST_ERROR ("Failed to allocate memory..\n");
+               bret = FALSE;
+               goto exit;
+       }
+
+       /* Copy PPS data */
+       strncpy ((char*)pps_data, (char*)pps_start, pps_len);
+       pps_data[pps_len] = '\0';
+       tmp_pps_ptr = pps_data;
+
+       GST_DEBUG ("PPS data = %s\n", pps_data);
+
+       /* 6 bytes of metadata */
+       *packetized_dci_len = 8;
+
+       *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
+       if (NULL == *packetized_dci)
+       {
+               GST_ERROR ("Failed to allocate memory..\n");
+               bret = FALSE;
+               goto exit;
+       }
+
+       /* configurationVersion */
+       (*packetized_dci)[0] = 0x01;
+
+       /* AVCProfileIndication */
+       memset (tmp, 0x00, 3);
+
+       strncpy ((char*)tmp, (char*)sps_data+10, 2);
+       tmp[2] = '\0';
+
+       bret = int_from_string ((char*)tmp, NULL, &val , 16);
+       if (FALSE == bret)
+       {
+               GST_ERROR ("Failed to int from string...");
+               goto exit;
+       }
+
+       (*packetized_dci)[1] = val;
+
+       /* profile_compatibility*/
+       memset (tmp, 0x00, 3);
+       strncpy ((char*)tmp, (char*)sps_data+12, 2);
+       tmp[2] = '\0';
+       bret = int_from_string ((char*)tmp, NULL, &val , 16);
+       if (FALSE == bret)
+       {
+               GST_ERROR ("Failed to int from string...");
+               goto exit;
+       }
+       (*packetized_dci)[2] = val;
+
+       /* AVCLevelIndication */
+       memset (tmp, 0x00, 3);
+       strncpy ((char*)tmp, (char*)sps_data+14, 2);
+       tmp[2] = '\0';
+       bret = int_from_string ((char*)tmp, NULL, &val , 16);
+       if (FALSE == bret)
+       {
+               GST_ERROR ("Failed to int from string...");
+               goto exit;
+       }
+
+       (*packetized_dci)[3] = val;
+
+       /* Reserver (6) + LengthSizeMinusOne (2) */
+       (*packetized_dci)[4] = 0xff;     // hardcoding lengthoflength = 4 for present
+
+       /* Reserver (3) + numOfSequenceParameterSets (5) */
+       (*packetized_dci)[5] = 0xe1;     // hardcoding numOfSequenceParameterSets = 1 for present
+
+       /* avoiding NALU start code 0x00 00 00 01 */
+       sps_len = sps_len -8;
+       sps_data = sps_data + 8;
+
+       (*packetized_dci)[6] = (sps_len >>1) >> 16;
+       (*packetized_dci)[7] = (sps_len >>1);
+
+       *packetized_dci_len += (sps_len/2);
+
+       *packetized_dci = (unsigned char*) realloc (*packetized_dci, *packetized_dci_len);
+       if (NULL == *packetized_dci)
+       {
+               GST_ERROR ("Failed to allocate memory..\n");
+               bret = FALSE;
+               goto exit;
+       }
+
+       idx = 8;
+
+       /* convert SPS data and store*/
+       while (sps_len)
+       {
+               memset (tmp, 0x00, 3);
+               strncpy ((char*)tmp, (char*)sps_data, 2);
+               tmp[2] = '\0';
+               bret = int_from_string ((char*)tmp, NULL, &val , 16);
+               if (FALSE == bret)
+               {
+                       GST_ERROR ("Failed to int from string...");
+                       goto exit;
+               }
+               (*packetized_dci)[idx] = val;
+               sps_data += 2;
+               sps_len = sps_len - 2;
+               //g_print ("val = 0x%02x, sps_len = %d, idx = %d\n", val, sps_len, idx);
+               idx++;
+       }
+
+       /* avoiding NALU start code 0x00 00 00 01 */
+       pps_len = pps_len -8;
+       pps_data = pps_data + 8;
+
+       /* no.of PPS sets (1 byte) + Lengthof PPS (2 bytes) + PPS length */
+       *packetized_dci_len = *packetized_dci_len + 1 + 2 + (pps_len/2) ;
+       *packetized_dci = (unsigned char*)realloc (*packetized_dci, *packetized_dci_len);
+       if (NULL == *packetized_dci)
+       {
+               GST_ERROR ("Failed to allocate memory..\n");
+               bret = FALSE;
+               goto exit;
+       }
+
+       (*packetized_dci)[idx++] = 0x01; // Harding no.of PPS sets
+       (*packetized_dci)[idx++] = (pps_len>>1) >> 16;
+       (*packetized_dci)[idx++] = (pps_len >>1);
+
+       /* convert PPS data and store */
+       while (pps_len)
+       {
+               memset (tmp, 0x00, 3);
+               strncpy ((char*)tmp, (char*)pps_data, 2);
+               tmp[2] = '\0';
+               bret = int_from_string ((char*)tmp, NULL, &val , 16);
+               if (FALSE == bret)
+               {
+                       GST_ERROR ("Failed to int from string...");
+                       goto exit;
+               }
+
+               (*packetized_dci)[idx] = val;
+               pps_data += 2;
+               pps_len = pps_len - 2;
+               //g_print ("val = 0x%02x, pps_len = %d, idx = %d\n", val, pps_len, idx);
+               idx++;
+       }
+       idx = 0;
+
+#if 0
+       g_print ("\n\n");
+
+       g_print ("Complete VIDEO packetized_dci: 0x");
+       while (idx < *packetized_dci_len)
+       {
+               g_print ("%02x", (*packetized_dci)[idx]);
+               idx++;
+       }
+
+       g_print ("\n\n");
+#endif
+
+exit:
+       if (tmp_sps_ptr)
+       {
+               free (tmp_sps_ptr);
+               tmp_sps_ptr = NULL;
+       }
+       if (tmp_pps_ptr)
+       {
+               free (tmp_pps_ptr);
+               tmp_pps_ptr = NULL;
+       }
+       if ((FALSE == bret) && *packetized_dci)
+       {
+               free (*packetized_dci);
+               *packetized_dci = NULL;
+       }
+
+       return bret;
+
+#else
+       /* code for sending NALU DCI as it is */
+       guint nalu_dci_len = strlen ((char *)nalu_dci);
+       unsigned char *nalu = nalu_dci;
+       guint idx = 0;
+       unsigned char tmp[3] = {0, };
+       gboolean bret = TRUE;
+       int val = 0;
+
+       *packetized_dci_len = (nalu_dci_len/2);
+
+       *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
+       if (NULL == *packetized_dci)
+       {
+               GST_ERROR ("Failed to allocate memory..\n");
+               bret = FALSE;
+               goto exit;
+       }
+
+       /* copy entire DCI*/
+       while (nalu_dci_len)
+       {
+               memset (tmp, 0x00, 3);
+               strncpy ((char*)tmp, (char*)nalu, 2);
+               tmp[2] = '\0';
+               bret = int_from_string ((char*)tmp, NULL, &val , 16);
+               if (FALSE == bret)
+               {
+                       GST_ERROR ("Failed to int from string...");
+                       goto exit;
+               }
+               (*packetized_dci)[idx] = val;
+               nalu += 2;
+               nalu_dci_len = nalu_dci_len - 2;
+               //g_print ("val = 0x%02x, dci_len = %d, idx = %d\n", val, nalu_dci_len, idx);
+               idx++;
+       }
+
+      idx = 0;
+
+      g_print ("\n\n NEW DCI : 0x ");
+
+       while (idx < *packetized_dci_len)
+       {
+          g_print ("%02x", (*packetized_dci)[idx] );
+          idx++;
+       }
+
+       g_print ("\n\n\n");
+
+exit:
+
+       if ((FALSE == bret) && *packetized_dci)
+       {
+               free (*packetized_dci);
+               *packetized_dci = NULL;
+       }
+
+       return bret;
+#endif
+}
+
diff --git a/ssdemux/src/ssmanifestparse.h b/ssdemux/src/ssmanifestparse.h
new file mode 100755 (executable)
index 0000000..21c4042
--- /dev/null
@@ -0,0 +1,129 @@
+
+
+#ifndef __SS_MANIFEST_PARSE_H__
+#define __SS_MANIFEST_PARSE_H__
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <libxml2/libxml/tree.h>
+
+G_BEGIN_DECLS
+typedef struct _GstSSMParse GstSSMParse;
+
+#define GST_SSMPARESE(m) ((GstSSMParse*)m)
+#define XML_MAKE_FOURCC(a,b,c,d)        ((guint32)((a)|(b)<<8|(c)<<16|(d)<<24))
+#define BITRATE_SWITCH_UPPER_THRESHOLD 0.4
+#define BITRATE_SWITCH_LOWER_THRESHOLD 0.1
+
+
+typedef enum
+{
+  SS_STREAM_UNKNOWN = -1,
+  SS_STREAM_VIDEO = 0,
+  SS_STREAM_AUDIO,
+  SS_STREAM_TEXT,
+  SS_STREAM_NUM,
+}SS_STREAM_TYPE;
+
+typedef enum
+{
+  SS_MODE_NO_SWITCH, /* no switch is need */
+  SS_MODE_AONLY, /* switch to audio only */
+  SS_MODE_AV,
+}SS_BW_MODE;
+
+typedef struct
+{
+  guint64 StreamTimeScale;
+  guint64 stream_duration;
+  SS_STREAM_TYPE type;
+  guint nChunks;
+  guint nQualityLevels;
+  guint MaxWidth;
+  guint MaxHeight;
+  guint DisplayWidth;
+  guint DisplayHeight;
+  GList *quality_lists;
+  GList *fragment_lists;
+  gchar *StreamType;
+  gchar *StreamUrl;
+  gchar *StreamSubType;
+  gchar *StreamName;
+  gboolean fraglist_eos;
+  GMutex *frag_lock;
+  GCond *frag_cond;
+}GstSSMStreamNode;
+
+typedef struct
+{
+  guint index;
+  guint bitrate;
+  guint max_width;
+  guint max_height;
+  guint samplingrate;
+  guint channels;
+  guint bps; /* bits per sample */
+  guint packet_size;
+  guint audio_tag;
+  guint NALULengthofLength;
+  gchar *fourcc;
+  gchar *codec_data;
+}GstSSMQualityNode;
+
+typedef struct
+{
+  guint num;
+  guint64 dur;
+  guint64 time;
+  guint media_type;
+}GstSSMFragmentNode;
+
+typedef struct
+{
+  gchar *SystemID;
+  gchar *Content;
+  guint ContentSize;
+}GstSSMProtectionNode;
+
+typedef struct
+{
+  guint MajorVersion;
+  guint MinorVersion;
+  guint64 TimeScale;
+  guint64 Duration;
+  guint LookAheadCount;
+  guint64 DVRWindowLength;
+  gboolean PresentationIsLive;
+  GList *streams[SS_STREAM_NUM];
+  GstSSMProtectionNode *ProtectNode;
+}GstSSMRootNode;
+
+struct _GstSSMParse
+{
+  gchar *uri; /* manifest URI */
+  gchar *presentation_uri;
+  GstSSMRootNode *RootNode;
+  GMutex *lock;
+  guint64 ns_start;
+};
+
+#define gst_ssm_parse_check_stream(parser, stream_type) (parser->RootNode->streams[stream_type])
+#define GST_SSM_PARSE_GET_DURATION(parser) (parser->RootNode->Duration)
+#define GST_SSM_PARSE_GET_TIMESCALE(parser) (parser->RootNode->TimeScale)
+#define GST_SSM_PARSE_IS_LIVE_PRESENTATION(parser) (parser->RootNode->PresentationIsLive)
+#define GST_SSM_PARSE_LOOKAHEAD_COUNT(parser) (parser->RootNode->LookAheadCount)
+#define GST_SSM_PARSE_NS_START(parser) (parser->ns_start)
+
+const gchar *ssm_parse_get_stream_name(SS_STREAM_TYPE type);
+GstSSMParse *gst_ssm_parse_new (const gchar * uri);
+void gst_ssm_parse_free (GstSSMParse *parser);
+gboolean gst_ssm_parse_manifest (GstSSMParse *parser, char *data, unsigned int size);
+gboolean gst_ssm_parse_get_next_fragment_url (GstSSMParse *parser, SS_STREAM_TYPE stream_type, gchar **uri, guint64 *start_ts);
+gboolean gst_ssm_parse_append_next_fragment (GstSSMParse *parser, SS_STREAM_TYPE stream_type, guint64 timestamp, guint64 duration);
+GstCaps *ssm_parse_get_stream_caps (GstSSMParse *parser, SS_STREAM_TYPE stream_type);
+SS_BW_MODE
+gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate);
+gboolean gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_time);
+G_END_DECLS
+#endif /* __SS_MANIFEST_PARSE_H__ */
+